Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411595 Posts in 69386 Topics- by 58444 Members - Latest Member: FightingFoxGame

May 07, 2024, 02:33:55 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)how do I make a thing move toward another thing
Pages: [1]
Print
Author Topic: how do I make a thing move toward another thing  (Read 3335 times)
William Broom
Level 10
*****


formerly chutup


View Profile
« on: January 30, 2009, 04:33:18 AM »

It almost sounds like a joke but I am actually quite serious. What I am trying to do is very simple, just moving an object in the direction of a certain point, regardless of what direction that point may lie. The reason I want to do this is for a line-of-sight system, and I cannot work it out.

I'm using GM, btw, but I get the feeling that the solution would be basically the same in any language, right?
Logged

Ishi
Pixelhead
Level 10
******


coffee&coding


View Profile WWW
« Reply #1 on: January 30, 2009, 04:41:14 AM »

Basic solution, work out the line that goes from one to the other as X and Y distances, then divide it into however many steps you want to take along the line. Only works properly with floating point calculations though, not ints.

Code:
steps = 20;
differenceX = endPointX - startPointX;
differenceY = endPointY - startPointY;
stepX = differenceX / steps;
stepY = differenceY / steps;

currentX = startPointX;
currentY = startPointY;
loop 20 times
{
   currentX = currentX + stepX;
   currentY = currentY + stepY;

   check point currentX, currentY;
}
Logged

___
Vice President of Marketing, Romeo Pie Software
Level 10
*


View Profile
« Reply #2 on: January 30, 2009, 06:56:51 AM »

You're using GM?  Have you tried:

move_towards_point(x,y,sp) Moves the instances with speed sp toward position (x,y).
Logged
Gold Cray
Level 10
*****


Gold Cray


View Profile WWW
« Reply #3 on: January 30, 2009, 08:02:57 AM »

You're using GM?  Have you tried:

move_towards_point(x,y,sp) Moves the instances with speed sp toward position (x,y).
Easy-of-game-development scoreboard:
GM: 1  |  C++: 0

For the record, I never really figured out how to use GM.

In C++, I usually do

Code:
xoff = thing1.xpos - thing2.xpos;
yoff = thing1.ypos - thing2.ypos;
dist = xoff*xoff + yoff*yoff;     //Optional sqrt()

thing1.xvel =- xoff/dist;         //switch the - and = to make if accelerate toward the object
thing1.yvel =- yoff/dist;         //instead of just moving toward it

Which is just slightly different than Ishi's, but can be changed to move away or to do acceleration pretty easily if the things you're moving are set up to work with position and velocity.
« Last Edit: January 30, 2009, 08:38:07 AM by Gold Cray » Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #4 on: January 30, 2009, 08:27:53 AM »

GM: 1  |  C++: 0
God, no. GameMaker has a built in function for this? So what. Your C++ seems to assume you aren't using any libraries. With a vector library (prolly comes with your game/graphics library), you'd have code like this:
Code:
object.velocity = (thing2.position-thing1.position).Normalize() * speed;
Mmm, operator overloading...
Logged
Alex May
...is probably drunk right now.
Level 10
*


hen hao wan


View Profile WWW
« Reply #5 on: January 30, 2009, 08:41:00 AM »

Theory-wise, it works like this



You want to move A towards B.

The vector s from A to B is equal to the position of B minus the position of A.

s = B - A

If you add this on to the position of A, A will be at the same position as B.

So you can normalise the vector to get the direction - this changes s to be 1 unit in length (known as a unit vector), which is useful for a lot of things. To normalise a vector, you divide each component of the vector by the length of the vector. In maths it's usually noted with a circumflex.

Now you can multiply this direction vector by some scalar value (i.e. a speed), depending on how fast you want A to move towards B, and then add that onto the position of A.
Logged

Cymon
Level 9
****


Computer Kid


View Profile WWW
« Reply #6 on: January 30, 2009, 08:46:57 AM »

For line of sight you definately want to do lines. However, you may want to bone up on field of vision.

