Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 [Tutorial] Moving an Object Towards a Target
Index -> General Programming
Goto page 1, 2  Next
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
Aziz




PostPosted: Fri Aug 25, 2006 8:26 pm   Post subject: [Tutorial] Moving an Object Towards a Target

Moving an Object Towards a Target


Introduction

The object of this tutorial is to move an object (an (x,y) point) towards a target (another (x,y) point). This can include a ball moving towards another ball, a worm moving towards the cursor. If you have two points, you can make one move to the other (and with some creative thinking, make them both move towards each other, make one accelerate, etc!)

Let's get on with it

Okay, let's start with a simple example. We want to make a ball move around the screen. Okay, simple enough. The ball will have an x and y coordinate (we won't worry about radius). And for every animation loop, we'll move the ball a certain amount, we'll call this value 'speed'. So we move the ball like this.

code:
x += speed
y += speed


But of course the ball won't always be moving 45 degrees, it could be moving horizontally or vertically. We replace 'speed' with two value, xSpeed and ySpeed.

code:
x += xSpeed
y += ySpeed


Here's an example program:

code:
int x = 10
int y = 20

int xSpeed = 10
int ySpeed = 5

loop
    x += xSpeed
    y += ySpeed
end


That's all good. The ball will move across the screen at a shallow slope, increasing in x and lot more than y. That's all good.

Speed of an object

Okay, that's nice, but what if we want to know how fast our ball is moving? I don't mean how fast it's moving in the x or y direction, I mean, overall. When you're traveling in a direction between north and north-east at 50 km/h, you're still going 50km/h if you change to going north. So our ball, in the example above, isn't moving at 5 pixels per loop, or 10 pixels per loop.

What speed is it going? First, let's rename xSpeed and ySpeed. We'll call them dx and dy, or delta x and delta y. Because they're the x and y differences between the ball's current coordinate and the ball's next coordinate.

Okay, let's look at the dx and dy as vectors. If you remember grade 10 science, you remember that vectors have magnitude and direction. Well, dx has a magnitude of 10 and a direction in the +ve x direction, while dy has a magnitude of 5 and a direction in the +ve y direction.

Now, this is from grade 11 physics, so it might be new to you. Try to follow, and trust me. If you have any questions, I'm usually on the irc channel.

Let's make a vector diagram. B(10,20) is the ball's current coordinate. We'll draw dx going to the right, because we're adding that onto x. And we'll then draw dy going up, because we're adding that onto y. We can figure out where these get us, and that's our new point. Now, the vector labelled 'v' is the speed or velocity of the ball, and is drawn from B to the new position:

Posted Image, might have been reduced in size. Click Image to view fullscreen.

From this diagram, we can see that v = dx + dy (a little bit of physics, that's call vector addition. When you add vectors a and b, you draw a and then draw b starting from the head of a). So we can arrange the vectors into a vector addition diagram:

Posted Image, might have been reduced in size. Click Image to view fullscreen.

How this helps us you ask? Well, we want to know the length of 'v' here, because that's the ball's velocity. (Remember velocity is the change in distance of the change in time). How does this diagram help us? Look at it, it's a right triangle! And I know you passed grade 9 math, so we can easily use Pythagorean's theorem, a^2 + b^2 = c^2, where a and b are sides of a right triangle and c is the hypotenuse.

So in this case

code:
v^2 = dx^2 + dy^2

or

v = sqrt(dx^2 + dy^2)


So, let's update are example to calculate and show the ball's speed. In the example we'll use speed instead of 'v' for sake of readability:

code:
int x = 10
int y = 10

int dx = 10
int dy = 5

int speed

loop
    x += dx
    y += dy
   
    speed = sqrt(dx^2 + dy^2)
   
    print("Speed = " + speed)
end


Our output should be:

code:
11.18034


So we'll round that off, and say our ball is moving at 11.2 pixels per loop.

Now, off course, this is only the first step. We don't even know the problem.

The Problem

What's the problem I'm trying to address? Well, just this. Say you want you're object to move towards a point. You would find the difference in x and y between you're object and the target.

code:
    int diffx = targetx - x
    int diffy = targety - y


You'll move you're ball towards in the x direction and in the y direction. A simple selection structure:

code:
    if diffx < dx
        x = targetx
    else if diffx > 0
        x += dx
    else if diffx < 0
        x -= dx
    end
   
    if diffy < dy
        y = targety
    else if diffy > 0
        y += dy
    else if diffy < 0
        y -= dy
    end


What we're doing here:

First, if the distance between this x/y and the target's x/y is less than the ball's movement speed in that direction, we'll simply move right to the target x/y (since we don't want to go over it). Otherwise, we'll move pos/neg x/y direction in order to get to that point. The object will move according to its own x and y speeds.

