Submit Your Article Guild Wars 2 Forum RPG Maker VX.com
 
RPG Maker
 

 Username:
 Password:
   Not a member? Register!



Home > Tutorials > Ruby Game Scripting System > RGSS For Dummies Tutorial 7: Windows for Dummies

RGSS For Dummies Tutorial 7: Windows for Dummies


Introduction

I thought it would be nice to have a practical tutorial for a change. After all, the last tutorials had lots of talk and little code. In this tutorial, you will learn about creating windows and scenes. We will add a new "About" option to the main menu; this option will simply show a window with some information about the game.

Contents

1. Basic Stuff
2. The Window Class
3. Creating the Window Class
4. Creating the Scene Class
5. Adding the 'About' item to the Main Menu
6. Annoying Play Time WIndow
7. Conclusion
8. Summary

1. Basic Stuff

Before we jump to creating the about window, it's better to get a basic idea about how menus work. As mentioned in the previous tutorial, scenes control input, processing, and output. Each menu option (item for example) has its own Scene class, as well as a window class. The window class (Window_Item for example) defines the shape and contents of the window, this class has a refresh method that actually draws text or images on the windows. Note that the window class only controls how the window looks like, but not how the user interacts with the window. This is why there is a scene class (such as Scene_Item), which detects input and does various actions depending on the input (like using an item if you press the action key). Our goal is to add an 'About' option to the main menu, so we will need an about window class (I'll call it Window_About, you can call it whatever you like though) and an about scene class (I'll call it Scene_About). We will also need to modify the main menu to add a new About option under 'exit'.

2. The Window Class

Let me introduce you to the Window family (Window class heirarchy). It's an ancient noble family known for it's ability to provide boxes to interact with users. The head of the family is the very old Mr. Window, he has a basic drawing board (window). He doesn't have any paper (bitmap) though, just a wooden drawing board.

Mr. Window has one son (child class) named Window_Base. Window_Base inherited his father's drawing board, but couldn't find papers either. However, he learned new abilities (methods) such as drawing names of heroes, drawing HP and MP, drawing item icons, etc.

Later, Window_Base had many children. All of them inherited his abilities and added to them. For example, his eldest daughter Window_Help had a paper (bitmap) along with the drawing board; on that paper, she can draw some information during battle (like magic and enemy names). Window_Base' second son Window_Gold also had a paper that could be used to display the amount of gold held by party. Other children include Window_PlayTime, Window_Steps, Window_BattleResult, etc.

One of Window Base' children was special. Although Window_Selectable didn't get drawing papers like his siblings, he got a special ability that allows him to directly interact with users by providing selectable items. He was able to detect user input to move the cursor through various items on the drawing board. Window_Selectable was a sad person because he didn't have paper, but he was happy to know that his children did have papers and that made them very useful in both battle and field. The first of his children was Window_Command, which was a basic selectable window with the ability to draw (has a bitmap) items to be selected. Examples of command windows would be the "start / load / exit" window at the title screen, the left menu in the main menu, and the battle menu (attack, defend, etc.). Window_Selectable had many other children like window items (you can select items), parts of the equip menu, etc.

What was that about? It was an introduction to the window classes. At the top there's the built-in Window class, it has basic properties but no contents bitmap (you need to create the bitmap yourself, window.contents = Bitmap.new(100, 200)). The Window Base class adds more drawing methods to the Window class. Window_Selectable inherits Window_Base but adds the ability to move a cursor through items. The other windows either inherit Window_Base or Window_Selectable.

To create your own window, you should also inherit one of them. If you need a basic window to show some text or images, but without providing choices, inherit from Window_Base. If you need an interactive window with choices, inherit from Window_Selectable. Since our About window will only show some text and offers no choices, our Window_About will inherit Window_Base. You can find what the default classes inherit from by checking the name in the class definition, for example 'class Window_Xxxx < Window_Base' means that Window_Xxxx inherits from Window_Base.

Before actually getting to the code, note that these two basic windows provide no bitmaps. Bitmaps are like drawing papers, you can draw text or images on bitmaps. The basic windows actually have a 'contents' member that is used to represent the bitmap, but it's empty (nil). Therefore, the only way to draw anything on the window is to create the bitmap by specifying its size (or an image file to load the bitmap from).

3. Creating the Window Class

All you need in a Window class is an initialize method, and a refresh method. The initialize method sets the basic properties of the class (position, width, height, etc.) and creates a bitmap. Setting size and position could be done through a call to the initialize method of Window_Base using the super keyword. So if you do super(0,0,100,200) you create a window at the upper left of the screen with a width of 100 and a height of 200 pixels. As for creating the bitmap, you just assign Bitmap.new(width, height) to your window's contents (self.contents). Since the window have a border, you'll always need to make your bitmap 32 pixels smaller in both width and height, or else the bitmap will be too big for the window. Bitmap.new(width - 32, height - 32) will do that for you.

As for the refresh method, this is where you draw stuff. Drawing refers to placing stuff at the window, such as text or pictures. You start with clearing anything already on the bitmap (like erasing stuff on a paper before drawing) by invoking the clear method of the contents bitmap (self.contents.clear). After that you can use the draw_text method to draw any text you need. The syntax for draw_text is: draw_text(x, y, width, height, string), you can also add an extra number after string to specify how the text is aligned. x and y set the position of text on the bitmap, where 0,0 is the upper left pixel and bitmap width, bitmap height is the lower right pixel. width and height parameters specify the size of the 'text box' that the text is drawn in. If the string is longer than the width then it will be cut off. Finally, string is the text you want to draw. The draw_text method is part of the bitmap class, so it's called from the bitmap (self.contents.draw_text(x, y, width, height, string)).

Open a new project in RMXP, go to the Script Editor and right click on Arrow_Base (right under Window_DebugRight). Select Insert (the first item) in the drop down menu, a new empty code section will be creating it. Select the empty section and call it Window_About (type the name in the text box under the scripts list to the left). Inside the empty page to the right, type the following:

Code:
# Class Window_About inherits from Window_Base
class Window_About < Window_Base

# The initialize method.
# Called when the Window_About window is created.
def initialize

# First set the window size by calling the initialize
# method of window base with a size of 640 * 480
super(0, 0, 640, 480)

#Then create the contents bitmap. The width and
# height are set to windiw width - 32 and height - 32
self.contents = Bitmap.new(width - 32, height - 32)

# Call the refresh method to draw text
refresh

end

# The refresh method.
# Called to draw stuff on the contentsbitmap.
def refresh

#Clear any existing contents.
self.contents.clear

# Draw some text at the given position,
# refer to the previous paragraph for more info.
self.contents.draw_text(0, 0, 200, 32, "About My Game")
self.contents.draw_text(0, 32, 200, 32, "1. My game is the best.")
self.contents.draw_text(0, 64, 200, 32, "2. It's better than yours.")
self.contents.draw_text(100, 200, 200, 32, "Monkeys rule!")

end

#This end closes the class definition block
end


4. Creating the Scene Class

We also need two methods for the scene class. main and update. The main method will be called when we enter the About scene. You need to have some sort of loop in main to update graphics and input. This can be done using the simple do loop which keeps looping until you break out of it. And the condition for breaking will be changing the scene (like going back to main menu). Before entering the loop, we need to use a transition to make the new window appear in a smoother way, this is done using Graphics.transition. Graphics is a module that controls RMXP's graphic engine, it has several methods such as transition and update. We also need to create the Window_About object before the loop. Creating a window calls the window's initialize method and then shows the window. Once inside the loop, you update the Graphics and Input, if you don't do it then nothing you draw will be shown and the scene won't respond to input (you'll be stuck in an infinite loop!). After that the update method is called, then a check is made to see if the scene changed (user pressed the cancel key). If the scene isn't equal to Scene_About (self), then we break out of the loop. Once out we freeze the graphics (must be done before doing a transition, which the next scene will do before its main loop), freezing the graphics simply stops any drawing during the transition. Finally, the Window_About object that we created must be disposed. Disposing means removing it from memory and erasing the window.

The update method is called in each iteration of the main loop. The Scene_About update method just checks if the cancel key (B) is pressed, if it is, the cancel system sound is played, and the scene is changed back to the main menu. Changing the scene is creating a new scene using Scene_Xxxx.New and assigning it to the $scene global variable. In this case, $scene = Scene_Menu.new(6) will do the trick. The number 6 is just there to tell Scene_Menu that we need the menu cursor at item index 6, which will be the About item. If you omit the number (just Scene_Menu.new), the cursor will be at the first menu item by default, I suggest you try it to see what I mean.

Go to the Script Editor and right click on Main (the last item in the scripts list). Select Insert (the first item) in the drop down menu, a new empty code section will be create it. Select the empty section and call it Scene_About (type the name in the text box under the scripts list to the left). Inside the empty page to the right, type the following:

Code:
class Scene_About

#The main method.
# This method has the main loop which updates
# graphics and input, it also calls the update method.
def main

# Create a Window_About object called @about_window
@about_window = Window_About.new

# Perform a transition
Graphics.transition

# Loop forever
loop do

# Update graphics
Graphics.update

# Update input
Input.update

# Call the update method
update

# If the current scene isn't Scene_About
if $scene != self
# Exit the loop
break
end

end

# Freeze the graphics (prepare for transition)
Graphics.freeze

# Get rid of @about_window
@about_window.dispose

end

# The update method.
# Checks if cancel is pressed and exits this scene
def update

# If the cancel key (B) was pressed...
# Input::C = Decision Key, Input::B = Cancel key
# Inpit::LEFT = Left key, Input::Up = Up key etc.
if Input.trigger?(Input::B)
# Play the cancel sound effect
$game_system.se_play($data_system.cancel_se)

# Exit this scene by setting $scene to Scene_Menu
# 6 means the cursor should be at the 7th menu item
$scene = Scene_Menu.new(6)
end

end

#This end closes the class definition block
end


5. Adding the 'About' item to the Main Menu

1. In the script editor, click on Scene_Menu from the list to the left.
2. In the main method, find the following lines:

Code:
s1 = $data_system.words.item
s2 = $data_system.words.skill
s3 = $data_system.words.equip
s4 = "Status"
s5 = "Save"
s6 = "Exit"


3. Add the following line after (s6 = "Exit"):

Code:
s7 = "About"


4. Change the next line (@command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6])) to:

