By Trickster
Proofreading by Yeyinde and Kurisu
Purpose
The purpose of this tutorial is to inform other scripters about the proper conventions in writing scripts for rmxp. This is to improve script quality and to suggest conventions that everyone should follow while writing scripts for use in rmxp. Some of the conventions who will be reading are common sense are others are stated here for a reason. You don't have to follow all of the things stated here but it is a good idea to follow then for these reasons 1) Other scripters might be looking at your work 2) You might return to your own work one day 3) To increase the quality of the work produced here.
General Coding Conventions
These are the general things you should consider when writing your code. In general your code should be short but at the same time be easy to read and manage as well. Here is the list of the conventions.
Class Names
Class Names
Class names should hint at the use and function of the class. Class Names should be named as follows:
Method NamesWindow_(Name) if its a Window
Sprite_(Name) if it is a Sprite
Spriteset_(Name) if it is a Spriteset
Scene_(Name) if it is a Scene
Game_(Name) if it is Game data
Arrow_(Name) if it is an Arrow
The Actual Name of the class after that should follow the CamelHump style except that the first character is capitalized for example Window_PlayTime, Scene_SkillShop, and Scene_TricksterOwnsSeph.Sprite_(Name) if it is a Sprite
Spriteset_(Name) if it is a Spriteset
Scene_(Name) if it is a Scene
Game_(Name) if it is Game data
Arrow_(Name) if it is an Arrow
Method names should hint at the use and function of the method. It is of poor style to abbreviate method names or start a method name with a capitalized letter (this may confuse the Ruby Interpreter). Method names should be named in the underscore style. Here are some examples draw_circle, cut_and_chop, and start_phase1.
Types of methods and how they should be named.
Variable NamesTypes of methods and how they should be named.
Dangerous Methods (methods that modify the object) should be followed by an !
example (gsub!, slice!, sub!)
Query Methods (methods that check for something) should be followed by an ?
example (dead?, eof?, empty?)
Setter Methods (methods that set a value) should be followed by an =
example (hp=, line=, time=)
Getter Methods (methods that get a value) should be name the same as a the setter method but without the =
example (hp, line, time)
Variable names should hint at its purpose. It is of poor style to abbreviate the variable name as know one else will know what the variable name crcl does except the programmer who coded it. It is of good style to make the variable names descriptive. Variable names should be named with underscores.
Example of good variable naming:
Example of good variable naming:
counter
width
@change_rate
@destination_x
@moving
Example of bad variable namingwidth
@change_rate
@destination_x
@moving
cntr
w
@chan_r1
@desx
@mvg
w
@chan_r1
@desx
@mvg
Variable Types
Make sure that your variables are of the correct scope. That is temporary variables are of the scope local, a class's attributes are of the scope instance, etc.
Here is a list of what a variables type should be
IndentationHere is a list of what a variables type should be
Local
Local variables are temporary variables if you are working with a variable that you only need for, like a method then make it a local variable as they are removed when the method is finished executing
Instance
Instance variables exist within a class. If you are working with a value that is shared among methods in a class then you should make it an instance variable.
Class
Class variables should generally not be used as they aren't really used that often, but if you need a variable that is shared among instances of the same class then you need a class variable.
Global
See the section on Global Variables below. These should never be used unless in an emergency.
This is one of the most important conventions there is. It is the difference between your script looking like a garbled mess of junk and your script being well formatted. Also indentation helps to prevent the "Syntax error pointing to the last end statement error" which is sometimes called by improper indentation. Indentation also serves to increase code readability and also tells the programmer you actually care about how you present your code.
You should always indent after the following:
- After the declaration of your module
- After the declaration of your class
- After the declaration of your method
- After a code block
- After the following keywords
- if
- elsif
- else
- unless
- when (not case)
- begin
- rescue
- ensure
- while
- until
- for
This is where some scripters are lacking. It is good form to comment your code. Now every.single.line doesn't have to be commented but it doesn't hurt. You should comment lines that are a bit hard to understand or lines you are not sure of. Commenting helps other scripters understand what you were thinking as you coded your work and is used if you come back a few years and didn't know what you did. Commented lines do not hurt the script it is describing nor does it slow the processing speed of the script they are not read by the Ruby Interpreter.
Headers
Another place where scripters are lacking. Headers are just there for organization here are things in your script that should use a header
The Script Header:
The script header serves as the header for your whole script. Information shown here should include the Script's name, your name, version, and date. This header can also hold information such as what it does, setup information, a faq section, known problems, etc. The Script header is highly recommended
Here is an example of how it should look
The Class Header:
The class header serves as the header for your class. Information shown here should include the name of the class, the author of the class, the version number of the class if any, and a detailed description of the class.
Here is an example of how one looks
And here is another example
The Method Header:
Just like the class and script header the method header serves as you guessed it a header for your methods. Information should should include the name of the method, what the method does, and what arguments the method requires. Other information in the header can include the author, the return values of the method. Method headers are recommended for organization within a class.
Here is an example of how one should look
Here is another example.
Global VariablesThe Script Header:
The script header serves as the header for your whole script. Information shown here should include the Script's name, your name, version, and date. This header can also hold information such as what it does, setup information, a faq section, known problems, etc. The Script header is highly recommended
Here is an example of how it should look
Code:
#============================================================================
# ** Script Name
#----------------------------------------------------------------------------
# Your Name
# Version
# Date
#============================================================================
The class header serves as the header for your class. Information shown here should include the name of the class, the author of the class, the version number of the class if any, and a detailed description of the class.
Here is an example of how one looks
Code:
#=============================================================================
# ** Scene_Debug
#------------------------------------------------------------------------------
# This class performs debug screen processing.
#=============================================================================
Code:
#=============================================================================
# ** Animated Sprite Originally Scripted By RPG
# Edits by Trickster
#------------------------------------------------------------------------------
# A class for animated sprites, includes functions for moving
# (fix by Trickster to allow diagonal movement) also includes delay
# (also fixed by Trickster). Origanal work by RPG.
#=============================================================================
Just like the class and script header the method header serves as you guessed it a header for your methods. Information should should include the name of the method, what the method does, and what arguments the method requires. Other information in the header can include the author, the return values of the method. Method headers are recommended for organization within a class.
Here is an example of how one should look
Code:
#--------------------------------------------------------------------------
# * Set Maximum HP
# maxhp : new maximum HP
#--------------------------------------------------------------------------
Code:
#-------------------------------------------------------------------------
# Name: Random
# Info: Returns a Random element in the array
# Author: SephirothSpawn
# Call Info: No Arguments
#-------------------------------------------------------------------------
Global Variables should generally not be used. Global Variables are not an Object Oriented construct and violates information hiding. You do not want all of the scripts knowing about a variable, you only want your variables shown to methods/classes/scripts that need to view and perform operations on it. The only global variables that should be added are new $data_ and $game_ objects. System global variables created by RMXP (ex. $DEBUG and $scene are allowed). Global variables also consume more memory since they are not removed until the program terminates. The use of bad global variables is frowned upon, because you are cheating yourself, your script, and the users of your script.
Instead of Global Variables try these:
Object OrientedConstant
Constants are values that can not be changed, your data should be a constant if you are not planning on changing it mid game
Constants are values that can not be changed, your data should be a constant if you are not planning on changing it mid game
Temporary Variable
Your Data should be a temporary variable if you plan on changing it mid-game but it is not important that it doesn't need to be saved with the save data these variables are to be added to the Game_Temp class (Game Temp is not saved with save data)
Your Data should be a temporary variable if you plan on changing it mid-game but it is not important that it doesn't need to be saved with the save data these variables are to be added to the Game_Temp class (Game Temp is not saved with save data)
System Variable
Your Data should be a System variable if it is important and needs to be changed mid-game, and it needs to be saved per session of the game these variables are added to the Game_System class or another saving class (but usually Game_System use common sense do not add a window position variable to Game_Party that doesn't make any sense)
Your Data should be a System variable if it is important and needs to be changed mid-game, and it needs to be saved per session of the game these variables are added to the Game_System class or another saving class (but usually Game_System use common sense do not add a window position variable to Game_Party that doesn't make any sense)
Ruby is an Object Oriented langauge for the love of god take advantage of that. Create Classes for the Objects you will be using, for example, if you need a sprite to fade like example a fading sprite Don't Create a sprite and then add a fade implementation somewhere else. Just create a Fade_Sprite class (*1) (that is a child of the original sprite class) and implement the fading routine in that class. User created classes should represent an object and methods should represent an action or state that object has.
so instead of doing this in your scripts (2*)
Do this
You see how much better that looks, instead of the driver method (the method calling this) controlling the creation of the object the class creating the object is controlling its own creation.
Aliasingso instead of doing this in your scripts (2*)
Code:
@window = Window_Base.new(32, 32, 160, 64)
@window.contents = Bitmap.new(128, 32)
@window.contents.clear
@window.contents.draw_text(4, 0, 128, 32, "Hey isn't this poor style")
Code:
class Window_GoodStyle < Window_Base
def initialize
super(32, 32, 160, 64)
self.contents = Bitmap.new(width - 32, height - 32)
refresh
end
def refresh
self.contents.clear
self.contents.draw_text(4, 0, contents.width, 32, "Good Style :]")
end
end
@window = Window_GoodStyle.new
It is a really good idea to alias your code. Aliasing is giving an alias of that method and in general increases compatibility among scripts
So instead of this
Lets go for this
How do you alias?
One of two ways you can either use the keyword alias or call the method alias_method
Examples
where new_name is the new name of the method and old name is the old name of the method, with alias_method both arguments must be symbols
If you have trouble with aliasing I suggest you read a couple of tutorials about it. If you have trouble aliasing a particular method then contact me or make a post in the RGSS Support forum.
So instead of this
Code:
class Game_BattleAction
#--------------------------------------------------------------------------
# * Clear
#--------------------------------------------------------------------------
def clear
@speed = 0
@kind = 0
@basic = 3
@skill_id = 0
@item_id = 0
@target_index = -1
@forcing = false
# Clear Action Made Status
@action_made = false
end
end
Code:
class Game_BattleAction
#--------------------------------------------------------------------------
# * Clear
#--------------------------------------------------------------------------
alias_method :trick_timerbase_battleaction_clear, :clear
def clear
# The Usual
trick_timerbase_battleaction_clear
# Clear Action Made Status
@action_made = false
end
end
One of two ways you can either use the keyword alias or call the method alias_method
Examples
Code:
alias new_name old_name
alias_method :new_name, :old_name
If you have trouble with aliasing I suggest you read a couple of tutorials about it. If you have trouble aliasing a particular method then contact me or make a post in the RGSS Support forum.
Conclusion
I hope you all have learned something, and keep the above in mind while you are scripting. You don't have to follow these conventions, but it is recommended that you do. Some of these are common sense while others are the difference between your script being absolute crap and frowned upon, and your script being of good quality and very robust. I hope you enjoyed reading this and have learned something new from reading. This has been a tutorial from Trickster. Have a nice day.
Notes
*1 Yes Remember what I said about the class names here is one of those exceptions Sprite_Fade would seem like a silly name for a sprite that fades.
*2 Ignore what I said about variable naming here the variable @window is too general of a name, and I am just using poor naming here to prove my point.
*2 Ignore what I said about variable naming here the variable @window is too general of a name, and I am just using poor naming here to prove my point.