Note: This guide will not teach you how to script, it'll teach you how to learn to script.
Introduction
The End nooooo
Introduction
RMXP's Scripting feature is a gateway into the inner workings of the RMXP Engine. While we don't have access to the building blocks, we've been given plenty of room to poke and prod at the surface.
The Scripting Engine uses the high-level programming language Ruby. There are many guides to learning the programming language, such as Why's Poignant Guide to Ruby and Programming Ruby: The Pragmatic Programmer's Guide. By reading these, or at least glancing over the basics, you can get the basics and concepts down for programming syntax in Ruby.
This guide, however, is going to teach you more about RGSS, which is the default library for RMXP's built-in classes and methods. It'll also teach you about some of the naming conventions and subtleties of scripting in Ruby.
Step One... Or is this two?The Scripting Engine uses the high-level programming language Ruby. There are many guides to learning the programming language, such as Why's Poignant Guide to Ruby and Programming Ruby: The Pragmatic Programmer's Guide. By reading these, or at least glancing over the basics, you can get the basics and concepts down for programming syntax in Ruby.
This guide, however, is going to teach you more about RGSS, which is the default library for RMXP's built-in classes and methods. It'll also teach you about some of the naming conventions and subtleties of scripting in Ruby.
RGSS has Seven base class groups. These are seen in the editor, and are signified with their prefixes, which are:
We will also talk about the RPG Module, specifically the classes that extend it and their uses.
Game_*
Sprite_*
Spriteset_*
Window_*
Arrow_*
Interpretter
Scene_*
The RPG Module
- Game_*
- Sprite_*
- Spriteset_*
- Window_*
- Arrow_*
- Interpretter
- Scene_*
We will also talk about the RPG Module, specifically the classes that extend it and their uses.
Game_*
Game_* classes are the backbone of RMXP. They handle every last bit of important data, from storing it, to modifying it, to manipulating it. In the special case of Game_Player, it also takes input from the keyboard/joystick and manipulates that, but that kind of input is usually handled in the Scene_* classes.
It is wise for any beginner first looking at RMXP's Default classes to read the description header of each class, which will look something like this:
It is wise for any beginner first looking at RMXP's Default classes to read the description header of each class, which will look something like this:
#======================
# ** Game_System
#----------------------------
# This class handles data surrounding the system. Backround music, etc.
# is managed here as well. Refer to "$game_system" for the instance of
# this class.
#======================
It tells us everything we need to know about the class. Specifically, what data it deals with, what data it manipulates, and what global variable it is instanced as. [An instance of a Game_* class is usually a global variable, as they are used in almost every aspect of the game.]# ** Game_System
#----------------------------
# This class handles data surrounding the system. Backround music, etc.
# is managed here as well. Refer to "$game_system" for the instance of
# this class.
#======================
Sprite_*
Sprite_* classes are important as far as the visual aspect of RMXP goes. They always extend the RPG::Sprite or Sprite classes, and take data from the appropriate Game_* class and use it to create sprites to display the appropriate graphics.
Again, refering to the description header for the class will tell us all the information we need to know:
Note: The Sprite_Picture header is wrong. Most likely due to a lazy translator copy and pasting, it reads "It observes data from the Game_Character class.." but should read "It observes data from the Game_Picture class.." An obvious mistake, but worth mentioning.
Again, refering to the description header for the class will tell us all the information we need to know:
#======================
# ** Sprite_Character
#----------------------------
# This sprite is used to display the character.It observes the Game_Character
# class and automatically changes sprite conditions.
#======================
It tells us what its doing, and where it takes its information from.# ** Sprite_Character
#----------------------------
# This sprite is used to display the character.It observes the Game_Character
# class and automatically changes sprite conditions.
#======================
Note: The Sprite_Picture header is wrong. Most likely due to a lazy translator copy and pasting, it reads "It observes data from the Game_Character class.." but should read "It observes data from the Game_Picture class.." An obvious mistake, but worth mentioning.
Spriteset_*
Spriteset_* classes are pretty much handle all the sprites on the screen, as opposed to handling them individually within the appropriate Scene_* class. They always initialize all the sprites used on the screen, always update them, and always dispose them. For a scripter who works entirely within the RGSS scripts, it would be wise to remember this, instead of creating individual Sprite_* instances in the Scene_* classes.
There are some graphical phenomenae that don't use the Sprite_* classes. Nothing special in why they are used, except that the Sprite_* class isn't needed. These are for the Panorama, Fog, and Weather effects. Panorama and Fog are just fancy images, and use the Plane class.
Weather uses the RPG::Weather class, which actually models something along the lines of a 'dynamic sprite' in that it takes a Bitmap and draws rectangles on it to create dynamic weather animations.
Also, the maps are drawn using the Tilemap class. This is to handle priority, and autotile animation, among other things.
Neither the Plane nor the Tilemap classes are available for us to view/edit, however we can create new ones. This isn't suggested to anyone who would need to read this tutorial.
There are some graphical phenomenae that don't use the Sprite_* classes. Nothing special in why they are used, except that the Sprite_* class isn't needed. These are for the Panorama, Fog, and Weather effects. Panorama and Fog are just fancy images, and use the Plane class.
Weather uses the RPG::Weather class, which actually models something along the lines of a 'dynamic sprite' in that it takes a Bitmap and draws rectangles on it to create dynamic weather animations.
Also, the maps are drawn using the Tilemap class. This is to handle priority, and autotile animation, among other things.
Neither the Plane nor the Tilemap classes are available for us to view/edit, however we can create new ones. This isn't suggested to anyone who would need to read this tutorial.
Window_*
Window_* is what a new RGSS scripter is going to be using a lot. Window_* classes always extend the Window class, or the Window_Selectable class (which extends the Window class). The Window class isn't available to us, but it for the most part just handles drawing the sprite based on the information from the Windowskin, so its nothing we really need to deal with.
The Window_* classes that already exist are a great example of how to use them. They are mainly used to display the data found in the Game_* classes and the $data_* global variables. They should never change any of the information that they use. They simply display it.
Notes: While not a rule, most Window classes are initialized using this format:
The reason I note this is for two purposes, first of all if the window does not use the 'super()' function, it won't have any dimensions and will most likely crash. Second, the contents must be defined before any drawing of text and such can be done. (See the Bitmap class in the help file for a list of the stuff that can be done to a bitmap.) If you don't define it with the parameters width-32, height-32, it will in most cases draw arrows on the sides of the window, indicating that there is additional information in the window that isn't being viewed. I have no idea why it does this, but just stick to using what i've put here and you won't have any problems.
The Window_* classes that already exist are a great example of how to use them. They are mainly used to display the data found in the Game_* classes and the $data_* global variables. They should never change any of the information that they use. They simply display it.
Notes: While not a rule, most Window classes are initialized using this format:
Code:
def initialize
super([i]x_position, y_position, width, height[/i])
self.contents = Bitmap.new(width - 32, height - 32)
Arrow_*
The Arrow_* classes are just fancy handlers for a Sprite that is part of the Windowskin. If you ever intend to use these sprites (the two in the bottom right corner), it's probably not a bad idea to use the Arrow_Base class as an extension to an Arrow_* class, and use it that way. Just to maintain consistancy.
Interpretter
The interpretter is a bit of a mess to read for someone who isn't a pretty good scripter. What the Interpretter does is take the Event commands from an event/common event/battle event, and turn them into RGSS Script (Ruby code). There are very few reasons you'd ever want to use this, and often can avoid using it entirely by taking certain steps. I'd suggest that if possible, avoid editting the Interpretter class until you are comfortable as a scripter and understand what you are doing.
Scene_*
These are probably one of the most important types of classes. They are a wrapper for any situation that is going on in your game. For instance, you are walking around on the map (Scene_Map), you are in the menu (Scene_Menu), you are in a fight sequence (Scene_Battle), etc.
For the most part, they handle button Input, reference whatever window is active, and perform all the necessary actions based on that. If I want it so a variable $number is increased by 1 every time I press Space, i'd add that to the Update method of the Scene. If I want a window that displays that number, i'd create the appropriate window class, and initialize/dispose the window object in the Main method of the scene. And any other number of situations and possibilities.
Note: The best example of a complicated yet efficient Scene class is the Scene_Battle class. Its massive, contains tons of menus, processes, conditions, etc. and is a great example of everything a Scene can do.
For the most part, they handle button Input, reference whatever window is active, and perform all the necessary actions based on that. If I want it so a variable $number is increased by 1 every time I press Space, i'd add that to the Update method of the Scene. If I want a window that displays that number, i'd create the appropriate window class, and initialize/dispose the window object in the Main method of the scene. And any other number of situations and possibilities.
Note: The best example of a complicated yet efficient Scene class is the Scene_Battle class. Its massive, contains tons of menus, processes, conditions, etc. and is a great example of everything a Scene can do.
The RPG Module
The RPG Module is something you might not even be aware of. It is hardcoded, but all the code needed is in the Help File. The RPG Module contains a wealth of classes, which for the most part are used to store data as objects. When you save the database, and the data is loaded (in Scene_Title) into the $data_* variables, what it is actually doing is initializing tons of RPG::* classes with the information you've set up in the Database.
We can add information to these classes. You can't do it normally, by putting it in the Initialize statement, because of the way the information is taken from the database files. Below is an example of how I would do it:
Then after initializing the $data_skills variable, i'd simply perform this iterator:
That will set all the information needed. This is MUCH better than say, using an Element tag, or adding a [#] to the skill name, or using one of the existing stats to represent the new stat.
We can add information to these classes. You can't do it normally, by putting it in the Initialize statement, because of the way the information is taken from the database files. Below is an example of how I would do it:
Code:
module RPG
class Skill
attr_accessor :hp_cost
def setup
@hp_cost = 0
case @name # or it could be @id, whatever you want.
when 'Cross Cut'
@hp_cost = 10
when 'Leg Sweep'
@hp_cost = 5
# etc.
end
end
end
end
Code:
for skill in $data_skills
next unless skill
skill.setup
end
The End nooooo
As you can probably tell, you haven't learned a lick of Ruby or Scripting (unless you read the guides at the start which I suggest you do!) but maybe, just maybe, you can see why people have such a hard time learning how to script. To put it in simple terms, people do some of the stupidest shit. Putting input in the Window_* classes, putting Sprites in the Game_* classes, making classes that do the work of both the Window class and the Scene class, when they should clearly be seperate.. Its just retarded.