Gw Temp

Menu

Tutorial - 'Making a professional-styled RPG menu in GameMake' by Guest

An item about Gamemaker posted on

Blurb

Need to improve that menu in Gamemaker? Then this is the tutorial for you!

Body

Creating a RPG style menu with Game Maker

This article will show a starter with Game Maker, how to create a menu system like those in FF7, FF10 and so on. Our menu will show character profiles on the left margin of the screen while the other half will show the items held. A margin along the top of the screen will be inserted with some choices, like use item or disregard item. Before we start you should know, all my inserted quotes will be in (), got it?

First will define all profile slots and items slots. We want to use global variables for all, they're safer, trust me. Besides, we want to change there value from any instance (object).

global.ProfileSlotA = sprNoProfile; (use an unseen sprite to represent emptiness. We want to use a sprite because we'll be using this variable to draw it's value to the screen with the "draw_sprite" command. If the variable held a numeric value, an error would occur because "draw_text is used for that.)

global.ProfileSlotB = sprNoProfile;
global.ProfileSlotC = sprNoProfile;

No that we have our three slots defined (based on the fact you have a party of three), we'll create the item slots. You can make as many as you want, but for this tutorial or article I'll make five slots.

global.ItemSlot1 = "Empty"; (This value should be a string, since our items will have a string name and using that string name with an "if statement" we will draw the sprite, makes sense?)
global.ItemSlot2 = "Empty";
global.ItemSlot3 = "Empty";
global.ItemSlot4 = "Empty";
global.ItemSlot5 = "Empty";

global.NumberOfPotion = 0; (We also will make-up some items so we can set a "number of" variable. Basically, how many of that item does the party have.)

global.NumberOfGreenHerb = 0;
global.NumberOfCottonPanty = 0;
global.NumberOfDrive = 0;
global.NumberOfStimulant = 0;

Now create sprites that will represent each of your items. These sprites will be draw to the screen in our menu, and slots will only take up so much space. We want the menu neat so don't make these sprites too large, think about the item spacing or item slot spacing. I'll make my item sprites 100 x 50 and Hero profiles 100 x 100.

Create a room (1020 x 700 with full screen mode is best with Game Maker. Enable the views with this and set the view to 1020 x 700.) Give your room a respectful name, I'll call my menu room "MainMenu." (Menus can also be draw to the screen without creating a separate room to hold them, but I won't cover that here.)

Create an object that will be the "Draw" control for the menu and set it in the room. In the Draw event of the "Draw" controller, we'll start building. This is were the Mathematics come in.

