• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

How can I do apply impulse like movement without physics enabled?

A

anynameyouwish

Guest
I am new to game maker and have never really programmed before.

I'm trying to make a spaceship object that doesn't just instantly change direction and speed like using move_towards_point does.

With physics enabled I can use physics_apply_local_impulse for up and phy_rotation for left and right and get the movement I want but from what I have read using physics is probably not a good idea for my game as nothing else I want to do needs physics and I would like to make an warp jump feature later on.

How can I do this without physics? Is there a tutorial somewhere were I could learn this?

I have seen there is a motion_add function but I'm not sure how to use it get the same type of movement. I tried

if speed < 10
{
motion_add(image_index, 0.2);
}

for the up key but then once I reach top speed its impossible to change direction.
 

Smiechu

Member
You need to use vectors...

First there has to be movement vector... it describes what is the translation of the object every step (if it's [0,0] there is no movement, if it's [1,-5] it moves 1 pixel in x direction and -5 pixels in y direction) ..
Movement vector is modified by adding other vectors to it i.e. acceleration, deceleration, friction, wind, gravity whatever you need...
This is all very basic knowledge from math and phisycs...

If you don't manage to solve it, I can post some code from my game...
 
A

anynameyouwish

Guest
I doubt I'll be able to figure it out easily but I'll read up on it some. If you don't mind posting some code that would be great. I have never used vectors before and have no idea where to even start.
 
S

Syorx

Guest
There is a VERY simple way to this but it only works in straight lines (like north,east,west,south):

Code:
in key pressed event:

if (active) {                                       // any other variable name is fine
x += ImpulseDistance;              // can be x(horizontal) or y(vertical), + or -
alarm[0] = interval;                  // interval being time between each impulse and ImpulseDistance being the distance traveled each impulse;
active = false;
}

in alarm[0]:
active = true;

of course there are ways to make this in all directions but this is very simple.
 

Smiechu

Member
Create event:
Code:
// Kinematics
    v_x                = 0                        // Movement vector x
    v_y                = 0;                    // Movement vector y
    a_x                = undefined;            // Acceleration vector x
    a_y                = undefined;            // Acceleration vector y
    a_angle            = irandom_range(0,360);    // Acceleration angle
    a_accel            = 0;                    // Acceleration factor
    a_state            = 0;                    // Acceleration state

    spd                = 0;            // Current speed
    spd_max            = 3;            // Unit max speed
    acc                = 0.1;            // Acceleration/Deceleration value
Step event:
Code:
#region KINEMATICS
    // Acceleration
        if keyboard_check(vk_up)
            {
            a_accel = acc;
            }
        else if keyboard_check(vk_down)
            {
            a_accel = 0;
            spd -= acc;
            }  
        else
            {
            a_accel = 0;
            }

    // Movement
        if spd <= 0
        {
        spd = 0;
        }
   
        a_x = lengthdir_x(a_accel,a_angle);
        a_y = lengthdir_y(a_accel,a_angle);
        v_x = lengthdir_x(spd,direction);
        v_y = lengthdir_y(spd,direction);

        v_x += a_x;
        v_y += a_y;

        spd = clamp(point_distance(0,0,v_x,v_y),0,spd_max);

        speed = spd;
        direction = point_direction(0,0,v_x,v_y);
       
#endregion KINEMATICS

// Sprite rotation
    image_angle = 270 + a_angle;   // 270 is a correction value of the sprite angle aligment
OK... this is part of the code from my ship object... it"s originally controlled by A.I... I've created a simple code for acceleration, rotation you need to do it on your own...

a_angle: this is the angle of the ship sprite (not the direction of the movement), the "left" and "right" arrow keys should simply add or substract the "rotation speed" from it.

If you need delta time in this, than I can help you also with it...
 
So you want to accelerate relative to the direction you your ship is facing. But you also want to cap the ship's speed so it can't go above a certain value.

