RGSS For Newbies (Ongoing Series)

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
Hey gales and guys!

I'm known as Elder (or Gamezopher). A few of you may remember me for a game I've released a decade ago with RPG Maker VX. A long time ago I've released a commercial game with RPG Maker VX: https://en.wikipedia.org/wiki/Eternal_Eden

I've decided to resurrect a series of tutorials I wrote 10 years ago, and if you people believe it's helpful, I'm planning to write more of them from now on. The goal is to help beginners to understand how RGSS works. Together we're going to dissect each part of RGSS bit by bit. Then we'll be ready to progress with more complex tutorials such a building complex features from scratch such as a battle system, custom menus, etc, to improve your RPG.

Feel free to bookmark my website: http://www.gamezopher.com/ and ask questions or request tutorials.

Feel free to ask questions if you want to know anything about RGSS.
 
Last edited:

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
Part 1 - Hello World Program

There is an ancient folklore in computer programming that says that your first program in any language should be a ‘Hello World’ display program. This tradition also states that such program should be very easy, as few lines as possible.

Without further ado, let’s follow these steps:

1-) Open RPG Maker (VX, VX Ace) and open the Script Editor (F11).
2-) Delete every page of code there. Absolutely everything.
3-) Insert a new entry and name it something like ‘My New Script’
4-) Enter the following piece of code in the editor.

Code:
my_sprite = Sprite.new()
my_bitmap = Bitmap.new(544, 416)
my_sprite.bitmap = my_bitmap
my_sprite.bitmap.draw_text(0, 0, 320, 300, "Hello World!", 2)

loop do
  Graphics.update
end
Watch this video for the above steps:

Let's break the code down

To display text on the screen, we use two built-in classes from the RPG Maker class library: Sprite and Bitmap. Beware: the Bitmap class alone isn't enough to display something on the screen. It may sound a bit confusing for a newbie, but the best analogy for both Bitmap and Sprite classes is a soul/body relationship. The bitmap object contains the data (soul), and the sprite object is the visual container for the data (body). The Sprite class possesses a property called 'bitmap', which is nothing else than an encapsulated Bitmap class object. So, it makes it easy for us to branch things together: my_sprite.bitmap = my_bitmap.

This Bitmap class requires a bit more labor. We initialize it to (544, 416), which is the same dimension of the smallest screen resolution. Then we used its method <em>draw_text</em> to print our 'Hello World!' message on the screen.

Finally, we use the RGSS2/RGSS3 built-in module 'Graphics' and its update method Graphics.update. It refreshes the game screen and advances time by 1 frame. So, set it inside a loop statement: loop do(...)end; otherwise the screen is going to be black.

Source: http://www.gamezopher.com/
 
Last edited:

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
Part 2 - Plotting Pixels

The current demo is the 'pixel' equivalent of our previous 'Hello World' program, except we're going to plot a green pixel in the middle of the screen. Follow these steps.

1-) Open RPG Maker and open the Script Edition (F11).
2-) Delete every piece of code there. Absolutely everything.
3-) Insert a new script and name it to something like “My Script”
4-) Enter the following snippet of code in the editor.

PLOT A PIXEL ON THE SCREEN

Code:
my_bitmap = Bitmap.new(544, 416)

my_color = Color.new(0,255,0)

my_sprite = Sprite.new()
my_sprite.bitmap = my_bitmap
my_sprite.bitmap.set_pixel(272,208, my_color)

loop do
  Graphics.update
end



If you've followed the previous 'Hello World' tutorial carefully, you'll notice that only two lines are new. my_color = Color.new(0,255,0) is used to store a color in a variable from the Color class. It use the RBGA format, which stands for red, blue, green and alpha. Then my_sprite.bitmap.set_pixel(272,208, my_color) allows us to plot a single colored pixel on the screen at [x, y]. This method is declared like this: set_pixel(x, y, color). Pretty simple, huh?

DRAW A SIMPLE LINE ON THE SCREEN

Let's draw a simple line with a For-Loop statement.

