Godot 4 GDScript 中如何让 2D 角色按一次按钮时执行 32 个像素的一步?

问题描述 投票:0回答:1

我编写了一个脚本,在按下按钮一步后移动 2D 角色。但它只移动 1 个像素而不是 32 个像素,并且还向上跳跃 1 个像素。

有一个功能可以测量角色行走的距离,并在达到该距离时停止角色。现在我正在努力实现逻辑,因为这个脚本似乎是正确的,但角色只走了 1 个像素,但调试说它走了 32 个。不知怎的,问题甚至在velocity.y值上扩展,因为角色只跳跃 1 个像素(大约 1 个像素)框架)。我知道我错过了一些东西,但不明白到底在哪里。

我对 Godot 4 引擎比较陌生,请帮助我,因为我已经花了几天时间解决这个问题并观看教程。如果您发现其他我没有看到的小问题或可以优化的内容,也请告诉我。如果您知道有关此主题的好教程,我将不胜感激您的分享。

这是执行该步骤的函数:

func step(dir, delta):
    #if 32 or -32 pixels move character, if not stop character
    if dir != 0:
        velocity.x = dir * speed * delta #move player 32 pixels left or right
        measured_distance += abs(velocity.x) #add walked value to a measurer (and make it always positive)
        measured_distance = min(measured_distance, abs(dir)) #if measurer exceeds 32 pixels make it 32
        print ("measured_distance: ", measured_distance) #debug , always works
        #if measurer equals to 32 pixels or exceeds it
        if measured_distance >= abs(dir):
            print(measured_distance, " px passed") #debug, always works
            dir_distance = 0 #reset universal directory distance to 0
            stepping = false #announcing the end of stepping process
    else:
        stop_step() 

这是完整的脚本:

extends CharacterBody2D

#MOVEMENT
@export var speed: int = 100
@export var step_distance: int = 32 #distance of 32 pixels
@export var jump_velocity: int = -230
var measured_distance: int = 0 #variable used to measure walked distance each step
var stepping: bool = false
var dir_distance: int = 0 #variable that inherits step_distance but changes direction to negative or positive

#PHYSICS
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

#function called from the _physics_process one, it resets the measured_distance and announce stepping process
func start_measure ():
    stepping = true
    measured_distance = 0

#stops player movement along x value (horizontal)
func stop_step ():
    velocity.x = move_toward(velocity.x, 0, speed)


func step(dir, delta):
    #if 32 or -32 pixels move character, if not stop character
    if dir != 0:
        velocity.x = dir * speed * delta #move player 32 pixels left or right
        measured_distance += abs(velocity.x) #add walked value to a measurer (and make it always positive)
        measured_distance = min(measured_distance, abs(dir)) #if measurer exceeds 32 pixels make it 32
        print ("measured_distance: ", measured_distance) #debug , always works
        #if measurer equals to 32 pixels or exceeds it
        if measured_distance >= abs(dir):
            print(measured_distance, " px passed") #debug, always works
            dir_distance = 0 #reset universal directory distance to 0
            stepping = false #announcing the end of stepping process
    else:
        stop_step() 

#script starts here
func _physics_process(delta):
        #if not standing on floor add gravity
    if !is_on_floor():
        velocity.y += gravity * delta
    #if jump pressed once...
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_velocity * delta

    #if not doing any step currently allow to press left or right buttons
    if !stepping:
        if Input.is_action_just_pressed("right"):
            dir_distance = step_distance #inherit value with positive value (right)
            start_measure()
        elif Input.is_action_just_pressed("left"):
            dir_distance = -step_distance #inherit value with negative value (left)
            start_measure()

        #constantly update movement
    step(dir_distance, delta) #passes direction (32 pixels left or right) and delta value
    move_and_slide()

Here is how it looks in the game

game-physics game-development godot gdscript godot4
1个回答
0
投票

我不是 100% 确定,但我认为 move_and_slide 已经将增量添加到速度中,因此您实际移动的距离与测量的距离不同。

我不是 100% 确定,但我认为 move_and_slide 已经应用了 delta,这可以解释为什么你只移动 1 个像素。但是从velocity.x 中删除delta 并没有做到这一点,所以我为您提供了另一个解决方案。当您开始移动并检查每次迭代时,如果玩家向左或向右移动了 32 px,您可以保存开始位置,而不是添加您不确定的距离。 这样,当玩家达到 32 像素时,您实际上可以硬设置玩家的位置。

你的步骤部分看起来像这样:

func step(dir, delta):
#if 32 or -32 pixels move character, if not stop character
if dir != 0:
    velocity.x = dir * speed * delta #move player 32 pixels left or right
    
    if abs(position.x - start_pos.x) >= abs(dir):
        print(measured_distance, " px passed") #debug, always works
        dir_distance = 0 #reset universal directory distance to 0
        stepping = false #announcing the end of stepping process
        position.x = start_pos.x + dir #hard set the position to start+32
        velocity.x = 0 #destination reached, so no need to move further
else:
    stop_step() 

start_pos 将在 pysics_process 部分设置,用于检查步进:

if !stepping:
    if Input.is_action_just_pressed("right"):
        start_pos = position
        dir_distance = step_distance #inherit value with positive value (right)
        start_measure()
    elif Input.is_action_just_pressed("left"):
        start_pos = position
        dir_distance = -step_distance #inherit value with negative value (left)
        start_measure()

Node:您应该检查 move_and_slide 是否与某些物体发生碰撞,如果是,则结束移动。否则直接操纵位置可能会导致不必要的行为(例如卡在墙上)。

© www.soinside.com 2019 - 2024. All rights reserved.