I have developed a new framework for my current game, and would like to invite the Blitz community to pull it apart and insult my coding as much as you can.
Essentially i'd like to know how you would improve upon it.
Features:
* Object based Game States
* Multiple screen layers in single game list
* Delta time
* Free
Essentially i'd like to know how you would improve upon it.
Features:
* Object based Game States
* Multiple screen layers in single game list
* Delta time
* Free
'FRAMEWORK 'Si Dunford, Nov 2007 'V1.01 ' SuperStrict Const MAXFramerate:Float = 60.0 '# SCREEN LAYERS Const LAYER_BACKGROUND% = 0 Const LAYER_SCENERY% = 1 Const LAYER_PLAYER% = 2 Const LAYER_ENEMIES% = 3 Const LAYER_INTERFACE% = 4 '# Initialise the drawing layers Graphics 800, 600 Tlayers.Create( 5 ) '############################################################ '# GAME LOOP Global game:TGame = New TGame.Create( New TStateSplash ) '# Run the game game.start() '############################################################ '# GAME STATES Type TState Method enter() ; End Method Method update() ; End Method Method leave() ; End Method End Type '============================================================ Type TStateSplash Extends TState Global timeout% = MilliSecs() + 2000 '---------------------------------------- Method enter() '# Create Static Text New TText.Create( "TESTING", Null, -1, 100 ) New TText.Create( "(c) Si Dunford", Null, -1, 200 ) '# Create background New TBackground.Create() End Method '---------------------------------------- Method update() If MilliSecs() > timeout Then game.changeState( New TStateInit ) End Method '---------------------------------------- Method leave() TText.zap() End Method End Type '============================================================ Type TStateInit Extends TState '---------------------------------------- Method enter() TLayers.zap() game.changeState( New TStateStart ) New TFps.Create( 10,10 ) '# Frames per second counter End Method '---------------------------------------- Method leave() '# Create background '# Needed here again cos we destroyed the whole game list in enter) New TBackground.Create() End Method End Type '============================================================ Type TStateStart Extends TState '---------------------------------------- Method enter() New TText.Create( "GAME FRAMEWORK", Null, -1, 300 ) New TMenu.Create( "Start Game", Null, -1, 350, New TStatePlay, True) New TMenu.Create( "Exit", Null, -1, 400, New TStateQuit) End Method '---------------------------------------- Method leave() TText.zap() TMenu.zap() '# Create player and enemies End Method End Type '============================================================ Type TStatePause Extends TState '---------------------------------------- Method enter() '# Create Static Text New TText.Create( "PAUSED", Null, -1, 300 ) New TMenu.Create( "Continue", Null, -1, 350, New TStatePlay, True) New TMenu.Create( "Quit game" , Null , -1, 400 , New TStateInit) game.pause() End Method '---------------------------------------- Method leave() TText.zap() TMenu.zap() game.pause( False ) End Method End Type '============================================================ Type TStatePlay Extends TState '---------------------------------------- Method enter() New TText.Create( "RUNNING", Null, -1, 300 ) New TText.Create( "Press ESC to pause", Null, -1, 350 ) End Method '---------------------------------------- Method update() If KeyDown( KEY_ESCAPE ) Then game.changeState( New TStatePause ) End Method '---------------------------------------- Method leave() TText.zap() End Method End Type '============================================================ Type TStateQuit Extends TState Method enter() game.quit() End Method End Type '############################################################ '# GAME SYSTEM Type TGame 'v1.1 Field _paused:Int = 0 Field _currentState:TState Field _hasQuit% = False '# Delta Timing Global _deltaTime:Float Global _delay% '---------------------------------------- Method Free() _currentState.leave() End Method '---------------------------------------- Method Create:TGame( initialState:TState ) Final _currentState = initialState Return Self End Method '---------------------------------------- Method _Update() Final '# Update Delta Timing _deltaTime = (MilliSecs() - _Delay ) * 0.001 '# px / second _Delay = MilliSecs() '# Update Gamestate _currentState.update() update() '# Update Game objects TGameobj.updateAll() '# Draw screen layers ( Clearing screen between layers ) TLayers.draw() End Method '---------------------------------------- Method update() ; End Method '---------------------------------------- Method changeState( newState:Tstate ) _currentState.leave() _currentState = newState _currentState.enter() End Method '---------------------------------------- Method quit:Int() Final _hasQuit = True End Method '---------------------------------------- Method isRunning:Int() Final Return Not(_hasQuit) End Method '---------------------------------------- Function deltaTime:Float() Final Return _deltaTime End Function '---------------------------------------- Method pause( state% = True ) Final _paused = state End Method '---------------------------------------- Method paused:Int() Final Return _paused End Method '---------------------------------------- Method start() Final '# Initialise the current state _currentState.enter() '# Initialise delta Timing _delay = MilliSecs() '# Run the game loop While Not(_hasquit) 'isRunning() _update() Wend End Method End Type '############################################################ '# LAYERED GAME LIST Type TLayers 'v1,1 Global layers:TList[] ' Field items:TList '# List of objects in this layer '---------------------------------------- Function Create( count% ) layers = layers[..count] For Local element% = 0 To count -1 layers[element] = CreateList() Next End Function '---------------------------------------- Function add( obj:TGameObj, l%) layers[l].addlast( obj ) End Function '---------------------------------------- '# If you need a clear screen, create a background object in layer 0. '# In it's draw() method, do the cls. Function draw() For Local layer:TList = EachIn layers For Local obj:TGameObj = EachIn layer obj.draw() Next Next Flip End Function '---------------------------------------- Function zap() For Local layer:TList = EachIn layers layer.clear() Next End Function End Type '############################################################ '# GAME OBJECTS Type TGameObj 'v1.2 Global list:TList = CreateList() Field x:Float , y:Float Field rotation% =0 Field speed:Float =1 Field image:TImage Field gameLink:TLink Field layerLink:TLink '---------------------------------------- Function updateAll() For Local obj:TGameObj = EachIn list obj.update() Next End Function '---------------------------------------- Method update() ; End Method '---------------------------------------- Method draw() SetScale 1 , 1 SetRotation( rotation ) SetColor 255,255,255 DrawImage( image , x , y ) End Method '---------------------------------------- Method add( layer% ) Final gameLink = list.addlast( Self ) layerLink = TLayers.layers[layer].addlast(Self) End Method '---------------------------------------- Method remove() Final If gamelink Then gamelink.remove() If layerlink Then layerlink.remove() gameLink = Null layerlink = Null End Method End Type '============================================================ Type TBackground Extends TGameObj '---------------------------------------- Method Create:TBackground() add( LAYER_BACKGROUND ) End Method '---------------------------------------- Method draw() Cls End Method End Type '============================================================ Type TPlayer Extends TGameObj Method update() If KeyDown( KEY_LEFT ) Then x=x - 10 If KeyDown( KEY_RIGHT ) Then x = x + 10 If KeyDown( KEY_P ) Then game.changeState( New TStatePause ) End Method End Type '============================================================ Type TText Extends TGameObj Field text$ Field Font:TImageFont Field col% = rgb( 0 , 255 , 255 ) '---------------------------------------- Method Create:TText(Text:String , Font:TImageFont , x%, y%) Self.text = text Self.Font = Font SetImageFont( font ) If x = -1 Then x= GraphicsWidth() /2 '# Centre of screen if x=-1 Self.X = X Self.Y = Y add( LAYER_INTERFACE ) End Method '---------------------------------------- Method colour( red% , green% , blue% ) col = rgb( red, green, blue ) End Method '---------------------------------------- ' For all you americans Method color( red% , green% , blue% ) colour( red, green, blue ) End Method '---------------------------------------- Method draw() SetImageFont(Font) SetRotation 0 SetScale 1.0,1.0 SetColor getRed( col ) , getGreen( col ) , getblue( col ) DrawText Text,x - TextWidth(text) /2 ,Y End Method '---------------------------------------- '# Remove ALL objects of this type. Function zap() For Local obj:TText = EachIn list obj.remove() Next End Function End Type '============================================================ '# Frames per second counter Type TFPS Extends TGameObj 'v1.0 Field counter%, time%, fps% Field Font:TImageFont Field col% = rgb( 0 , 255 , 255 ) '---------------------------------------- Method Create:TFPS( x%, y%, Font:TImageFont =Null) Self.Font = Font SetImageFont( font ) Self.X = X Self.Y = Y add( LAYER_INTERFACE ) End Method '---------------------------------------- Method colour( red% , green% , blue% ) col = rgb( red, green, blue ) End Method '---------------------------------------- ' For all you americans Method color( red% , green% , blue% ) colour( red, green, blue ) End Method '---------------------------------------- Method update() counter:+1 If time < MilliSecs() fps = counter' <- Frames/Sec time = MilliSecs() + 1000 'Update counter = 0 EndIf End Method '---------------------------------------- Method draw() SetImageFont(Font) SetRotation 0 SetScale 1.0,1.0 SetColor getRed( col ) , getGreen( col ) , getblue( col ) DrawText "FPS: "+fps,x,Y End Method End Type '============================================================ Type TMenu Extends TGameObj Field text$ Field Font:TImageFont Field col% = rgb( 255 , 255 , 255 ) Field option:TState Field selected% = False Field dir% = -1 Field fade% = 255 '------------------------------------------------------------ Method Create:TMenu(Text:String , Font:TImageFont, x% , y%, option:TState, selected%=False) Self.text = text Self.Font = Font SetImageFont( font ) If x = -1 Then x= GraphicsWidth() /2 '# Centre of screen if x=-1 Self.X = X Self.Y = Y Self.option = option Self.selected = selected add( LAYER_INTERFACE ) End Method '---------------------------------------- Method colour( red% , green% , blue% ) col = rgb( red, green, blue ) End Method '---------------------------------------- ' For all you americans Method color( red% , green% , blue% ) colour( red, green, blue ) End Method '------------------------------------------------------------ Method draw() Local str$ = text SetImageFont(Font) SetRotation 0 SetScale 1.0,1.0 If selected Then SetColor fade , fade , fade str = "["+text+"]" Else SetColor getRed( col ) , getGreen( col ) , getblue( col ) End If DrawText Text,x - TextWidth(text) /2 ,Y End Method '------------------------------------------------------------ Method update() If KeyDown( KEY_ENTER ) Then game.changestate(TMenu.getOption() ) If KeyHit(KEY_UP) Then prevItem() If KeyHit(KEY_DOWN) Then nextItem() fade:+ dir * Int(255.0*game.deltatime()) '# 1 colour phase/second If fade > 255 Then fade = 255 dir = - dir ElseIf fade < 0 Then fade = 0 dir = - dir EndIf '# Required to stop key presses running over into sub-menu's FlushKeys() End Method '------------------------------------------------------------ Function getOption:TState() For Local o:TMenu=EachIn list If o.selected Then Return o.option Next End Function '------------------------------------------------------------ Function prevItem() Local last:Tmenu = Null Local item:Tmenu For Local o:TMenu=EachIn list If o.selected Then o.selected = False '# Remove old selection item = last '# Select the previous item End If last = o Next '# Wrap around If Not item Then item = last '# Select item item.selected = True End Function '------------------------------------------------------------ Function nextItem() Local first:Tmenu = Null Local item:Tmenu Local found% = False For Local o:TMenu=EachIn list If Not first Then first = o If found Then item = o found = False End If If o.selected Then o.selected = False '# Remove old selection found = True End If Next '# Wrap around If Not item Then item = first '# Select item item.selected = True End Function '---------------------------------------- '# Remove ALL objects of this type. Function zap() For Local obj:TMenu = EachIn list obj.remove() Next End Function End Type '############################################################ '# Colour functions Function rgb%(r%, g%, b%) ; Return (r Shl 16) + (g Shl 8) + b ; End Function 'Function getA%(argb%) ; Return argb Shr 24 & $ff ; End Function Function getRed%(rgb%) ; Return rgb Shr 16 & $ff ; End Function Function getGreen%(rgb%) ; Return (rgb Shr 8) & $ff ; End Function Function getBlue%(rgb%) ; Return rgb & $ff ;End Function '