Code:
screen_width = 544
screen_height = 416
y_axis = screen_height / 2

my_sprite = Sprite.new()
my_sprite.bitmap = Bitmap.new(screen_width, screen_height)
my_color = Color.new(0,255,0)

for x in 0..screen_width
  my_sprite.bitmap.set_pixel(x, y_axis, my_color)
end

loop do
  Graphics.update
end


In this demo, a new pixel is plotted on the screen at each For-Loop increment. Keep in mind it's not the smartest way to draw a line on the screen. Under normal circumstances you'll want to use the Bresenham's line algorithm, which I'll cover in a future demo if requested.

I've added a few more lines in the code. It's important to remember to avoid magic numbers as much as possible. For example, Bitmap.new(544, 416) is bad, because you have to guess what these numbers stand for. It's easier to understand the purpose of Bitmap.new(screen_width, screen_height). Still, for my upcoming demos I may still use some magic number for the sake of keeping code very short.

FILL THE SCREEN WITH LINEAR GRADIANT COLORS

Now that we're at it, let's fill the screen with gradient colors.

Code:
my_sprite = Sprite.new()
my_sprite.bitmap = Bitmap.new(544, 416)
my_color = Color.new(0, 0, 0)

for x in 0..544
  for y in 0..416
    my_color.set(0, x, y)
    my_sprite.bitmap.set_pixel(x, y, my_color)
  end
end

loop do
  Graphics.update
end


The result is quite interesting. The rendering process is quite slow but these examples are mostly for the sake of testing. Surely later we'll be ready to test more complex and funnier scripts.

One important mention about color. Each RGBA value is from 0 to 255. Values out of range are automatically corrected. So in the above demo, it doesn't matter whether the value exceeds 255 during the for-loop iteration.

Source: http://www.gamezopher.com/
 
Last edited:

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
Part 3 - Magic of using Viewports



The easiest way to understand what a viewport do is to imagine them as layers or separate screens on a device.

A viewport is a surface that can fill a portion of the display screen. In general, you'll want to fill the whole display area with the viewport's box: Viewport.new(0, 0, 544, 416). With that notion in mind, viewports can act like layers when juxtaposed on top of each other.

But if you want, you can split your screen with two, three, four or more viewport zones. It's even possible to mimic the Nintendo 2DS with a bit of imagination. Sprites assigned to a viewport won't overlap with other viewports, they'll stay confined to the active one, unless dynamically programmed to move from one viewport to another.

The following demo split the screen in two halves and assign a sprite in them. Given that these sprites are bigger than the viewports, they'll be cropped/clipped.

Code:
viewport1 = Viewport.new(0, 0, 544/2, 416)
viewport1.z = 50

viewport2 = Viewport.new(544/2, 0, 544/2, 416)
viewport2.z = 100

my_spriteA = Sprite.new()
my_spriteA.viewport = viewport1
file = "Graphics/Battlers/Behemoth"
my_spriteA.bitmap = Bitmap.new(file)

my_spriteB = Sprite.new()
my_spriteB.viewport = viewport2
file = "Graphics/Battlers/Demon"
my_spriteB.bitmap = Bitmap.new(file)

loop do
  Graphics.update
end


MIMIC 3DS LAYOUT WITH VIEWPORTS

We can do a fun project and mimic the layout of the 3DS handheld console for testing viewports.

Code:
### SETTINGS

screen_width = 640
screen_height = 480

Graphics.resize_screen(screen_width, screen_height)

bmp_3ds = Bitmap.new("Graphics/Pictures/nintendo_3DS")
center_x = (screen_width/2) - (bmp_3ds.width/2)

### VIEWPORT FOR FULL SCREEN (BG)

viewport_A = Viewport.new(0, 0, screen_width, screen_height)
viewport_A.ox -= center_x
viewport_A.z = 0

my_sprite_A = Sprite.new()
my_sprite_A.viewport = viewport_A
my_sprite_A.bitmap = bmp_3ds

### 3DS TOP SCREEN VIEWPORT