I want to draw my character profiles on the left side of the screen, about 5 pixels or so from the edge. Slot A will be on top, below that slot B and below that one slot C. Lets say my Character profiles are 100 x 100 pixel in size (I'm basing this on the origin of the sprite being at the middle). When drawing a sprite to the screen, with it's origin being the middle, the x and y coordinates that mark the spot were the sprite will be drawn will also mark the center of the sprite. Example:

draw_sprite(sprHero1profile, 0, 510, 350);

If "sprHero1profile" was draw to the screen at those coordinates, it would be in the center of the screen because our room is 1020 x 700 and half of 1020 is 510 and half of 700 is 350. The origin of our 100 x 100 sprite is at the center, so "sprHero1profile" should be drawn in the center of the screen, but we don't want this, we want to draw it on the left about five pixels from the left edge of the screen. We will use the "built in" variables "view_left" and "view_top." If your room's view is set on view zero in the view settings than you will address that with the "view" variables. Example:

view_left[0];
view_top[0];

Now lets write the code that line-up our character profiles, but we'll be using the variables we created earlier.

draw_sprite(global.ProfileSlotA, 0, view_left[0]+55, view_top[0]+200);

This is the code for our first profile, let me break it down.

Global.ProfileSlotA is a transparent sprite right now, because we assign it the invisible sprite earlier, right? At some point in the game when a party is assembled, global.ProfileSlotA, B and C will be given the real profile values, like "sprHero1profile."

Lets say our "Slot variables" are holding the real values, Hero1 in slotA , Hero2 in slotB and so on. Our code above will draw "sprHero1profile" at position view_left[0]+55 and view_top[0]+200. View_left[0] is simply saying, from the left side of the screen the sprite's x position will be 55 pixels to the right. Given the fact our "sprHero1profile" is 100 x 100, that means since the origin of the sprite is it's center, fifty pixels are on the left of the center and fifty pixels are on the right of the center, that gives us our 100 pixel width, with me? Since we are drawing our sprite 55 pixels from the left, our sprite extends back to the left 50 pixels from it's origin thus leaving a space of 5 pixels from the left side of the screen, got that?

Our view_top[0]+200 is just like the "view_left[0]" but it's setting the y origin value of our sprite. View_top[0] is to top of the screen so when using addition, we are actually moving down. Y plus in Game Maker is down while Y minus is going up, so view_top[0]+200 sets our y origin position at 200 pixels from the top of the screen going down (Again, this is based on sprites with centered origins. If your sprites' origins are not centered, calculations will be different or if your sprites are larger than 100 x 100). Given the fact our "Hero Profiles Sprites" are 100 x 100, we should end up with 150 pixels of free space at the top of our screen because the view_top[0]+200 place our sprite's y position at 200 pixels from the top of the screen and our sprite is extending fifty pixels back up towards the top. The sprite's height is 100, the origin is at 50, so when placed at 200 pixels from 0 (from the top) the top of the sprite will land at 150 pixels from the top and the origin of the sprite will be at 200, get it? So.......Lets sum it up.

draw_sprite(global.ProfileSlotA, 0, view_left[0]+55, view_top[0]+200); (The top of the "first profile" will be 150 pixels from the top of the screen and the left side of the profile will be 5 pixels from the left.)

