1. 程式人生 > >PyGmae:有限狀態機實踐(三)

PyGmae:有限狀態機實踐(三)

#   _*_ coding:utf-8 _*_
from random import randint
import sys
import pygame
from pygame.locals import *
from gameobjects.vector2 import Vector2
import time

__author__ = 'admin'

'''
    螞蟻狀態機(三)
    實現了狀態機內部訊號自動轉換,不依靠外界訊號
    螞蟻最初為waiting
    轉變為exploring後再判斷是否發現目標葉子,期間穿插waiting(使用隨機數決定發生頻率)
    發現葉子轉為seeking
    達到葉子後轉為exploring,否則繼續seeking
'''

SCREEN_SIZE = (640, 480)
NEST_POSITION = (320, 240)
NEST_SIZE = 100.

WHITE = (255, 255, 255)
pygame.init()

screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
clock = pygame.time.Clock()


class Microcosm(object):
    def __init__(self):
        self.objects_dict = {}
        self.obj_id = 0
        self.objects_list = []

    def addObj(self, obj):
        self.objects_list.append(obj)
        self.objects_dict[self.obj_id] = obj
        #   是在這個位置為物件附上id屬性的,下面刪除字典元素時要用到這個id
        obj.id = self.obj_id
        self.obj_id += 1

    def getObj(self, obj_id):
        return self.objects_dict[obj_id]

    def get_closeTo_obj(self, name, location, range=50):
        for obj in self.objects_dict.values():
            if obj.name == name:
                distance = location.get_distance_to(obj.location)
                if distance <= range:
                    return obj
        return None


class ObjProduct(object):
    def __init__(self, microcosm, name, path):
        self.microcosm = microcosm
        self.name = name
        self.op_path = path
        self.op = pygame.image.load(self.op_path).convert_alpha()
        self.state = 0
        self.fsm = None
        self.id = 0
        self.speed = 0
        self.location = Vector2(0, 0)
        self.destination = Vector2(0, 0)

    def bind(self, state, fsm):
        self.fsm = fsm
        self.state = state


class Leaf(ObjProduct):
    def __init__(self, microcosm, name, path):
        ObjProduct.__init__(self, microcosm, name, path)
        self.leaf = self.op
        self.location = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))
        self.leaf_position = self.location
        self.draw(self.leaf_position)

    def draw(self, location):
        screen.blit(self.leaf, location)

    def wait(self):
        self.draw(self.leaf_position)

