# How do I limit speed on 2d vectors?

From the Asset Store
Have you ever dreamed of playing in a Speedball game or tournament?
• I began an attempt at implementing steering vectors with the 8direction behavior, but seem to have run into a wall early on. I would expect that the sprite orbits around the target when approaching at an angle, but it intermittently cuts most (but not all) of its horizontal or vertical velocity upon passing the target, but only sometimes... Am I approaching this wrong in the following?

+ System: Every tick

-> Sprite: Set 8Direction vector X to clamp(-1×abs(Self.8Direction.Maxspeed×cos(angle(Self.X,Self.Y,Target.X,Target.Y))),Self.8Direction.VectorX+Self.8Direction.Acceleration×dt×cos(angle(Self.X,Self.Y,Target.X,Target.Y)),abs(Self.8Direction.Maxspeed×cos(angle(Self.X,Self.Y,Target.X,Target.Y))))

-> Sprite: Set 8Direction vector Y to clamp(-1×abs(Self.8Direction.Maxspeed×sin(angle(Self.X,Self.Y,Target.X,Target.Y))),Self.8Direction.VectorY+Self.8Direction.Acceleration×dt×sin(angle(Self.X,Self.Y,Target.X,Target.Y)),abs(Self.8Direction.Maxspeed×sin(angle(Self.X,Self.Y,Target.X,Target.Y))))

• It’s a bit hard to debug big formulas like those, but basically you’re accelerating toward the target and limiting the the speed?

I’d break it up into multiple steps and once that works you can combine it again.

Local number a

Local number speed

Every tick

Set a to angle(sprite.x, sprite.y, target.x, target.y)

Set vectorX to vectorX + accel*dt*cos(a)

Set vectorY to vectorY + accel*dt*sin(a)

Set speed to sqrt(vectorX^2+vectorY^2)

Compare: speed>maxspeed

Set vectorX to vectorX/speed*maxspeed

Set vectorY to vectorY/speed*maxspeed

• I was thinking this was a good one for ROJOhound! :)

that works nicely... we don't need to limit the speed because the 8Direction behavior does that automatically. it settles into an orbit around the target.

I have a feeling oosyrag might want the sprite to converge on the target - as if it has gravity.

how would you make the orbit shrink so that the sprite converges on the target?

https://www.rieperts.com/games/forum/orbit3.c3p

• Well originally I had thought that the built in speed limit was causing issues resulting in unnatural paths if either the x or y vectors were already near or at the speed limit when attempting a turn, and prevent acceleration on the other axis when setting the vectors manually.

Eventually I was aiming for variable speed limits to allow for slingshotting and more responsive obstacle avoidance. But then when I tried to add a simple clamp for the max speed I already ran into more issues.

Seems like (I think?) clamping the vector with the sin and cos functions were not symmetrical, causing irregularities. Guess that's why all the articles I read normalize the vector first.

Regarding gravity and decay of orbit, that could be done with adding either an overall deceleration force, or a local one when near the target.

Thanks for the help!

• Oh true. I forgot about the behavior enforcing the max speed for you.

He said he was expecting an orbit, but real gravity would be similar.

To stop the orbit you could apply a brake to the tangent speed so it would fall straight down. The break could be just a velocity opposite the tangent velocity and you could make it inversely proportional to the distance. Basically that would make it brake faster the closer it is.

a = angle(sprite to target)+90

tanvel = vectorX*cos(a)+vectorY*sin(a)

d = distance(sprite to target)

If d>0

vectorX = vectorX - tanvel/d*cos(a)

VectorY = vectorY - tanvel/d*sin(a)

• I've done similar code in a different context.Usually there are a lot of problems when you're

using cos/sin with absolute values as well as switching between positive and negative manually(by mulitplying by *-1). The reason is what you just said. absolute values ONLY accept positive values(in your case it's only negative values I believe because you multiplied by *-1)

Also, you should look at"maths and trigonometry cheat sheet for 2D and 3D games" online.The list contains the majority of math equations needed for practically everything (I believe it's on github.)

Also, you're using the clamp function. The clamp functions uses these parameters (value,upper bound,lower bound) The value will be between upper and lower bound. THAT ALMOST always has problems with abruptness in cases like these. You're "clamping" between 2 points(an analogy is an oyster clamping a pearl in it's mouth)

You should definitely use r0jhound's method.

Just curious, what game are you making?

• ## Try Construct 3

Develop games in your browser. Powerful, performant & highly capable.

Construct 3 users don't see these ads