viewport_B = Viewport.new(center_x+79, 39, 314, 190)
viewport_B.z = 100

my_sprite_B = Sprite.new()
my_sprite_B.viewport = viewport_B
my_sprite_B.bitmap = Bitmap.new("Graphics/Battlers/Demon")

### 3DS BOTTOM SCREEN VIEWPORT

viewport_C = Viewport.new(center_x+109, 280, 254, 192)
viewport_C.z = 100

my_sprite_C = Sprite.new()
my_sprite_C.viewport = viewport_C
my_sprite_C.bitmap = Bitmap.new("Graphics/Battlers/Behemoth")

### MAIN LOOP

loop do
  Graphics.update
end


It's important to know that the viewport has two types of coordinates. Regular coordinates and offset coordinates. Regular coordinates can be set only during the object initialization: Viewport.new(0, 0, screen_width, screen_height). The regular coordinate is the absolute position of the viewport within the screen. Offset coordinates will shift the content inside the viewport horizontally and vertically.

I've created three viewports for this scene. One is covering the entire screen and is used to display the Nintendo 3DS in the background. The 3DS image itself doesn't fill the entire screen, so used this simple formula, center_x = (screen_width/2) - (bmp_3ds.width/2), and then shifted the offset value horizontally, viewport_A.ox -= center_x, to center the image.

The two other viewports are drawn over the background viewport. Just like the 3DS screens, their contents will never get outside the boundary of the rectangular area for each viewport. In the above snapshot, the monsters have been clipped to their respective viewport.

TEST TOP SCREEN WITH GAMEPAD/KEYBOARD INPUT

To see the top viewport in action, you can add the following snippet in the loop-do block:

Code:
loop do
  Graphics.update
 
  dir = Input.dir4
  Input.update
 
  case dir
  when 2
    my_sprite_B.y += 1
  when 4
    my_sprite_B.x -= 1
  when 6
   my_sprite_B.x += 1
  when 8
    my_sprite_B.y -= 1
  else
  end
end
source: www.gamezopher.com
 
Last edited:

Knayter

*teleport behind you* Nothing personal kid
Veteran
Joined
May 2, 2016
Messages
234
Reaction score
489
First Language
Viet Nam
Primarily Uses
RMVXA
Thanks a lot for writing this!! I hope you can keep going in the future XD
 

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
4,720
Reaction score
5,401
First Language
Indonesian
Primarily Uses
RMVXA
2-) Delete every page of code there. Absolutely everything.
Not necessary. You will still need it especially if you're about to learn Window_Base, as it requires window tone from DataManager.init
What you do is just to create a new script slot, and write everything there.

Great tutorial btw, I'll be checking these if maybe I could contribute a bit.
 

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
Other tutorials are coming, I've been jotting down some kind of roadmap for upcoming series. I'll maintain a good rate if I feel there's enough people interested in learning RGSS and more complex scripts from scratch.

You can find the main table of contents for the ongoing 'Fundamentals of RGSS' series here: http://www.gamezopher.com/2018/07/03/this-is-a-test-post/
 
Last edited:

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
RGSS: MAP, TILESETS and TILEMAP

HOW TO LOAD A MAP?


It's very easy to load a map in the RPG Maker script editor. We simply need to use the load_data() function. This function only needs the path+filename as a parameter. Example:

Code:
load_data("Data/Map001.rvdata2")
We can use the sprintf() function with re-usability in mind (which borrows from the C language), but such explanation would require a longer in-depth tutorial. Anyway, here's an example of the usage:

Code:
map_id = 1
@map = load_data(   sprintf("Data/Map%03d.rvdata2", map_id)   )
What's interesting about the above snippet is that this function allows to use a special flag in the string format that acts like a dynamic variable. The %3d sequence allows to pad a digit with three leading zeros. More lines of code would be required if such feature had to be written by hand. So, it's wise to remember the sprintf() function for this kind of situation.

As you can see, it's very easy to load a map via scripting. P.S. The load_data() function can be used for all rvdata files, as demonstrated in the next section.

