Crazy Lander

Crazy Lander is another (mostly) BASIC game for Commander X16. We will introduce some new technologies not used before in our projects. It is a variation of Lander type games where we have to guide and land the space capsule to dedicated platforms using thrusters and navigating through natural and man-made obstacles. To make the game more challenging we have to be mindful of the fuel used and land gently. Few highlights:

  • Running in bitmap mode
  • It is a game of precision so we have to assure pixel perfect collision control
  • Animated obstacles unique to each level
  • Music and sound effects

Project Specs

  • Emulator Version R.38
  • Low resolution bitmap mode 320 x 240 in 16 colors on Layer 0
  • Use the menu system to choose difficulty, turn music on and off, display instructions, quit and of course start the game
  • Animated sprites for displaying capsule as well as thruster exhaust and explosion animation
  • Tile layer 1 is used for HUD and for messages and menus
  • Assembly subroutine for pixel perfect collision detection
  • 4 distinct levels with flexibility to add more
  • Scoring is based on the landing platform multiplier times the remaining fuel
  • Keyboard/Joystick controls
    • Left Arrow / Joystick Left fire left thruster pushing lander right
    • Right Arrow / Joystick Right fire right thruster pushing lander left
    • Space / Fire button main thruster pushing lander up
  • Music in the background using Music Library for BASIC programs
  • Sound effects using direct programming PSG from BASIC using VPOKE
  • 256 color splash screen

Game Graphics

We will push the limits of Commander X16 graphics with this game by using all of its capabilities. We will use Tile mode, Bitmap mode for Title screen and play field and of course Sprites. In tile mode we will load a custom Font, add few custom tiles and even use VERA for playing background music and sound effects. As a result we will use almost all of 128K of Video RAM.
During the game play the setup will be as follows:




Layer 0 will be in Bitmap mode displaying the landscape against which we will be checking collisions. However, Layer 0 is not completely static, we will use BASIC to add different dynamic and animated obstacles directly into background graphics.

Sprites will be used to display the lander, thrusters and animated destruction of the lander. The Sprite sheet will be loaded as a binary file and contains the following graphics in 256 colors:




Layer 1 is a standard 40x30 tile text mode in 16 colors. To give it “space looks” we will load a custom font with some modifications so we can display the fuel and G force gauges.

Bitmap Mode

Since this is the first game we are covering that uses bitmap mode, let's summarize quickly how bitmap modes on Commander X16 work.
In short, in bitmap mode we do not use tiles but instead we draw pixels directly. Commander X16 is capable of displaying bitmaps in several different configurations. Main differences are the resolution and how many colors per pixel we want to display and those result in the memory requirements.
In our game we will use two different bitmap mode configurations:

Title Screen: 320 x 240 pixels in 256 colors



Game Screen: 320 x 240 pixels in 16 colors




Clearly for the Title Screen we use one byte per pixel and those pixels are stored in memory in sequence starting with the top left pixel, followed by one right of it and so on for 320 bytes and then we go to the second row and so on.


Game screen is more efficient and less colorful and uses 4 bits per pixel which means that each byte in memory can represent two pixels. Top four bits define the first pixel and low four bits define the second pixel next to it to the right.


One important thing to note here is that Commander X16 BASIC does not have any drawing commands and even if it did it would probably be too slow for drawing game objects in real time so we use LOAD to load graphics directly into Video RAM and then just point VERA to the correct location.

Sound

Let’s prove that even BASIC games with a little help from a music library can play music in the background and generate sound effects without much affecting the performance of the program and still remain perfectly playable.
For background music we will use the Music Player Library and the tune I chose is Blue Danube to recreate the 2001 Space Odyssey atmosphere. Ok that is a little bit optimistic but nevertheless I think it provides an interesting calm background to the stressful gameplay. The song uses three voices and piano for all three and continuously repeats.
Of course the menu has an option to turn it off if it becomes too annoying.

Sound effects are recreated using two channels. Primarily they are used for main engine and side thrusters and since they can be used simultaneously we use two separate channels. We also use both channels for explosion.

Collision detection

