Godot 4.0 平台游戏运动不起作用

huangapple go评论85阅读模式
英文:

Godot 4.0 Platformer Movement Not Working

问题

Here is the code after making some modifications to address the issue of continuous movement and improve its readability:

extends CharacterBody2D

@export var speed: float = 200.0

# Jumping physics
@export var jump_height: float
@export var jump_time_to_peak: float
@export var jump_time_to_descend: float

var jump_velocity: float
var jump_gravity: float
var fall_gravity: float

var previous_direction: int = 0

var friction: float = 0.01

var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")

func _ready():
    jump_velocity = ((2.0 * jump_height) / jump_time_to_peak) * -1.0
    jump_gravity = ((-2.0 * jump_height) / jump_time_to_peak * jump_time_to_peak) * -1.0
    fall_gravity = ((-2.0 * jump_height) / jump_time_to_descend * jump_time_to_descend) * -1.0

func _physics_process(delta: float) -> void:
    velocity.y += _get_gravity() * delta
    
    var direction: float = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
    
    if direction != 0.0:
        if direction > 0.0:
            previous_direction = 1
        else:
            previous_direction = -1
        velocity.x = previous_direction * speed
    else:
        if is_on_floor():
            velocity.x = move_toward(velocity.x, 0, friction * delta)
        else:
            if velocity.x != 0.0:
                var sign: float
                if velocity.x > 0.0:
                    sign = 1.0
                else:
                    sign = -1.0
                velocity.x = move_toward(velocity.x, 0, friction * delta) + sign * speed * delta

    if Input.is_action_just_pressed("jump") and is_on_floor():
        _jump()

    move_and_slide(velocity, Vector2.UP)

func _get_gravity() -> float:
    return jump_gravity if velocity.y < 0.0 else fall_gravity

func _jump() -> void:
    velocity.y = jump_velocity

The main change made here is in the _physics_process function, where the move_and_slide function is updated to include the velocity vector as its first argument. This ensures that the character's movement is properly controlled, and the issue of continuous movement should be resolved.

Please replace your existing code with this modified code, and it should help with the issue you were facing.

英文:

I'm new to coding and the game developing scene, so for my first project, I'm trying to make a Mario esc platformer in Godot. Using multiple YouTube tutorials as well as ChatGPT, I came up with code for the movement. However, I've run into an issue where whenever I don't stop moving. This occurred after asking GPT to help me add friction. This is what the code looks like now:

extends CharacterBody2D
@export var speed: float = 200.0
# Jumping physics
@export var jump_height: float
@export var jump_time_to_peak: float
@export var jump_time_to_descend: float
var jump_velocity: float
var jump_gravity: float
var fall_gravity: float
var previous_direction: int = 0
var friction: float = 0.01
var gravity: float = ProjectSettings.get_setting(&quot;physics/2d/default_gravity&quot;)
func _ready():
jump_velocity = ((2.0 * jump_height) / jump_time_to_peak) * -1.0
jump_gravity = ((-2.0 * jump_height) / jump_time_to_peak * jump_time_to_peak) * -1.0
fall_gravity = ((-2.0 * jump_height) / jump_time_to_descend * jump_time_to_descend) * -1.0
func _physics_process(delta: float) -&gt; void:
velocity.y += _get_gravity() * delta
var direction: float = Input.get_action_strength(&quot;move_right&quot;) - Input.get_action_strength(&quot;move_left&quot;)
if direction != 0.0:
if direction &gt; 0.0:
previous_direction = 1
else:
previous_direction = -1
velocity.x = previous_direction * speed
else:
if is_on_floor():
velocity.x = move_toward(velocity.x, 0, friction * delta)
else:
if velocity.x != 0.0:
var sign: float
if velocity.x &gt; 0.0:
sign = 1.0
else:
sign = -1.0
velocity.x = move_toward(velocity.x, 0, friction * delta) + sign * speed * delta
velocity.x = previous_direction * speed
if Input.is_action_just_pressed(&quot;jump&quot;) and is_on_floor():
_jump()
if Input.is_action_just_pressed(&quot;jump&quot;) and is_on_floor():
_jump()
move_and_slide()
func _get_gravity() -&gt; float:
return jump_gravity if velocity.y &lt; 0.0 else fall_gravity
func _jump() -&gt; void:
velocity.y = jump_velocity

I've tried if else blocks, syntax errors, and asking ChatGPT to help multiple times. Nothing has worked.

答案1

得分: 0

以下是我在代码中注意到的问题:

  • 你正在将 float 类型与 0.0 进行比较,有时可能没问题,但一般来说,由于可能存在舍入误差,我们不能指望每帧稳定增加或减少的 float 类型会准确达到 0.0。因此,我们使用 is_zero_approx 方法。你可能也会对 is_equal_approx 感兴趣。

  • 你的摩擦似乎太小了。move_toward 方法的第三个参数是它可以改变的最大量,你传递的是 friction * delta,其中 delta 是从上一帧到现在的时间(通常是小于 1.0 的值,否则可能会出现更大的问题),而 friction 设置为 0.01... 由于你在 2D 空间中工作,你的距离单位是像素。所以我们在谈论每秒最多改变一个像素的速率,这将不会被注意到。

  • 我无法理解在空中移动的逻辑,既施加了减缓速度的摩擦,又在同一方向上增加了速度。

  • 而且摩擦实际上什么也做不了,因为你在条件后覆盖了对 velocity.x 的更改,即 velocity.x = previous_direction * speed(因此无论输入如何,都会发生这种情况)。由于这是你问的问题(它不会停止移动),首先移除这行

  • 在调用 _jump 的条件语句中,多余地进行了重复。

事实上,我认为你根本不需要保留 previous_direction,相反,你可以使用 signf(direction) - 或者更好的做法是:直接使用 direction,这将为你提供对模拟输入的支持(这也是使用 get_action_strength 而不是 is_action_pressed 的目的)。

根据你计划实现的内容,将来也许会用到 previous_direction 这个变量,但如果将其移除可能会简化你的代码,如果需要的话,稍后你可以重新引入它。

英文:

This are the issues I notice on the code:

  • You are comparing floats with 0.0, which sometimes it is fine, but in general we cannot rely on a float that is steadily incremented or decremented each frame to hit exactly 0.0 due to possible rounding issues. So, instead we use the method is_zero_approx. You might also be interested in is_equal_approx.

  • Your friction seems to be too small. The method move_toward takes as third parameter the maximum amount it can change, and you are passing friction * delta, where delta is a time in seconds from the last frame (so it is usually a value less than 1.0 or you have bigger problems) and friction is set to 0.01... And since you are working in 2D, your distance units are pixels. So we are talking of a maximum change rate of a fraction of a pixel per second, which won't be noticeable.

  • I fail to understand the logic for the movement in the air which both applies a friction that reduces the speed, but you are also adding a speed in the same direction.

  • And the friction won't do anything anyway, because you overwrite the changes to velocity.x with velocity.x = previous_direction * speed after the conditional (so this happens regardless of input). Since that is the problem you are asking about (it does not stop moving) start by removing this line.

  • The conditional where you call _jump is needlessly duplicated.

In fact, I believe you don't need to keep previous_direction at all, instead you could use signf(direction) - or better yet: use direction directly, which would give you support for analog input (which is the point of using get_action_strength instead of is_action_pressed).

The variable previous_direction might be useful in the future depending on what do you plan to implement, but removing it might simplify your code, and you might reintroduce it later if you need it.

huangapple
  • 本文由 发表于 2023年7月17日 09:34:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76701048.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定