用状态枚举和状态变量重构了代码,稍微清晰了一些。
extends KinematicBody2Dvar 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_AIRfunc _physics_process(delta):match n_state:state.STATE_ON_AIR:# 掉到地板if is_on_floor():n_state = state.STATE_ON_FLOORelse:# 实现下落velocity.y += gravity * deltavelocity = 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_forcen_state = state.STATE_ON_AIRvelocity = move_and_slide(velocity,Vector2.UP)if is_on_wall():n_state = state.STATE_ON_WALLstate.STATE_ON_TIZI:if is_on_floor():velocity.x = velocity.x * 0.9else:velocity.x = Input.get_axis("ui_left","ui_right") * speedvelocity.y = Input.get_axis("ui_up","ui_down") * speedmove_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)state.STATE_ON_WALL:velocity.y = Input.get_axis("ui_up","ui_down") * speedvelocity.x = Input.get_axis("ui_left","ui_right") * speedif Input.is_action_just_pressed("ui_accept"): # 按空格键velocity.y = -jump_forcevelocity = move_and_slide(velocity,Vector2.UP)if velocity.x != 0:velocity = move_and_slide(velocity,Vector2.UP)n_state = state.STATE_ON_AIRelse:velocity = move_and_slide_with_snap(velocity,get_floor_normal(),Vector2.UP)if not is_on_wall():n_state = state.STATE_ON_AIR
改进后的代码
extends KinematicBody2Dvar 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_AIRfunc input_x():velocity.x = Input.get_axis("ui_left","ui_right") * speedfunc input_y():velocity.y = Input.get_axis("ui_up","ui_down") * speedfunc input_jump() -> bool:return Input.is_action_just_pressed("ui_accept")func change_stage(new_state:int):n_state = new_statefunc _physics_process(delta):match n_state:state.STATE_ON_AIR:# 掉到地板if is_on_floor():change_stage(state.STATE_ON_FLOOR)else:# 实现下落velocity.y += gravity * deltavelocity = 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_forcechange_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.9else: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 Nodevar 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 KinematicBody2Dvar 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_AIRfunc input_x():velocity.x = MInput.get_x() * speedfunc input_y():velocity.y = MInput.get_y() * speedfunc change_stage(new_state:int):n_state = new_statefunc _physics_process(delta):match n_state:state.STATE_ON_AIR:# 掉到地板if is_on_floor():change_stage(state.STATE_ON_FLOOR)else:# 实现下落velocity.y += gravity * deltavelocity = move_and_slide(velocity,Vector2.UP)state.STATE_ON_FLOOR:velocity.y = 0# 左右移动input_x()# 跳跃if MInput.input_jump(): # 按空格键velocity.y = -jump_forcechange_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.9else: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)