What's the problem with this? Well, look at what can happen:

Posted Image, might have been reduced in size. Click Image to view fullscreen.

If the ball reaches the target's x position before the y position, or vice versa (which, if the target is not pre-calculated, will almost always happen), we get some weird motion. Now say you're trying to get a ball to move towards something. If you walk towards something, do you do some crazy weird path? No, you go straight towards it.

So how do we do this? Watch and be amazed! This is how we move an object. We move it by changing its x and its y. And that will give us a speed. So, if we want to move an object towards something, we can't predetermine it's x and y changes. We do need something, and we can set a speed. It's pretty simple to want your ball to move at about 30 pixels per loop, right? Well, it's a little more complicated to do it, but it makes sense. So we have 3 values for movement: dx, dy, and speed.

Posted Image, might have been reduced in size. Click Image to view fullscreen.

We can find any of the other values if we have the two others.

code:
speed^2 = dx^2 + dy^2
dx ^2 = speed ^2 - dy^2
dy ^2 = speed ^2 - dx ^2


dx and dy will form a triangle with speed because we want the ball to move at a constant speed, or rather, the speed we set it to.

But we only have one value, speed. So we'll turn to the idea of proportional triangles. If we have two similar triangles, their sides are proportional. Take the following diagram:

Posted Image, might have been reduced in size. Click Image to view fullscreen.

The smaller triangle has sides a, c, and e. The large triangle has sides (a+b), (c+d), f

So, in this example, a/(a+b) = c/(c+d) = e/f

This is also true the other way around, (a+b)/a = (c+d)/c = f/e.

BE WARNED though, a/(a+b) != (c+d)/c. All the sides of one triangle have to be on the top of the fractions, while the sides of the triangles are on the bottom.

How do we apply this? Well, let's make a diagram with our movement triangle and the target. We want the ball to move towards the target, so we'll set it's speed in that direction.

Posted Image, might have been reduced in size. Click Image to view fullscreen.

I've introduced some new values here: diffx and diffy are the x/y differences between the ball and the target. And 'dist' is the distance between the ball and the target, which can be easily found using Pythagoreans theorem with diffx and diffy.

We can use the rule above. Here's how it works:

code:
speed    dx      dy
----- = ----- = -----
dist    diffx   diffy


Values we know (given)

  • diffx -> targetx - x
  • diffy -> targety - y
  • dist -> Pythagoreans theorem using diffx and diffy
  • speed -> We set it to some value


And what we don't know, (coincidently what we need in order to move the ball):


  • dx
  • dy


Now, our fractions, with # replacing our known values. Also, so you can read this better:

code:
##   dx   dy
-- = -- = --
##   ##   ##


Split this up into to expressions:

code:
dx / diffx = speed / dist
dx = (speed / dist) * diffx


And in the same way:

code:
dy = (speed / dist) * diffy


So now we have a direct way to find dx and dy. And we're translating our ball by dx and dy, so thus we have a direct way to move our ball directly towards a target. And you can bet that sqrt(dx^2 + dy^2) will be exactly speed. Or, as close as possible. I recommend leaving dx and dy as a double/real type, and round when you change the x and y values. Also, leave 'dist' as a double/real, and you don't have to round it ever.

Here's an example program where the ball will follow the mouse cursor at 30px/loop, written in no particular language but easy to convert to any.

