Game Maker Spaceship Engine Names
Motion is critical to just about any video game. Nearly every game has moving things in it, and how they move is a vital part of the game. Learning how to program motion and control it effectively is one of the most important parts of a successful game. There are a number of possible approaches to handling position and movement.
May 02, 2017 In this video, I give you an overview and rundown of everything that is included in my spaceship generator asset, as well as how to use it. Any questions, comments, or feedback is appreciated. Here the list of all functions in Game Maker. See Category:Functions for all functions in this Wiki. List of all functions Edit. MCIcommand; abs; actionanotherroom; actionbounce; actioncdpause; actioncdplay; actioncdplaying; actioncdpresent; actioncdresume; actioncdstop; actionchangeobject; actioncolor; actioncreateobject.
Learning how these work will help you make better games. This isn’t absolutely everything there is to know about motion, but it’s a great overview to start with, and covers everything I’ve learned with respect to motion in GM:S. Position Variables: x, y The current x and y coordinates of the instance. These are in reference to the absolute x and y coordinates in the room.
The left-top corner of the room is (0,0), and the right-bottom corner of the room is (roomwidth, roomheight). Coordinates outside the room are valid locations — objects don’t automatically cease to exist or stop functioning just because they are outside the room. Indeed, they continue to exist and function, unless you code them otherwise, and of course they can come back inside the room. Think of the room as the “stage” of a theater that the player views; the area outside the room is “off-stage”. Stuff still exists when it goes off-stage, and things can happen to that stuff. However, positions that lie outside the room will never be displayed in the game. The game will stop scrolling at the edge of a room, showing no space outside of it.
Xprevious, yprevious The former x and y coordinate of the instance, from the previous step. Comes in handy when you need to compare where an object is to where it was, or if you’re trying to handle collisions with high-speed objects (see below).
Xstart, ystart The x and y coordinates of the instance when it was created. Useful if you need to return an object back to where it started from.
You can also change the values to update the starting point (such as if the player reaches a new save point.) GML move functions There are a number of GML functions built in to GameMaker, whose names start with “move” that are good to be aware of. Movesnap(hsnap, vsnap) Moves the instance to the nearest position in the room, aligned to an invisible grid of “cells” of a size defined by the hsnap and vsnap arguments. This is pretty easy to understand. Let’s say you want to base your game off of a grid of 32×32 pixel cells. You want your instances to align to this grid. If an instance is at a position such that instance.x and instance.y are both mulitples of 32, then it is aligned to the grid. If the instance is not aligned to the grid, this function will move the instance to the nearest location that is a grid intersection.
A common problem you may encounter with this function is if you have a grid within the room but that does not take up the entire room. Say you have a chess board in the room, but there is a border around the chess board. You want cells in the invisible grid to align with the squares of the chess board, but because of the border, there’s an offset because the border is not a width that aligns to the grid. To adjust, you simply need to offset the positions of the instance after calling movesnap. Movesnap ( 32, 32 ); x += borderx; //borderx and bordery must be defined by the programmer. Y += bordery; movesnap(32, 32); x += borderx; //borderx and bordery must be defined by the programmer. Y += bordery; Keep in mind, too, that the instance’s sprite origin can confuse the location where the instance is being drawn.
If the origin is centered, the instance will appear centered on the grid intersection (like a stone in Go) rather than centered inside the grid cell (like a chess piece). The results from movesnap are based on the instance’s x and y, so how it ends up looking will depend on the instance’s sprite’s origin. Moverandom(hsnap, vsnap) The moverandom function moves the instance to a random location in the room that is an intersection on the invisible grid defined by the hsnap and vsnap arguments. As with movesnap, moverandom has the same issues to be aware of with grid offset and sprite offset. Movetowardspoint(x, y, speed) This function sets the speed and direction of the instance so that it will move towards the point (x, y) as defined by the first two arguments.
It’s convenient in that the function figures out the direction to travel for you, based on the spatial relationship between the calling instance and the destination point. Movecontactall(dir, maxdist), movecontactsolid(dir, maxdist) Moves the calling instance in direction dir, up to maxdist pixels, or until the instance contacts another instance. This does not set a speed, so it is using the position assignment method to move the instance. If the moving instance does encounter an obstacle, it stops just short of triggering a collision.
The movecontactsolid function works only with objects that have the solid property. This is a very useful function for platformer games.
Movebounceall(advanced), movebouncesolid(advanced) Calling this function causes the object to bounce when it encounters another instance (or solid instance) in the game. The instance will only bounce off of other instances if they have a sprite or mask index. The bounce function calculates the new direction and applies it to the instance. If the advanced parameter is set to true, the bounce direction is calculated with greater precision. This requires greater processing and can slow the game down if too many instances are using it. Realistic bouncing is probably better done using the new Box2D physics. This movebounce is an older GML function that has been around in GameMaker since long before the new physics engine was added.
You can still use this function if you don’t want to bother with the full physics system. Moveoutsideall(direction, maxdist), moveoutsidesolid(direction, maxdist) These two functions are the inverse of movecontactall and movecontactsolid. They are intended for when two objects are in collision, and can be useful to resolve a collision event so that the collision event does not happen automatically again during the next step.
They work by relocating the calling instance up to maxdist pixels away, in direction, until a collision condition is no longer present. If no value is provided for maxdist, GameMaker will assume a value of 1000 pixels. The catch here is that the instance will move until it is outside of any collision condition. So if the moveoutside function is triggered by a collision with one instance, and moving just outside of collision with the first instance would result in a collision with another instance, the calling object will continue to move until it is positioned outside of any and all collisions, or maxdist is reached. This is possibly not desirable, since you may need the collision with the next instance to be triggered as well.
In this case, the best thing to do is set maxdist to a small value, such as the calling instance’s sprite offset. The moveoutsidesolid function can be useful to get an object out of collision condition with solid objects. One of the annoying things about solid objects is that when they overlap (collide) with an object, they prevent the object from moving, causing it to become stuck or embedded inside the solid object. An object with a speed and direction will not move through a Solid object, and if it is in collision with a Solid object, it cannot move by its speed and direction vector any longer. The only way to move it is by position assignment. The moveoutsidesolid function does the necessary calculations to place the calling instance just outside of the collision mask of the Solid object.
A lot of GameMaker developers avoid using the Solid property entirely, opting instead to handle objects which they wish to behave as though they were solid using their own code. Movewrap Mentioned here for completeness, but discussed in depth in the section. Vector variables: In GameMaker, a motion vector is a speed (in pixels per step), combined with a direction. Direction The current direction of motion of the instance, in degrees. 0 = right/”east”. 90 = up/”north”. 180 = left/”west”.
270 = down/”south”. Direction model for Box2D Physics You’ll need to compensate for this if you ever need to convert a GM Object’s direction to a Box2D fixture’s direction. GameMaker direction = Box2D direction + 90 Box2D direction = GameMaker direction – 90 Related to direction is imageangle, which is a built-in GML variable that is used to rotate the sprite belonging to an instance.
If you only change an instance’s direction, it will move in that direction but the sprite will continue to be drawn with its orientation unchanged. If you want the sprite to rotate, you can set imageangle = direction.
This is why it is usually best to draw your sprites so that they face right, so that imageangle = 0 looks correct for direction = 0. Speed The speed in pixels per step in the current direction. Negative = moving “backward”; positive = moving “forward” with respect to the current direction. Hspeed The horizontal component of the instance’s speed, in pixels/step. Negative = moving left; positive = moving right. Vspeed The vertical component of the instance’s speed, in pixels/step. Negative = moving up, positive = moving down.
Up being negative often seems counter-intuitive to new programmers, since “up” should be “higher”. Just remember that the room coordinate system starts with its origin at top left, at (0,0), and counts upward to positions that are vertically down from the origin. Tip: speed, hspeed, and vspeed The values of speed/ direction, hspeed, and vspeed are interdependent, and are updated automatically by the game each step when one of their values changes. For example, if you set and speed = 8 direction = 0, your instance will be moving to the right at a speed of 8px/step. If you look at the value of hspeed, it will also be 8, even though you never directly set hspeed. This means that hspeed and vspeed and speed are always accurate to the actual motion of the object in the game. This is very useful.
For example, if your instance is not moving at an orthogonal angle (eg, 0, 90, 180, 270), and you need to know the horizontal or vertical component of motion for some reason, without hspeed and vspeed, in order to know its precise horizontal or vertical speed, you would need to perform trigonometry functions in order to isolate the horizontal and vertical components of the object’s motion vector. But, thanks to hspeed and vspeed, this is already done for you, “for free.” One thing to note about this is that changes to hspeed or vspeed can change direction, but changes to absolute speed do not change direction. To illustrate this, take an instance in your game moving at speed = 8, direction = 0. It is moving 8px/step to the right. To reverse its motion, you could use either speed = -speed, or direction += 180. In the first case, you’ve reversed speed but in the other you’ve reversed direction.
Visually, the result is identical (unless the sprite’s imageangle is also updated, or you swap spritefacingright with spritefacingleft). If we watch the variables, we see that it’s possible to have negative speed, so that it’s possible to move “backward” at a negative speed, but that when hspeed or vspeed reverses, direction also reverses. An object with a negative hspeed will always have a direction between 90 and 270; positive hspeed, a direction between 0-90 or 270-360.
And object with a negative vspeed will have a direction between 0-180; positive vspeed, between 180-360. This can be easier to understand with the following demo. Your browser does not support iframes. Go to to experience the demo. Use the left/right arrow keys to increase/decrease hspeed.
Up/Down arrows to increase/decrease vspeed. W/S to increase/decrease absolute speed, A/D to increase/decrease direction. Watch how the values relate to each other as they change. Gravity Acceleration in a given direction (270 down) at a given rate. Gravity can be a little tricky to get right. We think of gravity in the real world as a force which attracts massive objects together. In GameMaker, it is just a vector, a force which adds speed in a given direction.The vector is added to the instance each step, so it can add up quickly and come to dominate the instance’s motion.
In the real world, we think of gravity as a force which affects everything equally, but in GameMaker, gravity is set on a per-instance basis. This means that you can set different forces and/or direction for each instance. This could be used, for example, to create MC Escher spaces in 2D where gravity works differently for each object, depending which surface they are standing on. Or for creating some objects that are affected by gravity while others are not. The official documentation recommends using a small value, such as 0.2. I often like to start with a small value, but add to gravity over time to give a more pronounced accelerating effect.
Over time the acceleration due to gravity can really add up, leading to very high speeds, which can lead to problems with collision detection (see below). Often it’s desirable/necessary to cap an instance’s speed with a “terminal velocity” so speed doesn’t get too crazy.
Spaceship Design Games
You can set a negative speed to gravity, which is equivalent to setting gravity in the opposite direction. Gravity is very useful as a component of jumping mechanics, or for ballistic trajectories of flying objects. You can also use gravity for more novel purposes, such as to simulate the force of a strong wind pushing against objects, blowing them away. Unfortunately, you cannot have multiple gravity forces acting on a single instance. (You can, however, write your own “pseudo-gravity” functions to do this.) Also, gravity does not have a location — it does not attract an instance to a particular point in the room, it just adds speed in the direction set by the instance’s gravitydirection. (You can fake a gravity toward some object or point in the room, if you update gravity’s direction each step, and use pointdirection(x, y, attractorx, attractory) Again, you can just write your own code to create this behavior if desired. Friction Deceleration, slowing the instance, until speed reaches 0.
Friction is useful for simulating slippery surfaces like ice, where an object shouldn’t stop immediately, or viscous surfaces, like mud, where constant effort is necessary in order to keep moving. Friction has no direction; by its nature it works in opposition to the present direction of the instance it is working on, by reducing its speed until it reaches 0. You can set negative friction, which is essentially the same as setting gravity in a direction which constantly matches the instance’s direction.
Techniques You can change the values of these functions in any mathematical way you can imagine. Understanding the math is important to getting the behavior you expected. Position assignment. Speed = min (maxspeed, speed + accel ); speed = min(maxspeed, speed + accel); Speed increases each step by accel pixels/step until maxspeed is reached.
Note maxspeed and accel are not built-in variables, and must be created and assigned values in the program. As you can see, most normal motion can be expressed through simple value assignment (the equals sign) or through addition or subtraction. Other math is possible, of course.
These numbers are just numbers, and you can perform any math on numbers. You can get some interesting effects using multiply, divide, exponents, square root, logarithms, trig functions, etc.
In many different ways to modify position, speed, or direction.Oftentimes it’s useful to multiply a base speed by another number to get a range of relative speeds for walking, running, or whatever. Linear interpolation and extrapolation with the lerp function One gml function that is very useful for movement is lerp, the linear interpolation function. Lerp(a, b, amt) returns a value between a and b that is interpolated by the amount (when amt is between 0 and 1).
Lerp can be used in many ways, usually it’s best to lerp iteratively each step, so in the Step event, or in an Alarm loop: lerp the position (x,y) coordinates of an instance, to smoothly approach a position: x = lerp(x, destinationx, percent); y = lerp(y, destinationy, percent); lerp the speed to smoothly accelerate or decelerate to a target speed. Speed = lerp(speed, desiredspeed, accl); lerp direction, to smoothly turn towards a desired direction. Direction = lerp(direction, desireddirection, turnrate); You can even use lerp to extrapolate rather than interpolate, by using a value greater than 1 for the amt argument. The help file provides a cool example that you can use to predict the position of an instance one second in the future based on its current hspeed and vspeed: futurex = lerp(x, x+hspeed, roomspeed); futurey = lerp(y, y+vspeed, roomspeed); This can be used to target where an object will be, assuming its speed and direction don’t change. You can replace roomspeed in the example above with the number of steps in the future you need. Other techniques Find the distance or direction GML provides a few functions that are useful for determining where things are, which can help you know where you want to go:. instancenearest(x,y,obj): returns the id of the nearest instance of the named object class to the point named at (x,y).
If you call a parent object, the function will return the nearest object that is of the parent class, or any of its descendants. instancefurthest(x,y,obj): returns the id of the most distant instance of the named object to the point named at (x,y). distancetopoint(x,y): returns the distance from the bounding box of the current instance to (x,y). Note that there is a subtle, crucial difference between the bounding box and the x,y position of the calling object (normally a point somewhere within the bounding box of the object’s sprite). distancetoobject(obj): returns the distance in pixels from the calling object to the nearest edge of the bounding box of the instance specified in argument0, or the nearest object specified if an object name is used instead of an instance. Again, there is a difference between the bounding box edge and the x,y position of the target instance. pointdirection(x1,y1,x2,y2): returns the direction (in degrees) from point (x1,y1) to (x2,y2).
pointdistance(x1,y1,x2,y2): returns the distance (in pixels) from point (x1,y1) to (x2,y2). Relative Positioning An instance’s x and y variables always refer to the absolute coordinates within (or sometimes outside of) the room. Oftentimes, though, it’s easier to think of a position as being relative to the position of some other instance. We don’t care where in the room something happens, we care that it happens exactly M pixels to the left and N pixels up from some object in the room, which might be anywhere. It’s easy to use the object of interest’s position as a reference point, by calling instance.x and instance.y, and then using simple math to offset an amount of room pixels relative to the instance’s position. Rather than using the instance’s x and y position, it’s also possible to use the bounding box of the instance’s sprite:.
instance.bboxtop. instance.bboxbottom. instance.bboxleft.
instance.bboxright You can also use the sprite’s height and width:. instance.spritewidth. instance.spriteheight Finally, you may want a position that is some distance from a point, in an arbitrary direction.
To do this you can use trig functions;in GML, the trig functions all take the angle argument in radians, and direction is in degrees, so you have to convert direction to radians using degtorad. Update: this is changing with GM:S 1.3, which will introduce degrees-based trig functions. As well, the imageangle variable is also degrees. x - distance. sin(degtorad(direction)). y + distance.
cos(degtorad(direction)) GM:S 1.3 on:. x - distance. dsin(direction);.
y + distance. dcos(direction); Actually, in GameMaker, there is a pair of functions that do this math for you. I included the trig functions method to expose the underlying math, and to make the example more relevant to other languages and frameworks, but if you’re using GameMaker, you can use these built-in functions instead:.
lengthdirx(length, direction). lengthdiry(length, direction) When using the lengthdir functions, it expects the direction argument in degrees, so you don’t need to convert it to radians. Sprite direction and Motion direction are independent If you change an instance’s direction, it will move at speed in the new direction. Note however that the instance’s sprite still points in the same orientation as before. Unless your sprite is completely symmetrical, this probably doesn’t look right. In the Lite edition of GameMaker, you can use the sprite editor to create a rotation animation, and then every step in the game you can update the imageindex for the object to match the correct facing image in the sprite.
This is a tedious and limited approach, since it uses up the sprite’s animation capability to perform the rotation, eliminating the possibility of performing other animation. In the paid editions of GameMaker, you can rotate the sprite in code, and make it point in the direction of motion: imageangle = direction; This works fine if all you need is for your sprite to rotate to point the direction of the instance’s motion. It’s a great approach to take for top-down spaceship or car games. This approach is not right for all games, though. For example, the original Legend of Zelda had separate views of each side of each character: front, back, left, right. These were not simple rotations of the same image, but rather were different images depicting the character from the front, side, side, or back. There are a lot of ways to implement a 4-sprite system.
You could use a single object, and just change which sprite is drawn based on the direction the object is facing. Or you could create a group of objects, each one representing the character facing a given direction. The four-object approach sounds like more work and more complexity, but it actually allows you to keep each object much simpler. To start out, it’s optional, but handy to create constants to make your code more legible. If your goal is simply to make a ball that will bounce, that’s not too hard. There are many ways to do it, but is probably the easiest.
In general, the GameMaker documentation available at is the best place to start when you want to learn how to do something. There’s also good tutorials built into GM:S, if you look at the projects in the Tutorials tab you can see clearly how many different types of games are built.
If you’re new to GameMaker, they’re the best place to start. If you actually want to draw a line that traces the path the ball takes when it bounces, that’s a different matter. Your best bet would be to ask your question on the, in the Questions & Answers forum. If you haven’t yet, try asking this on the.
Lots of people will help. This could be tricky if you need to calculate the motion with each step, but could be very easy to do if you use Paths, which I didn’t cover in this article. The easiest non-paths way to do it would be to provide an initial motion to the projectile, by setting speed and direction, and give the projectile some gravity. A linear velocity plus downward acceleration due to gravity will result in a parabolic arc emerging naturally, although to get it to be positioned exactly where you want it, at the speed you want it, could take some trial and error tweaking. Thanks so much for the kind words. When I was learning the basics in GameMaker, I found that as I learned things, I'd forget them again if I didn't use them all the time.
After a while, I realized that taking notes and explaining to myself how stuff worked helped a lot — as much as reading the Help file, if not more so. And I realized that this had value beyond simply writing it for myself, so I put it up on my website to share with people, hoping it could benefit many.
To this day, this is the most popular thing I've written, and it's always good to hear from people who found it useful.