Processing 狀態機應用研究(線性轉換)

狀態機(State Machine)是一個抽象概念,是一個邏輯嚴謹的數學抽象。它的這種概念在現實生活中到處都有應用,或者說現實世界就充滿狀態機。要討論狀態機,就涉及到相關概念,好比:State 狀態,Event 事件,Action 動做,Transition 轉換。狀態機是計算機科學的重要基礎概念之一,也能夠說是一種總結概括問題的思想,應用範圍很是普遍。[1]
若是要便於理解,那麼舉燈開關現象的例子是最合適不過的!燈有兩種狀態:開和關,而狀態間的轉換是瞬間完成的,由開關動做觸發轉換,而整個觸發轉換的過程就是事件,如圖:
java

那麼上述就是燈的「狀態機」。它描述了燈運行時的狀況,有了這個,那麼用程序邏輯就能夠很好地解釋它,模擬它,否則太過於具象了,很難用邏輯去表示它。
固然狀態機還分類別,不一樣的事物抽象出來的狀態機都不盡相同,並且結構都不同。固然,它也有共通性[2]:編程

(1)可用「狀態」來描述事物,而且任一時刻,事物老是處於一種狀態
(2)事物擁有的狀態總數是有限的,因此學名成爲「有限狀態機」(Finite-state machine, FSM)
(3)經過觸發事物的某些行爲,能夠致使事物從一種狀態過渡到另外一種狀態(自動機制)
(4)事物狀態變化是有規則的,例如:A狀態能夠變換到B,B能夠變換到C,A卻不必定能變換到C
(5)同一種行爲,能夠將事物從多種狀態變成同種狀態,可是不能從同種狀態變成多種狀態數據結構

總之,它是表示有限個狀態以及在這些狀態之間的轉移和動做等行爲的數學模型。看一些比較複雜的狀態機模型:
動畫

<來自百度圖片搜索>

this

筆者才疏學淺,就此對狀態機介紹到這,讀者感興趣還想了解可自行查閱相關文檔。操作系統


既然狀態機很重要,那麼在Processing的應用中也不可避免地會使用到相關概念和技術。早在2017年筆者就以狀態量概念探討了在Processing程序中的應用,見下文:
https://blog.csdn.net/fddxsyf123/article/details/62848357 ---Processing 狀態量控制動畫技巧.net

固然那沒有機(系統)的概念。此次就以最簡單的一種形式來初探-----線性的狀態切換的狀況設計

情景設計:

【一個裝置有三盞燈組成,依次標爲A、B、C。只有一個按鈕用於轉換裝置狀態,該裝置可經過按鈕或者自行的觸發器依次循環點亮A、B、C三盞燈。】
咱們畫一張狀態機示例:
調試

代碼實現

State類:code

class State
{
  boolean canChange = true;
  int temp = 0;
  void Enter() {
    temp = 0;
    println(this.getClass().getName()+" - Enter !");
  }

  void Update() {
    //println(this.getClass().getName()+" - Update !");
    temp ++;
  }

  void Exit() {
    println(this.getClass().getName()+" - Exit !");
  }
}

設了EnterUndateExit三個方法模擬狀態的進入、執行(保持)、退出的過程,還有一個temp變量,只是臨時爲了調試方便設計的,方便查看Update方法的執行與否。這裏其實能夠設爲抽象類,更科學。

StateMachine類:

class StateMachine
{
  State currentState;
  State lastState;

  StateMachine(State initState)
  {
    SwitchTo(initState);
  }

  public void SwitchTo(State newState)
  {
    if (currentState!=null)
    {
      this.lastState = currentState; 
      lastState.Exit();
    }
    currentState = newState;
    currentState.Enter();
  }

  public void Update()
  {
    this.currentState.Update();
  }
}

存有當前狀態舊時狀態,並賦予SwitchTo()Update()兩個方法,依次分別是切換狀態方法執行狀態方法

Operator類:

class Operator
{
  public StateMachine stateMachine;
  private ArrayList<State> states;
  private boolean mousePressedThisFrame = false;

  boolean ischecked = false;

  Operator()
  {
    states = new ArrayList<State>();
    this.states.add(new StageA());
    this.states.add(new StageB());
    this.states.add(new StageC());
    stateMachine = new StateMachine(states.get(0));
  }

  void NextStage()
  {
    if (states.size() > 0)
    {
      State firstStage = states.remove(0);
      states.add(firstStage);
      stateMachine.SwitchTo(states.get(0));
    }
  }

  void setChecked()
  {
    ischecked = true;
  }

