代码之家  ›  专栏  ›  技术社区  ›  Mimo

在Godot的4GDScript中,当按下一次按钮时,如何使2D角色执行32像素的一步操作?

  •  0
  • Mimo  · 技术社区  · 2 年前

    我写了一个脚本,在按下一个按钮一步后移动我的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

    0 回复  |  直到 2 年前
        1
  •  0
  •   Bugfish    2 年前

    我不能100%确定,但我认为move_and_slide已经在速度上添加了delta,所以你实际移动的距离与测量的距离不同。

    我不能100%确定,但我认为move_and_slide已经应用了delta,这可以解释为什么你只移动1个像素。但是从velocity.x中去掉delta并不能做到这一点,所以我有另一个解决方案。如果玩家向左或向右移动了32像素,当你开始移动并检查每次迭代时,你可以保存开始位置,而不是添加一个距离,你不确定。 这样,当玩家达到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()
    

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

    编辑:包括我的整个剧本,因为它似乎对Mimo不起作用

    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)
    
    var start_pos
    
    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
                velocity.x = 0
        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"):
                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()
    
            #constantly update movement
        step(dir_distance, delta) #passes direction (32 pixels left or right) and delta value
        if not velocity == Vector2.ZERO:
            print(velocity)
        move_and_slide()