The easiest way to understand the role of the viewport is to imagine them as layers or screens.
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.
Do the following steps:
1-) Open RPG Maker and open the Script Edition (F11).
2-) Delete every piece of code there. Absolutely everything.
3-) Insert a new entry and name it something like “My Program”
4-) Enter the following piece of code in the editor.
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)
MIMIC 3DS LAYOUT WITH VIEWPORTS
We can do a fun project and mimic the layout of the 3DS handheld console for testing viewports.
screen_width = 640
screen_height = 480
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
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:
dir = Input.dir4
my_sprite_B.y += 1
my_sprite_B.x -= 1
my_sprite_B.x += 1
my_sprite_B.y -= 1
See the end result in action here: