How do I fix my mid-air dash?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Harmonikinesis

I managed to code a mid-air dash to my Megaman X-inspired game,but there’s a problem. The character basically teleports from point A to point B,instead of going from point A to point B quickly. Is there a way I can code my mid-air dash in a way the character moves in a straight line (without being affected by gravity) from point A to point B without being a teleport?

Here’s the code I have so far (I’m using GDScript):

`extends KinematicBody2D

onready var gravity = ProjectSettings.get_setting(“physics/2d/default_gravity”)
var MOTION_SPEED = 100 * 2
var DASH_SPEED = 2
const JUMP_SPEED = 600
var velocity = Vector2()
var is_moving = false
var facing_x = 1
var is_dashing = false
var timer = 0
var dash_direction = 1
var midair_dash = 0

func _physics_process(delta):
var motion = Vector2()
var leftBool = Input.is_action_pressed(“left”)
var rightBool = Input.is_action_pressed(“right”)
var left
var right

if !leftBool: 
	left = 0
else: 
	left = 1

if !rightBool: 
	right = 0
else: 
	right = 1


var x_direction = right - left
motion += Vector2(x_direction,0)


if !(x_direction == 0):
	is_moving = true
	facing_x = x_direction


velocity.y += (gravity * 15 ) * delta
velocity = move_and_slide_with_snap(velocity, Vector2.DOWN, Vector2.UP)
if is_on_floor() and Input.is_action_just_pressed("jump"):
	velocity.y = -JUMP_SPEED
if Input.is_action_just_released("jump") and velocity.y <= 0:
	velocity.y = 0

if is_on_floor():
	midair_dash = 0


if timer > 0:
	if is_on_floor():
		timer -= 1
		DASH_SPEED = 2
	else:
		timer = 1
		DASH_SPEED = 0.5
	motion += Vector2(DASH_SPEED*dash_direction,0)
elif Input.is_action_just_pressed("dash"):
	if is_on_floor():
		timer = 20
		dash_direction = facing_x
		if Input.is_action_just_pressed("left") and facing_x == 1:
			motion = Vector2(0,0)
		if Input.is_action_just_pressed("right") and facing_x == -1:
			motion = Vector2(0,0)
	else:
		if midair_dash < 1:
			midair_dash += 1
			motion += Vector2(50*facing_x,0)
		
motion = motion * MOTION_SPEED

move_and_slide(motion)`

Is there any reason why you’re calling move_and_slide twice? The is_on_floor() functions will update only on the next frame regardless, just use it once with proper UP vector provided. I’m not an expert by any means, but as far as I know the best practice is to just calculate the motion throughout the whole code and just execute it using move_and_slide or move_and_slide_with_snap at the end.

I really don’t get why you’re trying to apply gravity separately from the rest of the movement. I’m not exactly sure what’s causing the unexpected behavior, but if I were you, I’d just rewrite it and clean it up to only have a single motion variable (instead of separate motion and velocity, whatever they may mean) and a single move_and_slite.

Elkondo | 2020-04-24 22:09

I’m getting started now,so basically I barely have any idea of what I’m doing lmao. I wanted my character’s speed to be constant even when dashing,without any variation,but I also wanted a smooth jump,so I copy+pasted the jump code from the Kinematic Character 2D template and someone helped me to code the horizontal movement alongside the dash.

I could rewrite the code,but the problem is I have no idea how I could clean my code. As I said,I just got started. The two move_and_slide commands are copy+pasted from codes from Godot templates,and my game doesn’t properly work without them in place,and I don’t know how to make it work while only calling it once.

The is_on_floor() functions will update only on the next frame regardless, just use it once with proper UP vector provided.

I don’t know what you mean by that,sorry. Could you elaborate?

Harmonikinesis | 2020-04-24 23:18

Ok, so first of all, if you’re new, it’s much better to start by following some youtube tutorials than by just copying code. It’ll be slower, but the tutorial will explain exactly what each line means and why it’s there.

The two move_and_slide commands probably aren’t an error, but I’d rather do without them.
In your physics_process function, you first calculate the direction the player is moving and save it as X coordinate of your ‘motion’ variable. That’s perfectly fine.
Next, you calculate gravity, but for some reason, instead of saving it as the Y coordinate of your motion variable, you save it as a separate one and execute it instantly with move_and_slide_with_snap().
You later do some checks for dash etc. and replace the regular movement with the dash one for a certain period of time.
And finally, the horizontal movement is executed with move_and_slide().

What I would change is instead of saving the gravity to the ‘velocity’ variable, just save it to the motion variable again and get rid of the first move_and_slide_with_snap. Then later, in your dash code, you’ll be able to simply set motion.y to 0, meaning you’ll remove whatever influence gravity had on player’s movement.
Also, you’ll need to replace motion = motion * MOTION_SPEED with motion.x = motion.x * SPEED, so that the MOTION_SPEED variable only affects the horizontal speed, not vertical.

As for your question, when you’re making a 2D platformer, move_and_slide() requires second parameter - an UP vector. Functions like is_on_floor() need to somehow check which direction the floor is. Maybe you’re making a ninja game when the player’s running upwards, or maybe the gravity is inverted, the game doesn’t know that unless you tell it.
So when you use move_and_slide() you need two parameters: first is the motion vector, which tells it which direction to move the object it’s controlling (here: the player). The second tells it which way is UP, so it can perform correct floor and ceiling checks for those functions I mentioned.
So in your case, the correct way to use it would be move_and_slide(motion, Vector2.UP) or move_and_slide(motion, Vector2(0, -1)) or move_and_slide(motion, Vector2.UP). The latter works, since Godot knows it’s a commonly used value and they just have it preset. You actually did use that unknowingly in move_and_slide_with_snap in your code already.

Hope that clears it up a bit. Now go and follow some tutorial so that you actually know what you’re doing next time :slight_smile:

Elkondo | 2020-04-25 20:04