Can you guys (and girls, if any?
Some remarks:
- All interacting game objects must have at least: :update(dt) and :draw() methods.
- All game states must have at least: .init(), .update(dt) and .draw() functions.
Required methods and functions can be dummy of course, if you don't need them.
Put example scripts in same directory and run the main.hws script. Be sure to save example scripts with correct names.
Code: Select all
;
; Game template module: game.hws
;
game = {}
game.updateRate = 20 ; Default to 20 millisec = 50 fps.
game.dt = 0
game.fps = 0
; Game setup function for the user.
Function game.load()
; Our game must override this dummy function.
EndFunction
; Game update function for the user
Function game.update(dt)
; Our game must override this dummy function.
EndFunction
; Game draw frame function for the user
Function game.draw()
; Our game must override this dummy function.
EndFunction
; Our game framework init function. Calls just user game setup function for now
; and starts double buffering.
Function game.init()
game.load()
BeginDoubleBuffer()
EndFunction
; Basic game loop function for our framework.
Function game.loop(dt)
game.state.states[game.state.state].update(dt)
game.state.states[game.state.state].draw()
Flip()
EndFunction
; Set update rate for the game.
Function game:setUpdateRate(fps)
self.updateRate = 1000 / fps
EndFunction
; Get the current fps-rate.
Function game:getFPS()
Return(Round(1000 / (self.dt * 1000)))
EndFunction
; Runs the game, handles calling the game loop and timing.
Function game.run()
StartTimer(1)
StartTimer(2)
Repeat
; Try to lock the frame update rate to game.updateRate
WaitTimer(1, game.updateRate)
; Get the actual time it took to update the frame.
ftime = GetTimer(2)
ResetTimer(2)
; Delta time in seconds between the two last frames.
game.dt = game.updateRate / 1000 * ftime / game.updateRate
game.loop(game.dt)
Forever
EndFunction
; Simple game state manager
game.state = {}
game.state.states = {}
game.state.states[0] = {} ; Default state
game.state.states[0].init = Function () EndFunction ; Initialized once on startup.
game.state.states[0].update = Function (dt) game.update(dt) EndFunction
game.state.states[0].draw = Function () game.draw() EndFunction
game.state.state = 0
game.state.ids = {}
; Registers new game state by name.
Function game.state:register(statename, state)
self.states[statename] = state
InsertItem(self.ids, statename)
EndFunction
; Remove game state from manager by state name.
Function game.state:remove(statename)
self.states[statename] = {}
Local i, v = NextItem(self.ids)
While GetType(i) <> #NIL
If self.ids[i] = statename Then RemoveItem(self.ids, i)
i, v = NextItem(self.ids, i)
Wend
EndFunction
; Clears all states from manager except default state.
Function game.state:clear()
Local i, v = NextItem(self.ids)
While GetType(i) <> #NIL
self.states[v] = {}
i, v = NextItem(self.ids, i)
Wend
self.ids = {}
EndFunction
; Set active game state by name
Function game.state:set(statename)
self.state = statename
self.states[self.state].init()
EndFunction
; Get name of the current active game state
Function game.state:get()
Return(self.state)
EndFunction
Code: Select all
;
; Intro state: intro.hws
;
intro = {}
Function intro.init()
intro.counter = 0
EndFunction
Function intro.update(dt)
intro.counter = intro.counter + dt
If intro.counter >= 7
intro.counter = 0
game.state:set(0) ; Switch to default game state.
EndIf
EndFunction
Function intro.draw()
Cls()
If intro.counter < 5
drawscene()
TextOut(#CENTER, #CENTER, "GET READY: " ..Round(intro.counter))
player:draw()
Else
drawscene()
TextOut(#CENTER, #CENTER, "GO!")
player:draw()
EndIf
EndFunction
Code: Select all
;
; Player module: player.hws
;
player = {}
player.shootdelay = 1 ; Shoot delay in seconds.
Function player:init(x, y, width, height, speed)
self.x = x
self.y = y
self.width = width
self.height = height
self.speed = speed
EndFunction
Function player:draw()
SetFillStyle(#FILLCOLOR)
Box(self.x, self.y, self.width, self.height, #GREEN)
EndFunction
Function player:update(dt)
If IsKeyDown("LEFT")
self.x = self.x - self.speed * dt
If self.x < 0 Then self.x = 0
ElseIf IsKeyDown("RIGHT")
self.x = self.x + self.speed * dt
If self.x > 800 - self.width Then self.x = 800 - self.width
EndIf
self.shootdelay = self.shootdelay + dt
If IsKeyDown("SPACE") Then self:shoot()
EndFunction
Function player:shoot()
If self.shootdelay >= 1
Local missile = {}
missile.x = self.x + (self.width / 2)
missile.y = self.y
pmissiles:add(missile) ; Add player missile.
self.shootdelay = 0 ; Reset shoot delay.
EndIf
EndFunction
Code: Select all
;
; Player missiles module: pmissiles.hws
;
pmissiles = {}
pmissiles.missiles = {} ; Table for missiles: missile = { x, y }
pmissiles.width = 2
pmissiles.height = 5
pmissiles.speed = 100
Function pmissiles:add(missile)
InsertItem(self.missiles, missile)
EndFunction
Function pmissiles:update(dt)
Local i, v = NextItem(self.missiles)
While GetType(i) <> #NIL
; Move missile upwards
v.y = v.y - self.speed * dt
If v.y < 0 ; Remove missile outside the screen.
RemoveItem(self.missiles, i)
Else
; Check collision against aliens.
EndIf
i, v = NextItem(self.missiles, i)
Wend
EndFunction
Function pmissiles:draw()
Local i, v = NextItem(self.missiles)
While GetType(i) <> #NIL
SetFillStyle(#FILLCOLOR)
Box(v.x, v.y, self.width, self.height, #WHITE)
i, v = NextItem(self.missiles, i)
Wend
EndFunction
Code: Select all
;
; Main module: main.hws
;
@DISPLAY {Width = 800, Height = 600, Title = "Game State Example"}
; include game framework
@INCLUDE "game.hws" ; include our game framework template
; Include game objects
@INCLUDE "player.hws" ; include player object
@INCLUDE "pmissiles.hws" ; include player missiles object
; Include game states
@INCLUDE "intro.hws" ; include intro state
Function game.load()
game.state:register("intro", intro) ; Register new game state
game:setUpdateRate(50) ; Set the game update rate
player:init(380, 500, 40, 20, 120) ; Setup game object
game.state:set("intro") ; Start in intro state
EndFunction
Function game.update(dt)
player:update(dt)
pmissiles:update(dt)
EndFunction
Function game.draw()
drawscene()
player:draw()
pmissiles:draw()
EndFunction
Function drawscene()
Cls()
SetFillStyle(#FILLCOLOR)
Box(0, 520, 800, 600, #GRAY)
EndFunction
; Game time!
game.init()
game.run()