• 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!

Movement Code Optimization

P

PointBlankX79

Guest
Hello everyone, I'm mostly new to coding and completely new to GameMaker, so I want to stress immediately that I'm not attempting to get anyone to build my game for me or anything like that. This is my first thread, and I want to (in some minor way) make something useful for other beginners like me.

Below is the player movement code for my first project, which is best described as a side-scrolling shooter... just I want to use something other than shooting. It's meant to reflect inertia with arcadey feeling movement at 60 fps.

diag = rate at which movement has to be multiplied to not have "diagonal" movement be faster than other movement
movespd = "movement speed" multiplier for quick adjustments
U, L, D, R moment = "Up, Left, Down, Right momentum" variables to impart inertia when moving (slightly different from friction, I think)
x, y dir = "horizontal 'x' or vertical 'y' direction" variables

Create Event
Code:
///Variables

diag = 0.707
movespd = 1
Umoment = 0
Lmoment = 0
Dmoment = 0
Rmoment = 0
Step Event
Code:
///Player Movement

//Input
xdir = keyboard_check(ord('D')) - keyboard_check(ord('A'));
ydir = keyboard_check(ord('S')) - keyboard_check(ord('W'));

//Restrictions
if x > room_width - (sprite_width / 2)
    {
    x = room_width - (sprite_width / 2)
    }
if x < sprite_width / 2
    {
    x = sprite_width / 2
    }
if y > room_height - (sprite_height / 2)
    {
    y = room_height - (sprite_height / 2)
    }
if y < sprite_height / 2
    {
    y = sprite_height / 2
    }

//Momentum
if ydir == -1
    {
    Umoment += 1
    }
    else
        {
        Umoment -= 1
        }
if Umoment > 12
    {
    Umoment = 12
    }
if Umoment < 0
    {
    Umoment = 0
    }

if xdir == -1
    {
    Lmoment += 1
    }
    else
        {
        Lmoment -=1
        }
if Lmoment > 12
    {
    Lmoment = 12
    }
if Lmoment < 0
    {
    Lmoment = 0
    }
  
if ydir == 1
    {
    Dmoment += 1
    }
    else
        {
        Dmoment -=1
        }
if Dmoment > 12
    {
    Dmoment = 12
    }
if Dmoment < 0
    {
    Dmoment = 0
    }
  
if xdir == 1
    {
    Rmoment += 1
    }
    else
        {
        Rmoment -= 1
        }
if Rmoment > 12
    {
    Rmoment = 12
    }
if Rmoment < 0
    {
    Rmoment = 0
    }

//Final Calculation
if xdir != 0 && ydir != 0
    {
    x += (Rmoment - Lmoment) * movespd * diag;
    y += (Dmoment - Umoment) * movespd * diag;
    }
    else
        {
        x += (Rmoment - Lmoment) * movespd;
        y += (Dmoment - Umoment) * movespd;
        }
The only potential problem I've found with this method so far is that the momentum system allows the player instance to go slightly outside of the room's boundaries, but I personally kind of like the way it manifests in-game for my project. The primary reason I'm sharing this is selfish in that I am asking if anyone else sees any flaws or obvious optimizations with the code. The secondary reason for this is altruistic in that I consider it worthy of sharing to other novices who might need guidance on their own 2D movement code (by the way, this is not meant to work for platformers at all).

