Gw Temp

Menu

Tutorial - 'RPG Basics in GameMaker' by Kuro

An item about Gamemaker posted on

Blurb

A well written RPG tutorial for Game Maker. This is about the basics of RPG making in Game Maker. Take a look!

Body

Rpg Basics in Game Maker
By Kuro

Man I'd never thought I'd be doing this again. Lately, I've been working in Game Maker because 1.) I'm bored and 2.) I lost my copy of MSVC. So anyway, I think I've gethered enough knowledge to put together a simple RPG engine. Hopefully after reading this, you'll be able to get the gist of it and try one yourself. They're not too difficult.


Part I: The Setup

Okay, if you've been using D&D (Drag and Drop, e.g. the icons in the object window) up to today, you're going to need to learn a bit of GML before you proceed any further. Everything I do in Game Maker is through GML code and believe me, its much better and more organized.

Let's start with the hero object. This is the main object the view will focus on, and it will need to be able to have user control and such. So go ahead and create two (yes, two) objects, one named 'Hero' and the other named whatever you wish. I suggest naming it your person's name in lowercase letters. With the object window open (your hero, not the 'Hero' object) select the 'Persistent' checkbox and make sure visible is checked. Now create these events: Create, Begin Step, End Step, and Draw. In the draw event, drag on a 'code' icon and in the edit box, type in this (copy and paste if you're lazy)

if(self.sprite_index != -1)
draw_sprite(self.sprite_index,self.image_single,self.x,self.y);

What this does is pretty obvious, but just to be sure, the code checks to see if the object has a sprite, and if it does, it will draw the current single image. It may seem a bit weird that I used self.image_single instead of self.image_index (and if it isn't weird then, whatever) but it allows for a bit more variety in your sprites and can actually eliminate a few standing sprites later on. Now move to your Create event and put this in.

self.move_horiz = 0;
self.move_vert = 0;
self.facing = "right";

self.talk = false;
self.menu = false;
self.action = false;

self.spd = 4;

Those are our State Variables, and they'll allow us to manipulate the sprite. Later on, you'll be able to add your own for cutscenes and special poses and such. For now, we need to get the basics down. In the Begin Step event, put this code in:

if(self.action){
if(keyboard_check(vk_left)){
self.move_horiz = -self.spd;
self.facing = "left";
}else if(keyboard_check(vk_right)){
self.move_horiz = self.spd;
self.facing = "right"
}else{
self.move_horiz = 0;
}

if(keyboard_check(vk_up)){
self.move_vert = -self.spd;
self.facing = "up";
}else if(keyboard_check(vk_down)){
self.move_vert = self.spd;
self.facing = "down";
}else{
self.move_vert = 0;
}
}

Okay, let me explain the above. The first thing the code checks is if the user has keyboard control over the hero. The self.action variable will be a toggle later on when we don't want the user to move the hero, like during cutscenes. Moving on, the code receives user input and when the directional arrows are pushed, variables are changed later for the State Machine. The move_horiz and move_vert keep track of which arrows you have currently pushed. The facing variable keeps track of the last direction you pushed, so when you let go of the arrow keys, the State Machine will know which direction you're supposed to be facing. Let's move on to the End Step event.


Part II: The Pitch

This is the main artery of the hero object, not quite the heart, but its still important. Check out this code.

if(global.action){
if(place_free(self.x + self.move_horiz, self.y))
self.x += self.move_horiz;
if(place_free(self.x, self.y + self.move_vert))
self.y += self.move_vert;

switch(self.facing){
case "up":
self.sprite_index = sprite_up_walk;
break;

case "down":
self.sprite_index = sprite_down_walk;
break;

case "left":
self.sprite_index = sprite_left_walk;
break;

case "right":
self.sprite_index = sprite_right_walk;
break;
}

if(self.move_horiz == 0 && self.move_vert == 0)
self.image_single = 0;
else
self.image_single = -1;
}

Whew, okay that's all that goes into the End Step event, but you'll be editing it later at your own leisure. Let me explain what you just typed or copied.

The first line checks to see if the global.action variable is true. (This works like the self.action variable, only this one can freeze sprite manipulation. Its just another security measure I put in so I have better control over my object.) If we do, then it checks to see if the object can move itself dependent on its move_horiz and move_vert variables. This is the main collision code here, and you probably will never need to use a collision event either, you just have to use solid objects for buildings and such.

The main secion of the code checks which way you were last facing and changes the sprite_index accordingly. Now this is a double-edged sword technique. While we have free-reign over the sprite directions, the code can get pretty bulky when you start adding your own special sprite poses. Also, if you haven't noticed already, whenever you're holding, lets say left-up, you'll always be facing up when you move until you let go of the up-arrow. The reason is because of the ordering of the Begin Step code. Now if we were to change it like so:

if(self.action){
if(keyboard_check(vk_up)){
self.move_vert = -self.spd;
self.facing = "up";
}else if(keyboard_check(vk_down)){
self.move_vert = self.spd;
self.facing = "down";
}else{
self.move_vert = 0;
}

if(keyboard_check(vk_left)){
self.move_horiz = -self.spd;
self.facing = "left";
}else if(keyboard_check(vk_right)){
self.move_horiz = self.spd;
self.facing = "right"
}else{
self.move_horiz = 0;
}
}

Then the opposite would happen and we'd always face left when we held left-up. Its really you're own choice on the way you'd want the character to face, so change your code up to the above if you want. Moving on, we have this code repeated in every case statement:

self.sprite_index = sprite_direction_walk;

The actual sprite index name you can change to match whatever you named your sprites, but that's how I usually name mine. Now zoom to the last bit of code. This checks if the sprite was actually moving at all and if it wasn't, then change the image_single variable to 0. (which should be a standing frame of your sprite) And in fact that if it was moving, set the variable to -1. And if you remember from your Draw event, I told the draw_sprite() function to use the image_single variable. Now you know why. So instead of making a standing frame for your sprite, you can just use your walking animation's first frame! The last thing you need to do is in the object window, click the Parent drop-down list and choose the Hero object I told you to make earlier. Now close this object and create a test room. We're almost done.

Part III: The Swing

Now in your test room, alter the size of your room to whatever you need. After that, click on the settings tab and click the creation code button. Now in the new window, type this:

global.action = true;
global.p1 = instance_create(some_x,some_y,name_of_your_hero); // replace some_x and some_y with your own numbers, as well as name_of_your_hero. Duh.
global.p1.action = true;

That's it! Now you can run your game, and with some satisfaction, you'll be able to move and everything! You can even put some solid objects in and watch as your hero can't run through them! When you're done being amazed, close your game and return to the Game Maker API; I still have a few more tips for you.

First off, the variable global.p1 is what I call my Hero Handle. It works like a pointer, for those who know c++, and it can allow you to manipulate your hero object just by accessing it like you normally would. If I wanted to cut off the player from using the keyboard, all I'd have to do is put the statement

global.p1.action = false;

wherever I needed to and voila! You're probably sick of reading all of this stuff, and I'm pretty tired of typing all of it, so let me wrap this tutorial up.

- In your game options, you may want to have 'Treat uninitialized variables as Value 0' marked. Its just a good habit of mine to do that since I often forget to initialize some variable in my eagerness to test my game.

- Remember when I told you to mark the persistent checkbox earlier. Well it comes into play when you create your hero. Chances are, you're going to want to create your hero somewhere else outside the room creation event. With that said, you should always do an !instance_exists(global.p1) check to be sure you're not creating your hero when he already exists!

- I haven't even gotten to the dynamics of Game Maker Rpgs like view manipulation and static backgrounds. Yeah, static backgrounds aren't tile-based since we're not on a tile system. They're like the backgrounds from Final Fantasy 7 and they're fun to do. But that's for a later date.


I hope this tutorial helped you in some way. Its a bit intermediate in my opinion but I tried to walk through every aspect of the basic hero object. I know I didn't cover the point of creating the Hero object, but to give you an idea, its for handling high-level functions of the hero that can be applied to every hero in the game. That's all I have to say about that. Oh yeah, one more thing. Boobies.


Kuro