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.
Preliminary Steps
- Open RPG Maker VX and open the Script Editor (F11).
- Delete every pieces of code there. Absolutely everything.
- Create a new entry and name it ‘My New Script’ or a similar title.
- Copy and paste the following piece of code in the editor.
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 { Graphics.update }
Mimic 3DS layout with viewports
We can do a fun project and mimic the layout of the 3DS handheld console for testing viewports.
### 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 { Graphics.update }
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 or keyboard input
To see the top viewport in action, you can add the following snippet in the loop-do block:
loop {
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
}
See the end result in action here:
Leave a Reply