Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

General Scripting Conventions

General Scripting Conventions

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 should hint at the use and function of the class. Class Names should be named as follows:
Window_(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.
Method Names
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.
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
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:
counter
width
@change_rate
@destination_x
@moving
Example of bad variable naming
cntr
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
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.
Indentation
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
Commenting
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
Code:
 #============================================================================
  # ** Script Name
  #----------------------------------------------------------------------------
  # Your Name
  # Version
  # Date
  #============================================================================
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
Code:
#=============================================================================
# ** Scene_Debug
#------------------------------------------------------------------------------
#  This class performs debug screen processing.
#=============================================================================
And here is another example
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.
#=============================================================================
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
Code:
 #--------------------------------------------------------------------------
  # * Set Maximum HP
  #     maxhp : new maximum HP
  #--------------------------------------------------------------------------
Here is another example.
Code:
 #-------------------------------------------------------------------------
  #   Name:      Random
  #   Info:      Returns a Random element in the array
  #   Author:    SephirothSpawn
  #   Call Info: No Arguments
  #-------------------------------------------------------------------------
Global Variables
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:
Constant
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)
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)
Object Oriented
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*)
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")
Do this
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
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.
Aliasing
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
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
Lets go for this
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
How do you alias?

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
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.

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.​
 
Well the method names were from MACL and they are pretty much common sense stuff

but I really hope other scripters take note of the information I have presented here.

And on a side note call it a last and final note if you will

A Good Script is not a good script if it doesn't follow the conventions I don't care if it can even solves world hunger or calculate the meaning of life it is a Bad (Poorly written) script if it doesn't follow the conventions. The output of the script contributes little if not nothing to how good it is it is how it is coded.
 
I like it... especially because I can read through it with most of my scripts in mind and honestly think: "Yeah, that's exactly the way I did it..." ^_^ (aside from the commenting part, of course... strange that I don't like commenting my scripts, while having written a commenting tutorial at the same time XD )
 
Mac;192431 said:
I love it trickster, very helpful :) *bookmarks*

Thanks

BlueScope;192435 said:
I like it... especially because I can read through it with most of my scripts in mind and honestly think: "Yeah, that's exactly the way I did it..." ^_^ (aside from the commenting part, of course... strange that I don't like commenting my scripts, while having written a commenting tutorial at the same time XD )

Yes very ironic

pmhoa;192694 said:
man there are lots of things i want to learn but dont have time ;_ ;
great tut man

Thanks

Raiju;192944 said:
You should note that aliasing is only a good idea if you plan to release your script. If you're making a script for yourself or one person, then aliasing is inefficient (you're adding more method call depth) and really not necessary since you're not trying to make it compatable with all comers.

Well it depends sure it is more effective to just overwrite when you alias the same method alot of different times, but what if you want to implement that script in many different projects? Aliasing makes code more portable and I'm sure it wouldn't hurt much if you aliased the same method a few times. But it is pretty much a habit for me when writing code to use alias it instead of overwriting or changing the default methods its too messy for me :-/

But you have made a good point, but my intention was for this tutorial to be targeted on writing public scripts since lately I have been seeing a decline in the quality of the work being produced (I probably should have stated that in the first post)
 
This will prove useful as I learn some scripting. Thanks! I don't like messy scripts, so if I ever do make a script for my own I'll know the proper techniques to make it legible.
 
Come on one of the reasons I wrote this tutorial was to put something to this effect in it
Scene_TricksterOwnsSeph
YOU COULD HAVE AT LEAST SAID SOMETHING ABOUT IT!!!!! :mad:


one little thing to add when adding onto an existing class you do not need the < Superclass and in some cases it can generate errors in scripts (as defining a new superclass will delete each method from a class since ruby doesn't have multiple inheritance) even says so in the help file

RMXP Help File":mwqbjd11 said:
When a class is already defined, writing a class definition with the same class name will add to the existing class definition.

Code:
class Foo < Array
  def foo
  end
end

class Foo
  def bar
  end
end
 

Ozuf

Member

Excellent. Some lessons are learned the hard way but you're giving people a fair chance to get out easily. Prospective scripters should definitely dwell and take it to heart, especially those that at first do not feel like it's necessary.


Some comments might be in order.

Dangerous Methods (methods that modify the object) should be followed by an !
example (gsub!, slice!, sub!)
Certainly all suffix-! methods are dangerous methods by ruby standards but the majority of dangerous methods and the de facto ruby and RGSS standard does not follow your convention. I would love that this was the convention, or rather, that the equivalent !-method was implicitely defined by the regular methods. Perhaps you want this as well but confusing the beginners may do more harm than good.
More accurately, for an ad hoc (used enough) subset of dangerous methods, non-suffix-! and suffix-! pairs are defined where the non-suffix-! method returns the result (usually of the same instance as the base class) and the suffix-! method either changes the callee object into the result, or performs an arbitrary operation resulting in some intuitive counterpart and then either returns the object itself or the result.

Highlighting examples
* x.gsub, x isA String
Returns a copy of x (i.e. a String) with substitutions (=result)
* x.gsub!
Substitutes in x (self changed to result).
returns x (=result and =self).

* x.slice, x isA Array (or String for that matter)
Returns a subarray of x (=result).
* x.slice!
Removes a subarray of x (self changed by a counterpart, the complement of the result here).
Returns the subarray of [the original] x (=result).

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
To avoid confusion, you might want to explicitly mention that it is the previous clear method that is named trick_timerbase_battleaction_clear and yours is now clear.

# Info: Returns a Random element in the array
Perhaps return and param <param-name> lines?
How about requirements on installed enhancements?



I believe someone should comment on the line length and line breaking. RMXP does follow the (I think it is) ANSI standard: at most 80 characters per line, unfortunately that does not fit into the RMXP script editor.


P.S. is there a way to increase the size of the quick reply. On my browsers it's some 16 characters wide.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top