Now lets draw in our other two profiles. Given the fact "sprHero1profile" y origin is at view_top[0]+200 (200 pixels from the top of screen), that means the bottom half of the sprite (half below y origin) is extending 50 more pixels down because our sprite height is 100. To draw "sprHero2profile" below "sprHero1profile" with a spacing of 5 pixels, we draw it 105 pixels lower....why you ask? SprHero1profile y origin is at the center of the 100 x 100 sprite (practically cutting it's height in half) and that center has been placed at 200 pixels from the top of the screen with the code, view_top[0]+200. SprHero1profile extends fifty more pixels from origin, downward. Two hundred and fifty (250) pixels mark the bottom of "sprHero1profile." Therefore, "sprHero2profile" drawn at view_top[0]+300 will place the top of it's sprite meeting with the bottom of "sprHero1profile." Remember, "sprHero2profile" origin is at 300 but the top half of that origin is fifty (100 height, remember?) so it's extending upward 50 from the 300 which places the top at 250, which is the bottom of "sprHero1profile." To avoid this, simply use view_top[0]+305 with the y coordinate when placing "sprHero2profile." That will create a space of 5 pixels. You might want more than this so go ahead and add more, but keep in mind the screen's height is only 700 and you want to keep spacing even for neatness.

(This is off the topic a little, but I just have to share this. When using a 640 x 480 resolution with Game Maker, in full screen mode, the screen is covered with the scene, but what you get is larger pixels in your pictures not to mention less in the view. So why not go for small pixels, more scenery in the view and a full screen? The magic number is 1020 x 700! Anything larger than this usually scales your scene down too small, so don't increase the 1020 or 700. Make sure full screen mode is selected and it's at 100. Never use exclusive mode!!! If you want to see some screenshot proof of this, email me at nug1978@aol.com. Now back to this tutorial or article....which ever one beeeeooochhhh! Just kidding.)

Finish drawing your three hero faces to the screen. My coding looks like this:

draw_sprite(global.ProfileSlotA, 0, view_left[0]+55, view_top[0]+200);
draw_sprite(global.ProfileSlotB, 0, view_left[0]+55, view_top[0]+305);
draw_sprite(global.ProfileSlotC, 0, view_left[0]+55, view_top[0]+410);

This creates a spacing of 5 pixels between the profiles going vertically. Now we'll jump to the items.

My "Item Slots" (referring to the space they take up) are 100 x 50, because my item sprites are 100 x 50 (sprite size is slot size). My item sprites' origins are centered, like wise mate. You can begin your item columns anywhere you like, but just for this article, I'll start item slot "row 1" going down the center of the screen. Since we have that 150 pixel margin at the top of the screen preserved for other menu selections, we don't want to draw our slots in that area. Our slots' height is 50, so a centered origin cuts it in have, leaving 50 pixels of sprite below it and above it. Before we draw slots, lets look at the "if" statement that will handle the task.

Our slot global variables hold a string value, global.ItemSlot1 = "Empty." We can't use the "draw_sprite" function with this. Instead, we use an if statement to check the value in each slot then draw the appropriate sprite to the screen. Such coding looks like this:

if (global.ItemSlot1 = "Potion"){
draw_sprite(sprPotionItem, 0, view+left[0]+560, view_top[0]+175);
}
else{
if (global.ItemSlot1 = "Stimulant"){
draw_sprite(sprStimulantItem, 0, view+left[0]+560, view_top[0]+175);
}
else{
if (global.ItemSlot1 = "Drive"){
draw_sprite(sprDriveItem, 0, view+left[0]+560, view_top[0]+175);
}
else{
if (global.ItemSlot1 = "Cotton Panty"){
draw_sprite(sprCottonPantyItem, 0, view+left[0]+560, view_top[0]+175);
}
if (global.ItemSlot1 = "GreenHerb"){
draw_sprite(sprGreenHerbItem, 0, view+left[0]+560, view_top[0]+175);
}
else{
if (global.ItemSlot1 = "Empty"){

}

}
}
}
}

This code checks to see if an item is in slot 1 and if yes, it draws it to the screen or it draws nothing if the slot is "Empty." The code is written to check all item possibilities. The same code will be written for Item Slots 2, 3, 4 and 5. Just change the "global.ItemSlot1" to global.ItemSlot2 and so forth. It's faster to just copy and paste the code in a separate code sheet, then use the tool bar button in Game Maker that replaces a string with another one instantly (that button is at the top of your screen while viewing a code). Don't forget, you want to draw Item Slot 2 below Slot 1 and Slot 3 below 2, you get the picture. The "view_top[0]+175)" will be changed for each slot. After doing the "Hero Profiles" on the left, I'm sure you can figure this one out on your own. Once you have all your slots neatly aligned, we want to draw the number that represent item amount on the right side of the item sprite. To do this just add a "draw_text" to your coding, I should of told you this earlier I guess.

font_size = 8;
font_color = c_lime;
font_name = "Papyrus";
font_style = fs_normal;

if (global.ItemSlot1 = "Potion"){
draw_sprite(sprPotionItem, 0, view+left[0]+560, view_top[0]+175);
draw_text(view_left[0]+620, view_top[0]+180, global.NumberOfPotion);
}
else{
if (global.ItemSlot1 = "Stimulant"){
draw_sprite(sprStimulantItem, 0, view+left[0]+560, view_top[0]+175);
draw_text(view_left[0]+620, view_top[0]+180, global.NumberOfStimulant);
}
else{
if (global.ItemSlot1 = "Drive"){
draw_sprite(sprDriveItem, 0, view+left[0]+560, view_top[0]+175);
draw_text(view_left[0]+620, view_top[0]+180, global.NumberOfDrive);
}
else{
if (global.ItemSlot1 = "Cotton Panty"){
draw_sprite(sprCottonPantyItem, 0, view+left[0]+560, view_top[0]+175);
draw_text(view_left[0]+620, view_top[0]+180, global.NumberOfCottonPanty;
}
if (global.ItemSlot1 = "GreenHerb"){
draw_sprite(sprGreenHerbItem, 0, view+left[0]+560, view_top[0]+175);
draw_text(view_left[0]+620, view_top[0]+180, global.NumberOfHerb);
}
else{
if (global.ItemSlot1 = "Empty"){

}

}
}
}
}

Now we should have the total number of an item draw out to it's sprite's right side (Note: You have to change the "Empty" in your "ItemSlot" variables to the name of the item that will be occupying the space, then set the number of that item using the "NumberOf" variable). Your numbers drawn to the screen origins aren't centered so you might have to make some value adjustments to align it neatly. Now, if you haven't given your "MainMenu" a background go ahead and do so. In fact, you'll be using two backgrounds. You want one 1020 x 145 (leave a little space above slots and profiles) to go across the top of your screen and of course the large 1020 x 700 main background. You can do this many different ways.

1. Using gif sprites is lighter on the memory (hard drive space). Create two BG sprites, one 1020 x 700 and the other 1020 x 145. Place them in the Menu.

2. Use the "draw_rectangle" function in Game Maker to draw the BGs. This is very cheap on the memory, but doesn't look as good as textured BGs.

3. Use the normal background set up in Game Maker and set two different BGs in your menu. The one with shorter height (top piece) will lay on top of the overall one.

Be a little fancy here, just don't throw in two BGs. You can have your main BG (1020x700) designed with a split, separating the items from the profiles, cool huh!?

That's about it for the rookie level Menu designing. There are a lot more things you can do once you get more advanced with Game Maker's language. Luckily for me, Game Maker's language looks like Python with a little Java so I can dive right into it. In fact, Game Maker's language is easier than Python, because when writing an "if" statement in Python, the spaces really do matter. Python doesn't us the "{ }" brackets with if statements, it uses the " : ". I like the "{ }" instead.

I'll end this tutorial given you a taste of more complex coding (which is rather easy):

//Place an item in Menu Script. This is an example of checking on slot.

if (global.PlacingPotionInMenu = true){

if (global.MenuSlot1 = "Empty"){
global.NumberOfPotion += 1;
global.MenuSlot1 = "Potion";
global.PlacingPotionInMenu = false;
}
else{
if (global.MenuSlot2 = "Empty"){
global.NumberOfPotion += 1;
global.MenuSlot2 = "Potion";
global.PlacingPotionInMenu = false;
}
else{
if (global.MenuSlot3 = "Empty"){
global.NumberOfPotion += 1;
global.MenuSlot3 = "Potion";
global.PlacingPotionInMenu = false;
}
else{
if (global.MenuSlot4 = "Empty"){
global.NumberOfPotion += 1;
global.MenuSlot4 = "Potion";
global.PlacingPotionInMenu = false;
}
else{
if (global.MenuSlot5 = "Empty"){
global.NumberOfPotion += 1;
global.MenuSlot5 = "Potion";
global.PlacingPotionInMenu = false;
}
else{
//Call "menu is full" script. This will call the coding that takes care of the "full Menu" situation.
global.PlacingPotionInMenu = false;
ItemMenuIsFull();
}

}
}
}
}

}

Here's a question.....how would one check to see if an item is already in the Menu or not? Simple, if "global.NumberOfPotion > 0", it is in the Menu. When an item's amount value hit zero (0) you want to have a piece of coding in a step event somewhere that detects this, thus setting the slot the item was in back to "Empty." Writing such a code is the reverse of the "adding a item" code above, it's not hard to figure out.

Well that's it. It'll take a lot of other codes to fine-tune your Menu (like adding an arrow selector), but when your done you should have yourself a more professional styled RPG menu system (with Game Maker). Any questions, email: nug1978@aol.com

Piece,
"Nugman" Nugster
(PS: If I made typing errors, sorry.)