0 votes

Hello! Im a beginner here, and trying to make a stellaris-like rts as my first game. Making spaceships a kinematic body didn't quite satisfy me (bcuz acceleration and decelration have to be handled manually, and even then arent perfect), so I want to learn to use rigid bodies. So far I`ve been trying to get it to move to the cursor, and left its rotation (and turning) for later:

func move(delta):
if Input.is_action_pressed("follow"):
    target = get_global_mouse_position()
velocity = position.direction_to(target) * speed
apply_central_impulse(velocity * delta)

But it doesn't work too well, either. The ship (from a standstill) doesn't move straight to the target (though it accelerates smoothly, at least), but takes sort of a curved path, and then orbits around the target, oscillating back and forth. I also want it to decelerate before it arrives at the target, so that it wouldn't overshoot, and I would usually try to do that by inverting velocity or applying negative impulse, but seeing how curved the path is... As well as that, I want it to make smooth turns, but when I tried applying torque impulse, it turned into quite a mess, so I chose to ask for help instead. Any help appreciated :)

Godot version 3.4.4 stable
in Engine by (12 points)

I would actually recommend not using rigid bodies as it is actually easier to control kinematic bodies. Implementing acceleration and deacceleration is not difficult.

Anyway, moving the node is easy. If you can't do that, look up some youtube tutorials.

But as far as moving to a target, you might considering something like this:

Note that I haven't tested this so there might be bugs, but hopefully it'll give you an idea or two!

extends KinematicBody2D

# when we are 1 pixel away from the target. depends how large your bodies are.
const TARGET_REACHED_THRESHOLD = 1.0
const ACCEL = 10 # add this to velocity every second.
const MAX_VELOCITY = 100 # clamp velocity to this to prevent accelerating indefinately
var velocity := Vector2()

var is_following := false
var target_node = null

func set_follow_target(node:Node):
    target_node = node
    is_following = true

func _process(delta:float):
    if is_following:
        var dist_to_target = global_position.distance_to(target_node.global_position)
        if dist_to_target <= TARGET_REACHED_THRESHOLD:
            is_following = false
        else:
            var direction = global_position.direction_to(target_node.global_position)
            velocity += direction * ACCEL * delta

func _physics_process(delta):
    if velocity.length() > MAX_VELOCITY:
        velocity = velocity.normalized * MAX_VELOCITY
    move_and_collide(velocity)

Hmm, this looks promising. I've done smth similar, but your seems better - the turns are gradual, and all left to to do is to add deceleration and rotation. I'll tinker with it and update later. Thx for the reply

1 Answer

0 votes

You can easily do this with tween and parallel () functions. There's a YouTube video about it somewhere with code like the following:

`var tween := createtween ().settrans (Tween.TRANSQUINT).setease (Tween.EASEINOUT)
tween.tweenproperty (self, "globalposition", getglobalmouse_position (), 1.0)

var targetrotation := globalposition.directionto (getglobalmouseposition()).angle () + PI / 2.0
tween.parallel ().tweenproperty (self, "rotation", targetrotation, 0.5)`

That code was ripped from the video, so if it doesn't work...

by (141 points)
edited by

Thx for the reply, Ill look into tweens. Gonna try and find the vid u mention

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.