Movement like in Asteroids

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By kochw
:warning: Old Version Published before Godot 3 was released.

Hey there,

I’m currently trying to learn game development by implementing some classic games.
I’m somewhat struggling to implement the propper movement like it is in Asteroids.

I can rotate the ship and accelerate but when I change the direction and accelerate again I travel in that direction at full speed. So I also cannot turn 180° and slow down.

Any help would be appreciated!

My code is the following:

extends RigidBody2D

export var player_speed = 200
export var rotate_speed = 250
var screen_size
var current_speed = 0

export var acc = 5



func _ready():
screen_size = get_viewport().get_rect().size
set_fixed_process(true)
set_gravity_scale(0)


func move(speed, acceleration, delta):
	current_speed = lerp(current_speed, speed, acceleration*delta)
	
	set_linear_velocity(Vector2(0,current_speed).rotated(get_rot()))

func _fixed_process(delta):

	
#Rotate left
if (Input.is_action_pressed("left")):
	rotate(deg2rad(delta*rotate_speed))

#Rotate right
if Input.is_action_pressed("right"):
	rotate(-deg2rad(delta*rotate_speed))

if Input.is_action_pressed("up"):
	move(-player_speed,acc,delta)


var ship_pos = get_pos()
if (ship_pos.x < 0):
	ship_pos.x = screen_size.x-1
if (ship_pos.x > screen_size.x):
	ship_pos.x = 1
if (ship_pos.y < 0):
	ship_pos.y = screen_size.y
if (ship_pos.y > screen_size.y):
	ship_pos.y = 1

set_pos(ship_pos)

Hey again,

thanks everyone for their help!

I think I have a working solution now, in case someone else stumbles across the same problem.

I changed my move function to limit the maximum speed and it works without stuttering as well.

func move(speed, acceleration):

current_speed = get_linear_velocity()
if (current_speed.length()>player_speed):
	set_linear_velocity(get_linear_velocity().normalized()*(player_speed-1))
else:
	apply_impulse(Vector2(get_pos().x,get_pos().y),Vector2(0,-acceleration).rotated(get_rot()))

Okay Happy godoting everyone! :slight_smile:

kochw | 2016-04-14 15:19

:bust_in_silhouette: Reply From: MechFive

Have you considered using apply_impulse() function instead the linear velocity for an easy fix?

Hey!

Thanks a lot, I hadn’t considered it, but it seems to work well enough now.
Maybe you also have an idea on how to limit the movement speed, because now it’s just accelerating to infinity :slight_smile:

if Input.is_action_pressed("up"):
	#move(-player_speed,acc,delta)
	apply_impulse(Vector2(get_pos().x,get_pos().y),Vector2 (0,-acc).rotated(get_rot()))

I tried setting the linear velocity if my speed is faster than my player_speed, but that just lead to stuttering somehow.

But anyways, thanks a lot again for the help!

kochw | 2016-04-14 08:23

Try to separate is_action_pressed() and apply_impulse()

I put is_action_pressed() in func _process(delta) and save the move state.

The apply_impulse() is inside func _fixed_process(delta) and run based on move state.

On my game _fixed_process(delta) was called in irregular intervals and i got stuttering movements.

puppetmaster- | 2016-04-14 11:30

I guess you could add a small equation to act as a drag.

Equation would be: impulse = impulse * ((max_speed - current_speed) / max_speed)

This way there will be no impulse if current speed is max speed. It also adds smaller impulse at higher speed so acceleration decreases as velocity increases.

MechFive | 2016-04-14 12:54