Shmup Game First Steps
After playing with both AMOS and Blitz Basic, I initially had an overall poor impression of Blitz Basic mostly due to stability issues. This was disappointing to me because it seemed pretty clear that AMOS was a little bit slower, but at least it did seem more approachable.
Ultimately though, when I reflected on the various game ideas I had floating around in my head, I really figured I would end up quickly outgrowing AMOS from a performance perspective. So I decided I would look at Blitz Basic again, but try to see what I could do (if anything) to work around the stability issues I had run into earlier. I should note at this point that yes, I did have the runtime debugger enabled, so I don't think that was the cause of any of the crashes I was seeing. That was the first thing I checked when I was having issues. Some of the crashes weren't even occurring while a program was running anyway...
First, I decided that I would not use the "mousable labels" support. Blitz's editor "TED" pops up a side navigation
pane showing your program's labels for quick navigation only if your program has any. A "mouseable label" is just an
ordinary label that you would use with GOTO
or GOSUB
with the exception that it should start with a period, e.g.
.renderPlayfield:
instead of renderPlayfield:
. I had noticed some random crashing that would occur when I was
fiddling around with some of the sample programs that included these types of labels. Additionally, I had encountered
a severe problem with the updated TED version included in the Blitz Support Suite ("SuperTED" I believe it was
called? Or might have been the update before that?) where it would immediately crash when opening a program with any
of these types of labels. Definitely seemed to me that the editor support for it was at least partially broken... at
least for me, though I'm not sure what I could have done to cause these issues, heh.
Second, I had finished completely reading through the user guide (which is honestly a quick read, less than 100
pages) and had run across the recommendations and warnings for using "Blitz mode" (which you will undoubtedly want
to use for performance reasons). Most importantly, any disk access or other concurrent OS processing that occurs
while a program is running in Blitz mode (or as it first enters Blitz mode) can cause crashes! How about that. I
suppose it's possible that this accounts for at least some of the instability I was encountering before. The user
guide recommends doing something like VWait 120
just before a BLITZ
call to ensure that any disk buffers have
had time to be flushed (evidently the OS does so every two seconds?). It notes that there is no software method to
check for whether stuff like disk activity has completed so this seems like the only way to protect against this
kind of crash. Also it is important to note that none of the sample programs that use Blitz mode do this, thus
furthering my belief that this was at least part of the problem I had run into when previously toying about with
Blitz Basic.
Anyway... so far so good! I've only had one crash all weekend, and I believe that actually was related to my misuse of Blitz mode and/or of some dual playfield slice functionality. For most of the weekend, I was booted up into a Blitz Basic 1.7 floppy and not using the hard disk functionality provided by my ACA500plus. I wanted to remove as much other possible factors as I could and that seemed like a big one. Late this afternoon I resumed using the ACA500plus and CF card hard disk and have so far been running completely stable as well with that configuration. Fingers crossed that it stays that way.
Without having to worry about crashes, I was able to get a lot of experimentation and learning done and got some very preliminary work done on a basic vertical shmup type game. Nothing fancy, but I'm happy for a few hours work with lots of flipping around through manuals slowing things down (really want to get a physical copy of the Blitz Basic Reference Manual... I hate having to constantly look up commands in PDFs).
I'll try not to make posting big code dumps a habit on this blog, but here's what I've got so far:
; shmup test
#KEY_ESCAPE = $45
#KEY_UP = $4c
#KEY_DOWN = $4d
#KEY_LEFT = $4f
#KEY_RIGHT = $4e
#KEY_SPACE = $40
#SPEED = 2
#STATUSBAR_HEIGHT = 32
#PLAYFIELD_HEIGHT = 256 - #STATUSBAR_HEIGHT
#PAL_GAME = 0
#BMP_STATUSBAR = 0
#BMP_PLAYFIELD = 1
#SLICE_STATUSBAR = 0
#SLICE_PLAYFIELD = 1
#SHAPE_LRG_ENEMY = 0
#SHAPE_MED_ENEMY = 2
#SHAPE_SML_ENEMY = 4
#SHAPE_PLAYER = 6
#SHAPE_BULLETS = 16
#SHAPE_EXPLOSION = 20
#SHAPE_POWERUPS = 25
ASSET_ROOT$ = "Projects:resources/"
ASSET_SHAPES$ = ASSET_ROOT$ + "shmup.iff"
ASSET_STARS_BG$ = ASSET_ROOT$ + "shmup_stars_bg.iff"
DEFTYPE .w
Statement ASSET_LoadPalette{pal}
SHARED ASSET_SHAPES$
LoadPalette pal,ASSET_SHAPES$
End Statement
Statement ASSET_LoadStarsBg{destBmp}
SHARED ASSET_STARS_BG$
BitMap destBmp,320,512,5
LoadBitMap destBmp,ASSET_STARS_BG$
Scroll 0,0,320,256,0,256,destBmp
End Statement
Statement ASSET_LoadShapes{}
SHARED ASSET_SHAPES$
BitMap 0,192,256,5
LoadBitMap bmp,ASSET_SHAPES$
GetaShape #SHAPE_LRG_ENEMY,0,0,32,32
GetaShape #SHAPE_LRG_ENEMY+1,32,0,32,32
GetaShape #SHAPE_MED_ENEMY,64,0,32,16
GetaShape #SHAPE_MED_ENEMY,96,0,32,16
GetaShape #SHAPE_SML_ENEMY,64,16,16,16
GetaShape #SHAPE_SML_ENEMY,80,16,16,16
For i=0 To 4
GetaShape #SHAPE_PLAYER+i,0+(i*16),32,16,24
GetaShape #SHAPE_PLAYER+i+5,0+(i*16),56,16,24
Next i
GetaShape #SHAPE_BULLETS,80,32,16,16
GetaShape #SHAPE_BULLETS+1,96,32,16,16
GetaShape #SHAPE_BULLETS+2,80,48,16,16
GetaShape #SHAPE_BULLETS+3,96,48,16,16
For i=0 To 5
GetaShape #SHAPE_EXPLOSION+i,0+(i*16),80,16,16
Next i
GetaShape #SHAPE_POWERUPS,80,64,16,16
GetaShape #SHAPE_POWERUPS+1,96,64,16,16
GetaShape #SHAPE_POWERUPS+2,80,80,16,16
GetaShape #SHAPE_POWERUPS+3,96,80,16,16
Free BitMap 0
End Statement
Statement ASSET_Load{}
NPrint "Loading palette ..."
ASSET_LoadPalette{#PAL_GAME}
NPrint "Loading stars background ..."
ASSET_LoadStarsBg{#BMP_PLAYFIELD}
NPrint "Loading shapes ..."
ASSET_LoadShapes{}
NPrint "Done loading assets!"
End Statement
; -------------------------------------------------------------------
Statement GAME_Init{}
VWait 120
BLITZ
Buffer #BMP_PLAYFIELD,16384
BitMap #BMP_STATUSBAR,320,#STATUSBAR_HEIGHT,5
Slice #SLICE_STATUSBAR,44,320,#STATUSBAR_HEIGHT,$fff8,5,8,32,320,320
Use Palette #PAL_GAME
Slice #SLICE_PLAYFIELD,44+#STATUSBAR_HEIGHT,320,#PLAYFIELD_HEIGHT,$fff8,5,8,32,320,320
Use Palette #PAL_GAME
End Statement
Statement DRAW_StatusBar{}
Use Slice #SLICE_STATUSBAR
Use BitMap #BMP_STATUSBAR
BitMapOutput #BMP_STATUSBAR
Cls 14
Print "TODO: Awesome statusbar here"
Show #BMP_STATUSBAR
End Statement
Statement DRAW_Playfield{}
SHARED scrollY, playerX.q, playerTiltOffset, animateOffset
Use BitMap #BMP_PLAYFIELD
Use Slice #SLICE_PLAYFIELD
UnBuffer #BMP_PLAYFIELD
Show #BMP_PLAYFIELD,0,scrollY
tile = #SHAPE_PLAYER+2+playerTiltOffset+(animateOffset*5)
y = #PLAYFIELD_HEIGHT-32+scrollY
BBlit #BMP_PLAYFIELD,tile,playerX,y
End Statement
;
; -------------------------------------------------------------------
;
ASSET_Load{}
GAME_Init{}
animateFrame = 0
animateOffset = 0
playerTiltOffset = 0
playerHorizAccel.q = 0
playerX.q = 320/2-32/2
scrollY = 0
DRAW_StatusBar{}
DRAW_Playfield{}
While NOT RawStatus(#KEY_ESCAPE)
scrollY = QWrap(scrollY - #SPEED, 0, 256)
animateFrame = QWrap(animateFrame+1, 0, 5)
If animateFrame = 0
animateOffset = QWrap(animateOffset+1, 0, 2)
EndIf
If RawStatus(#KEY_LEFT)
playerHorizAccel - 1
EndIf
If RawStatus(#KEY_RIGHT)
playerHorizAccel + 1
EndIf
playerHorizAccel = playerHorizAccel * 0.7
playerX = QLimit(playerX + playerHorizAccel, 0, 320-16)
playerTiltOffset = Int(playerHorizAccel)
VWait
DRAW_Playfield{}
Wend
End
So yeah, very basic and/or crude for now. It doesn't look very impressive running yet either:
All you can do is fly the ship back and forth (but hey, it animates and the ship tilts a bit from side-to-side as you move left and right... exciting, right!?). I'm using the art assets from this package on OpenGameArt. Packaged everything together with a separate simple star background and exported as an IFF.
Actually the asset management has been a slight bit of a pain so far. I first noticed that Photoshop has the ability to save as Amiga IFF, so I would pre-convert the image I was working with to indexed colour mode and set up a 32 colour table and then save as an IFF. This seems to produce something that always is loadable by Blitz Basic (and AMOS for that matter), but occasionally produces a file that Deluxe Paint says is "mangled." Also sometimes, when loaded in Blitz Basic, the palette is somewhat off. Some colours will be totally different, but most will be correct. In this case, I've noticed I can fix the problem by opening the IFF in Deluxe Paint, and if it doesn't complain that it's mangled, I can simply re-save the file and the problem goes away. My suspicion is that Photoshop saves the palette information in a different way then what Blitz Basic is expecting, but I have not investigated this fully yet. I also tried using XnConvert by exporting from Photoshop as a indexed colour PNG or GIF and then converting to Amiga IFF with XnConvert, but still have run into the same issue (I think? I might also have mixed up my working files, heh, so will need to confirm that first I guess). At any rate, I definitely still have lots to do to nail down my asset preparation process.
Next steps will be putting together some custom font routines (I'm not sure how to generate the "Blitzfonts" that Blitz Basic supports, but at any rate, I don't think that supports bitmap fonts which is what I really want to use anyway). Following that will be adding the ability for the player to shoot and then adding enemies. I'm really curious to see how quickly I run into slowdowns.