Constant Velocity along a Vector?

Published February 05, 2010
Advertisement
OK, I feel pretty dumb here. I know I've seen the solution to this before, but I'm drawing some blanks here. I'm working on a basic RTS prototype with Lua and Love, and I'm having difficulties getting my ship to smoothly move at a constant speed to wherever I click. Right now my below code basically works, but I'm either not calculating ship[0].factor_y or ship[0].factor_x correctly or I'm not applying them correctly. The angle is drastically affecting the speed of ship, which is definitely not what I want. Could anyone point me in the right direction here?

Calculated on the click of the mouse -
if math.abs(ship[0].target_x - ship[0].start_x) > math.abs(ship[0].target_y - ship[0].start_y) then	ship[0].factor_x = (math.abs(ship[0].target_x - ship[0].start_x) / math.abs(ship[0].target_y - ship[0].start_y))end		if math.abs(ship[0].target_x - ship[0].start_x) < math.abs(ship[0].target_y - ship[0].start_y) then	ship[0].factor_y = (math.abs(ship[0].target_y - ship[0].start_y) / math.abs(ship[0].target_x - ship[0].start_x))end


Within characterUpdate (dt) -
if ship[0].x ~= ship[0].target_x then	if (ship[0].start_x > ship[0].target_x) and (ship[0].x > ship[0].target_x) then		ship[0].x = ship[0].x - (dt / ship[0].speed) * ship[0].factor_x	elseif (ship[0].start_x < ship[0].target_x) and (ship[0].x < ship[0].target_x) then		ship[0].x = ship[0].x + (dt / ship[0].speed) * ship[0].factor_x	endend	if ship[0].y ~= ship[0].target_y then	if (ship[0].start_y > ship[0].target_y) and (ship[0].y > ship[0].target_y) then		ship[0].y = ship[0].y - (dt / ship[0].speed) * ship[0].factor_y	elseif (ship[0].start_y < ship[0].target_y) and (ship[0].y < ship[0].target_y) then		ship[0].y = ship[0].y + (dt / ship[0].speed) * ship[0].factor_y	endend
Previous Entry The Small Guys
Next Entry LoveRTS Roadmap
0 likes 4 comments

Comments

shadowcomplex
Given:
Point Start
Point Target
Number Speed

Find:
Vector Velocity
Number Distance

Velocity.x = Target.x - Start.x
Velocity.y = Target.y - Start.y

Distance = Velocity.Length() //cache distance before normalizing

Velocity.Normalize()
Velocity *= Speed //Scalar multiply

In your update:
Pos.x += Velocity.x * deltaTime
Pos.y += Velocity.y * deltaTime

TrackDistance += Velocity.Length() * deltaTime

//Check if we reached or passed our target
if( TrackDistance >= Distance )
{
Pos = Target
Velocity.Zero()
TrackDistance = 0
}

The deltaTime is needed if you aren't running on a frame based or fixed time step system. (Edit: I see you are already using a dt system, so this note is just repeating the obvious :)
February 05, 2010 10:02 PM
zer0wolf
Thanks for your help! It it working now, with only one small hiccup. If I update to a new target destination while the ship is moving, and has moved along a fairly small percentage of the vector, then the ship teleports straight to the new target. I'm going to have to think about this one a bit. In any case, here is the updated code I'm using -

On input -

if mouse.button == 'r' then
	
	-- point start
	ship[0].move.start.x = ship[0].pos.x
	ship[0].move.start.y = ship[0].pos.y
		
	-- point target
	ship[0].move.target.x = mouse.x - 64 - offset.x
	ship[0].move.target.y = mouse.y - 96 - offset.y
		
	-- find velocity
	ship[0].move.velocity.x = ship[0].move.target.x - ship[0].move.start.x
	ship[0].move.velocity.y = ship[0].move.target.y - ship[0].move.start.y
		
	-- find the distance
	ship[0].move.distance.target = math.sqrt (math.pow(ship[0].move.velocity.x, 2) + math.pow(ship[0].move.velocity.y, 2))
		
	-- normalize the velocity ...
	ship[0].move.velocity.x = ship[0].move.velocity.x / math.abs(ship[0].move.distance.target)
	ship[0].move.velocity.y = ship[0].move.velocity.y / math.abs(ship[0].move.distance.target)
		
	-- ... and scale it based on the ship's speed
	ship[0].move.velocity.x = ship[0].move.velocity.x * ship[0].speed
	ship[0].move.velocity.y = ship[0].move.velocity.y * ship[0].speed
	
end


In characterUpdate (dt) -

deltaTime = dt
	
-- update the ship's position
ship[0].pos.x = ship[0].pos.x + (ship[0].move.velocity.x * deltaTime)
ship[0].pos.y = ship[0].pos.y + (ship[0].move.velocity.y * deltaTime)
	
-- update the distance
ship[0].move.distance.update = math.sqrt (math.pow(ship[0].move.velocity.x, 2) + math.pow(ship[0].move.velocity.y, 2))
	
-- tracks how far along the vector the ship has moved
ship[0].move.distance.track = ship[0].move.distance.track + (ship[0].move.distance.update * deltaTime)
	
-- if you've reach the destination or past it, set to the target destination
if ship[0].move.distance.track >= ship[0].move.distance.target then
	
	ship[0].pos.x = ship[0].move.target.x
	ship[0].pos.y = ship[0].move.target.y
	ship[0].move.velocity.x = 0
	ship[0].move.velocity.y = 0
	ship[0].move.distance.track = 0
	
end
February 06, 2010 02:32 PM
shadowcomplex
Sounds like a variable isn't getting reset on the new input when the finish condition isn't previously met.

My guess would be:
ship[0].move.distance.track

If that's the case just set it to 0 when you receive a new input and need to recalculate your velocity etc.

How's life in Austin these days?
February 06, 2010 03:19 PM
zer0wolf
I went ahead and reinitialized all of my move variables on click just in case and everything is working great now. I'm probably going to be adding to this code later, so I might as well just setup up a block of initializations to be safe [wink]


Austin is great, but it has definitely taken some time to get used to how much warmer it is here. Work at SEI has been absolutely nuts, as I posted about a bit ago. If you ever come around Austin at some point in time, we'll have to meet up!
February 06, 2010 04:17 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement

Latest Entries

Where the Jobs Are

1407 views

Job Search Metrics

1542 views

Hired!

1970 views

Interviews :)

1761 views

The Job Hunt

1558 views

Making the Cut

1171 views

A Look Back

1418 views

LoveRTS Roadmap

1317 views
Advertisement