Move object to a position across line


#1

Hi there!

I am currently working on a space shooter for the arduboy, but I have a part I don’t know how to make.
So what I want to do is give the enemy the position it should go to, and where it needs to go. But I just can’t figure out how I can accomplish this with code. I want it to move smoothly to that position.

this is what i mean:
image

Does somebody know how I can accomplish this or better if somebody has a piece of example code

Thanks! :slight_smile:


(Shawn) #2

A simple way would be to calculate a delta x and a delta y (the difference in the x and y coordinates between where the enemy currently is and where you want it to finally end up). Then you can take into account how many frames (affects how long it takes for the enemy to get there) it should take to divide delta x and delta y so that each frame/loop of your game code the enemy will move one step in the correct direction. There are other ways of doing this by giving objects directions, velocities and accelerations but this method is a simple first step.

Example: The enemy is currently at x,y=0,0 and you want to move it to x,y(final)=10,10 over the course of 5 frames. So each frame then the enemy would need to increment x and y by 2 (x=x+2, y=y+2).


#3

Thanks! I got it to work :smiley:
Here is the code I made

if (enemies[enemyindex].x > enemies[enemyindex].finalx) {
              enemies[enemyindex].x -= (enemies[enemyindex].x - enemies[enemyindex].finalx) / enemies[enemyindex].framesLeft;
            } else {
              enemies[enemyindex].x += (enemies[enemyindex].finalx - enemies[enemyindex].x) / enemies[enemyindex].framesLeft;
            }

            if (enemies[enemyindex].y > enemies[enemyindex].finaly) {
              enemies[enemyindex].y -= (enemies[enemyindex].y - enemies[enemyindex].finaly) / enemies[enemyindex].framesLeft;
            } else {
              enemies[enemyindex].y += (enemies[enemyindex].finaly - enemies[enemyindex].y) / enemies[enemyindex].framesLeft;
            }
            
            enemies[enemyindex].framesLeft -= 1;
            if (enemies[enemyindex].x == enemies[enemyindex].finalx && enemies[enemyindex].y == enemies[enemyindex].finaly) {
              enemies[enemyindex].atFinalLocation = true;
            }

(Pharap) #4

This is somewhat complicated.

A few questions:

  • Do you know how to use structs?
  • Are you able to use floats, or do you want to avoid them?
  • Will there be obstacles that the enemy needs to avoid?
  • Is it just the one point the enemy needs to travel to or does the enemy need to follow a path?
  • Are there any other specifics that you haven’t mentioned?

The typical solution (assuming that the enemy doesn’t have to account for obstacles) would be to give the enemy:

  • A position
  • A velocity
    • (basically a speed with both an x and y component - see here)
  • A target point

And then you make sure that the velocity faces towards the target,
and each frame the enemy moves by that velocity,
(sometimes multiplied with the amount of time that has passed - a concept called ‘delta timing’),
and while moving the enemy checks if it’s going to overshoot the destination,
and if it is going to overshoot the destination then it just moves straight to the destination instead.

Which looks something a bit like this:

auto distanceVector = (enemy.target - enemy.position);

if(distanceVector.getMagnitude() < enemy.velocity.getMagnitude())
{
	enemy.position = enemy.target;
	enemy.velocity = Vector2(0, 0);
}
else
{
	enemy.position += enemy.velocity;
}

(I’m using a thing called vector arithmetic to simplify things. If it doesn’t make sense I can explain)


#5

I’ve just started learning structs and they are very handy once you understand them.

I am able to use floats, but I’d prefer to avoid them since I don’t need that precision and it saves me a little bit of RAM when I use a byte or uint8_t instead.

The enemy doesn’t need to avoid anything, they only move to a specific position at spawn, after that they do a basic movement (like going in a circle which I’ve done using sin and cos)

It is only 1 path, which is only used just after they spawned.

And nope, I only needed something very basic that would move the enemy to a specific spot.
I got it working using a 2 locations and a frame counter.
So I give it a location where it needs to go to, and a location where I want it to start. And it calculates how big each step must be to reach the destination within the limited amount of frames I give it.


(Pharap) #6

That makes matters easier.

You could also try fixed points if you need a bit of extra precision.
(I know a good library for that.)

An SQ8x8 gives you 8 bits of signed integer and 8 bits of fraction,
which means it can represent 1/256th of a pixel for movement purposes.

It still uses half as many bytes as floats do,
although multiplication can be expensive.

That makes it somewhat easier.
If you need to switch movment pattern then that’s a bit more complex.
If you only need one or two patterns then it’s not too bad,
a simple state machine should do.

When I say ‘path’, I’m thinking more like multiple points to follow.
Just moving to a single point is less of a path and more of a direct line.

The downside to that approach is that it can be imprecise when using integers.
E.g. if you wanted to move from 0, 0 to 10, 9 over 5 frames,
10 / 5 will correctly give you 2, but 9 / 5 will give you 1,
so you actually end up at 10, 5.

It would work using floats or fixed points though.

Ultimately it depends whether you want to be able to say “move from here to here in N frames” or “move from here to here at this speed”.


#7

I’ve fixed that part now, I use floats for the actual position of the enemy so the line is actually smooth. It did cost me another 24 bytes of RAM


(Pharap) #8

As I say, fixed points are a cheaper alternative if you want to give them a go.

Otherwise you should be fine for now.