  void Update()
  {
    if ((mousePressed && !mousePressedThisFrame) || ischecked)
    {
      mousePressedThisFrame = true;
      ischecked = false;
      if (stateMachine.currentState.canChange)
      {
        println("try Change To Next Stage.");
        this.NextStage();
      }
    }

    this.stateMachine.Update();

    if (!mousePressed && mousePressedThisFrame)
    {
      mousePressedThisFrame = false;
    }
  }
}

這是操控的類,顧名思義是操做運行建立好的狀態機。成員變量有狀態鏈表、狀態機等。還有轉換下一個狀態NextStage()的具體方法和實時檢測刷新的方法Update()


Light類:

class Light {
  int cc;
  PVector pos;
  int alpha = 0;
  boolean isopen;
  Light(int _cc, int posx, int posy)
  {
    cc = _cc; //固定顏色
    isopen = false;//默認關的狀態
    pos = new PVector(posx, posy);
  }
  //開關
  public void update(boolean b)
  {
    isopen = b;
    if( isopen == false ) //若是關了,亮度歸位
    	alpha = 0;
  }

  //運行時
  public void working()
  {
    if (isopen)
      alpha += 1;   //若是開着,慢慢變量
    alpha = constrain(alpha, 0, 255);
    //println(alpha);
  }

  public void draw()
  {
    if (isopen)//若是開,慢慢量
    {
      fill(cc, alpha);
    } else//若是關,黑色的
    {
      fill(20, 250);
    }
    push();
    translate(pos.x, pos.y);
    rect(0, 0, 80, 150);//燈的表現形式
    pop();
  }
}

下面是三個state實現類:

class StageA extends State
{

  StageA()
  {
  }

  void Enter()
  {
    super.Enter();
    light1.update(true);
  }

  void Update()
  {
    super.Update();    
    if (temp == 1)
      println(this.getClass().getName()+" - Update !");

    light1.working();
  }

  void Exit() {
    println(this.getClass().getName()+" - Exit !");
    light1.update(false);
  }
}

class StageB extends State
{

  StageB()
  {
  }

  void Enter()
  {    
    super.Enter();
    light2.update(true);
  }

  void Update()
  {    
    super.Update();
    if (temp == 1)

      println(this.getClass().getName()+" - Update !");
    light2.working();
  }

  void Exit() {
    println(this.getClass().getName()+" - Exit !");    
    light2.update(false);
  }
}

class StageC extends State
{

  StageC()
  {
  }

  void Enter()
  {    
    super.Enter();
    light3.update(true);
  }

  void Update()
  {   
    super.Update();
    if (temp == 1)
      println(this.getClass().getName()+" - Update !");
    light3.working();
  }

  void Exit() {
    println(this.getClass().getName()+" - Exit !");
    light3.update(false);
  }
}

最後是主程序:

Operator operSystem;

float timePassed;
float nextCheckTime;
float lastCheckTime;
float timeLapse = 1500;

Light light1;
Light light2;
Light light3;


void setup()
{
  size(600,500);

  timePassed = 0;
  lastCheckTime = 0;
  nextCheckTime = timeLapse*2; //首次計時長一點
  
  light1 = new Light(color(240,20,20),100,100);
  light2 = new Light(color(20,240,20),250,100);
  light3 = new Light(color(20,20,240),400,100);
  operSystem = new Operator();
}

void draw()
{
  timePassed = millis() - lastCheckTime;
  
  operSystem.Update();   //「操做系統」 實時運行
  
  light1.draw();
  light2.draw();
  light3.draw();
  
  //計時器 - 觸發(轉換)
  if(timePassed > nextCheckTime)
  {
    //println("Check!");
     lastCheckTime = millis();
     //nextCheckTime = lastCheckTime + timeLapse;
     nextCheckTime = timeLapse;
     operSystem.setChecked();
  }
  
}

void mouseClicked()
{
}

void keyPressed()
{
}

類的關係圖參考:

總結

這是一個很好的有限狀態機入門案例,一種線性的狀態切換場景。下回咱們來看看進一步的狀態機,也就是離散的狀態切換,其實有點像學數據結構的知識,那個狀態機鏈表咱們能夠隨意設計並調用。相信讀者看到這,對狀態機有個初步的認識了,並能在實際開發中嘗試使用它,但願一切順利,感謝您的閱讀😘。


參考:
[1] https://zhuanlan.zhihu.com/p/47434856 ---- 什麼是狀態機
[2] https://www.zhihu.com/question/22363777/answer/652758029 -----什麼是狀態機?
[3] https://zhuanlan.zhihu.com/p/101020131 一輩子萬物——Processing創意編程碎片

相關文章
相關標籤/搜索