Otherwise, if anyone wants to share anything else that could help improve the code in other ways, that would be very helpful to me and any potential lurkers out there (how could this code be modified by physics? how easy would it be to expand this system with more movement mechanics? is the system just a trash fire? etc). I built this from a cross stitching of tutorials and my own *adjusts glasses* genius, but I'm already pretty happy with the code as it is. I just thought I'd see if there was something in the later GameMaker tutorials or GML overview that I missed (I'll get to the rest soon, I promise) or if any of you had even better code and wanted to share.

Thanks to anyone that responds with anything other than rudeness, and I apologize if I'm irritating anyone here :D
 
C

Corablue

Guest
I'm a little tired to go through the movement code right now, but your restriction section can greatly be simplified.

Code:
//Restrictions
x = clamp(x, 0 + sprite_width/2, room_width - sprite_width/2);
y = clamp(y, 0 + sprite_height/2, room_height - sprite_height/2);
If you want to be able to go slightly outside the room like you mentioned, take out the +sprite_width/2 part. This code restricts you to the room completely. Clamp is really useful and forces your variables to stay between two values. I'm very sure your movement code can similarly be simplified, I might get to it another time. I hope this helps. :)
 
A

Aura

Guest
Welcome to the GMC~♫

You can similarly limit your Xmoment variables between 0 and 12 by using clamp():

Code:
Lmoment = clamp(Lmoment, 0, 12);
Rmoment = clamp(Rmoment, 0, 12);
Umoment = clamp(Umoment, 0, 12);
Dmoment = clamp(Dmoment, 0, 12);
 
C

Corablue

Guest
Okay. Apologies for the double post, but I tinkered for a few minutes. At this point after testing the movement is exactly the same except for a slight deviation in the acceleration and deceleration. You can tinker with that if you think it takes too long now.

Code:
--Create--
///Variables

diag = 0.707
movespd = 1
maxspeed = 11
Xmom = 0
Ymom = 0
Code:
--Step--
///Player Movement

//Input
xdir = keyboard_check(ord('D')) - keyboard_check(ord('A'));
ydir = keyboard_check(ord('S')) - keyboard_check(ord('W'));

//Restrictions
x = clamp(x, 0 + sprite_width/2, room_width - sprite_width/2);
y = clamp(y, 0 + sprite_height/2, room_height - sprite_height/2);

//Momentum
Xmom = clamp(Xmom, -maxspeed, maxspeed);
if xdir != 0{
    Xmom += xdir;
} else {
    Xmom += -sign(Xmom);
}

Ymom = clamp(Ymom, -maxspeed, maxspeed);
if ydir != 0{
    Ymom += ydir;
} else {
    Ymom += -sign(Ymom);
}

//Final Calculation
if xdir != 0 && ydir != 0
    {
    x += (Xmom) * movespd * diag;
    y += (Ymom) * movespd * diag;
    }
    else
        {
        x += (Xmom) * movespd;
        y += (Ymom) * movespd;
        }
You had a good thing going with linking horizontal movement to a single variable, why not control horizontal speed with a single variable also? You now have only 2 speed variables instead of 4. The code is a little simpler as well. If you need any explanation about how anything here is working I'd be happy to explain it.
 
P

PointBlankX79

Guest
Interestingly, the clamp command actually exhibits very similar behavior to my solution when it comes to editing the //Restrictions area. I copy-pasted your...

*opens new reply*

Well, it seems you were already testing it for me Corablue. You're very helpful! XD

-

Thanks Aura, glad to be here! :)
 
Last edited by a moderator:
C

Corablue

Guest
Interestingly, the clamp command actually exhibits very similar behavior to my solution when it comes to editing the //Restrictions area. I copy-pasted your...

*opens new reply*

Well, it seems you were already testing it for me Corablue. You're very helpful! XD

-

Thanks Aura, glad to be here! :)
Happy to help! XD
 
I

icuurd12b42

Guest
you go outside because you clamp before you move. move the clamping code to the end

And the simplest version of your code is this
//Input
xdir = keyboard_check(ord('D')) - keyboard_check(ord('A'));
ydir = keyboard_check(ord('S')) - keyboard_check(ord('W'));

//Momentum
if(xdir!=0 || ydir != 0)
{
a = point_direction(0,0,xdir,ydir);
Xmom+=lengthdir_x(movespeed,a);
Ymom+=lengthdir_y(movespeed,a);
Xmom = clamp(Xmom, -maxspeed, maxspeed);
Ymom = clamp(Ymom, -maxspeed, maxspeed);
}

//Move
x+=Xmom;
y+=Ymom;

//Restrictions
x = clamp(x, 0 + sprite_width/2, room_width - sprite_width/2);
y = clamp(y, 0 + sprite_height/2, room_height - sprite_height/2);
 
Last edited by a moderator:
C

Corablue

Guest
you go outside because you clamp before you move. move the clamping code to the end

And the simplest version of your code is this
//Input
xdir = keyboard_check(ord('D')) - keyboard_check(ord('A'));
ydir = keyboard_check(ord('S')) - keyboard_check(ord('W'));

//Momentum
a = point_direction(0,0,xdir,ydir);
Xmom+=lengthdir_x(movespeed,a);
Ymom+=lengthdir_y(movespeed,a);
Xmom = clamp(Xmom, -maxspeed, maxspeed);
Ymom = clamp(Ymom, -maxspeed, maxspeed);

//Move
x+=Xmom;
y+=Ymom;

//Restrictions
x = clamp(x, 0 + sprite_width/2, room_width - sprite_width/2);
y = clamp(y, 0 + sprite_height/2, room_height - sprite_height/2);
I figured vector functions might be a little too difficult to grasp for someone just starting out, but this is a possible solution. The problem with the code here is that since a 0 length vector still defaults to 0 degrees, you're going to continuously move right even when you have no inputs. Additionally there's no native deceleration here. But again, with some tweaking it's a possible solution.
 
I

icuurd12b42

Guest
Yeah, I forget the if(xdir!=0 || ydir != 0). updating

I dont think it'll be too difficult to grasp since he's halfway there with the xdir and ydir fetch
 
P

PointBlankX79

Guest
Happy to help! XD
The moment I realized exactly how sign and clamp worked together in that code, I was all "Welp, obviously this guy's John Carmack in disguise." (I'm being a bit hyperbolic, of course but still lol)

-

Thanks for the reply icuurd12b42! You're all helping so much, but I definitely have tons more to learn. I think I'll spend a little bit more time in the tutorials before I post something else in this manner :)