code:
//Start our ball at (10,10)
int x = 10
int y = 10

//The x and y offsets to move the ball
double dx
double dy

//Our ball will move 30 pixels per loop
int speed = 30

//Values for the target's x and y
int targetx
int targety

//The loop
loop
    //Set the target to the mouse's position
    targetx = mouseX
    targety = mouseY
   
    //Find the x and y differences between the ball and the target
    int diffx = targetx - x
    int diffy = targety - y
   
    //Calculate the distance between the ball and the target
    double dist = sqrt(diffx^2 + diffy^2)
   
    //Calculate the x and y offsets to move the ball
    dx = (speed / dist) * diffx
    dy = (speed / dist) * diffy
   
    //If the ball moves past the target, keep it at the target
    if abs(diffx) < abs(dx)
        x = targetx
    end
   
    if abs(diffy) < abs(dy)
        y = targety
    end
   
    //Move the ball
    x += round(dx)
    y += round(dy)
   
    //Draw the ball
    drawball(x, y)
end


There you go! Try it, any questions or suggestions PLEASE post, or talk to me on the irc channel. Thanks for listening Smile
Sponsor
Sponsor
Sponsor
sponsor
Aziz




PostPosted: Sat Aug 26, 2006 12:56 am   Post subject: (No subject)

Here's an example program in Turing

Turing:
View.Set ("graphics:800;600,position:center;center,title:Chase the mouse,offscreenonly")

%Start our ball at (10,10)
var x : int := 10
var y : int := 10

%The x and y offsets to move the ball
var dx, dy : real

%Our ball will move 5 pixels per loop
var speed : int := 5

%Values for the target's x and y
var targetx, targety : int

%Just a button value, no use to us
var button : int

%The loop
loop
    %Set the target to the mouse's position
    Mouse.Where (targetx, targety, button)

    %Find the x and y differences between the ball and the target
    var diffx := targetx - x
    var diffy := targety - y

    %Calculate the distance between the ball and the target
    var dist := sqrt (diffx ** 2 + diffy ** 2)

    %If the ball is ontop of the mouse, set it there, otherwise calculate movement.
    %This prevents divide by zero errors.
    if dist <= 0 then
        x := targetx
        y := targety
    else
        %Calculate the x and y offsets to move the ball
        dx := (speed / dist) * diffx
        dy := (speed / dist) * diffy
    end if

    %If the ball moves past the target, keep it at the target
    if abs (diffx) < abs (dx) then
        x := targetx
    end if

    if abs (diffy) < abs (dy) then
        y := targety
    end if

    %Move the ball
    x += round (dx)
    y += round (dy)

    %Draw background
    drawfillbox (0, 0, maxx, maxy, white)

    %Draw the ball
    drawfilloval (x, y, 5, 5, red)

    %Draw the speed
    locate (1, 1)
    put "DX ", dx : 0 : 4, " DY ", dy : 0 : 4, " DESIRED SPEED ", speed, " ACTUAL SPEED ", sqrt (dx ** 2 + dy ** 2) : 0 : 4

    View.Update

    delay (10)
end loop
Tony




PostPosted: Sat Aug 26, 2006 2:25 am   Post subject: (No subject)

excellent tutorial! diagrams, explanations, sample code.
+150 Bits

Next challenge - moving an object with a limited turn radius. Currently your object just goes in a straight line on cruise control. See if you can implement object's orientation and curved turns. Such as a car or a snake facing one way, and having a non-straight-line target.
Latest from compsci.ca/blog: Tony's programming blog. DWITE - a programming contest.
Clayton




PostPosted: Sat Aug 26, 2006 8:59 am   Post subject: (No subject)

for that would you not just use some sort of difference constant (or something of the sort), to control how much the dx and dy values change? for example, if you (using the program above [pseudo or not]) have the ball following the mouse, and swing it upwards, the dy value would change almost opposite, but you could just change it so that it changes no greater than say 4 pixels? am i right or am i wrong?
Aziz




