Unit Gameform

This code is donated to the public domain by me John Biddiscombe (The Lord of Darkness) - Feb 96. Mar 96. J.Biddiscombe@rl.ac.uk Distribute freely, use any of it you like. Send me some mail, It's nice to get feedback. Enjoy ! second note - the code is a mess. I know. But it is only supposed to be a crappy game - I'm not trying to flog this as professional work. I've written all this in a 3 week period - not any more ! - But I haven't added much lately - Mar 96 and not made any effort at all to tidy any up as I go along. Some bits are inefficient - but I've left them for reasons of my own. (mainly for future expansion etc etc) I will change all the bullets and bonuses, and add some more things too. On my machine in 800x600 mode Win95 it looks fine. On windows 3.x the bullets down the screen can look dodgy due to the lack of vertical retrace sync. Looks fine on win95 I don't care about win3.x - though it might be that the win3.x machine I've been testing on is 1024x768 - Just don't know. Having said that...I've modified the game heavily so that it now runs OK on win3.x + Delphi 1, but the bullets still look dodgy. (too dark in a bright office - live in a cave - much better) I've put some comments in to guide anyone who isn't confident about this sort of thing. Apologies if it is trivial or wrong especially as I've put the comments in weeks after I wrote the code !!! you have been warned. when I put debug after a comment it usually means I put something in to test different ways of doing it, and the comment is just so I/we know The thing about games is that you try and optimize the code to do exactly what you want as fast as possible, so most of this is not - reusable - in the normal sense, but it will provide ideas. I listen to the radio while writing and often put records I hear in comments, Ignore them.

Classes

TBonus - more to be added
TBonuslist -
TBullet -
TBulletlist -
Tdoubly_linked_list - This is a bit excessive really, it works though ! } { bigger than it needs to be because of dynamic allocation and fixed limits } { by which I mean - maximum number of bullets is fixed, so linked list has limits at both ends } { .
TGame_Form - the best way to get speed increases is to use the game rules to limit wasted checks etc.
TMonster -
TMonstergroup - probablity distribution for bonuses
Tmultiple_bitmap - all the objects are created at startup, none are created or destroyed during play - changes are made to images etc by changing pointers or rects
TPowerMeter -
TScoremeter -
TSprite - .

Functions

Types

directions
indexarray
objectarray
PRectArray
spritestate
TRectArray
typeofbonus

Constants

bonusfreq
boolresult
difficulty1
difficulty1m1
difficulty2
difficulty2m1
d_factor
emptyRect
left_col_x
monsters_per_side
monsters_per_sidem1
new_monsters_per_sheet
pphit
randhoriz
randvert
right_col_x
time_average
top_row_y

Variables

blankimage
bonusallowed
bonuses
bonusgallery
bonushit
bullet_damage
Bullet_speed
creation
dir_keys
dull_bitmap
energyimage
explosionimage
frames
Game_DC
Game_Form
lastbonusscore
lastlr
lastpause
lastud
leftmonsters
levelcaption
levelsheet
MonsterBullets
monstergallery
monstersgoinghome
paused
powerlevel
rightmonsters
scorecaption
scoreimage
scoresheet
sheet
sheetmaxmon
shipbullets
shipbullettick
shipimage
shiprect
shootlevel
smallexpimage
Source_BMP
Source_DC
spaceship
square
squareimage
stick
tickcount
topmonsters


Functions


Types


directions = array[0..2] of integer;
to check motion, firing etc
indexarray  = array[0..0] of integer;

objectarray = array[0..0] of TObject;

PRectArray = ^TRectArray
only use virtual when you must !!! - static calls are much faster Delphi components are wonderful for GUI's, but avoid them at times like these
spritestate = (normal,exploding,dead);

TRectArray = array[0..0] of TRect;

typeofbonus = (powerup2,powerup5,powerup10,firespeedup,firepowerup);

Constants

bonusfreq = (65,75,80,90,100)

boolresult = 0

some changes in Borlands implementation of API WIN32 - eg IntersectRect returns Boolean not integer } { Delphi 1

difficulty1 = 160

difficulty1m1 = difficulty1-1

difficulty2 = 30

difficulty2m1 = difficulty2-1

d_factor = 1

emptyRect = (left:0; top:0; right:0; bottom:0)

left_col_x = 64

all the squares are aligned on 64 pixel boundaries

monsters_per_side = 4

monsters_per_sidem1 = monsters_per_side-1

new_monsters_per_sheet = 3

pphit = 10

randhoriz = (0,1,2)

randvert = (0,3,4)

right_col_x = 512

this means I can do fast if (xx and 63) =0 tests

time_average = 0.0029

top_row_y = 64

the smaller the faster ! } { try it on 0.001 !!!

Variables

blankimage : TRect

bonusallowed : boolean

bonuses : TBonuslist

bonusgallery : array[0..9] of TRect

bonushit : TBonus

bullet_damage : integer

Bullet_speed : integer

creation : longint

dir_keys : array[0..5] of boolean

dull_bitmap : HBitmap

the bitmap with all the sprites on it

energyimage : TRect

explosionimage : TRect

frames : array[0..3] of frame_speed_obj

Game_DC : HDC

monitoring objects } To speed things up, and to prevent delphi farting around and releasing handles to windows and DC's, I've created a single Memory DC with all the bitmaps on it. Then I use TRects which are all tiny windows on the mem DC for each sprite, each is then StretchBlt'ed onto screen (yes odd though it is, Stretchblt is slightly faster than Bitblt, or it was last time I timed it anyway). Only one DC is used for all the source BMPs and one Screen DC is requested for the main window. I've had to change this - now I'm using a TPaintbox and getting the DC every loop, which is not my prefered way of doing it. But I was having problems with win3.x.

Game_Form : TGame_Form

don't let people tell you global variables are bad. They have a fixed address, so the compiler can put them in instead of pointer referencing Normally I don't do this, but for the game, It doesn't matter I don't need to encapsulate these in any objects. If it works. Then fine.

lastbonusscore : longint

the one the DC comes with

lastlr : integer

lastpause : boolean

lastud : integer

leftmonsters : TMonstergroup

levelcaption : TRect

levelsheet : TScoreMeter

MonsterBullets : TBulletList

monstergallery : array[1..20] of TRect

current level + 3 (for monsters)

monstersgoinghome : boolean

paused : boolean

debug

powerlevel : TPowerMeter

rightmonsters : TMonstergroup

scorecaption : TRect

scoreimage : TRect

scoresheet : TScoreMeter

sheet : integer

Ship position for bullet checks

sheetmaxmon : integer

current level

shipbullets : TBulletList

shipbullettick : longint

shipimage : TRect

shiprect : TRect

Game paused flag

shootlevel : TPowerMeter

smallexpimage : TRect

Source_BMP : TBitmap

the DC used for all game drawing

Source_DC : HDC

spaceship : TSprite

square : TSprite

squareimage : TRect

stick : longint

dodgy bodge used in debug

tickcount : longint

topmonsters : TMonstergroup