1 制作击中动画
添加击中动画,另存为hit_effect.tsc
2 将击中动画添加到hurtbox.gd
hurtbox 通用的effect的脚本,预加载
一旦检测到受击,实例化保存了击中动画的场景,添加为子节点
1 2 3 4 5 6 7 8 9 10 11 12 13
| extends Area2D
const HIT_EFFECT = preload("res://Effects/hit_effect.tscn")
func _on_area_entered(area: Area2D) -> void: var effect = HIT_EFFECT.instantiate() #不使用get_parent().add_child()实例化,因为parent会被free() var main = get_tree().current_scene main.add_child(effect) effect.global_position = global_position
|
3 由此产生的bug
草也使用effect.gd脚本播放动画,但不需要这个击中动画,怎么处理?
方案一:添加开关按钮解决,后面会优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| extends Area2D
+ @export var show_hit:bool = true
const HIT_EFFECT = preload("res://Effects/hit_effect.tscn")
func _on_area_entered(area: Area2D) -> void: + if show_hit: var effect = HIT_EFFECT.instantiate() #不使用get_parent().add_child()实例化,因为parent会被free() var main = get_tree().current_scene main.add_child(effect) effect.global_position = global_position
|
4 蝙蝠状态机
使用状态机控制蝙蝠状态的切换
1 2 3 4 5
| enum{ IDLE, WANDER, CHASE }
|
初始状态为IDLE
在状态机的IDLE里设置蝙蝠速度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| match state: IDLE: # 蝙蝠的击退速度 velocity=velocity.move_toward(Vector2.ZERO,FRICTION * delta) seek_player() WANDER: pass CHASE: pass move_and_slide() func seek_player(): pass
|
5 检测玩家进入
新建Area2d节点,命名为PlayerDetectionZone,添加碰撞形状,新建并挂载脚本player_detection_zone.gd,检测玩家进入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| extends Area2D
var player=null
#能否看到玩家 func can_see_player(): return player != null
#检测玩家进入 func _on_body_entered(body): player=body
func _on_body_exited(body): player=null
|
6 调整Bat碰撞层
怎样确保进入的是玩家?通过碰撞层区分。
打开Bat节点,引用侦测区域,添加碰撞形状

调整侦测层级,PlayerDetectionZone的mask只勾选play

7 完善追赶状态
调整追赶过程中,蝙蝠的朝向,
playerDetectionZone侦测区域不为null,
Bat.gd的CHASE部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| match state: IDLE: # 蝙蝠的击退速度 velocity=velocity.move_toward(Vector2.ZERO,FRICTION * delta) seek_player() WANDER: pass CHASE: + var player = playerDetectionZone.player + print(player) + if player != null: + var direction = (player.global_position - global_position).normalized() + velocity = velocity.move_toward(direction * MAX_SPEED ,ACCELERATION * delta) + else : #避免离开时追赶方向停不下来 + state = IDLE #调整追赶过程中,蝙蝠的朝向 sprite.flip_h = velocity.x < 0 move_and_slide() #这里的逻辑有得研究,这里seek_player() 放在match语句前执行就好,IDLE和CHASE都需要状态转换,而且它CHASE的那个判断很迷,就是等于seekplayer func seek_player(): + if playerDetectionZone.can_see_player(): + state = CHASE
|