However, for movement then scaled similar triangles would be better, so I'm gonna post the math on that just because:
Code:
X,Y = location of player.
dX, dY = direction vector of player.
X1,Y1 = location of object 1.
disX = X1 - X.
disY = Y1 - X.
dist = sqrt(disX^2 - disY^2)
Now you use the distance (dist) to determine the scale. if you want the person to move 5 units at a step your scale is dist/5. if you want the person to move 1 scale at a time your scale is dist/1 or dist. So:
Code:
scale = dist/step.
dX = disX / scale.
dY = disY / scale.
X += dX.
Y += dY.
I know it all looks complicated, but it's really very simple. You're scaling similar triangles.

I should mention you need to do all this math in floating point, not integers, or you may find yourself taking imprecise steps.

So you writing a roguelike?
Logged

Cymon's Games, free source code, tutorials, and a new game every week!
Follow me on twitter
Alex May
...is probably drunk right now.
Level 10
*


hen hao wan


View Profile WWW
« Reply #7 on: January 30, 2009, 08:52:25 AM »

iirc all game maker numbers are floating point anyway.

For line of sight, the line in my diagram from A to B (before you normalise it) will also let you test against other objects - if there's anything that collides with that line, you could say that A cannot see B.
Logged

Zaratustra
Level 7
**



View Profile WWW
« Reply #8 on: January 30, 2009, 10:42:32 AM »



angle = atan2(target.y-source.y, target.x-source.x)
speed = 0.5;
source.x += sin(angle) * speed;
source.y += cos(angle) * speed;
Logged

Ivan
Owl Country
Level 10
*


alright, let's see what we can see


View Profile
« Reply #9 on: January 30, 2009, 11:28:44 AM »

I love atan2
Logged

http://polycode.org/ - Free, cross-platform, open-source engine.
Gold Cray
Level 10
*****


Gold Cray


View Profile WWW
« Reply #10 on: January 30, 2009, 01:11:30 PM »

I love atan2
atan2 is not nearly as good as the original. It's just another soulless sequel with a few extra features to make it look innovative. I really like the basis of the original, and I think that they could have done a lot more with it using today's technology. ahtan, anyone? ahtanexpsinln? There's so much potential. All they have to do is stop being afraid of losing sales. Here's hoping atan3 is better.
Logged
bateleur
Level 10
*****



View Profile
« Reply #11 on: January 30, 2009, 02:40:25 PM »

atan2 is not nearly as good as the original.

I dunno, the original had way too many singularities for my tastes. Tongue
Logged

William Broom
Level 10
*****


formerly chutup


View Profile
« Reply #12 on: January 30, 2009, 04:39:59 PM »

Thanks everyone! You've obviously been a great help.

You're using GM?  Have you tried:

move_towards_point(x,y,sp) Moves the instances with speed sp toward position (x,y).
Unfortunately this wouldn't work for what I'm trying to do, since it moves toward something over a series of steps, moving (sp) each step. Whereas for a line of sight system it needs to travel the whole distance within a single loop.
Logged

Soulliard
Level 10
*****


The artist formerly known as Nightshade


View Profile WWW
« Reply #13 on: January 30, 2009, 05:45:06 PM »

I find point_direction(x1,y1,x2,y2) and point_distance(x1,y1,x2,y2) to be very useful scripts for pathfinding in general.

If you just need to check if there's no object intervening between two other objects, you can use collision_line(x1,y1,x2,y2,obj,prec,notme).

while loops are a good way to move objects multiple times in a single step.
Logged

andy wolff
Level 10
*****


-------


View Profile
« Reply #14 on: January 30, 2009, 05:57:38 PM »

i use my merge_number script (not just for this though), which is basically
#1+Δ(#2-#1)*mergevalue
 where mergevalue will return number 1 when its 0 and number 2 when its 1, but can be outside of the 0-1 range
return (argument0+((argument1-argument0)*argument2))

it looks like
x=merge_number(x,x2,.05orsomething)
y=merge_number(y,y2,.05orsomething)
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic