William Broom
|
|
« 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
|
|
« 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. 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
|
|
« 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
|
|
« 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 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
|
|
« 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: object.velocity = (thing2.position-thing1.position).Normalize() * speed; Mmm, operator overloading...
|
|
|
Logged
|
|
|
|
Alex May
...is probably drunk right now.
Level 10
hen hao wan
|
|
« 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
|
|
« 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: 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: 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
|
|
|
|
Alex May
...is probably drunk right now.
Level 10
hen hao wan
|
|
« 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
|
|
« 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
|
|
« Reply #9 on: January 30, 2009, 11:28:44 AM » |
|
I love atan2
|
|
|
Logged
|
|
|
|
Gold Cray
|
|
« 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
|
|
« 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.
|
|
|
Logged
|
|
|
|
William Broom
|
|
« 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
|
|
« 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
|
|
« 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
|
|
|
|
|