Have you ever wondered why these games feel so good to play?
If your answer is visuals then, No the key component is their controls. The character movement feels natural, and they move exactly how you want. A good character movement will always make the player feel that they are in total control of the character.
So, you are wondering how to achieve this?
Well, there are some tricks that professional developers use to make their control better. And today we are goanna see what they are and how you can do it in Godot.
VIDEO TUTORIAL
COMPLETE CODE:
extends KinematicBody2D
var velocity : Vector2
export var max_speed : int = 1000
export var gravity : float = 55
export var jump_force : int = 1600
export var acceleration : int = 50
export var jump_buffer_time : int = 15
export var cayote_time : int = 15
var jump_buffer_counter : int = 0
var cayote_counter : int = 0
func _physics_process(_delta):
if is_on_floor():
cayote_counter = cayote_time
if not is_on_floor():
if cayote_counter > 0:
cayote_counter -= 1
velocity.y += gravity
if velocity.y > 2000:
velocity.y = 2000
if Input.is_action_pressed("ui_right"):
velocity.x += acceleration
$Sprite.flip_h = false
elif Input.is_action_pressed("ui_left"):
velocity.x -= acceleration
$Sprite.flip_h = true
else:
velocity.x = lerp(velocity.x,0,0.2)
velocity.x = clamp(velocity.x, -max_speed, max_speed)
if Input.is_action_just_pressed("ui_select"):
jump_buffer_counter = jump_buffer_time
if jump_buffer_counter > 0:
jump_buffer_counter -= 1
if jump_buffer_counter > 0 and cayote_counter > 0:
velocity.y = -jump_force
jump_buffer_counter = 0
cayote_counter = 0
if Input.is_action_just_released("ui_select"):
if velocity.y < 0:
velocity.y += 400
velocity = move_and_slide(velocity, Vector2.UP)
Explanation:
Now the first trick is Using a capsule shape for player collision or at least use a circle collision shape at the foot. This little change will make your movement a lot better.
Basically, you don’t want to stop player from climbing when he is just 2 pixels below
This can make the player frustrated. And you don’t want that. The only downside of this is that you can also slip down from the platform, but we have a solution for this which we will discuss later.
BASIC MOVEMENT (LEFT, RIGHT AND JUMP)
extends KinematicBody2D
var velocity : Vector2
export var max_speed : int = 1000
export var gravity : float = 55
export var jump_force : int = 1600
func _physics_process(_delta):
if not is_on_floor():
velocity.y += gravity
if velocity.y > 2000:
velocity.y = 2000
if Input.is_action_pressed("ui_right"):
velocity.x = max_speed
$Sprite.flip_h = false
elif Input.is_action_pressed("ui_left"):
velocity.x = -max_speed
$Sprite.flip_h = true
else:
velocity.x = 0
if Input.is_action_pressed("ui_select"):
if is_on_floor():
velocity.y = -jump_force
velocity = move_and_slide(velocity, Vector2.UP)
First of all, I use a kinematic body for the player which allow me to use the move_and_slide() function. Now first I have declared a velocity vector and some basic variable that we need. Now create the physics_process function and inside it
We check when we are not on the ground.
Then we will apply gravity in the Y component of the velocity, so that our character falls when not on the ground. But we also don’t want to increase the velocity to infinite, so we clamp it in 2000.
Then we check when the player has pressed the “ui_right” key. Which is nothing but the right arrow key So, when we detect the input, we want to move our character to the right. That's why we set X component of velocity to our max speed, and I am setting the flip of the sprite, so it looks at the direction of movement.
Similarly, when we press the left arrow key. we will set X component of the velocity to negative max speed and at last set the flip of the flip of the sprite.
Now if we press none of the buttons, we want the player to stop, thus we set the velocity.x to 0. Now for jumping, if we press the “ui_select” which is by the way your spacebar
We first make sure we are on the ground and then Set the velocity.y to negative jump_force which is the upward direction. And finally, we will put this velocity in the move and slide function Along with Velocity.UP to tell which direction is upward. And with that done your player can move left, right and jump.
Add Acceleration and Deceleration
if Input.is_action_pressed("ui_right"):
velocity.x += acceleration
$Sprite.flip_h = false
elif Input.is_action_pressed("ui_left"):
velocity.x -= acceleration
$Sprite.flip_h = true
And here instead of stopping the character suddenly we will use a lerp function Which stand for linear interpolation, this will take three values. First one is the starting value for this we will use whatever our current value is. The second one is the final value. For this I will write 0. And the third one decides how fast you want to complete it. For this demo I will use 0.2
But remember the higher the value the faster it will complete. And finally, when we are adding acceleration, we don’t want our velocity to go beyond our maximum speed. That’s why at last we use the clamp function to set our velocity within the limits.
else:
velocity.x = lerp(velocity.x,0,0.2)
velocity.x = clamp(velocity.x, -max_speed, max_speed)
variable jump height
This allows players to do short jumps by releasing the jump button early and still do long jumps by holding the jump button longer. This is done by applying additional downforce when we release the jump button.
To do this we just need to add these 3 lines. First, we look when the player has released the jump button. After that we check if the velocity.y < 0 Which means we are still going upwards.
So now we add some downward force in our velocity, for this demo 400 is fine. And with that done we can now do short jumps by releasing the jump button early.
if Input.is_action_just_released("ui_select"):
if velocity.y < 0:
velocity.y += 500
Jump buffer
next most important thing that you should definitely add to your game is “jump buffer” With jump buffer you give your player some extra margin in which if they press the jump button just before hitting the ground, they can still perform the jump. This because if the player presses jump button and your character doesn’t jump,
your game will feel unresponsive, and the player will quit So, for jump buffer we first need to create two variables One is buffer time and other is buffer counter
Now if you don’t know, the “physics process” function runs 60 times in 1 sec.
So, setting buffer time to 15 means ¼ of a sec. Now when the player presses jump button, we want to set the counter to buffer_time. Then outside of this block we check if the counter > 0 Then we reduce the counter by 1.
And again, outside the if statement we check if the counter > 0 and we are on floor Then we do the jump. And finally set counter to 0.
for example, let’s suppose we are falling
And as soon as we press the jump button, we basically start the counter.
And now for the next 15 frames the value of counter is going to be greater than 1
And if we hit the ground within this duration, we will do the jump. Otherwise, our timer will run out.
export var jump_buffer_time : int = 15
var jump_buffer_counter : int = 0
if Input.is_action_just_pressed("ui_select"):
jump_buffer_counter = jump_buffer_time
if jump_buffer_counter > 0:
jump_buffer_counter -= 1
if jump_buffer_counter > 0 and is_on_floor():
velocity.y = -jump_force
jump_buffer_counter = 0
coyote time
export var cayote_time : int = 15
var cayote_counter : int = 0
if is_on_floor():
cayote_counter = cayote_time
if not is_on_floor():
if cayote_counter > 0:
cayote_counter -= 1
if cayote_counter > 0 and jump_buffer_counter > 0:
velocity.y = -jump_force
cayote_counter = 0
jump_buffer_counter = 0
Comments
Post a Comment