The Map data structure comes with so many properties such as width, height, tilemap data, linked tilesets, etc. In a future tutorial, we'll learn how to create a procedural map from scratch by code.

TILESETS

RGSS has a data structure called Tileset. I find the term a bit misleading because in truth the structure holds more than only one tileset. There are in fact 9 slots referring to a tileset type as follow: A1, A2, A3, A4, A5, B, C, D, E. The RPG Maker team should have called this class something like Tilesets or TilesetPack to strengthen the idea it's a group of tilesets, not just one.

When you organize tilesets within the RPG Maker's tileset editor, each 'pack' of tilesets are stored in an array, and this array is then saved as "Tilesets.Rvdata2" within the Data folder.

What's more, each map in RPG Maker is associated to one of those packs of tilesets stored in "Tilesets.Rvdata2". A map has in fact a property called tileset_id which refer to an index of that array.

TILESET DIAPORAMA DEMO

Here's a quick demo that allows to display each image from a pack of tilesets associated to a map on the screen. You can cycle throughout the list of tilesets associated with a map using the Left and Right arrows.

Code:
map_id = 1
@map = load_data(sprintf("Data/Map%03d.rvdata2", map_id))

@tilesets_rvdata = load_data("Data/Tilesets.rvdata2")
@ts_pack = @tilesets_rvdata[@map.tileset_id]

@ts_images = []

@ts_pack.tileset_names.each do |str|
  @ts_images.push( Bitmap.new("Graphics/Tilesets/" + str) ) if str != ""
end

@show_tileset = Sprite.new

i = 0

loop do
  Graphics.update
 
  Input.update
 
  if Input.trigger?(:LEFT)
    i -= 1 if i > 0
  elsif Input.trigger?(:RIGHT)
    i += 1 if i < @ts_images.length-1
  end
 
  @show_tileset.bitmap = @ts_images[i]
 
end


First, we load our packs of tilesets in a variable that serves as an array: @tilesets_rvdata = load_data("Data/Tilesets.rvdata2"). Then, we find the tileset pack we need with our map's tileset id property: @tileset = @tilesets_rvdata[@map.tileset_id]. The Tileset data structure doesn't hold an array of images per se, it holds only the filenames in an array. So we create an array of bitmaps in which we use those filenames as the main parameter: @ts_pack.tileset_names.each do |str| @ts_images.push( Bitmap.new("Graphics/Tilesets/" + str) ) if str != "" end.

In summary, remember that a map hold a tileset_id that refers to the index of the 'tilesets.rvdata2' array. Each pack of tilesets has an array of 'filenames' that refer to image files in the folder. You use those filename to create bitmap objects in the code. There's more related to the Tileset data structure, such as tile collision, but it will be for another future lesson.

TILEMAP

RPG Maker has a built-in feature called Tilemap. This feature magically takes care of the rendering process of tiles assigned to it. Coding your own rendering engine would take a significant amount of efforts. It's something I plan to teach, if there's enough requests in the future. For the time being, the Tilemap class provided by the RPG Maker team does the trick with very little intervention from the coder—even if it's somewhat limited for complex mapping layouts. Here's the simplest way to init the Tilemap class:

Code:
@map = load_data("Data/Map001.rvdata2")

@tilemap = Tilemap.new
@tilemap.map_data = @map.data
In the following demo, the map's tileset image will switch at x interval of time, while preserving the tilemap data.

Code:
### SETTINGS

screen_width = 640
screen_height = 480
Graphics.resize_screen(screen_width, screen_height)

### LOAD EXISTING MAP

map_id = 1
@map = load_data(sprintf("Data/Map%03d.rvdata2", map_id))

### CREATE TILEMAP

@viewport = Viewport.new(0,0,screen_width, screen_height)
@tilemap = Tilemap.new(@viewport)
@tilemap.map_data = @map.data

### LOAD EXISTING TILESETS

path = "Graphics/Tilesets/"