Code:
@command_window = Window_Command.new(160, [s1, s2, s3, s4, s5, s6, s7])


What you just did what add a new item to the command window that is used to hold the menu items. The initialize method of Window_Command takes the width of the command window and an array of strings as a parameter. Each string will represent one menu item. So, we add a new string called s7 and set its value to "About", then we add it to the arguments passed to Window_Command's initialize method.

5. We're not done yet, we need to decide what happens when 'About' is selected. Scroll down in Scene Menu and go to the update_command method. You'll see a case statement with lots of when's. Find the last when:

Code:
when 5 # Japanese stuff
# Blah SE blah
$game_system.se_play($data_system.decision_se)
# Blah
$scene = Scene_End.new


6. Add the following right after $scene = Scene_End.new:

Code:
when 6
$game_system.se_play($data_system.decision_se)
$scene = Scene_About.new


Make sure there is an 'end' after the code you just added. This code simply checks if the 7th item was pressed (index 6), plays the decision sound effect and then changes the scene to scene about.

And that's it, run the game, go to menu, choose 'About' and the new menu should be shown. Press escape to exit.

6. Annoying Play Time Window

You might notice that the play time window is over the About option. The easiest way to fix it would be to go to Window_PlayTime and make it smaller by getting rid of the text over the game time.

1. Find the following line in the main method of Scene_Menu:

Code:
@playtime_window = Window_PlayTime.new
@playtime_window.x = 0
@playtime_window.y = 224


2. Change the last line to:

Code:
@playtime_window.y = 256


This shifts down the playtime window a bit.

3. Go to the Window_PlayTime script, find the following line in the refresh method:

Code:
self.contents.draw_text(4, 0, 120, 32, "Time")


(The text for "time" could be different in your RMXP version, it could be "Play Time", "Game Time", something like that)

4. Delete that line.
5. Find the last line in Window_PlayTime refresh method (self.contents.draw_text(4, 32, 120, 32, text, 2)) and change it to:

Code:
self.contents.draw_text(4, 0, 120, 32, text, 2)


What you did is delete the "time" text" and shift the time text up (y is 0 instead of 32 in draw_text).

6. In the initialize method of Window_PlayTime, change super(0, 0, 160, 96) to:

Code:
super(0, 0, 160, 64)


Doing so makes the play time window smaller.

7. That's it, test the game now. :)

If the text doesn't show for some reason, add the following line somewhere in main (last script section). Just put it before the loop...

Code:
Font.default_name = "Arial"


You could have any font name instead of "Arial"...

The final product:

picture


7. Conclusion

Whew, finally done. I know this tutorial might seem complicated at first, but you don't need to understand everything. It just gives you a general idea about windows and scenes. You can change the about menu to display everything you like. You can also examine other scenes and windows to see how they are coded. I hope this tutorial was useful for you.

8. Summary

1. No, I'm tired. 
Details
Tutorial: RGSS For Dummies Tutorial 7: Windows for Dummies
Date Listed: 2008-06-05
Author: RPG
Total Hits: 6322


Embed
Short URL:

HTML:

BB Code:



RPG RPG Revolution
RPG RPG Revolution is your #1 stop for game development and console RPG games, as well as those created by people like you. Link to us to support us, so we may grow to be better website community for you.

RPG RPG Revolution is an Privacy Policy and Legal