This part of code is obviously the most interesting because if we want to have a really smooth and fair game we have to implement “pixel perfect” collision detection. The goal is pretty simple. We have to check every single pixel of our lander and check if any overlaps any non black pixel on the background. It really doesn’t matter if we crash into a mountain or one of the animated parts of the background. 
Unfortunately BASIC simply can’t handle checking all the pixels that our lander overlaps in every cycle of game loop so we have to write a collision detection routine in assembly and call it from BASIC and then have a way to return the result back to BASIC.
Collision detection routine is about 1K bytes long and is loaded into memory starting at location $8000. So we call it from BASIC with simple call SYS $8000 And then we check if there was collision detected by reading memory location 6 using PEEK command. In BASIC Code that simply looks like this:

590 SYS $8000:IF PEEK(6)<>0 THEN GOTO 2000

Clearly if memory location 6 contains a non zero value there was a collision and we have to handle it otherwise we continue the execution of the Game loop.

At the end of this post I included a link to all the source code, including Assembly of collision detection. The detailed description is beyond the scope of this tutorial but just a few hints if you want to determine exactly how it works here are some pointers:

  1. It first reads the X and Y position of the Sprite 1 and stores it in local memory
  2. It then calculates the VRAM location of top left byte of graphics overlapped by sprite using the following formula: $2000 + Y*160+X/2
  3. This is followed by copying the VRAM content to local memory. We need to copy 16x16 pixels or 8x16 bytes.
  4. Because each byte in Video memory contains two pixels the sprite can be aligned to top or low nibble, therefore we need to choose the correct sprite mask.
  5. Now that all the heavy lifting is done, we simply run a loop and perform a logical AND function between the background and sprite mask.

Memory organization

CPU Memory

Location Description
$0801 Start of Basic Program
$8000 Start of COL.PRG, assembly collision detection function
$9000 Start of PLAY.PRG, Music Player
$9800 Start of Music data

Video memory

Memory range VERA Setting Size Description
$00000 - $01FFF $00 - MapBase $2000 Layer 1 HUD (128 x 2 x 32 = 8K)
$02000 - $0B5FF $10 - MapBase $9600 Layer 0 Background (320 x 240 / 2)
$0B800 - $1E3FF $5C - TileBase $12C00 Title Screen (320 x 240 = 75K)
$1E800 - $1EBFF $F4 - Tile Base $400 Font (128 x 8 = 1K)
$1EC00 - $1F7FF $60,$F - Pointer $C00 Sprites (16 x 16 x 12 = 3K)
$1F800 - $1F9BF $1C0 Free 448 bytes

Source Code Organization


Line Description
0-100 Setup
Game play loops and main entry points
100 Configure Graphics and Sound
200 Start of New Game
300 Set Level
400 New Life
500 Game loop start
700 Display main thruster
1000 Level 1 Custom function
1100 Level 2 Custom function
1200 Level 3 Custom function
1300 Level 4 Custom function
2000 Check landing
2100 Crashed
2200 Successfully landed
2500 Display Explosion animation
3000 Set Level 1 variables
3100 Set Level 2 variables
3200 Set Level 3 variables
3300 Set Level 4 variables
Display Functions
5000 Display Crash or Game Over Messages
6000 Game Won Message
7000 Display Score
7100 Display Descent rate
7200 Display Fuel gauge
7300 Display Message frame
8000 Display HUD on Layer 1
8500 Display Options
Graphics settings
10000 Set Layer 0 to Game play bitmap
10500 Set Layer 0 to Title screen
10800 Redefine color palette (blues and pure yellow)
10900 Return to default palette (for title screen)
11000 Configure Sprites for Lander and Thruster flame
Menu and Options
13000 Display Options
13100 Process Options
13500 Configure Options
Sound and Music
14000 Configure Voice 0 and 1 for main engine and side thrusters
14200 Load Music to memory
14500 Music data
14700 Music ON
14800 Music OFF

Files

Files used by the game:

Filename Description
CRAZYLANDER.BAS Main BASIC Program
COL.PRG Machine code function for collision detection
PLAY.PRG Music Library for BASIC programs
FONT.BIN Custom font
LANDER.BIN Spritesheet
TITLE.BIN Title Screen bitmap
LEVEL1.BIN Level 1 bitmap
LEVEL2.BIN Level 2 bitmap
LEVEL3.BIN Level 3 bitmap
LEVEL4.BIN Level 4 bitmap

Link to all the files is available on GitHub here.

Comments

Popular posts from this blog

Commander X16 Premium Keyboard

Default Palette

Hello VERA (BASIC vs C vs Assembly)