用状态枚举和状态变量重构了代码,稍微清晰了一些。
extends KinematicBody2D
var speed = 120.0 # 速度 像素/秒
var velocity = Vector2.ZERO # 速度向量
var gravity = 5000 # 重力加速度
var jump_force = 1000.0 # 单次跳跃高度
enum state {
STATE_ON_WALL,
STATE_ON_AIR,
STATE_ON_FLOOR,
STATE_ON_TIZI, # 在爬梯
}
var n_state = state.STATE_ON_AIR
func _physics_process(delta):
match n_state:
state.STATE_ON_AIR:
# 掉到地板
if is_on_floor():
n_state = state.STATE_ON_FLOOR
else:
# 实现下落
velocity.y += gravity * delta
velocity = move_and_slide(velocity,Vector2.UP)
state.STATE_ON_FLOOR:
velocity.y = 0
# 左右移动
velocity.x = Input.get_axis("ui_left","ui_right") * speed
# 跳跃
if Input.is_action_just_pressed("ui_accept"): # 按空格键
velocity.y = -jump_force
n_state = state.STATE_ON_AIR
velocity = move_and_slide(velocity,Vector2.UP)
if is_on_wall():
n_state = state.STATE_ON_WALL
state.STATE_ON_TIZI:
if is_on_floor():
velocity.x = velocity.x * 0.9
else:
velocity.x = Input.get_axis("ui_left","ui_right") * speed
velocity.y = Input.get_axis("ui_up","ui_down") * speed
move_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)
state.STATE_ON_WALL:
velocity.y = Input.get_axis("ui_up","ui_down") * speed
velocity.x = Input.get_axis("ui_left","ui_right") * speed
if Input.is_action_just_pressed("ui_accept"): # 按空格键
velocity.y = -jump_force
velocity = move_and_slide(velocity,Vector2.UP)
if velocity.x != 0:
velocity = move_and_slide(velocity,Vector2.UP)
n_state = state.STATE_ON_AIR
else:
velocity = move_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)
if not is_on_wall():
n_state = state.STATE_ON_AIR
改进后的代码
extends KinematicBody2D
var speed = 120.0 # 速度 像素/秒
var velocity = Vector2.ZERO # 速度向量
var gravity = 5000 # 重力加速度
var jump_force = 1000.0 # 单次跳跃高度
enum state {
STATE_ON_WALL,
STATE_ON_AIR,
STATE_ON_FLOOR,
STATE_ON_TIZI, # 在爬梯
}
var n_state = state.STATE_ON_AIR
func input_x():
velocity.x = Input.get_axis("ui_left","ui_right") * speed
func input_y():
velocity.y = Input.get_axis("ui_up","ui_down") * speed
func input_jump() -> bool:
return Input.is_action_just_pressed("ui_accept")
func change_stage(new_state:int):
n_state = new_state
func _physics_process(delta):
match n_state:
state.STATE_ON_AIR:
# 掉到地板
if is_on_floor():
change_stage(state.STATE_ON_FLOOR)
else:
# 实现下落
velocity.y += gravity * delta
velocity = move_and_slide(velocity,Vector2.UP)
state.STATE_ON_FLOOR:
velocity.y = 0
# 左右移动
velocity.x = Input.get_axis("ui_left","ui_right") * speed
# 跳跃
if input_jump(): # 按空格键
velocity.y = -jump_force
change_stage(state.STATE_ON_AIR)
velocity = move_and_slide(velocity,Vector2.UP)
if is_on_wall():
change_stage(state.STATE_ON_WALL)
state.STATE_ON_TIZI:
if is_on_floor():
velocity.x = velocity.x * 0.9
else:
input_x()
input_y()
move_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)
state.STATE_ON_WALL:
input_x()
input_y()
if input_jump(): # 按空格键
velocity.y = -jump_force / 2 # 在墙上时只能跳地面的一半
velocity = move_and_slide(velocity,Vector2.UP)
change_stage(state.STATE_ON_AIR)
if velocity.x != 0: # 按左右键
velocity = move_and_slide(velocity,Vector2.UP)
change_stage(state.STATE_ON_AIR)
else:
velocity = move_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)
if not is_on_wall():
change_stage(state.STATE_ON_AIR)
可以看到我们可以将按键语句封装为简单函数,这样对判断非常有利。
比如下面的形式
func input_jump() -> bool:
return Input.is_action_just_pressed("ui_accept")
或者干脆我们可以封装一个单例
# mInput.gd 单例 用于统一处理按键输入
extends Node
var left_action = "ui_left"
var right_action = "ui_right"
var up_action = "ui_up"
var down_action = "ui_down"
var jump_action = "ui_accept"
func just_pressed(action:String) -> bool:
return Input.is_action_just_pressed(action)
func pressed(action:String) -> bool:
return Input.is_action_pressed(action)
# 跳跃
func input_jump() -> bool:
return just_pressed(jump_action)
func get_x():
return Input.get_axis(left_action,right_action)
func get_y():
return Input.get_axis(left_action,right_action)
func get_dir():
return Input.get_vector(left_action,right_action,up_action,down_action)
此时,我们的玩家代码中将彻底看不到各种按键检测。
extends KinematicBody2D
var speed = 120.0 # 速度 像素/秒
var velocity = Vector2.ZERO # 速度向量
var gravity = 5000 # 重力加速度
var jump_force = 1000.0 # 单次跳跃高度
enum state {
STATE_ON_WALL,
STATE_ON_AIR,
STATE_ON_FLOOR,
STATE_ON_TIZI, # 在爬梯
}
var n_state = state.STATE_ON_AIR
func input_x():
velocity.x = MInput.get_x() * speed
func input_y():
velocity.y = MInput.get_y() * speed
func change_stage(new_state:int):
n_state = new_state
func _physics_process(delta):
match n_state:
state.STATE_ON_AIR:
# 掉到地板
if is_on_floor():
change_stage(state.STATE_ON_FLOOR)
else:
# 实现下落
velocity.y += gravity * delta
velocity = move_and_slide(velocity,Vector2.UP)
state.STATE_ON_FLOOR:
velocity.y = 0
# 左右移动
input_x()
# 跳跃
if MInput.input_jump(): # 按空格键
velocity.y = -jump_force
change_stage(state.STATE_ON_AIR)
velocity = move_and_slide(velocity,Vector2.UP)
if is_on_wall():
change_stage(state.STATE_ON_WALL)
state.STATE_ON_TIZI:
if is_on_floor():
velocity.x = velocity.x * 0.9
else:
input_x()
input_y()
move_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)
state.STATE_ON_WALL:
input_x()
input_y()
if MInput.input_jump(): # 按空格键
velocity.y = -jump_force / 2 # 在墙上时只能跳地面的一半
velocity = move_and_slide(velocity,Vector2.UP)
change_stage(state.STATE_ON_AIR)
if velocity.x != 0: # 按左右键
velocity = move_and_slide(velocity,Vector2.UP)
change_stage(state.STATE_ON_AIR)
else:
velocity = move_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)
if not is_on_wall():
change_stage(state.STATE_ON_AIR)