Trying to work with motion vectors

So what is my problem?
I want my spaceship (or sth like that) from the start of the game move in one direction with a certain speed. I used motion_set() and it works fine for me. But also i have 2 buttons to rotate spaceship (i used image_angle += *angle*). And the next step is that when player press key 'space' (for the example) the motion vector of the spaceship must be changed. And this is the main problem.

I can use motion_add() function, but if spaceship won't change direction and i will press 'space' again and again my speed will be increasing till the max speed and i don't need it.
Of course i can add if, for example:
----------------------------------------------------------
motion_add(dir, speed)
If speed > 4
motion_add(dir, -speed)
----------------------------------------------------------
But this way in different directions max speed of my spaceship will be different too. Also spaceship won't change it direction if deflection angle will be small.
I tried to find code of motion_add function, but I couldn't.

If you know how to solve this problem - please help
 

FredFredrickson

Artist, designer, & developer
GMC Elder
Instead of trying to cancel the current momentum when the speed is too great, just set the maximum speed like this:
GML:
speed = clamp(speed, 0, 4);
Your code for adding motion in another direction to coax the path of the ship should work just fine. Just place it before the speed limiter.
 
Thanks for helping, but i still interested in non-GMS function method. Is it possible to somehow edit the elements of the motion vector yourself. Or do you recommend using only the GMS functions?
 

chamaeleon

Member
Thanks for helping, but i still interested in non-GMS function method. Is it possible to somehow edit the elements of the motion vector yourself. Or do you recommend using only the GMS functions?
hspeed and vspeed are the two variables that tied to speed and direction. Modifying one pair (either one) means the other gets modified by GMS.
 

FredFredrickson

Artist, designer, & developer
GMC Elder
Thanks for helping, but i still interested in non-GMS function method. Is it possible to somehow edit the elements of the motion vector yourself. Or do you recommend using only the GMS functions?
You don't need to use the built-in variables if you don't want to - you can store the vectors in your own variables and change them at will. GameMaker just includes x, y, hspeed, vspeed, speed, friction, etc. to make things easier to get started.
 

Joe Ellis

Member
hspeed and vspeed are a vector. That's how simple vectors are really. They seem like this illusive clever math thing when you've never heard of them before but they are just a way of dealing with more than one coordinate on more than one axis. So a 2d vector is x & y, 3d is xyz.
In terms of the built in variables speed is the length of the vector and hspeed and vspeed are the x and y values.
Gm does a thing where if you change the speed it'll reduce the hspeed and vspeed scalar. Basically multiply them both by the same value to either reduce or increase the length of the vector. So this doesn't change the direction of it.
That's where direction comes in. That changes the hspeed and vspeed so they go in a different direction but it keeps the length the same.
It's just a few different math calculations. It works well, but I don't like\never use it. I prefer to just use my own variables, like xspeed, yspeed, and "spd" for speed cus you can't use that otherwise the instance will start moving on it's own.. (I wish you could disable that, like a checkbox on the object's properties next to visible, solid etc., just have like "use builtin motion".)

In terms of the alternative to using motion_add(dir, speed), it'd be something like this:

GML:
xspeed += lengthdir_x(accel, dir)
yspeed += lengthdir_y(accel, dir)
And then, to clamp the speed, you need to do this:

GML:
//Get length of speed vector
var d = point_distance(0, 0, xspeed, yspeed);

//Ask if the speed is higher than the max
if d > max_speed
{
//If it is, you need to reduce them both by the same factor
//so that the speed == the max_speed

//So normalize the vector
var
nx = xspeed / d,
ny = yspeed / d;

//Now nx & ny are 1 unit long (so a speed of 1)
//But the direction is kept intact cus they were divided by the same number

//So then all you need to do is multiply them both by max_speed
//Then set xspeed & yspeed to this

xspeed = nx * max_speed
yspeed = ny * max_speed

//See? The direction is never changed, (when multiplying scalar(both same amount))
//but the length of the vector can be adjusted to anything you want.

}
 
Top