One way you could do this fluidly is to introduce a drag or damping effect on your speed.
The amount of drag applied is carefully calculated to limit the ship's top speed to an exact value.
This is in contrast to having an extremely abrupt change in acceleration caused by hitting the speed cap. The idea here is damping fights acceleration, so that apparent acceleration gradually reduces to zero as you approach the top speed.

If you want you, you can have the damping effect only apply when acceleration is occurring, so that the ship will continue to drift at the same speed when not accelerating.

Code:
    //CREATE EVENT:
    top_speed = 6;
    acceleration = 0.5;
 
    //the higher the damping exponent, the more abruptly damping will kick in as you approach top speed
    //this means damping will be a lot lower at slow speeds
    //damping_exponent of 1 equals linear damping.
    damping_exponent = 6;
    damping_coefficient = acceleration / power(top_speed,damping_exponent);
then
Code:
    //get acceleration input vector
    //assuming here that forward is towards positive x when at zero rotation
    var _long = acceleration * (keyboard_check(ord("W")) - keyboard_check(ord("S")));
    var _lat = acceleration * (keyboard_check(ord("D")) - keyboard_check(ord("A")));
 
    //optional:  cancel out diagonal speed boosts (for example when holding W and D at the same time).
    if (_long != 0) and (_lat != 0) { _long *= 0.707107; _lat *= 0.707107; }
 
    //apply damping
    speed -= damping_coefficient*power(speed,damping_exponent);
 
    //rotate acceleration vector from ship space into global space.
    var _c = dcos(image_angle);
    var _s = dsin(image_angle);
    hspeed += _long *  _c + _lat * _s;
    vspeed += _long * -_s + _lat * _c;
 
Last edited:
A

anynameyouwish

Guest
Thanks for posting the code. I got it working like I want but still have very little understanding of how it actually works. Hopefully after reading up on vectors and slowly going over it it will make sense to me. If not I guess programming isn't for me.
 

Smiechu

Member
Thanks for posting the code. I got it working like I want but still have very little understanding of how it actually works. Hopefully after reading up on vectors and slowly going over it it will make sense to me. If not I guess programming isn't for me.
Don't worry...

It's not a problem of programming, it's all pure mathematics and very basic physics.
How old are you? I don't know what is the educational program in your country, in Poland I had this in school when i was approx 12yo.
The only thing is how to transpose the school knowlede in a usefull code.

I wish you luck with your game!
 
A

anynameyouwish

Guest
Don't worry...

It's not a problem of programming, it's all pure mathematics and very basic physics.
How old are you? I don't know what is the educational program in your country, in Poland I had this in school when i was approx 12yo.
The only thing is how to transpose the school knowlede in a usefull code.

I wish you luck with your game!
I'm 34. I think I might have had like a week 20 years ago on basic physics in school but remember nothing of the math behind it. Just looking at the code and all the variables and trying to figure out whats going on gives me a headache. My attention span is short.

I was preparing to type what I can't figure out by slowly going over it and looking at the documentation for lengthdir and point_direction and I'm not really confused anymore and can follow along reading the code but at the same time if I had 10 years to try to rewrite that code without looking at it I don't think I would be able to figure it out. I guess its just my lack of knowledge in the math of physics and vectors and not knowing the basic functions yet that makes it much harder to picture in my head what is going on. I think if I keep spending time playing around though it will become easier. I had only followed a few drag and drop tutorials up until about 3 weeks ago and there's a lot of new stuff in my head that I'm not very familiar with yet.
 

Smiechu

Member
I'm 34. I think I might have had like a week 20 years ago on basic physics in school but remember nothing of the math behind it. Just looking at the code and all the variables and trying to figure out whats going on gives me a headache. My attention span is short.

