Overview:
I wrote Biker Babe one weekend as a testament to senseless violence in video games. A friend helped by composing the complementary music and by drawing some of the graphics. The overall tone and artistic impression came out exactly as I wanted. Ironically, I now believe video game violence needs to be monitored to prevent the desensitization to humanity.
Game Design:
Biker Babe is a platform shooter with several levels. It is designed to be simple but absurd. To win, all you need to do is move Biker Babe to the far right end of each level while avoiding perverts, aliens, werewolves, and the typical male narcissist. The game is over when Biker Babe dies. That happens when she falls to an off screen location or gets way to close to an enemy.
A woman with a shotgun visually represents the playable character (Biker Babe). She has the ability to move left, right, jump or shoot and is affected by simulated gravity. Jumping is executed with a single button push. However, shooting requires two; the first cocks the gun and the second shoots. Animation is limited to a three-frame cycle for walking both right and left. Jumping requires one frame. Cocking the shotgun requires three-frames and halts player movement until complete.
There are several types of enemies. Each cycle through three frames of animation when walking and three addition frames are cycled when the enemy is blown apart. The first enemy (a pervert) only moves right and looks like an foul overweight male. In all, there are three left-only moving enemies. One looks innocent; but he is a pervert is disguise. Other enemies looks like a wizard and aliens. Each of the previously mentioned characters cannot junp. So, they drop of the screen when not supported by a platform. The werewolf is the exception. It is a left-only moving character. It is faster than the others and will jump when encountering the edge of a platform. The narcissist is the last character. It is left-only moving and fast. I can't recall if he jumps. Anyhow, all enemies are blown apart if hit by shot. After cycling the death animation, the enemies' image becomes part of the background. An enemy at that state cannot kill the player character.
There are multiple levels. The first looks like a park the second looks medieval. There is one that requires leaping through the trees to complete and another is an alien spaceship. They all look like a poorly drawn coloring book; takes the edge off the violence.
The game utilizes Protracker mods for theme music and background music. A friend composed both of these awesome tracks. Thanks! The game wouldn't be the same without them!
Game Development:
The following is a detailed explanation of the key design choices I made while developing this game. The code snippets are taken from BikerBabe.s.
[deleted code...]
lea backname,a1
moveq #0,d0
CALLEXEC OpenLibrary
tst.l d0
beq QUIT
move.l d0,_BackBase
move.l _BackBase,a6
moveq #1,d0
jsr -30(a6)
tst.l d0
bne QU
Games run best without the OS especially when the game reads and writes directly to the hardware devices. So, the OS is halted and a snapshot of the current state is recorded so it can be restored when the game exits. The BackStab library contains a routine to do this. So, let's use it!
[deleted code...]
SETUP move.w #32,$DFF1
When coding a game, I prefer PAL over NTSC because it gives more clock cycles during the vertical blank period - err... I mean, PAL allows more pretty smooth moving graphics than NTSC.
[deleted code...]
MOVECOP lea CList1,a1
move.l a1,$DFF080
move.w #$FFFF,$DFF088
move.w #$83C0,$DFF0
I cool feature of the Amiga is writing custom code for the Copper chip. My Copper list is used to create the pretty blue shaded background. However, one might use it to trace the raster as it is drawn in real time!
[deleted code...]
MAIN cmp.b #$45,Key
beq QUIT
cmp.w #195,BabeY
bgt DEAD
cmp.w #212,Distance
bge S1ANIM
jsr SHOOT
jsr DOMAIN
cmp.b #255,Help
beq mn6
cmp.w #18,PervA
bge mn5
move.w PervX,d0
move.w PervY,d1
sub.w BabeX,d0
bpl mn1
neg.w d0
mn1 sub.w BabeY,d1
bpl mn2
neg.w d1
mn2 add.w d0,d1
cmp.w #12,d1
ble TOUCH
mn5 cmp.w #18,BervA
bge mn6
move.w BervX,d0
move.w BervY,d1
sub.w BabeX,d0
bpl mn3
neg.w d0
mn3 sub.w BabeY,d1
bpl mn4
neg.w d1
mn4 add.w d0,d1
cmp.w #12,d1
ble TOUCH
mn6 jmp MA
This looks like a sloppy wrapper routine for the main routine, DOMAIN. This code iterates though all the possible ways which the game may end. End key pressed -Babe fell off screen - Level completed - Or, one of the two enemies got too close.
[deleted code...]
TOUCH move.w #45,Count
move.w #3600,BabeD
move.w #36,BabeA
move.w #15,BabeS
t1 jsr DOMAIN
sub.w #1,BabeS
bpl t2
move.w #6,BabeS
add.w #1800,BabeD
t2 sub.w #1,Count
bpl
You were touched by a pervert and the end animation needs to play before the game over is displayed.
[deleted code...]
DEAD cmp.w #9,Level
bne de0
cmp.w #200,Distance
bge THE
We fell off the screen but if this is the last level and we are at the end, the game is won.
[deleted code...]
S1ANIM add.w #1,Lev
The SxANIM routines are all in-game animation routines.
[deleted code...]
MVBACK btst.b #0,$DFF005
beq MVBACK
mb0 cmp.b #$30,$DFF006
bne mb0
move.l _BitMapY,d1
move.l _BitMapN,d0
move.l d1,_BitMapN
move.l d0,_BitMa
If you swap buffers while the CRT is drawing the screen, a noticable rift will appear in your game screen. So, we wait for the raster to reach the vertical blanking period (The time after the screen is drawn but before the next time it is drawn). Then, we swap buffers. This is an ideal time to begin writing to the alternate buffer because the display hardware isn't controlling the bus.
[deleted code...]
ADDMAP move.w #1,d1
ap1 move.l a1,a3
move.l CurMap,a0
lea BackMap,a4
move.w BMapOff,d7
sub.w d1,d7
cmp.w #13,d7
bge ap5
cmp.w #0,d7
blt ap5
move.w Distance,d6
move.w BMapOff,d7
sub.w d1,d7
ap3 lea 64(a3,d6),a3
move.w d7,d0
mulu #2304,d0
lea 64(a3,d0),a3
lsr.w #1,d6
add.w d6,a0
lsl.w #7,d7
lea 64(a0,d7),a0
moveq #0,d0
move.b (a0)+,d0
divu #20,d0
swap d0
lsl.w #1,d0
add.w d0,a4
swap d0
mulu #720,d0
add.w d0,a4
moveq #4,d5
jsr BLTWAIT
move.l #$FFFFFFFF,$DFF044
move.l #$0026007E,$DFF064
move.l #$09F00000,$DFF040
ap4 move.l a4,$DFF050
move.l a3,$DFF054
move.w #$0481,$DFF058
add.l #30000,a3
add.w #8000,a4
jsr BLTWAIT
dbf d5,ap4
ap5 dbf d1,ap1
r
The background is rendered using the classic tile technique. That is, tiles are taken from a source bitmap (The GetMap - see background image) and placed in the background during game play. We know what tile goes where because a data array (the LevMap) stores the tile arrangement. The code near BLTxxx annotation sets up the blitter hardware for an asyncronous data movement.
[deleted code...]
CLEANUP move.l _BitMapN,a5
add.l #158000,a5
move.l (a5)+,a0
jsr CLNDUDE
cu2 move.l _BitMapN,a5
add.l #160000,a5
cb2 move.l (a5)+,a0
jsr CLNDUDE
cb6 move.l _BitMapN,a5
add.l #156000,a5
move.l (a5),a0
move.l #0,(a5)+
jsr CLNDUDE
cu8 move.l _BitMapN,a5
add.l #154000,a5
move.l (a5),a0
move.l #0,(a5
All moving characters are blits (as opposed to a sprite). So, we need to restore the background (which we saved previously) before we move the character. Sprites do not require these extra data movements but they have size, number, and color restrictions.
[deleted code...]
QUIT tst.l _BackBase
beq q1
jsr mt_end
move.l _BackBase,a6
jsr -36(a6)
q1 tst.l _BckGrnd1
beq q2
move.l _BckGrnd1,a1
move.l #162000,d0
CALLEXEC FreeMem
q2 tst.l _BckGrnd2
beq q3
move.l _BckGrnd2,a1
move.l #162000,d0
CALLEXEC FreeMem
q3 move.l #0,d0
r
Oh yeah, before halting the OS, we did request the memory we needed for the game. This prevents writing over data currently used by the OS which would prevent the OS from properly restarting. So, the memory is freed before the program is exits.
[deleted code...]
CList1 dc.w $102,$0000
dc.w $E0,$0000
dc.w $E2,$0000
dc.w $E4,$0000
dc.w $E6,$0000
dc.w $E8,$0000
dc.w $EA,$0000
dc.w $EC,$0000
dc.w $EE,$0000
dc.w $F0,$0000
dc.w $F2,$0000
dc.w $FFFF,$FFFE
dc.w $1001,$FF00
dc.w $180,$000F
dc.w $2001,$FF00
dc.w $180,$000E
dc.w $3001,$FF00
dc.w $180,$000D
dc.w $4001,$FF00
dc.w $180,$000C
dc.w $5001,$FF00
dc.w $180,$000B
dc.w $6001,$FF00
dc.w $180,$000A
dc.w $7001,$FF00
dc.w $180,$0009
dc.w $8001,$FF00
dc.w $180,$0008
dc.w $9001,$FF00
dc.w $180,$0007
dc.w $A001,$FF00
dc.w $180,$0006
dc.w $B001,$FF00
dc.w $180,$0005
dc.w $C001,$FF00
dc.w $180,$0004
dc.w $D001,$FF00
dc.w $180,$0003
dc.w $E001,$FF00
dc.w $180,$0002
dc.w $F001,$FF00
dc.w $180,$0001
dc.w $FF01,$FF00
dc.w $180,$0000
dc.w $FFFF,$FF
This is the copper list. It is a program executable by the copper chip. This is clearly one of the coolest features of the Amiga. This is what makes midscreen resolution/palette changes possible.
|