[Godot] – 简单有限状态机FininateStateMachine

前言

之前在本站已经写过一篇有限状态机的博客,最近又看到一种新的实现方法,撰以记.

结构

本状态机使用继承的方法,首先创建一个角色类和一个状态机脚本(状态机类的代码),在角色类上添加状态机类节点.这里的代码是所有使用状态机的角色的统一规范.

角色类

Character 类中有所有角色最基本的节点,对于碰撞体积和动画精灵都不做定义和修改,因为这里相当于一个抽象父类(Java中的概念),用来定义规范和接口(主打一个封装).

FininateStateMachine – 状态机

状态机中的脚本:

extends Node
class_name FininateStateMachine

var states: Dictionary = {}
var previous_state: int = -1
var state = -1: 
	set = set_state	# 设置变量并读取变量

@onready var parent: Character = get_parent()	# 获取使用状态机的角色
@onready var animation_player: AnimationPlayer = parent.get_node("AnimationPlayer") # 获取角色下的动画播放器

func _physics_process(delta: float) -> void:
	if (state != -1):	# 当状态有效时执行
		_state_logic(delta)	# 状态的逻辑
		var transition:int = _get_transition()	# 检测是否需要切换状态,默认-1不转换
		if (transition != -1):
			set_state(transition)	# 将状态设置成新的状态

func _get_transition() -> int:
	# 检测是否需要切换状态,在子类中实现
	return -1
		
func _state_logic(_delta: float) -> void:
	# 状态的主要逻辑
	pass
	
func _add_state(new_state: String) -> void:
	# 在状态机字典中添加一种新的状态
	states[new_state] = states.size()

func _enter_state(_previous_state: int, _new_state: int) -> void:
	# 从旧的状态进入到新的状态时执行
	pass
	
func _exit_state(_state_exited: int) -> void:
	# 离开状态时执行
	pass
	
func set_state(new_state: int) -> void:
	# 将状态设置成新的状态时执行
	_exit_state(state)
	previous_state = state
	state = new_state
	_enter_state(previous_state, state)

状态机中定义了一些管理状态的接口规范.

Character – 角色类

角色类中只定义了最基本的角色们的规范.

@icon("res://AssetsPack/heroes/knight/knight_idle_anim_f0.png")
extends CharacterBody2D
class_name Character

@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D

const FRICTION:float = .15
@export var acceleration: int = 40
@export var max_speed: int = 10
var speed: int = 0

var move_direction: Vector2 = Vector2.ZERO

func _physics_process(_delta: float) -> void:
	move_and_slide()						# 移动
	velocity = lerp(velocity, Vector2.ZERO, FRICTION)	# 应用摩擦力
	
func move() -> void:
	move_direction = move_direction.normalized()	# 将向量长度变为1
	speed += acceleration
	speed = clampf(speed, -max_speed, max_speed)
	velocity += speed * move_direction

Player – 玩家类

我们利用 Character 类创建一个新的继承场景,重命名为 Player 作为我们玩家的类,接触继承后自带的状态机和 CharacterBody2d 上默认的父脚本,并重新创建两个脚本, 让他们分别继承状态机父类和角色的父类,例如我专门为玩家创建了一个文件夹并将玩家节点下的所有脚本以及场景放在其中,这里的状态机脚本就是继承得来的,我们在复写父类的空方法体即可.

player.gd – 玩家脚本

玩家脚本继承自父类角色类脚本,其实所有的游戏中的角色都应该继承自父类角色脚本,这样方便使用统一的接口.

extends Character

func _process(delta: float) -> void:
	var mouse_direction: Vector2 = (get_global_mouse_position() - global_position).normalized()	# 得到一个指向鼠标的单位向量 
	# 默认朝向右边,flip后朝向左边
	if (mouse_direction.x > 0):
		animated_sprite.flip_h = false
	else:
		animated_sprite.flip_h = true
func get_input() -> void:
	move_direction = Vector2.ZERO
	if (Input.is_action_pressed("down")):
		move_direction += Vector2.DOWN
	if (Input.is_action_pressed("up")):
		move_direction += Vector2.UP
	if (Input.is_action_pressed("left")):
		move_direction += Vector2.LEFT
	if (Input.is_action_pressed("right")):
		move_direction += Vector2.RIGHT

玩家状态机

玩家的状态机应该专门有自己的状态机逻辑,所以我们为玩家类单独创建了一个状态机节点.

extends FininateStateMachine

func _init() -> void:
	_add_state("idle")
	_add_state("move")

func _ready() -> void:
	set_state(states.idle)
	
func _state_logic(_delta: float) -> void:
	parent.get_input()
	parent.move()

func _get_transition() -> int:
	match state:
		states.idle:
			if (parent.velocity.length() > 10):
				return states.move
		states.move:
			if (parent.velocity.length() < 10):
				return states.idle
	return -1
	
func _enter_state(_previous_state: int, _new_state: int) -> void:
	match state:
		states.idle:
			animation_player.play("idle")
		states.move:
			animation_player.play("move")

func _exit_state(_state_exited: int) -> void:
	# 离开状态时执行
	pass

到这里就实现了玩家的状态机和玩家的主要逻辑,运行可以发现玩家可以正常移动和播放动画.

作者:Sy_
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