I was preparing to type what I can't figure out by slowly going over it and looking at the documentation for lengthdir and point_direction and I'm not really confused anymore and can follow along reading the code but at the same time if I had 10 years to try to rewrite that code without looking at it I don't think I would be able to figure it out. I guess its just my lack of knowledge in the math of physics and vectors and not knowing the basic functions yet that makes it much harder to picture in my head what is going on. I think if I keep spending time playing around though it will become easier. I had only followed a few drag and drop tutorials up until about 3 weeks ago and there's a lot of new stuff in my head that I'm not very familiar with yet.
So we"re almost the same age :)
It's not that I just remember all the things from school. It took me quite a while to bite into this, especially because of the weird axis system GMS uses where the angle is "opposite" to standard rules known from math and physics. Second thing is the behavior of built in GMS functions "speed" and "direction" (the direction is turned 180 deg when speed goes to a negative value). That's why there is additional variable spd.

To understand what is happening here, you need a drawing, without it it's impossible to get it... below is one of my pages from my notes...

Nowy Dokument 2018-04-23.jpg

As you see lenghtdir, point_direction, and point_distance are GMS built in trigonometric functions which in this case allow to transfer vectors from cartesian coordinates (x,y) into polar coordinates (lenght,angle). You could use standard sin and cos, but using built in GMS functions gives a little performance boost. When you have thousands of "ship" instances than it makes a difference...

Than like I said, you can add as many additional vectors as you need, i.e. gravity vector simulating the pulling force of a nearby sun, or a traction beam :D

The code of mine simply transfers the actual speed and direction, variables to cartesian, transfers the acceleration vector into cartesian, and adds this two up...

Always make notes, draw, sketch, make diagrams, tables... it helps a lot...

Good luck with your game!!
 
A

anynameyouwish

Guest
So we"re almost the same age :)
It's not that I just remember all the things from school. It took me quite a while to bite into this, especially because of the weird axis system GMS uses where the angle is "opposite" to standard rules known from math and physics. Second thing is the behavior of built in GMS functions "speed" and "direction" (the direction is turned 180 deg when speed goes to a negative value). That's why there is additional variable spd.

To understand what is happening here, you need a drawing, without it it's impossible to get it... below is one of my pages from my notes...



As you see lenghtdir, point_direction, and point_distance are GMS built in trigonometric functions which in this case allow to transfer vectors from cartesian coordinates (x,y) into polar coordinates (lenght,angle). You could use standard sin and cos, but using built in GMS functions gives a little performance boost. When you have thousands of "ship" instances than it makes a difference...

Than like I said, you can add as many additional vectors as you need, i.e. gravity vector simulating the pulling force of a nearby sun, or a traction beam :D

The code of mine simply transfers the actual speed and direction, variables to cartesian, transfers the acceleration vector into cartesian, and adds this two up...

Always make notes, draw, sketch, make diagrams, tables... it helps a lot...

Good luck with your game!!

Thanks for that note. I'm gonna print that out. It helps a lot in trying to understand how it works. I'm still very early in learning this stuff. I just spent some time reading up on how to use arrays which is pretty basic stuff to give you an idea of what I have yet to learn. Wanting to make a game is good motivation to keep me going though.
 
W

Wraithious

Guest
You could also just use a few variables and increment them and have the speed and direction change in the step event according to their values, you'd use the key, button or mouse PRESSED event to initiate them and then whle the key, button or mouse is down let the variables increase or decrease at a rate you want. When the key, button or mouse is released you can have those variables count back down at a specified rate so your player gradually slows down or turns.
 
if speed < 10
{
motion_add(image_index, 0.2);
}

for the up key but then once I reach top speed its impossible to change direction.
I didn't see any answer to this, so here's one.

Basically, you are adding 0.2 to the instances speed every step, once that speed equals or exceeds 10, your motion_add() function won't run anymore thanks to being wrapped in the if() statement. Therefore,
you would be prevented from applying any counter-thrust even if you are able to rotate your ship to face the opposite direction.

So you either need to apply a deceleration force, or change how you are checking the speed.