tileset_arr = []
tileset_arr[0] = "Outside_A1"
tileset_arr[1] = "Inside_A1"
tileset_arr[2] = "World_A1"

### MAIN LOOP

i = 0

loop do
  @tilemap.bitmaps[0] = Bitmap.new(path + tileset_arr[i])
 
  i += 1
  i = 0 if i > 2
 
  Graphics.update
  Graphics.wait(30)
end


So, that's the basic of it. Of course, there's more to learn, but that will be for another lesson. Stay tuned.

SOURCE: http://www.gamezopher.com/2018/07/03/this-is-a-test-post/
 
Last edited:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
4,720
Reaction score
5,401
First Language
Indonesian
Primarily Uses
RMVXA
Now that you brought Tilemap class in this tutorial, now I'm curious as of how it structured. Currently, it's the only RGSS3 mystery that yet have been solved for me. By I mean structure, the table structured by table of integer. How it represent which grid to render, how is their relation, and how is map data like passability is handled, etc. Knowing that, maybe I could play with "randomly generated" map later.
 

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
Now that you brought Tilemap class in this tutorial, now I'm curious as of how it structured. Currently, it's the only RGSS3 mystery that yet have been solved for me. By I mean structure, the table structured by table of integer. How it represent which grid to render, how is their relation, and how is map data like passability is handled, etc. Knowing that, maybe I could play with "randomly generated" map later.
Yup, it's part of another upcoming tutorial I've prepared in my road map (which should be soon). For this first batch, I try to keep things as simple as possible.

I will probably rework the above tutorial on my website and explain things a bit differently.

It's difficult to edit tutorial to more than one sources, so keep on eye on my blog as well for updates.
 
Last edited:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
4,720
Reaction score
5,401
First Language
Indonesian
Primarily Uses
RMVXA
Good luck, I reckon that explaining how autotiles works won't be an easy matter too.
 

Elder

Villager
Member
Joined
Mar 14, 2012
Messages
20
Reaction score
4
First Language
French
Primarily Uses
I'm currently writing a roadmap, which can keep us busy with tutorials for the rest of the year. There are going be three ongoing series.
  • 'Coding Fundamentals' Series. It will teach coding in general to help to start with RGSS. This course will feaure a quick primer of the Ruby language. Binary and Hexadecimal System. Bitwise operations. Regular Expressions. Data Structures and Algorithms. Etc.
  • 'RGSS Fundamentals' Series. It will deal will the basics of RGSS with fun demos and workshops.
  • 'Dissection of RPG Maker VX ACE Default Scripts' Series. This course will offer an analysis of every sections of code written by the RPG Maker team, from A to Z, and how you can tweak it for your needs with no hassle.
  • 'RGSS++' Series. A few years ago I rewrote the entire scripting section of RPG Maker from scratch for my own personal needs. The structure is friendlier, easier to understand and much shorter. I'd like to revise them and teach how to do it until it's fully available for the public.
I'm also planning a few bonus projects (maybe with the support of *******) such as creating a few projects with RGSS, with all zipped projects and sources. I have plans for mini-games (Tic-Tac-Toe, Chess, Cards). Creating slick HUDs and Menu systems. More advanced projects such as a battle system. Advances graphics effects, etc.

Let's hope it will be handy. Keep an eye on this thread. More updates are coming on www.gamezopher.com as well.
 
Last edited:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Trading has been halted on the TSX (Canadian stock market) because of "technical issues". Suspicious... I'm bracing myself for a sea of red tomorrow lol
The Loco-Motion song pre-dates the dance. Meaning the lyrics are kinda misleading. "Everybody's doing a brand new dance now"... No they weren't, you just used peer pressure to trick everyone into going along with it.
Love it when someone confuses "RPG Maker (or script/plugin) has a bug" with "I didn't set it up right and it's not working as I want (or gives an error)"
Is animation really as hard as I think it is?
Out of sudden, snow. Everywhere.

Forum statistics

Threads
94,579
Messages
922,038
Members
124,444
Latest member
GreenRelicanth
Top