This tutorial was developed using GB Studio V3.1 and is applicable to that specific version.
This tutorial is a continuation of the Dynamic Auto Scroller article. Make sure to read that first if you haven’t.
Part 2 – Screen Sized Boss
We’re now going to create a scene where the primary threat is a screen sized boss that instantly kills the player if they collide. The player must avoid random thrust forward attacks as the screen automatically scrolls left. The boss is always visible during play with a dynamic position during thrust attacks. The boss is created using the Overlay Window Layer and a sprite with the largest possible collision boundary box (128 x 128px). The sprite’s location is synchronized with the overlay window’s movement. The challenge here is that the overlay window and the sprite coordinates are relative to the screen and camera respectively. Pinned Actors won’t work as they lack the “On Hit” event, instead you’ll need to calculate the overlay window position as if it is a camera relative. Once the offset overlay position is known, set the sprite to that location. This needs to be done every frame to ensure that the boss’ collision boundary box is in the correct position.
The drill is positioned on the right side of the screen and attacks towards the left, this is both intentional and due to a limitation of the overlay. The top left corner of the overlay window can be positioned between (x = 0, y = 0) to (x = 160, y = 144), it cannot have the position (x = -80, y = 40) or any negative coordinate. I have designed this boss to work within the layer’s limitations: Using the overlay it is easy to use this to create a boss attack from right to left, bottom to top or bottom right to top left corner.
Drawing Tiles on the Overlay Window Layer
You can copy a subsection of the background layer into the window layer using VM_OVERLAY_SET_SUBMAP or VM_OVERLAY_SET_SUBMAP_EX GBVM commands. For our needs the VM_OVERLAY_SET_SUBMAP is simpler as we can use hard coded values.
Taken from the documentation:
VM_OVERLAY_SET_SUBMAP X, Y, W, H, SX, SY
|X-coordinate within the overlay window of the upper left corner in tiles
|Y-coordinate within the overlay window of the upper left corner in tiles
|Width of the area in tiles
|Height of the area in tiles
|X-coordinate within the level background map
|Y-coordinate within the level background map
At its largest, the overlay window is the same size as the screen, 160 x 144 pixels or 20 tiles horizontal and 18 tiles vertical. Ths background artwork contains a drill with the same dimensions (20 x 18 tiles) starting with the tile positioned at [x=60, y=0] to the bottom right tile [x=79, y=17].
The command below is all you need in a GVBM Script event to copy the drill from the background to the window overlay.
; copies a rectangle of background tiles from top left tile [x=60, y=0]
; to bottom right [x=79, y=17] over top of the entire overlay window layer
VM_OVERLAY_SET_SUBMAP 0, 0, 20, 18, 60, 0
Moving the Overlay Window Layer
; the overlay will scroll/move to the current position to the new position
; the position is tile based, tile (x=14, y=8) equals pixel (x=112, y=64)
VM_OVERLAY_MOVE_TO 14, 3, .OVERLAY_IN_SPEED
You will also need to set the VM_OVERLAY_WAIT so the overlay can move without stopping player movement:
VM_OVERLAY_WAIT .UI_MODAL .UI_WAIT_NONE
You only need to set the VM_OVERLAY_WAIT before you move the layer for the first time and after displaying dialogue since that event reset the wait.
Rendering Sprites on Top of the Overlay
Due to a way 3.1 renders sprites, priority only works when the overlay’s width is full screen.
Be default sprites are rendered behind the overlay window layer but can render in front of if desired. As of GB Studio 3.1 there is no inbuilt event but there is a GBVM variable, _show_actors_on_overlay which can be set to 0 or 1, 0 being behind and 1 being in front. VM_SET_CONST_UINT8 is used to set the value. This applies to all sprites on screen.
; Sprites behind of the overlay window layer
VM_SET_CONST_UINT8 _show_actors_on_overlay, 0
; Sprites in front of the overlay window layer
VM_SET_CONST_UINT8 _show_actors_on_overlay, 1
Since the overlay itself lacks native collision detection, we need to find a solution. The 1D method described in Part 1 of this article could work but it is less performant and harder to work with than standard collision group events. To leverage the inbuilt collision functionality we can use a sprite, which we will refer to as the “boss” sprite.
Setting Up the Collision Boundary Box
Within the sprite editor, you can set the collision boundary box which has a maximum 128 pixels for each axis. This unfortunately is less the maximum size of the overlay (160 x 144 pixels), if you want to cover the whole overlay there are a few solutions:
- Use multiple sprites, will impact performance
- Adjust the “boss” sprite’s position so that it aligns with where the player is likely to collide. If the player is near the top of the overlay, set the “boss” sprite to top and if near the bottom, set the “boss” sprite to bottom.
For the purposes of the tutorial the “boss” sprite only needs to be 16 tiles high (128px) as the player’s collision box is 24 pixels. Whether the player is on the top or the bottom of the screen, it will still collide.
To help visualize this, I’ve added an indicator via a sprite sheet to the “boss” sprite’s frame at the top and bottom of the collision boundaries. This exists to make sure everything is working properly, but can be removed once everything is debugged/tested.
Synchronizing the Collision Boundary Box with the Overlay Position
We need to add logic to the “boss” sprite’s “On Update” script so that its position is synchronized with the overlay. To do this we need to calculate the overlay’s position relative to the camera. This is stored in two variables that can be accessed by GBVM scripts:
|overlay’s X-coordinate within the screen
|overlay’s Y-coordinate within the screen
; get the overlay and camera position
VM_GET_UINT8 VAR_WX, _win_pos_x
VM_GET_UINT8 VAR_WY, _win_pos_y
VM_GET_INT16 VAR_CX, _camera_x
VM_GET_INT16 VAR_CY, _camera_y
The above script grabs both the Overlay position and camera position and stores them to global variables I’ve named WX and WY for the overlay position and CX and CY for the camera position (make sure to “activate” these first with a [Set Variable to Value] event before calling the GBVM Script so that they are accessible). With this information in hand, we can calculate its offset relative to the background, and store them to variables named BX and BY.
|boss sprite X
|camera x – (screen width / 2) + overlay x
|$BX = $CX – 80 + $WY
|boss sprite Y
|camera y – (screen height / 2) + overlay y
|$BY = $CX – 80 + $WY
Finally, use the Set Actor Position event using the $BX and $BY as the values. You’ll need to change the value type from tiles to px.
That’s it, you’re done, you know all the basic steps and tricks to getting an auto-scroller with an instant kill boss. The next steps are yours, you can polish the experience and optimize the collision detection. Hopefully you’ve found this two part tutorial useful and learned about some neat tricks with the Overlay Window Layer.
Aussie software developer, retro game collector, chiptune vinyl enthusiast, did someone say reinvent the wheel but buggier with less features?