But I laugh in the face of deceleration, because SPACE!!!! We want realism so no friction for us! So let's change how we check and limit the max speed. (Although theoretically the limit is the speed of light, that might get a little awkward for the player, so let's go for something a little smaller.)

And I'm a fan of motion_add(), so let's use it for this example.

Note, we apply the motion_add() function first, then we limit the max speed after that. This way we can still turn and apply force as we like.

oSpaceShip CREATE Event:
Code:
// The angle the player is facing (this is independent of movement direction, because SPACE!)
facing = 0;
// Forward direction acceleration and maximum speed
acceleration = 0.1;
max_speed = 5;
// Turning speed (constant - have not factored in turning acceleration in this example)
rotation_speed = 5;
// If you want the ship to slow down when player is not applying force, set this value
// to less than 1. Smaller values will stop the ship faster.
deceleration = 0.999;
oSpaceShip STEP Event:
Code:
// Grab Player Inputs
key_left = keyboard_check(ord("A"));
key_right = keyboard_check(ord("D"));
key_up = keyboard_check(ord("W"));
// Calculate turning direction
turn = key_right - key_left;
//    Update the direction the player is facing
//  This is space, so the direction the player is facing is separate
//  from the players direction of motion
facing -= turn * rotation_speed;
// Make sure the sprite is updating to match the facing direction
image_angle = facing;
// Apply acceleration / deceleration
// Note : Set deceleration to 1 in the
// Create event if we want frictionless movement
// like in real space.
if ( key_up )
{
    motion_add(facing,  acceleration);
}
else
{
    speed = speed * deceleration;
}
// Limit Speed to MAX Speed
if ( speed > max_speed )
{
    speed = max_speed;
}
 

Smiechu

Member
You could also just use a few variables and increment them and have the speed and direction change in the step event according to their values, you'd use the key, button or mouse PRESSED event to initiate them and then whle the key, button or mouse is down let the variables increase or decrease at a rate you want. When the key, button or mouse is released you can have those variables count back down at a specified rate so your player gradually slows down or turns.
Eee... no?
The idea here is to create a "gliding" effect. Your idea will only create a acceleration/deceleration effect. If you simply bind the controls with speed and direction, the object will behave more like a car, not like a space ship...
 
W

Wraithious

Guest
I'm trying to make a spaceship object that doesn't just instantly change direction and speed like using move_towards_point does.
I must somehow misunderstood what you said.. I think? My solution does answer that question tho
 
A

anynameyouwish

Guest
I didn't see any answer to this, so here's one.

Basically, you are adding 0.2 to the instances speed every step, once that speed equals or exceeds 10, your motion_add() function won't run anymore thanks to being wrapped in the if() statement. Therefore,
you would be prevented from applying any counter-thrust even if you are able to rotate your ship to face the opposite direction.

So you either need to apply a deceleration force, or change how you are checking the speed.

[/code]
Ya I knew why it stopped working once it reached top speed but I didn't know how to get around it while still having a top speed. Thanks for providing another method of coding it and the comments. Its interesting to see how the same thing can be done multiple ways.
 
@anynameyouwish

if you're going to add top speed you might as well add drag. There is no top speed in real life space (from your own point of view that is). What limits your max speed in real life is going to be the amount of fuel/propellant you cary.

have you tried using the non-linear damping I outlined above? The cool thing about it is that at low speeds, your ship will appear to drift as if there was little or no drag. I also showed you a way to calculate the damping so that it will cause your speed to exactly top out at your max_speed value. And the cool thing about that is you will ease into your top speed, you wont just suddenly stop accelerating. I dunno, when I use this method, movement just seems a lot smoother.
 
Last edited:
D

Dimitrygol

Guest
motion_add(image_angle, acceleration);
if (speed > maxsp)
{
speed = maxsp;
}

is this what your talking about??? And use the left and right arrows to turn?
 
Top