为什么我的Koopa虽然在代码里设置了速度,结果还是被冻住了?

编程语言 2026-07-10

我在用Godot重制原版的Super Mario Bros,但遇到一个问题。当我踩到Koopa时,它会变成壳子状态。不过,当它在大约10秒后停下来时,除了速度之外一切正常。它就在那里一动也不动。为什么会这样?下面是Koopa的节点树和代码(我使用的是Godot 4.6.2。):

Koopa
├╴AnimatedSprite2D
├╴CollisionShape2D
├╴SmushedArea
│ └╴SmushedCollision
├╴KillerArea
│ └╴KillerCollision
└╴ShelledTimer
# koopa.gd
extends CharacterBody2D

# editables
@export var max_speed := 1600.0
@export_enum('Alive', 'Shelled', 'Dead') var state := 'Alive'

@onready var prev_state := state

@onready var direction := max_speed

# inner nodes
@onready var sprite := $AnimatedSprite2D
@onready var collider := $CollisionShape2D

@onready var smushed := $SmushedArea
@onready var killer := $KillerArea

@onready var shelled_timer := $ShelledTimer

# player
@onready var player := $'..'/Player
@onready var smusher := $'..'/Player/SmusherArea
@onready var killed := $'..'/Player/KilledArea

@onready var camera := $'..'/Camera2D

func _physics_process(delta: float) -> void:
    if not is_on_floor():
        velocity += get_gravity() * delta

    if is_on_wall():
        direction *= -1

    velocity.x = direction * delta

    move_and_slide()

func _process(delta: float) -> void:
    if velocity.x != 0:
        if abs(velocity.x) != velocity.x:
            sprite.flip_h = true
        if abs(velocity.x) == velocity.x:
            sprite.flip_h = false

    print(velocity.x)

    if state != prev_state:
        if state == 'Alive':
            killer.set_deferred('monitoring', true)
            smushed.set_deferred('monitoring', true)

            velocity.x = direction * delta

            sprite.play('walk')

        elif state == 'Shell':
            direction = 0

            killer.set_deferred('monitoring', false)
            smushed.set_deferred('monitoring', false)

            player.velocity.y *= -0.7
            velocity.y = -100
            velocity.x = 0

            sprite.play('shell')

            shelled_timer.start()

    if state == 'Shell' and shelled_timer.time_left < 3:
        sprite.play("wiggling")

    prev_state = state

func _on_smushed_area_entered(area: Area2D) -> void:
    if area == smusher and\
    (abs(player.velocity.y) == player.velocity.y) and player.velocity.y != 0:
        state = 'Shell'

func _on_killer_area_entered(area: Area2D) -> void:
    if area == killed and player.is_alive:
        camera.follow_player = false
        player.is_alive = false

        await get_tree().create_timer(0.5).timeout

        player.collider.set_deferred('disabled', true)
        player.killed.set_deferred('monitoring', false)
        player.smusher.set_deferred('monitorable', false)

        player.velocity.y = player.jump_height

        await get_tree().create_timer(2.0).timeout

        player.queue_free()

func _on_shelled_timer_timeout() -> void:
    state = 'Alive'

解决方案

if state == 'Alive':
    killer.set_deferred('monitoring', true)
    smushed.set_deferred('monitoring', true)

    velocity.x = direction * delta

    sprite.play('walk')

elif state == 'Shell':
    direction = 0

    killer.set_deferred('monitoring', false)
    smushed.set_deferred('monitoring', false)

    player.velocity.y *= -0.7
    velocity.y = -100
    velocity.x = 0

direction = 0 在Shell状态中,在Alive状态将其设置为 -1或 1,也许它就会再次走动

if state == 'Alive':
    killer.set_deferred('monitoring', true)
    smushed.set_deferred('monitoring', true)

    direction = -1
    velocity.x = direction * delta

    sprite.play('walk')

找出一种记录它之前的方向的方法,然后在它仍然存活时再把方向设回去。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章