(I'll definitely see what I can pick up from your code too)

To be honest, I was getting burned out near the end of building that 4-way breakout game (I felt the tutorial was a little lacking, and it wasn't really my project, sooo...). I started grabbing random bits of knowledge from YouTube, the forums, the GML overview, and so on. My previous knowledge mostly comes from making text adventure games on a TI-83, so I'm learning a ton every moment

[2nd edit: I forgot to clarify that the calc uses x and y coordinates for many draw calls, and I did dabble in "cutscenes" (still pics interrupted by text) which is why I'm already familiar with them.]
 
Last edited by a moderator:
C

Corablue

Guest
The moment I realized exactly how sign and clamp worked together in that code, I was all "Welp, obviously this guy's John Carmack in disguise." (I'm being a bit hyperbolic, of course but still lol)

To be honest, I was getting burned out near the end of building that 4-way breakout game (I felt the tutorial was a little lacking, and it wasn't really my project, sooo...). I started grabbing random bits of knowledge from YouTube, the forums, the GML overview, and so on. My previous knowledge mostly comes from making text adventure games on a TI-83, so I'm learning a ton every moment.
Gal actually, but I've gotta be modest here, I'm struggling with teaching myself fragment shaders right now. Definitely no John Carmack. Teaching yourself through experimentation is really the best way to learn anything if you don't have an actual instructor handy. Keep at it. My first game ever was also a text adventure, just on a UNIX machine in college. :D
 
P

PointBlankX79

Guest
Gal actually, but I've gotta be modest here, I'm struggling with teaching myself fragment shaders right now. Definitely no John Carmack. Teaching yourself through experimentation is really the best way to learn anything if you don't have an actual instructor handy. Keep at it. My first game ever was also a text adventure, just on a UNIX machine in college. :D
Sorry for the misgender there, I'm still guilty of using 'he' pronouns as a default, trying to replace those with neutral pronouns. But yeah, awesome to hear, and thanks for the encouragement :)
 
I

icuurd12b42

Guest
It's true there is a lot to learn when making game, much more than a regular programming job would ever expose a programmer to.
 
1

12cats1housePart5

Guest
Okay. Apologies for the double post, but I tinkered for a few minutes. At this point after testing the movement is exactly the same except for a slight deviation in the acceleration and deceleration. You can tinker with that if you think it takes too long now.

Code:
--Create--
///Variables

diag = 0.707
movespd = 1
maxspeed = 11
Xmom = 0
Ymom = 0
Code:
--Step--
///Player Movement

//Input
xdir = keyboard_check(ord('D')) - keyboard_check(ord('A'));
ydir = keyboard_check(ord('S')) - keyboard_check(ord('W'));

//Restrictions
x = clamp(x, 0 + sprite_width/2, room_width - sprite_width/2);
y = clamp(y, 0 + sprite_height/2, room_height - sprite_height/2);

//Momentum
Xmom = clamp(Xmom, -maxspeed, maxspeed);
if xdir != 0{
    Xmom += xdir;
} else {
    Xmom += -sign(Xmom);
}

Ymom = clamp(Ymom, -maxspeed, maxspeed);
if ydir != 0{
    Ymom += ydir;
} else {
    Ymom += -sign(Ymom);
}

//Final Calculation
if xdir != 0 && ydir != 0
    {
    x += (Xmom) * movespd * diag;
    y += (Ymom) * movespd * diag;
    }
    else
        {
        x += (Xmom) * movespd;
        y += (Ymom) * movespd;
        }
You had a good thing going with linking horizontal movement to a single variable, why not control horizontal speed with a single variable also? You now have only 2 speed variables instead of 4. The code is a little simpler as well. If you need any explanation about how anything here is working I'd be happy to explain it.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Awesome information, this helps me understand how game maker comprehends movement. I have a question that may be kind of loaded, I hope you or someone can help me out with it.

- My question is why does this work? I understand what the create event and step events do, but how does the game world understand what line of code to run, or when it is appropriate to accelerate/decelerate movement if it is constantly checking all lines of code? I'm having a difficult time understanding the mechanics conceptually. ---- I admit that I am a Game Maker beginner, but I have some experience with 4 other programming languages.
 
Last edited by a moderator:
1

12cats1housePart5

Guest
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Awesome information, this helps me understand how game maker comprehends movement. I have a question that may be kind of loaded, I hope you or someone can help me out with it.

- My question is why does this work? I understand what the create event and step events do, but how does the game world understand what line of code to run, or when it is appropriate to accelerate/decelerate movement if it is constantly checking all lines of code? I'm having a difficult time understanding the mechanics conceptually. ---- I admit that I am a Game Maker beginner, but I have some experience with 4 other programming languages.
I figured it out :D
 
Top