It has a fixed time step and a probably really poor use and abuse of CallFunctionFast for pseudo objects. And it should compile and run in the demo version of purebasic(because that's all I had)! I've been away from this beautiful language for some time now so I expect there to be many mistakes or errors that I haven't encountered yet.
Code: Select all
Enumeration 0
#Ball
#Brick0
#RGB1
#RGB2
#RGB3
#RGB4
#Text1
#Text2
#Text3
#Paddle1
#Particle1
#Sheet1
#Paddle2
#Paddle3
#Pickup0; base image
#Pickup1
#Pickup2;
#Pickup3;
#Pickup4;
#Pickup5;
#Pickup6;
#Pickup7;
#Pickup8;
#Pickup9;
#Pickup10;
#Font1
EndEnumeration
;-Object structure
Structure Object
id.l ; set when added to object list
type.l ;
*parent;
x.d;
y.d;
w.d; ; width/height
h.d;
dir.d[2] ; movement vector
speed.l
intangible.b ; used for skipping objects that don't need collision testing such as particles
removed.b; removes from object list
expires.l ; similar to removed.b but delayed!
; function pointers
*fnConstructor ; unused, but could probably replace type
*fnDestructor
*fnRender
*fnStep
*extends ; pointer to an object defining structure
EndStructure
Structure BrickObject
hp.l
gfx.b;
EndStructure
Structure PickupObject
type.l
EndStructure
Structure PaddleObject
size.l
x2.d
EndStructure
Structure BallObject
lastParticleCreation.l
EndStructure
Structure ParticleObject
EndStructure
Structure Vector
x.d
y.d
EndStructure
Structure Profile
tps.l
tpsc.l
tpst.l
count1.l
count2.l
EndStructure
;-Game state structure
Structure State
width.l ; window dimensions
height.l
dt.l
now.l
running.b
active.b ;
score.l
balls.l
bricks.l
gameover.b;
continues.l
drawing.Profile
logic.Profile
uuidAccumulator.l ; used to create unique id's for objects
*paddle.Object; used for
Array objectsList.Object(1)
Array objectsQueue.Object(1)
EndStructure
;-Object declarations
Declare Paddle(*state.State, *ref.Object, x.l, y.l) ; constructor
Declare paddleDestructor(*ref.Object)
Declare paddleDraw(*ref.Object, dt.l)
Declare paddleStep(*ref.Object, *state.State)
Declare Ball(*state.State, *ref.Object, x.l, y.l)
Declare ballDestructor(*ref.Object)
Declare ballDraw(*ref.Object, dt.l)
Declare ballParticleSpawner(*this.Object, *state.State, delay.l=100, reverseDir.b = 1)
Declare ballStep(*ref.Object, *state.State)
Declare Brick(*state.State, *ref.Object, x.l, y.l, hp.l)
Declare brickDestructor(*ref.Object)
Declare brickDraw(*ref.Object, dt.l)
Declare brickStep(*ref.Object, *state.State)
Declare brickParticleSpawner(*this.BallObject, *state.State, delay.l=100, reverseDir.b=1)
Declare Particle(*state.State, *ref.Object, *parent.Object, x.l, y.l, *direction.Vector, expires.l)
Declare particleDestructor(*ref.Object)
Declare particleDraw(*ref.Object, dt.l)
Declare particleStep(*ref.Object, *state.State)
Declare Pickup(*state.State, *ref.Object, x.l, y.l, type.l)
Declare pickupDestructor(*ref.Object)
Declare pickupDraw(*ref.Object, dt.l)
Declare pickupStep(*ref.Object, *state.State)
; boring things declarations
Declare intersect2d(*a.Object, *b.Object)
Declare addObject(*game.State, *ref);
Declare flush(*state.State)
Declare update(*state.State)
Declare render(*state.State)
Declare isOffScreen(*this.Object, *state.State)
;Declare
;-Particle definition
Procedure Pickup(*state.State, *ref.Object, x.l, y.l, type.l);, reverseDir.b = 1)
*ptr.PickupObject = AllocateStructure(PickupObject)
*ptr\type = #Pickup0 + type
With *ref
\extends = *ptr
\parent = *parent
\x = x
\y = y
\w = 32 ;
\h = 32
\expires = 0
\dir[0] = 0.0
\dir[1] = 1.0
\speed = 3
\fnRender = @pickupDraw()
\fnStep = @pickupStep()
\fnConstructor = @Pickup()
\fnDestructor = @pickupDestructor()
\intangible = 0
EndWith
EndProcedure
Procedure pickupDestructor(*ref.Object)
FreeStructure(*ref\extends)
EndProcedure
Procedure pickupApply(*state.State, *this.Object, type.l=-1)
*self.PickupObject = *this\extends
*thatObj.PaddleObject = *state\paddle\extends
If (type.l = -1)
type = *self\type
EndIf
Select type
Case #Pickup1:
*state\continues+1
Case #Pickup4:
*thatObj\size + 1
Case #Pickup5:
If (*thatObj\size > 1)
*thatObj\size - 1
EndIf
Case #Pickup7:
Ball(*state, obj.Object, *this\x, *this\y)
addObject(*state, obj);
Case #Pickup8:
pickupApply(*state, *this, Random(9,0));
Default: *state\score = *state\score / 0.25
EndSelect
ProcedureReturn 0
EndProcedure
Procedure pickupStep(*this.Object, *state.State);
*self.PickupObject = *this\extends
With *this
\x = \x + (\dir[0] * \speed)
\y = \y + (\dir[1] * \speed)
EndWith
If (isOffScreen(*this, *state))
*this\removed = 1
EndIf
*that.Object = *state\paddle
collision = intersect2d(*this, *that)
If (*that\fnConstructor = @Paddle() And collision > 0 And *this\removed = 0)
pickupApply(*state, *this)
*this\removed = 1
ballParticleSpawner(*this, *state, 10, 1)
EndIf
EndProcedure
Procedure pickupDraw(*this.Object, dt.l)
*self.PickupObject = *this\extends
DisplayTransparentSprite(#Pickup0, *this\x, *this\y);
DisplayTransparentSprite(*self\type, *this\x, *this\y);
EndProcedure
;-Paddle definition
Procedure Paddle(*state.State, *ref.Object, x.l, y.l)
*ptr.PaddleObject = AllocateStructure(PaddleObject)
*ptr\size = 5
With *ref
\extends = *ptr
\x = x
\y = y
\removed = 0
\w = 100
\h = 16
\fnRender = @paddleDraw()
\fnStep = @paddleStep()
\fnConstructor = @Paddle()
\fnDestructor = @paddleDestructor()
EndWith
EndProcedure
Procedure paddleDestructor(*ref.Object)
EndProcedure
Procedure paddleParticleSpawner(*this.Object, *state.State, side.b);
For k = 1 To 2
dir.Vector\y = 1.0 + ((-4 + Random(8, 0)) / 10);;
dir\x = 0.0 + ((-4 + Random(8, 0)) / 10)
pos.Vector\x = *this\x + 5
pos\y = *this\y + *this\h;
If (side = 1)
pos\x = *this\x + *this\w - 10
EndIf
Particle(*state, particleObj.Object, *this, pos\x, pos\y, dir, *state\dt + Random(300, 100))
addObject(*state, particleObj)
Next
EndProcedure
Procedure paddleStep(*this.Object, *state.State);
*state\paddle = *this
*self.PaddleObject = *this\extends
*this\x = MouseX()
*this\w = 32 + (*self\size * 6 * 2)
If (*this\x + *this\w > *state\width)
*this\x = *state\width - *this\w
EndIf
paddleParticleSpawner(*this, *state, 0)
paddleParticleSpawner(*this, *state, 1)
EndProcedure
Procedure paddleDraw(*this.Object, dt.l)
*self.PaddleObject = *this\extends
size = *self\size * 2
DisplayTransparentSprite(#Paddle1, *this\x, *this\y)
DisplayTransparentSprite(#Paddle3, *this\x + 17 + (6 * size), *this\y)
For l = 1 To size
DisplayTransparentSprite(#Paddle2, *this\x + 5 + ( 6 * l), *this\y + 1)
Next
EndProcedure
;-Ball definition
Procedure Ball(*state.State, *ref.Object, x.l, y.l)
*state\balls + 1;
*ptr.BallObject = AllocateStructure(BallObject)
*ptr\lastParticleCreation = 0
With *ref
\extends = *ptr
\parent = *parent
\x = x;width / 2
\y = y;height - 50 ;
\removed = 0 ;
\speed = 10
\w = 16 ;
\h = 16
\dir[0] = 0.0
\dir[1] = -1.0
\fnRender = @ballDraw()
\fnStep = @ballStep()
\fnConstructor = @Ball()
\fnDestructor = @ballDestructor()
EndWith
EndProcedure
Procedure ballDestructor(*ref.Object)
FreeStructure(*ref\extends)
EndProcedure
Procedure ballParticleSpawner(*this.Object, *state.State, delay.l=100, reverseDir.b = 1)
*self.BallObject = *this\extends
If (*state\dt > *self\lastParticleCreation + delay)
*self\lastParticleCreation = *state\dt
For i = 0 To 10
dir.Vector\x = -((-8 + Random(16, 0)) / 10)
dir\y = -((-8 + Random(16, 0)) / 10)
Particle(*state, particleObj.Object, *this, *this\x, *this\y, dir, *state\dt + Random(300, 50))
addObject(*state, particleObj)
Next
EndIf
EndProcedure
Procedure ballStep(*this.Object, *state.State);
*self.BallObject = *this\extends
If (*state\active = 1)
tmp.Object
With tmp ; a copy of the object with future transforms applied to it
\x = *this\x + (*this\dir[0] * *this\speed)
\y = *this\y + (*this\dir[1] * *this\speed)
\w = *this\w
\h = *this\h
EndWith
For i = 0 To ArraySize(*state\objectsList()) - 1
that.Object = *state\objectsList(i);
; todo: collision will fail if a balls speed is more than the width or height of an object it could collide with
collision = intersect2d(tmp, that)
If (*this\id <> that\id And that\intangible = 0 And collision > 0)
If (that\fnConstructor = @Brick())
*ptr.BrickObject = that\extends
*ptr\hp = *ptr\hp - 1
top.Object\x = that\x + 1
top\y = that\y - that\h
top\w = that\w - 2
top\h = that\h + 5
bot.Object\x = that\x + 1;
bot\y = that\y + that\h - 5
bot\w = that\w - 2
bot\h = that\h
left.Object\x = that\x - that\w
left\y = that\y + 1
left\w = that\w + 5
left\h = that\h - 2
right.Object\x = that\x + that\w - 5;
right\y = that\y + 1
right\w = that\w
right\h = that\h - 2
If (intersect2d(tmp, top) Or intersect2d(tmp, bot))
*this\dir[1] = -(*this\dir[1])
ElseIf (intersect2d(tmp, left) Or intersect2d(tmp, right))
*this\dir[0] = -(*this\dir[0])
Else
*this\dir[0] = -(*this\dir[0])
*this\dir[1] = -(*this\dir[1])
EndIf
*state\score + 1
ballParticleSpawner(*this, *state, 10, 1)
ElseIf (that\fnConstructor = @Paddle())
rads = (((that\x - *this\x) + ((that\w - *this\w )/2) )) * #PI
*this\dir[0] = -Sin(rads / 180)
*this\dir[1] = -Cos(rads / 180)
ballParticleSpawner(*this, *state, 10, 1)
EndIf
EndIf
Next
c2 = isOffScreen(tmp, *state)
If (c2 = 4) ; bottom of the screen hit
*this\removed = 1
*state\balls - 1
ElseIf (c2 = 3) ; top
*this\dir[1] = -(*this\dir[1])
ElseIf (c2 > 0)
*this\dir[0] = -(*this\dir[0])
EndIf
If (c2 > 0)
ballParticleSpawner(*this, *state, 10, 0)
EndIf
With *this
\x = \x + (\dir[0] * \speed)
\y = \y + (\dir[1] * \speed)
EndWith
Else
With *this
\x = *state\paddle\x + ((*state\paddle\w/2) - (\w/2))
\y = *state\paddle\y - 20
EndWith
EndIf
EndProcedure
Procedure ballDraw(*this.Object, dt.l)
DisplayTransparentSprite(#Ball, *this\x, *this\y);
EndProcedure
;-Particle definition
Procedure Particle(*state.State, *ref.Object, *parent.Object, x.l, y.l, *direction.Vector, expires.l);, reverseDir.b = 1)
*ptr.ParticleObject = AllocateStructure(ParticleObject)
s = Random(5, 1)
With *ref
\extends = *ptr
\parent = *parent
\x = x
\y = y
\w = s ;
\h = s
\expires = expires
\dir[0] = *direction\x
\dir[1] = *direction\y
\speed = Random(10, 0);
\fnRender = @particleDraw()
\fnStep = @particleStep()
\fnConstructor = @Particle()
\fnDestructor = @particleDestructor()
\intangible = 1
EndWith
EndProcedure
Procedure particleDestructor(*ref.Object)
FreeStructure(*ref\extends)
EndProcedure
Procedure particleStep(*this.Object, *state.State);
*self.ParticleObject = *this\extends
With *this
\x = \x + (\dir[0] * \speed)
\y = \y + (\dir[1] * \speed)
\speed = \speed/2; - \speed
EndWith
EndProcedure
Procedure particleDraw(*this.Object, dt.l)
ZoomSprite(#Particle1, *this\w, *this\h)
DisplayTransparentSprite(#Particle1, *this\x, *this\y);
EndProcedure
;-Brick definition
Procedure Brick(*state.State, *ref.Object, x.l, y.l, hp.l)
*state\bricks + 1
*ptr.BrickObject = AllocateStructure(BrickObject)
*ptr\hp = hp
*ptr\gfx = Random(3, 0);
With *ref
\extends = *ptr
\x = x
\y = y
\removed = 0;
\w = 64;
\h = 32;
\fnRender = @brickDraw()
\fnStep = @brickStep()
\fnConstructor = @Brick()
\fnDestructor = @brickDestructor()
EndWith
EndProcedure
Procedure brickDestructor(*ref.Object)
;*self.BrickObject = *ref\extends
;FreeMemory(*self\ptrtest)
FreeStructure(*ref\extends)
EndProcedure
Procedure brickStep(*this.Object, *state.State);
*self.BrickObject = *this\extends
If (*self\hp < 1 And *this\removed = 0)
*this\removed = 1
*state\bricks - 1
Pickup(*state, obj.Object, *this\x, *this\y, Random(10, 1))
addObject(*state, obj);
EndIf
EndProcedure
Procedure brickDraw(*this.Object, dt.l)
*self.BrickObject = *this\extends
DisplayTransparentSprite(#Brick0, *this\x, *this\y);
DisplayTransparentSprite(#RGB1 + (*self\gfx), *this\x, *this\y);
EndProcedure
Procedure update(*state.State)
size = ArraySize(*state\objectsList());
For k = 0 To size - 1
If (*state\objectsList(k)\removed = 1)
Continue
EndIf
*addr = *state\objectsList(k)\fnStep;
CallFunctionFast(*addr, *state\objectsList(k), *state);
Next
If (*state\bricks = 0 And *state\gameover = 0)
*state\gameover = 1
EndIf
If (*state\balls = 0 And *state\gameover = 0)
If (*state\continues = 0)
*state\gameover = 2
Else
*state\continues - 1
*state\active = 0
Ball(*state, obj.Object, 0, 0)
addObject(*state, obj)
EndIf
EndIf
If (*state\active = 0 And MouseButton(#PB_MouseButton_Left) = 1)
*state\active = 1
EndIf
EndProcedure
Procedure render(*state.State)
ClearScreen(RGB(50, 100, 140));
For k = 0 To ArraySize(*state\objectsList()) - 1
item.Object = *state\objectsList(k)
If (item\removed = 1)
Continue
EndIf
*addr = *state\objectsList(k)\fnRender;
CallFunctionFast(*addr, *state\objectsList(k), *state);
;StartDrawing(ScreenOutput()) ; show bounds
;Line(item\x, item\y, item\w, 1, #Red)
;Line(item\x, item\y+item\h, item\w, 1, #Red)
;Line(item\x, item\y, 1, item\h, #Red)
;Line(item\x+item\w, item\y, 1, item\h, #Red)
;Line(item\x, item\y, item\w, item\h, #Red)
;StopDrawing()
Next
DisplayTransparentSprite(#Text1, *state\width - 150, 10);
DisplayTransparentSprite(#Text2, 10, 10)
If (*state\gameover > 0 Or *state\active = 0)
DisplayTransparentSprite(#Text3, *state\width/2 - 150, *state\height/2)
EndIf
FlipBuffers();
EndProcedure
Procedure addObject(*game.State, *ref)
o = ArraySize(*game\objectsQueue());
ReDim *game\objectsQueue.Object(o+1);
CopyStructure(*ref, @dref.Object, Object)
*game\objectsQueue(o) = dref;
EndProcedure
Procedure remakeHUDSprite(*state.State)
If (IsSprite(#Text2))
FreeSprite(#Text2)
EndIf
CreateSprite(#Text2, 200, 75);
StartDrawing(SpriteOutput(#Text2))
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(0, 0, "Score: " + Str(*state\score), RGB(1, 0, 0));
DrawText(0, 20, "Continues: " + Str(*state\continues), RGB(1, 0, 0));
StopDrawing()
EndProcedure
Procedure remakeGameOverSprite(*state.State, msg.s)
If (IsSprite(#Text3))
FreeSprite(#Text3)
EndIf
CreateSprite(#Text3, 300, 100);
StartDrawing(SpriteOutput(#Text3))
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(#Font1))
DrawText(0, 0, msg, RGB(1, 0, 0));
StopDrawing()
EndProcedure
Procedure remakeProfileSprite(*state.State)
If (IsSprite(#Text1))
FreeSprite(#Text1)
EndIf
CreateSprite(#Text1, 200, 120);
StartDrawing(SpriteOutput(#Text1))
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(0, 0, Str(*state\drawing\tps) + " - frames per sec", RGB(1, 0, 0));
DrawText(0, 20, Str(*state\logic\tps) + " - steps per sec", RGB(1, 0, 0));
DrawText(0, 40, Str(*state\logic\count1) + " - object count", RGB(1, 0, 0)) ;
DrawText(0, 60, Str(*state\logic\count2) + " - queue count", RGB(1, 0, 0))
DrawText(0, 80, Str(*state\balls) + " - balls", RGB(1, 0, 0))
DrawText(0, 100, Str(*state\bricks) + " - bricks", RGB(1, 0, 0)) ;
StopDrawing()
EndProcedure
Procedure init(*state.State)
LoadFont(#Font1, "Arial", 32, #PB_Font_Bold)
remakeProfileSprite(*state);
remakeHUDSprite(*state)
remakeGameOverSprite(*state, "Click to Start!")
LoadSprite(#Sheet1, "E:/assets/brickbreaker.png", #PB_Sprite_AlphaBlending);
CopySprite(#Sheet1, #Paddle1, #PB_Sprite_AlphaBlending) ; left
ClipSprite(#Paddle1, 0, 0, 16, 16)
CopySprite(#Sheet1, #Paddle2, #PB_Sprite_AlphaBlending) ; blue thing
ClipSprite(#Paddle2, 16, 0, 16, 16)
CopySprite(#Sheet1, #Paddle3, #PB_Sprite_AlphaBlending) ; right
ClipSprite(#Paddle3, 32, 0, 16, 16)
CopySprite(#Sheet1, #Ball, #PB_Sprite_AlphaBlending)
ClipSprite(#Ball, 16 * 3, 0, 16, 16)
CopySprite(#Sheet1, #Brick0, #PB_Sprite_AlphaBlending)
ClipSprite(#Brick0, 0, 64, 64, 32)
CreateSprite(#Particle1, 25, 25);
StartDrawing(SpriteOutput(#Particle1))
Box(0, 0, 20, 20, RGB(0, 0, 0)) ;
DrawingMode(#PB_2DDrawing_Default)
Box(0, 0, 50, 25, RGB(255, 255, 255));
StopDrawing()
For k = 0 To 3
CreateSprite(#RGB1 + k, 64, 32, #PB_Sprite_AlphaBlending);
StartDrawing(SpriteOutput(#RGB1 + k))
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0, 0, 64, 32, $00000000)
DrawingMode(#PB_2DDrawing_AlphaBlend)
Box(0, 0, 64, 32, RGBA(Random(255, 0), Random(255, 0), Random(255, 0), 100))
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0, 0, 2, 2, $00000000)
Box(62, 0, 2, 2, $00000000)
Box(0, 30, 2, 2, $00000000)
Box(62, 30, 2, 2, $00000000)
StopDrawing()
Next
CopySprite(#Sheet1, #Pickup0, #PB_Sprite_AlphaBlending)
ClipSprite(#Pickup0, 64, 0, 16, 16)
ZoomSprite(#Pickup0, 32, 32)
For k = 0 To 10
CopySprite(#Sheet1, #Pickup1 + k, #PB_Sprite_AlphaBlending)
ClipSprite(#Pickup1 + k, (16 * k), 16, 16, 16)
ZoomSprite(#Pickup1 + k, 32, 32)
Next
Paddle(*state, paddleObj.Object, *state\width / 2 - 50, *state\height - 100)
addObject(*state, paddleObj)
Ball(*state, ballObj.Object, 0, 0)
addObject(*state, ballObj)
For x = 0 To 59;99
tx = 50 + ((x % 10) * 70)
ty = 100 + ((x / 10) * 50)
Brick(*state, brickObj.Object, tx, ty, 1+(ty%3))
addObject(*state, brickObj)
Next
EndProcedure
Procedure isOffScreen(*this.Object, *state.State)
If (*this\x < 0) : ProcedureReturn 1 ; left
ElseIf (*this\x + *this\w > *state\width) : ProcedureReturn 2 ; right
ElseIf (*this\y < 0) : ProcedureReturn 3 ; top
ElseIf (*this\y + *this\h > *state\height) : ProcedureReturn 4 : EndIf ; bottom
ProcedureReturn 0
EndProcedure
Procedure intersect2d(*o.Object, *b.Object)
ax.d = *o\x
ay.d = *o\y
au.d = *o\x + *o\w
av.d = *o\y + *o\h
bx.d = *b\x
by.d = *b\y
bu.d = *b\x + *b\w
bv.d = *b\y + *b\h
If (ax <= bu And au >= bx And ay <= bv And av >= by)
ProcedureReturn 1
EndIf
ProcedureReturn 0
EndProcedure
Procedure flush(*state.State)
size = ArraySize(*state\objectsList())
For i = 0 To size - 1 ; clean up objects that were marked for removal
If (*state\objectsList(i)\removed = 1 Or (*state\objectsList(i)\expires > 0 And *state\dt > *state\objectsList(i)\expires))
*addr = *state\objectsList(i)\fnDestructor;
CallFunctionFast(*addr, *state\objectsList(i));
; i dont know how to properly resize arrays in purebasic so hopefully this won't be too slow :(
*state\objectsList(i) = *state\objectsList(size - 1) ; swap removing object with one at end
ReDim *state\objectsList.Object(size - 1)
size = size -1; have to modify loop or bad things will happen
i = i - 1; the object that was swapped must also be checked for removal
EndIf
Next
n = ArraySize(*state\objectsQueue());
If (n > 0) ; merge queued objects into the object list
o = ArraySize(*state\objectsList());
If (o >= 1000) ; this is just an arbitrary size limit for the number of objects to allow
ReDim *state\objectsQueue(0);
ProcedureReturn
EndIf
ReDim *state\objectsList(o+n);
For k = 0 To n ; the merge part
*state\uuidAccumulator = *state\uuidAccumulator + 1
*state\objectsList(o+k) = *state\objectsQueue(k);
*state\objectsList(o+k)\id = *state\uuidAccumulator
If (*state\objectsList(o+k)\fnConstructor = @Paddle())
*state\paddle = *state\objectsList(o+k)
EndIf
Next
ReDim *state\objectsQueue(0)
EndIf
EndProcedure
With game.State
\width = 800
\height = 800
\running = 1
\score = 0
\continues = 1
\now = ElapsedMilliseconds()
\dt = ElapsedMilliseconds();
Dim \objectsQueue.Object(0)
Dim \objectsList.Object(0)
EndWith
InitSprite()
InitMouse()
UsePNGImageDecoder()
OpenWindow(0, 0, 0, game\width, game\height, "Nostalgia", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget);
OpenWindowedScreen(WindowID(0), 0, 0, game\width, game\height, #False, #Null, #Null, #PB_Screen_NoSynchronization );
init(game)
;-Loop
While game\running = 1
Select WindowEvent()
Case #PB_Event_CloseWindow
game\running = 0
EndSelect
ExamineMouse()
If (game\dt > game\drawing\tpst + 1000)
game\drawing\tps = game\drawing\tpsc;
game\drawing\tpsc = 0 ;
game\logic\tps = game\drawing\tpsc;
game\logic\tpsc = 0 ;
game\drawing\tpst = game\dt ;
game\logic\count1 = ArraySize(game\objectsList())
game\logic\count2 = ArraySize(game\objectsQueue())
remakeProfileSprite(game);
EndIf
flush(game)
game\now = ElapsedMilliseconds();
If (game\now - game\dt > 1000) ; skip some logic steps because previous one took too long
game\dt = game\now;
EndIf
CopyStructure(@game, @prev.State, State) ; a copy of state to compare with after updating
While game\dt < game\now ; step game objects at a constant rate
game\dt = game\dt + 1000/30;
update(game);
game\logic\tpsc=game\logic\tpsc+1;
Wend
If (prev\score <> game\score Or prev\continues <> game\continues)
remakeHUDSprite(game)
EndIf
If (prev\gameover <> game\gameover Or prev\active <> game\active)
msg.s = "Click to start!"
If (game\gameover = 2)
msg.s = "Game over!!"
ElseIf (game\gameover = 1)
msg.s = "You win!"
EndIf
remakeGameOverSprite(game, msg)
EndIf
render(game)
game\drawing\tpsc=game\drawing\tpsc+1;
Wend