今天UP主的这节课没什么内容,主要时优化了跳跃和移动,本来像提前看UP主的下一个视频:在场景中增加移动的砖块,但是因为一些事情耽搁,这篇文章写完的时候已经快11点钟了,自己也有点累了,今天就学到这里把。
优化移动和跳跃
目前角色的移动方式是按下就走,放开按键就立马停止,像个机器人。我们可以利用move_toward()
函数实现一个加速效果,这样角色在移动和停止的时候会有一个加速和减速效果。
# 如果在地上则给与地面加速度,如果在空中则给与空中加速度,这是要给GDScript中的三元表达式,if后面的表达式如果为真则将前面的额值给acc,否则给后面的值
var acc = acceleration if is_on_floor() else air_acceleration
# move_toward 利用delta值从a值到b值进行增量增长,到达max_speed
velocity.x = move_toward(velocity.x, direction * max_speed, acc * delta)
跳跃的更改了大部分以前的跳跃逻辑,之前的角色在平台上跳跃出去后在空中还可以进行一次二段跳,这有点不符合逻辑,所以这里更改了跳跃逻辑。
首先解决从平台上跳跃出去后还可以在空中跳跃一次的问题。增了一个主要状态变量can_jump
,因为代码很琐碎,等会直接把代码贴上来把。我在这里说下主体思路把。
首先跳跃不能仅仅判断角色是否处于跳跃状态了,还得判断是否在地板上,如果是刚刚刚离开地面一定时间内允许跳跃,超过了则不允许。所以这里要用要新的节点组件Timer
,这个就时一个计时器,可以控制多少时间内计时一次。让角色在离开里面时便开始计时,如果在指定时间内则允许继续跳跃(课件作者这个好像有点不严谨,如果在地面上跳跃不是会有一个很短的2连跳?)
且怎加了一个小跳功能,如果在跳跃状态松开了跳跃按钮,且跳跃高度低于设定的小跳高度则变为小跳。
另外增加角色的快要落地时玩家想立马起跳的判断,之前时角色必须完全落地时才能进行跳跃。
修改后的相关代码如下:
extends KinematicBody2D
# 设置人物重力
const gravity = 2000
# 设置人物移动速度
const max_speed = 350
# 地面的加速度和空中的加速度
const acceleration = max_speed / 0.2
const air_acceleration = max_speed / 0.05
# 设置人物跳跃高度
const jump_force = 800
# 速度
var velocity = Vector2.ZERO
# 是否处于跳跃状态
var is_jumping = false
# 人物方向
var direction
# 在Godot可以通过$符号获取当前目录的所有节点,onready表示只要游戏一准备好就首先把节点取出来存到变量中
onready var animation_palyer = $AnimationPlayer
onready var sprite = $Sprite
# 获取两个计时器的节点对象
onready var coyote_timer = $CoyoteTimer
onready var jump_request_timer = $JumpRequestTimer
# 物理帧处理,delta参数忘记是啥意思了,好像是同步画面的。
func _physics_process(_delta):
# 在每一帧判断角色是否在地板之上
var was_on_floor = is_on_floor()
# move_and_slide为父类函数,用于sprite移动,第二个参数指定天花板是那个方向
velocity = move_and_slide(velocity, Vector2.UP)
# is_on_floor父类函数,如果主体在地板上,则返回true。仅在调用move_and_slide()时更新。
if is_on_floor():
# 如果人物在地板上则允许进行跳操作
is_jumping = false
# 如果在地板上,且是允许跳跃状态才进行跳跃
elif was_on_floor and not is_jumping:
# 在跳跃的瞬间开其计时器
coyote_timer.start()
#sprite.flip_h = direction
# 检测玩家输入(这个函数只在玩家有按下按键时才进行调用)
func _input(event):
# 实现落地的瞬间跳跃功能,开启计时器
if event.is_action_pressed("move_jump"):
jump_request_timer.start()
# 通过event.is_action_released判断是否在起跳过程中释放了空格键,并且跳跃高度没有超过小跳高度则进行小跳。
if event.is_action_released("move_jump") and velocity.y < -jump_force / 2:
velocity.y = -jump_force / 2
# 每一帧都会执行这个函数
func _process(delta):
# 检测用户按钮,get_action_strength返回按下状态,按下为1,没按则0,如果按下right则返回复数,按下left返回正数
direction = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
# 如果在地上则给与地面加速度,如果在空中则给与空中加速度,这是要给GDScript中的三元表达式,if后面的表达式如果为真则将前面的额值给acc,否则给后面的值
var acc = acceleration if is_on_floor() else air_acceleration
# 利用获取到的方向值进行人物左右移动。
# move_toward 利用delta值让从a值到b值进行增量增长,到达max_speed
velocity.x = move_toward(velocity.x, direction * max_speed, acc * delta)
# 跳跃
velocity.y += gravity * delta
# 新增状态变量can_jump ,如果在地上,或者coyote_timer小于0.2则允许跳跃
var can_jump = is_on_floor() or coyote_timer.time_left < 0
# 如果允许跳跃(在地上或者处于coyote时间内)或者同时处于落地瞬间,则可触犯跳状态则让精灵腾空
if can_jump and jump_request_timer.time_left > 0:
velocity.y = -jump_force
# 设置跳跃状态,避免可以进行连跳操作
is_jumping = true
# 避免bug,关闭掉两个计时器
jump_request_timer.stop()
coyote_timer.stop()
# 控制sprite动画
# 如果处于可跳跃状态,则播放跳跃动画
if is_jumping:
animation_palyer.play("jump")
# 空闲状态播放空闲动画
elif velocity.x == 0:
animation_palyer.play("idle")
# 移动状态则播放移动动画
else:
animation_palyer.play("walk")
# 根据移动方向更新角色朝向
if direction != 0:
sprite.flip_h = direction < 0