PostPosted: Sat Aug 26, 2006 10:13 am   Post subject: (No subject)

I'm not exactly sure what you're talking about, but let me see:

You mean, have it so that the dx and dy can change, but no more than 4? So what if the ball is at (10,10) and the target is at (20, 200). If both dx and dy are four, the ball would move at an angle to get nearest to the target, but it wouldn't be travelling towards the target. Look at the third picture (It's under "The Problem") that's what I mean.

Now I'm not sure that's what you're talking about. If you could, write a sample program (or alter mine) and paste it?
Tony




PostPosted: Sat Aug 26, 2006 2:10 pm   Post subject: (No subject)

SuperFreak82 wrote:
you could just change it so that it changes no greater than say 4 pixels? am i right or am i wrong?

wrong

if your dy was 2, and then the new target is in exact opposite direction, so that dy becomes -2 => your |acceleration| is 4, but you have just turned 90 degrees on the spot.

Something along the lines of the following image

Posted Image, might have been reduced in size. Click Image to view fullscreen.
Latest from compsci.ca/blog: Tony's programming blog. DWITE - a programming contest.
rizzix




PostPosted: Sat Aug 11, 2007 2:20 pm   Post subject: RE:[Tutorial] Moving an Object Towards a Target

I want to point out that some of these characters are unreadable/gibberish on my browser (firefox) running on Vista.

If you wish to use mathematical notations please use the compsci's [tex] tag

Edit: apparently its your apostrophe that's messed up, Aziz.
Aziz




PostPosted: Mon Aug 13, 2007 10:29 am   Post subject: RE:[Tutorial] Moving an Object Towards a Target

It's like that with all the old posts from v2. It does it with XP as well.
Sponsor
Sponsor
Sponsor
sponsor
Nick




PostPosted: Mon Aug 13, 2007 11:17 am   Post subject: Re: RE:[Tutorial] Moving an Object Towards a Target

Aziz @ Mon Aug 13, 2007 10:29 am wrote:
It's like that with all the old posts from v2. It does it with XP as well.


i'd like to point out that it does it with ME as well... nice tuturial btw this will help me in games... im thinking of a rts which will come extremly handy koudos (however you spell it)
Aziz




PostPosted: Mon Aug 13, 2007 12:02 pm   Post subject: RE:[Tutorial] Moving an Object Towards a Target

I think it's spelt "kudos" but beats me. I think it's what happened when Dan moved the forums from v2 to v3, so it's OS independent.

This is where my math courses came in. Take Geometry and Discreet Math if you can, it's great.
Nick




PostPosted: Mon Aug 13, 2007 2:07 pm   Post subject: RE:[Tutorial] Moving an Object Towards a Target

im great at math so i definatly will ^_^
Clayton




PostPosted: Wed Aug 15, 2007 7:39 pm   Post subject: RE:[Tutorial] Moving an Object Towards a Target

Geometry and Discrete Mathematics no longer exists in the Ontario High School Curriculum.
Aziz




PostPosted: Wed Aug 15, 2007 10:06 pm   Post subject: RE:[Tutorial] Moving an Object Towards a Target

That's right, my teacher from Grade 12 told me that a few weeks ago . . . What are they replacing it with?
Clayton




PostPosted: Thu Aug 16, 2007 7:15 pm   Post subject: RE:[Tutorial] Moving an Object Towards a Target

They are actually taking out the old Geometry and Discrete and Calculus courses, and replacing them with an Advanced Functions (4U) course, and a new calc course, Calculus and Vectors (also 4U). From what I understand, Advanced Functions is a soft introduction to ideas from Geometry and Discrete, as well as Calculus, and is therefore a prereq for Calculus and Vectors.
Nick




PostPosted: Fri Aug 17, 2007 4:00 pm   Post subject: RE:[Tutorial] Moving an Object Towards a Target

well than ill just have to take that Razz
Display posts from previous:   
   Index -> General Programming
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 2  [ 16 Posts ]
Goto page 1, 2  Next
Jump to:   


Style:  
Search: