HTML5 2D平台游戏开发#4状态机
在實現了《HTML5 2D平臺游戲開發——角色動作篇之沖刺》之后,我發現隨著角色動作的增加,代碼中的邏輯判斷越來越多,鋪天蓋地的if() else()語句實在讓我捉襟見肘:
這還僅僅是角色只有數個動作的情況下,如果后期角色動作越來越多,那么這種編碼方式不僅容易出錯,而且還難以維護,我意識到自己正在朝一個錯誤的方向前進。在做了一番調研后,發現有限狀態機(Finite-state machine,簡稱FSM)是解決這類問題的方案之一。不過在使用狀態機之前,首先要明確都有些什么狀態,狀態之間是如何切換的。在稿紙上畫一張草圖來整理一下思路:
?
可以發現,雖然現在角色只有四種狀態,但按鍵分支已經達到八種,而且還沒有考慮到在每個狀態中雖然按下按鍵但不改變狀態的情況,比如跳躍中按下A/D鍵能左右移動但還是跳躍狀態。
下面就到了實現狀態機的階段了。狀態機首先要有一個標識當前狀態的成員,另外還需要一個設置這個成員的方法:
function FSM() {var activeState = null;//@param state {Function} 每一個狀態對應一個執行函數this.setState = function(state) {activeState = state;};this.update = function() {if (activeState != null) {activeState();}}; }var f = new FSM(); var flag = true;f.setState(function() {console.log('現在是站立狀態'); });//模擬狀態切換 (function updateState() {if (flag) {f.setState(function() {console.log('現在是移動狀態');});flag = !flag;} else {f.setState(function() {console.log('現在是站立狀態');});flag = !flag;}f.update();setTimeout(updateState, 1000); })();不過,這個狀態機在游戲中不會用到?,這里只是用來表述一種思路。還有一種是基于堆棧的狀態機,有時稱之為下推自動機(Pushdown automata)
這種狀態機在工作時,只有棧頂的元素處于激活狀態。
一次只允許一種狀態激活,這樣就方便了游戲在各種狀態間進行切換,同時避免了代碼邏輯混亂的問題。
在update中使用條件選擇語句來進入各個分支:
update(dt) {switch (state) {case STATE.IDLE: //空閑this.updateIdle(dt);break;case STATE.WALKING: //移動this.updateWalking(dt);break;case STATE.JUMPING: //跳躍this.updateJumping(dt);break;case STATE.DASHING: //沖刺this.updateDashing(dt);break;case STATE.DASHING_JUMPING: //沖刺跳this.updateDashingJumping(dt);break;} }再次回顧一下上面的思路草圖,在空閑狀態,角色能過渡到的狀態有跳躍、移動、沖刺,代碼實現如下:
//空閑 updateIdle(dt) {this.speed.x = 0; //處于靜止狀態,速度為0if (key[65]) { //向左移動this.speed.x -= this.speedX;this.direction = -1;this.state = STATE.WALKING; //進入移動狀態this.play(); //播放移動狀態時的動畫 }if (key[68]) { //向右移動this.speed.x += this.speedX;this.direction = 1;this.state = STATE.WALKING;//同上this.play();}if (key[75]) { //跳躍if (!this.jumping) { //這里不用判斷onGround,因為處于idle狀態必然是onGroundthis.state = STATE.JUMPING;//進入跳躍狀態this.jumping = true;this.speed.y = this.jumpSpeed;}}if (key[85]) { //沖刺if (!this.dashing) {this.dashLifeTime = CONFIG.MAX_DASH_LIFE_TIME;this.state = STATE.DASHING;//進入沖刺狀態this.dashing = true;this.speed.x += CONFIG.DASH_SPEED * this.direction;}} else {this.dashing = false;}this.speed.y += this.gravity;//更新位置this.moveX(dt);this.moveY(dt);if (this.pos.y >= 9.375) {this.speed.y = 0;this.pos.y = 9.375;if (!key[75]) this.jumping = false;} }在上面的代碼中,如果按下了移動鍵,則會進入移動狀態,游戲再次循環時,就會執行updateWalking方法。如法炮制,就能很輕易地實現剩余的方法。
//移動 updateWalking(dt) {this.state = STATE.IDLE;this.speed.x = 0;if (key[65]) {this.speed.x -= this.speedX;this.state = STATE.WALKING;this.direction = -1;}else if (key[68]) {this.speed.x += this.speedX;this.state = STATE.WALKING;this.direction = 1;}if (key[75]) {if (!this.jumping) {this.state = STATE.JUMPING;this.jumping = true;this.speed.y = this.jumpSpeed;}} else {this.jumping = false;}if (key[85]) { //沖刺if (!this.dashing) {this.dashLifeTime = CONFIG.MAX_DASH_LIFE_TIME;this.state = STATE.DASHING;this.dashing = true;this.speed.x += CONFIG.DASH_SPEED * this.direction;}} else {this.dashing = false;}this.moveX(dt);this.moveY(dt);if (this.state === STATE.IDLE) this.play(); }本篇結束,有空再繼續更新。
P.S.在沒有使用狀態機之前,我考慮的是通過記錄按鍵的順序與組合來實現各種動作,既繁瑣又容易出錯,代碼感覺都看不下去了,還好懸崖勒馬,才避免了許多無用功?。
?
轉載于:https://www.cnblogs.com/undefined000/p/use-finite-state-machine-in-2D-Platform-Game.html
總結
以上是生活随笔為你收集整理的HTML5 2D平台游戏开发#4状态机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [PY3]——IO——文件目录操作
- 下一篇: day 55 前端