>> Download the project used in this tutorial here <<
Introduction
Though this tutorial is mainly for beginner, you are expected to have some basic knowledge of Game Maker. I’d recommend you to read Derek Yu’s Game Maker tutorial for beginner first. Follow his great tutorial up to chapter 2 or 3 should get you ready.
Making your character
Last time we manage to able to create our main game GUI. Now, it’s time that we put our character that represents our player into the game field.
First of all, we need to find a graphic to represent the player character. This can be anything, really. But in this tutorial, I’ll use this sprite as our player representation.
Pixel Ship by Squirrelsquid
Though this is a gif file and don’t really need to add it externally to make the transparency work, we’ll just do that to keep the consistency here. Feel free to do whatever you like though: D
Ok, first of all go to your game folder again. Inside the dat/img folder, create a new folder call ‘player’. This will be used to store any graphics related to the player ship. Put a graphic that you’d like to represent the player inside that folder.
Then, go to our load_graphics script, and add these lines.
| //LOAD PLAYER
global.spr_player = sprite_add_alpha(“dat/img/player/paxship_01.gif”,4,false,false,16,16); |
Alternatively, if you don’t want to type all those global prefix every time you refer to a sprite, you can also do the following:
- Create a new sprite in GM, make it blank and untick the transparent option.
- Name it sprPlayer
- Then use this script instead of the above one
| //LOAD PLAYER
sprite_replace_alpha(sprPlayer,”dat/img/player/paxship_01.gif”,4,false,false,16,16); |
The result of both methods is the same, loading a graphic and stores it to some variable. The first method store it in global.spr_player while the second method replace sprPlayer sprite’s graphic with the one you load. If you want a auto highlight in the script editor, the second one should be a better way to go. In this tutorial, I’ll go with the second one anyway: P
Next step is to create a player object. We’ll call this object objPlayer. Now, assign a sprite to this object. You can do this by clicking on the icon on the right in the sprite panel. Once clicked, you should see a dropdown list and you can choose sprPlayer from there.
If you assign the sprite to global.sprPlayer, apparently this is not going to work. You can assign the sprite by adding a creation event. And inside that event you can add an action Execute A Piece Of Code which is in the control tab and is the first icon in the Code group. Drag it and drop it into your action box, double click on it to add some script.
| //Assign sprite to objPlayer
sprite_index = global.sprPlayer |
Of course, even if you use the second method, you can still do this and no need to mess with the dropdown box. Just replace global.sprPlayer with sprPlayer and it will work the same way. Basically what we are doing here is telling this object which sprite it’s going to use. Easy, eh?
Now, go to the shmup_room and place the objPlayer somewhere on the screen. Then you can run the game and see how our lovely sprite works.
If you’re using the sprite I’m using, you’ll see that the sprite animated WAYYY too fast. Go back to your creation event and add these lines to your script.
| //Change the animation speed
image_speed = 0.4 |
Of course, you can adjust this to fix your need. Negative number will reverse your animation, however.
Move your character
The player character won’t do any good if we cannot control them. Now, it’s time to work on more codings!
First of all, we need to initialize all the variables that the player need to have for the movement part. In order to do this, we go back to objPlayer’s creation event and add these lines to the script ( or add a new piece of script if you don’t already have one)
| //Player parameter initialization
normal_speed = 5 focus_speed = 2 is_focus = false is_move_vert = false is_move_hori = false move_speed = normal_speed |
Here are some explanations of each variable.
- Normal_speed and focus _speed should be self-explanatory. The speed that we will be using will be move_speed, but move_speed will refer to normal_speed or focus_speed, depending on the player’s state.
- Is_focus is used to determine whether the player is now in the focus state or not. By focusing, I mean the state of holding SHIFT button in Touhou to slow down the movement.
- Is_move_vert and is_move_hori is used to tell the program whether we are moving horizontally or vertically. This will also be used to calculate the movement later on.
Next step is to code the movement control part. Since this code will be called every frame, it is only logical to put it somewhere that will be called every frame, and that somewhere is inside our Step event.
So, create a step event in objPlayer and add Execute A Piece of Code action to it. Add these lines of script to let your ship movable!
| //Check and control player movement
is_move_vert = false is_move_hori = false dx = 0 dy = 0 divider = 1.0; //Check which speed to use if(keyboard_check(vk_shift)) { is_focus = true; }else { is_focus = false; } if(is_focus == true) { move_speed = focus_speed } else { move_speed = normal_speed } //Check differences in x and y coordinate according to key pressed. //Check differences in x and y coordinate according to key pressed. if (keyboard_check(vk_up)) { dy = -move_speed; } if (keyboard_check(vk_down)) { dy = move_speed; } if (keyboard_check(vk_left)) { dx= -move_speed; } if (keyboard_check(vk_right)) { dx = move_speed; } //Check movement orientation if (keyboard_check(vk_up) or keyboard_check(vk_down)) { is_move_vert = true; } if (keyboard_check(vk_left) or keyboard_check(vk_right)) { is_move_hori = true; } //If move diagonally, then we need to divide the distance in x and y by square root of 2. if( is_move_vert == true and is_move_hori == true ) { divider = sqrt(2); } x+=dx/divider y+=dy/divider |
Ok, that was the longest code we have so far, but it isn’t as scary as it looks like. I’ll go over each section of the code step by step to explain
| //Check and control player movement
is_move_vert = false is_move_hori = false dx = 0 dy = 0 divider = 1.0; |
There is nothing much in this part. Basically we reinitialize all the required variables every frame. This is because the movement can change any moment. The dx and dy variables refer to the distant of the ongoing movement. That mean, if dx equals to 5, we will move 5 pixels to the right. Divider is there to normalize the diagonal movement, which you will see later on.
| //Check which speed to use
if(keyboard_check(vk_shift)) { is_focus = true; }else { is_focus = false; } if(is_focus == true) { move_speed = focus_speed } else { move_speed = normal_speed } |
This code is pretty self-explanatory. If you press shift, then you’re in focus mode. And if you’re focus, then the move_speed will refer to focus_speed, otherwise it will refer to the normal one.
| //Check differences in x and y coordinate according to key pressed.
if (keyboard_check(vk_up)) { dy = -move_speed; } if (keyboard_check(vk_down)) { dy = move_speed; } if (keyboard_check(vk_left)) { dx= -move_speed; } if (keyboard_check(vk_right)) { dx = move_speed; } |
And this is the part that calculates the distant that your character will be moving. If you press up, then you’ll be moving upward with the distant of whatever move_speed is currently refer to.
However, if you do just this and not the next section of the code, there will be a mistake in diagonal movement. Why, you may ask? You can see the reason from this link here ->http://www.analyzemath.com/Trigonometry_problems/special_triangles.html
As we can see, moving upward a pixel and moving rightward a pixel, does not mean you are moving diagonally with the same number of pixels. It turns out that you are actually moving diagonally pixels, which is more than you actually need to move! So what do we do? Simple. We’ll check that if there’s a diagonal movement, we will divide the distance by before moving. And this is exactly what the next section of code does.
| //Check movement orientation
if (keyboard_check(vk_up) or keyboard_check(vk_down)) { is_move_vert = true; } if (keyboard_check(vk_left) or keyboard_check(vk_right)) { is_move_hori = true; } //If move diagonally, then we need to divide the distance in x and y by square root of 2. if( is_move_vert == true and is_move_hori == true ) { divider = sqrt(2); } x+=dx/divider y+=dy/divider |
As we can see, we first check to see whether both is_move_hori and is_move_vert are true true. If they are, that means we are moving both horizontally and vertically, which is moving diagonally. Then we change the value of divider from 1 to sqrt(2)
The last two lines are very easy. We then add the displacement to the current x and y position, by divided them by the divider first in order to normalize the diagonal movement.
Now run the game and you should be able to control your ship with the keyboard arrow. Holding shift while moving should slow down your ship
Adjust the boundary and depth
You should notice something funny’s here. You can go over the GUI! And that is not good :O Now, let’s do something about that, shall we?
First of all, the reason our ship is drawn over our GUI is because it is at the same depth as the GUI. If the instances have the same depth value, the newer ones will be drawn over the older ones. However, we want to GUI to always be above the player, and we can do this by adjust the depth value of the objGUIFrame object. Double click the object and you should see Depth value on the left. For safety sake, I’ll suggest you to use something like -100, in case there are other objects that need to be drawn over the player ship but should be covered by the GUI as well ( namely enemy bullets
)
Run the game again and you should see that once we move out of the play field, we will be covered by the GUI and thus cannot see the ship. Still, this is not desirable! We don’t want the player to move out of the playing field at all.
In order to do this, we have to determine the boundary of the playing field. This is an easy task, as we can see from the picture below.
As we can see, the left most that our ship can go is 32 and the right most is 32 + 385 = 417, and you can do the similar calculation with the topmost and the bottommost. However, it isn’t really wise to hard code these numbers into the game, since we might change it later. However, these kind of variables aren’t really changing during the play, hence it would be better if we make them constant.
And yes Game Maker has this feature for us! Double click on Global Game Setting and click on the Constant tab. Once you see the constant variable editor, enter each field like the picture below.
And then when you type FIELD_X or FIELD_Y in the script, Game Maker will automatically highlight those words for us so we know that they constant.
Now it’s time to put these constants into good use. Go to our objPlayer’s step event, and add this to the bottom.
| //Keep player inside the playing field
if( x > FIELD_X + FIELD_WIDTH) x = FIELD_X + FIELD_WIDTH if( x < FIELD_X) x = FIELD_X if( y < FIELD_Y) y = FIELD_Y if( y > FIELD_Y + FIELD_HEIGHT) y = FIELD_Y + FIELD_HEIGHT} |
This code will make sure that if the player ever out of field, their position will be reset to the boundary position. Now, run the game and you should be able to move your character freely but limited to inside the game play field.
And that’s it for this chapter. Until next time.












Recent Comments