class Ant(ObjProduct):
    def __init__(self, microcosm, name, path):
        ObjProduct.__init__(self, microcosm, name, path)
        self.ant = self.op
        self.location = Vector2(100, 100)
        self.ant_position = self.location
        self.draw(self.ant_position)
        self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))
        #   這裡讓leaf_id為None,單純就是不想給它一個數字而已,避免這個預設值作為Key使用時報錯
        self.leaf_id = None

    def draw(self, location):
        screen.blit(self.ant, location)

    def explore(self):
        print("探索中.....")
        distance = self.destination - self.ant_position
        #   獲取此時螞蟻距離目標點間的向量長度(即兩點間的實際距離)
        x = self.ant_position.get_distance_to(self.destination)
        #   獲取單位向量,即每次螞蟻移動的向量
        heading = distance.normalise()
        #   如果螞蟻再移動單位向量就會越過目標點
        if x <= heading.get_length():
            print("到達目的地了....前往下一個點")
            self.destination = Vector2(randint(0, SCREEN_SIZE[0] // 2), randint(0, SCREEN_SIZE[1] // 2))
        else:
            self.ant_position += heading
            self.draw(self.ant_position)

    def wait(self):
        print("停頓下,思考人生.....")
        pygame.time.delay(10)
        self.draw(self.ant_position)

class State(object):
    def exec(self, obj):
        pass

    def exit(self, obj):
        pass


class ExploreState(State):
    def exec(self, obj):
        #   決定探索過程中觸發wait的頻率
        if randint(1, 1000) == 1:
            #   訊號置為0
            obj.state = 0
        else:
            #   判斷當前螞蟻物件附近範圍內是否有葉子存在,並獲取這個葉子物件
            leaf_ = obj.microcosm.get_closeTo_obj('leaf', obj.location)
            #   如果有這樣的葉子物件
            if leaf_ is not None:
                #   為當前螞蟻物件新增該目標葉子id屬性(將該葉子繫結到該螞蟻上,方便呼叫)
                obj.leaf_id = leaf_.id
                #   訊號置為seek
                obj.state = 2
            else:
                #   附近沒有葉子就執行explore
                obj.explore()

class WaitSate(State):
    def exec(self, obj):
        #   執行wait方法
        obj.wait()
        #   訊號置為1,使得螞蟻再動起來
        obj.state = 1


class SeekState(State):
    def exec(self, obj):
        #   當前螞蟻物件是否綁定了leaf_id屬性(這點可以說明螞蟻附近是否有葉子)
        if obj.leaf_id is not None:
            #   通過已知的葉子id獲取對應的葉子物件
            leaf_ = obj.microcosm.getObj(obj.leaf_id)
            print("發現目標葉子..走過去")
            #   將葉子的位置當做螞蟻本次行為的終點
            obj.destination = leaf_.location
            #   獲取此時螞蟻起點->終點的向量
            distance = obj.destination - obj.ant_position
            #   獲取此時螞蟻距離目標點間的向量長度(即兩點間的實際距離)
            x = obj.ant_position.get_distance_to(obj.destination)
            #   獲取單位向量,即每次螞蟻移動的向量
            heading = distance.normalise()
            obj.draw(obj.ant_position)
            #   如果螞蟻再移動單位向量就會越過目標點
            if x <= heading.get_length():
                print("已達到目標葉子")
                #   讓螞蟻吃掉葉子,即在字典和列表中刪除葉子物件,以防止下一次explore時螞蟻距離該葉子還很近再被拉回
                obj.microcosm.objects_dict.pop(leaf_.id)
                obj.microcosm.objects_list.remove(leaf_)
                #   將該螞蟻繫結的葉子id置為None
                obj.leaf_id = None
                #   將訊號置為1,繼續探索
                obj.state = 1
            #   螞蟻還未到達葉子,即還需要繼續走一個heading
            else:
                obj.ant_position += heading
                #   繼續執行seeking
                obj.state = 2
        else:
            #   當前螞蟻附近沒有葉子了,執行探索
            obj.state = 1



class StateMachine(object):
    def __init__(self):
        #   狀態集合
        self.states = {0: WaitSate(), 1: ExploreState(), 2: SeekState()}

    #   改變狀態
    def changeState(self, objs):
        for obj in objs:
            #   這裡先留著吧,考慮下state是否有為None的必要
            if obj.state is None:
                return
            else:
                if obj.name == 'leaf':
                    curFsm = self.states[0]
                    curFsm.exec(obj)
                else:
                    print("name[%s]--state[%d]" % (obj.name, obj.state))
                    newFsm = self.states[obj.state]
                    newFsm.exec(obj)

def checkForOut():
    for event in pygame.event.get():
        if event.type == 12:
            sys.exit()
        if event.type == 2:
            if event.key == 27:
                exit()


micr = Microcosm()
sm = StateMachine()
for i in range(1):
    ant = Ant(micr, 'ant', r"E:\PycharmProjects\PGStudy\resource\ant.png")
    ant.bind(0, sm.states[0])
    micr.addObj(ant)

while True:
    checkForOut()
    screen.fill(WHITE)
    pygame.draw.circle(screen, (200, 255, 200), NEST_POSITION, int(NEST_SIZE))
    if randint(1, 500) == 1:
        leaf = Leaf(micr, 'leaf', r"E:\PycharmProjects\PGStudy\resource\leaf.png")
        leaf.bind(0, sm.states[0])
        micr.addObj(leaf)
    sm.changeState(micr.objects_list)
    pygame.display.update()
    pygame.time.delay(10)

相關推薦

PyGmae有限狀態實踐()

# _*_ coding:utf-8 _*_ from random import randint import sys import pygame from pygame.locals import * from gameobjects.vector2 import V

PyGmae有限狀態實踐(九)

# _*_ coding:utf-8 _*_ from random import randint import sys import pygame from pygame.locals import * from gameobjects.vector2 import V

Python有限狀態小用例

# _*_ coding:utf-8 _*_ from random import randint from time import sleep __author__ = 'admin' ''' 23種設計模式之狀態模式:有限狀態機 下面介紹了燈的三種

TCP次握手、四次端口和有限狀態

TCP三次握手、四次端口和有限狀態機1、TCP用三次握手(three-way handshake) 一對終端同時初始化一個它們之間的連接是可能的。但通常是由一端打開一個套接字(socket)然後監聽來自另一方的連接,這就是通常所指的被動打開(passive open)。服務器端被被動打開以後,用戶端就能開始創

文字版 描述TCP次握手和四次揮手以及有限狀態

切換 list 遠方 是什麽 int last 關閉 ive tcp報文 客戶端和服務器 ,雙方都處於第一次交互的情況下展開通信 三次握手 1.首先 服務器 需要是處於listen收聽狀態下才能接受報文客戶端由closed狀態 打開並向服務器發送報文SYN=1 申請建

有限狀態(FSM)寫法的個人總結(一段式,二段式,段式)

      狀態機描述時關鍵是要描述清楚幾個狀態機的要素,即如何進行狀態轉移,每個狀態的輸出是什麼,狀態轉移的條件等。具體描述時方法各種各樣,最常見的有三種描述方式:      (1)一段式:整個狀態機寫到一個always模組裡面,在該模組中既描述狀態轉移,又描述狀態的輸入

學習筆記() 簡單的狀態模式&FSM有限狀態框架的實現(二)

之前釋出的那篇部落格可能說的並是不非常清楚,所以整理了一下,也參考了一些文件,於是又寫了一篇總結。 一、有限狀態機FSM的要點 1、擁有一組狀態,並且可以再這組狀態之間進行切換。 2、狀態機同時只能存在一個狀態,英雄不能能同時處於跳躍和站立。而防止這一點就是使用

【遊戲設計模式】之 狀態模式、有限狀態 & Unity版本實現

毛星雲,網路ID「淺墨」,90後,熱愛遊戲開發、遊戲引擎、計算機圖形、實時渲染等技術,就職於騰訊互娛。 微軟最有價值專家 著作《Windows遊戲程式設計之從零開始》、《OpenCV3程式設計入門》 碩士就讀於南京航空航天大學航天學院(2013級碩士研究生),已於2016年三月畢業。本科

段式有限狀態Verilog代碼

cas 而且 moore 特定 ram 簡寫 color col 轉移 狀態機由狀態寄存器和組合邏輯電路構成,能夠根據控制信號按照預先設定的狀態進行狀態轉移,是協調相關信號動作、完成特定操作的控制中心。有限狀態機簡寫為FSM(Finite State Machine),主要

詞法分析從RE(正則表示式)到DFA(確定的有限狀態

模式識別(Pattern recognization)是現在非常流行的一個詞,我們對詞法的分析也是基於模式(pattern-based)的。我們用正則表示式(Regular Expression)來定義單詞的模式,而在詞法分析時,有限狀態機(Finite Aut

最佳實踐有限狀態

有限狀態機(Finite State Machine,FSM),簡稱狀態機。今天這篇文件的主體思路,來自本人授權的一項發明專利。第一次嘗試寫出來,希望分享給更多人。 我當時寫這個專利的時候,太有感覺了。非常的激動,同時我也很想分享給同事,但是可能太抽象了,未果。然後我想申請優秀專利獎,沒有渠道!所以最近刷屏的

獨立項目-角色控制器-有限狀態(FSM)

技術分享 OS pos .com com 過渡 動畫過渡 unity 狀態機   學習內容:     Unity5的新動畫系統       1.動畫導入 分動畫       2.創建動畫狀態機       3.設置動畫過渡 設置動畫跳轉條件       4.動畫重定向 獨立

go - FSM(有限狀態)初體驗

層次 time lba 當前 時機 警告 pen nil 自定義 FSM有限狀態機 /** * @Author: wsp * @Time : 2018/4/11 16:45 * @Description: */ package fsmStrudy import

Verilog筆記.3.有限狀態

情況 || mage 參數 lose default def ril 定義 有限狀態機有限狀態機是由寄存器組和組合邏輯構成的硬件時序電路,其狀態(即由寄存器組的1和0的組合狀態所構成的有限個狀態)只可能在同一時鐘跳變沿的情況下才能從一個狀態轉向另一個狀態,究竟轉向哪一狀態還

FPGA學習筆記(七)——FSM(Finite State Machine,有限狀態)設計

fault mil 系統 time 編碼 代碼 ril esc 寫法   FPGA設計中,最重要的設計思想就是狀態機的設計思想!狀態機的本質就是對具有邏輯順序和時序規律的事件的一種描述方法,它有三個要素:狀態、輸入、輸出:狀態也叫做狀態變量(比如可以用電機的不同轉速作為狀態

從React Redux的實際業務場景來看有限狀態

寫在前面 上一篇:從Promise的實現來看有限狀態機 上一篇講到了一個簡單的,利用了有限狀態機的前端實現Promise。Promise的有限狀態機除了start以及finish兩個狀態,其核心的三個狀態其實就是一個非同步行為的三種狀態:PENDING、FULFILLED、REJECTED。通過非同步行為

前端狀態管理與有限狀態

原文連結 當下前端流行的框架,都是用狀態來描述介面(state => view),可以說前端開發實際上就是在維護各種狀態(state),這已經成為目前前端開發的共識。 View = ViewModel(Model); 複製程式碼 理想情況下,ViewModel 是純函式,給定相同的 Mod

Verilog_有限狀態

名詞解釋 狀態機就是一種能夠描述具有邏輯順序和時序順序事件的方法。 狀態機有兩大類:Mealy型和Moore型。 Moore型狀態機的輸出只與當前狀態有關,而Mealy型狀態機的輸出不僅取決於當前狀態,還受到輸入的直接控制,並且可能與狀態無關。 當使用Veril

有限狀態(FSM)的設計

有限狀態機(FSM)的設計_zhangxianhe  有限狀態機(FSM)是一種常見的電路,由時序電路和組合電路組成。  設計有限狀態機的第一步是確定採用Moore 狀態機還是採用Mealy 狀態機。 Mealy 型:狀態的轉變不僅和當前狀態有關,而且跟各輸入訊號有關; Moo

Unity簡單有限狀態實現

【前言】 本篇來說一下關於簡單有限狀態機的演算法實現,當然我們的幾個狀態會比較簡單,而且本身我也是處於入門狀態,所以當成一個簡單的知識積累。有限狀態機,顧名思義,狀態是有限個的,而且狀態之間是關聯的,本篇寫的狀態機,其實是類似寫遊戲裡面的AI機器人,就是那些遊戲