Setting up a game

BlitzMax Forums/BlitzMax Beginners Area/Setting up a game

I'm trying to figure out how to actually setup a game skeleton. Right now i'm trying pass a bunch of classes to different methods. I don't know if this is the best method? Could anyone help me out? Thanks.

HideMouse()

Type TPlayer

	Field x:Float
	Field y:Float
	
	Method Draw(x:Int, y:Int)
		
		DrawRect(x, y, 20, 20)
	EndMethod
	
	Method Logic(p:TPlayer, e:TEnemy, l:TLevel)	
		
		If(p.y < l.maxY - 20) 
			p.y = p.y + 1
		
		Else If (p.y > l.maxY - 20) 
			p.y = p.y		
		EndIf
		
		If(KeyDown(KEY_UP)) p.y = p.y - 4
		If(KeyDown(KEY_LEFT)) p.x = p.x - 2
		If(KeyDown(KEY_RIGHT)) p.x = p.x + 2
	EndMethod
	
EndType

Type TEnemy

	Field x:Float
	Field y:Float
	
	Method Draw(x:Int, y:Int)
	
		DrawOval(x, y, 20, 30)
	EndMethod
	
	Method Logic(p:TPlayer, t:TEnemy)

		t.x = t.x + 1		
	EndMethod	
EndType

Type TLevel
	
	Const maxY:Float = 400
	
	Method DrawLevel()
	
		DrawLine(0, maxY, 640, maxY, True)		
	EndMethod
	
	Method Logic()	
		
	EndMethod
EndType


Type TGame

	Method UpdateDraw(player:TPlayer, enemy:TEnemy, level:TLevel)
		player.Draw(player.x, player.y)
		enemy.Draw(enemy.x, enemy.y)	
		level.DrawLevel()		
	EndMethod
	
	Method UpdateLogic(player:TPlayer, enemy:TEnemy, level:TLevel)
		player.Logic(player, enemy, level)	
		enemy.Logic(player, enemy)
		level.Logic()
	EndMethod
	
EndType


Local player:TPlayer = New TPlayer
player.x = 20
player.y = 300
Local enemy:TEnemy = New TEnemy
Local level:TLevel =  New TLevel

Local game:TGame = New TGame

While(Not(KeyDown(KEY_ESCAPE)))

	game.UpdateDraw(player, enemy, level)
	game.UpdateLogic(player, enemy, level)
	Flip()
	Cls()
Wend


That looks like a good starting point!

You could change the main loop a bit e.g Cls -> Draw -> Flip then logic, or include the Cls and Flip in the UpdateDraw method!

You could also look into timing as you can have more logic cycles than draw cycles due to refresh rates.

Just search on here for fixed rate and delta timing.

You might want a list of enemies, bullets ect...

Thanks. So is passing all those types all over the place the best way to do that?

I mean at this rate my main update will look like

t.UpdateDraw(player, enemy, level, bullet, etc, etc)

then the player update logic and draw will probably have to take

t.UpdatePlayer(enemy, level, bullet, etc)

is that fine?

Passing objects is fine but reduces the flexibility of methods and functions which in most cases is fine when functions and methods are specific to the game only. I wouldn't recomend it if you are crating a general purpose library for other games. From my understanding both have drawbacks one in terms of speed and the other in terms of flexibility
If you pass values each value is pushed to a stack and then it is accessed by the function and that spends time.
if you pass objects, it only pushes one address per object to the stack and each field can be access directly.
By passing objects, you have direct access to fields in the object and can manipulate it at will. While passing values, results have to be returned and reasigned.
On the note of speed, it's is so insignificantly that it's hardly worth mentioning. I would conclude that it's a matter of personal preference.

Why are you passing in objects you don't even use?

EG:

Method Logic(p:TPlayer, t:TEnemy)
	t.x = t.x + 1		
EndMethod

You don't use P, so why are you passing it?

OK I think you need to encapsulate more,
e.g. include the player and enemy within the Game object.

This means you only have to pass them in during setup that should make the code more encapsulated this reduces the complexity a bit as well, so you don't need to add Bullets, Bombs, Explosions to your functions parameters as you go!

Here is an example:
HideMouse()

'Here I have combinged the common elements used in TPlayer and TEnemy into a base object TUnit using Inheritance
' this can simplify the higher level objects and make it easier to maintain their common features
Type TUnit
	Field x:Float
	Field y:Float
	
	Method Draw() ' Removed the variables x and y as stored in the object
		
		DrawRect(x, y, 20, 20)
	EndMethod
	
End Type	

Type TPlayer Extends TUNit

	' Removed the player parameter as this method is within and acts on the player by default
	Method Logic(e:TEnemy, l:TLevel)	
		
		If(y < l.maxY - 20) 
			y = y + 1
		
		Else If (y > l.maxY - 20) 
			y = y		
		EndIf
		
		If(KeyDown(KEY_UP)) y = y - 4
		If(KeyDown(KEY_LEFT)) x = x - 2
		If(KeyDown(KEY_RIGHT)) x = x + 2
	EndMethod
	
EndType

Type TEnemy Extends TUnit
	
	Method Draw()
	
		DrawOval(x, y, 20, 30)
	EndMethod
	
	Method Logic(p:TPlayer, l:TLevel)

		x = x + 1		
	EndMethod	
EndType

Type TLevel
	
	Const maxY:Float = 400
	
	Method DrawLevel()
	
		DrawLine(0, maxY, 640, maxY, True)		
	EndMethod
	
	Method Logic()	
		
	EndMethod
EndType


Type TGame

	' Incorporated player, enemy and level into the game object to reduce coupling
	
	Field player:TPlayer
	Field enemy:TEnemy
	Field level:TLevel
	
	' Added a create function that sets up the player
	Function Create:TGame()
		Local newGame:TGame = New TGame
		newGame.Setup()
		Return newGame
	End Function
	
	Method Setup()
	
		Graphics 800,600
		
		player = New TPlayer
		
		' should really be added to a player Create/Setup Call
		player.x = 20
		player.y = 300

		enemy  = New TEnemy
		level  = New TLevel	
	End Method
	
	Method UpdateDraw()
		Cls()
		player.Draw()
		enemy.Draw()	
		level.DrawLevel()		
		Flip()
	EndMethod
	
	Method UpdateLogic()
		player.Logic( enemy, level)	
		enemy.Logic(player, level)
		level.Logic()
	EndMethod
	
	Method Run()
		While(Not(KeyDown(KEY_ESCAPE)))
			UpdateDraw()
			UpdateLogic()
		Wend
	End Method
	
	
EndType

' Note how the game now simplifies the setup
Local game:TGame = TGame.Create()

game.Run()


Hopefully you can see how much simpler the code looks when you Inherit common features and encapsulate objects within objects that use them!

Don't call it Logic.. give them names that describe what they do.

Like Draw and Update?

Or Render and Update.

Thanks everybody for there help and Merx for your code and help.