General Game Structure: Part 2

BlitzMax Forums/BlitzMax Beginners Area/General Game Structure: Part 2

Apollonius(Posted 2007) [#1]
Hi Everyone!

I'm still trying to figure out how I'll ultimately structure my game for good performance and ease of read, but I haven't found the ultimate way of doing this but I have had some ideas after playing around with Types and Functions.

If I understand correctly, Types can be used for almsot everything that needs to be redone more then once. The only downside is the fact that they depends on inside values to function so the difference between two of the same type is limited. If that makes any sense. The way I see it, is:

Let's say you have Type TButton... and you have a TRoom and you wana place Buttons into a room it can be done(via method and functions) but it will be the same for all the rooms you may be able to change the values of those button inside the TRoom type but not how many you have of them.

So basicly Types is basicly duplicable storage space with internal behavior (mewthod and functions), no?

So I though then I have no other way to make it so every room is different then to make an outside Functions to contain all the information of all the different room as.. follow:

This is the simple structure I came out with, it's jsut a global idea of how I'd do it:

Graphics 800,600,0

Global CurrentRoom:Int=0

Global intro:TRoom=New TRoom
intro.Name="Intro"
Global menu:TRoom=New TRoom
menu.Name="Menu"

While Not KeyHit(KEY_ESCAPE)

UpdateRoom()

Flip; Cls
Wend; End


Type TRoom
	Field Name:String
End Type

Function UpdateRoom()
	If CurrentRoom=0 Then
		' Room Intro
		DrawText intro.Name,10,10
		
		If KeyHit(KEY_ENTER)
			CurrentRoom:+1
		EndIf
		
	EndIf
	If CurrentRoom=1 Then
		' Room Menu
		DrawText menu.Name,10,10
		
	EndIf
End Function


What do you guys think? Any better ideas? Am I way off? Or over complicating stuff.. like I usually do lol?


TomToad(Posted 2007) [#2]
Here is a great tutorial on types if you haven't read it yet.
http://www.blitzbasic.com/Community/posts.php?topic=59233

I'd might do your example like this, keeping Update() within the type:



Apollonius(Posted 2007) [#3]
I know about doing it that way, however did you read my second or third paragraph, what if you wana add alot of different information for a room, you cannot insert that kind of information into an object that is why I did it the way I did.

If you have TButton, TTextfield... Let's say I wana place 3 TButton and 2 TTextfield in the first room then 5 TButton and 1 TTextfield in the second room.. You cannot insert very differencial information into an object...

Graphics 800,600,0


Local intro:TRoom=New TRoom
Local CurrentRoom:TRoom = intro 'point CurrentRoom to the first room

intro.Name="Intro"

Local menu:TRoom=New TRoom
menu.Name="Menu"

intro.NextRoom = menu 'the room you enter when you press "Enter" key
menu.NextRoom = intro

While Not KeyHit(KEY_ESCAPE)
	Cls
	CurrentRoom = CurrentRoom.Update()

	Flip
Wend

Type TRoom
	Field Name:String
	Field NextRoom:TRoom
	
	Method Update:TRoom()
		DrawText Name,10,10
		
		If KeyHit(KEY_ENTER)
			Return NextRoom 'if enter is pressed, return the next room
		Else
			Return Self 'if not, then return the current room
		End If
	End Method
End Type

Type TButton
	Field x:Int, y:Int
	Field width:Int
	Field height:Int
	
	Method Create( xstart:Int, ystart:Int, wstart:Int, hstart:Int)
		x=xstart
		y=ystart
		w=wstart
		h=hstart
	End Method
	
End Type


Can't add 2 TButtons to the Update of TRoom without it applying to all rooms .. what if you want to add different number of TButtons per room.. Hmm

Hope it make sense somewhat?

EDITED
rooms will contain alot of stuff thus why i think i need to make a function to make/controle all the stff inside the room...

i wonder why shouldt i use Select Case instead of if then?


TomToad(Posted 2007) [#4]
Did you read the tutorial in the link I provided? It will give you a lot of info about types and how to better use them.
As far as different objects in the room, it is quite possible to have each room with it's own TButtons, TTexts, TItems, TMonsters, etc.... Each room can have the same number, different number or none at all.
There are different ways to do this, reading the tutorial and some of the posts here will show you a few. One way is to use arrays.



Apollonius(Posted 2007) [#5]
This is just awesome, I didn't know you could use types like this, I have read Types tutorials but I couldn't come up with something like this.

That is extremely useful, I'll have to re-read a few time and try to understand this better.

Thanks a bunch.
And about that tutorial I just finished downloading the PDF read(reformated recently).


Apollonius(Posted 2007) [#6]
Oh my oh my, I think I understand! I can put a list of object inside another object such as TButton into TRoom via an array. And then use the TRoom's Update to loop through via a for loop to update all the buttons in that array.

There's still a place I'm abit fuzzy on but not quite clear on what it is so when I am, I'll post back here lol.


Czar Flavius(Posted 2007) [#7]
Yes yes I think you're getting it now!

You'll basically have an array of TRooms and each TRoom will have its own array of buttons, monsters etc.


These rooms... are the rooms in your level, or "scenes" of some kind? Because intro and menu don't seem like names of rooms in a dungeon lol.


Apollonius(Posted 2007) [#8]
Yeah, that is why I need to change the concept abit.

So basicly TRoom will be all the stuff before actually being in-game, like:

@ Introduction( intro:TRoom )
Logo(s), Story Clip(Cinematic if you can call it that)

@ Main Menu ( menu:TRoom )
The player could now choose from "Singleplayer", "Multiplayer"(not any time soon), "Settings", "Credits", "Exit"

And then Rooms for all thoses probably except Exit.

I'll focus on the Singleplayer story mode and making the mechanics of the game, like the tile system, player, enemies... ect.

It will take long but it sure will be a challenge and fun :D

As for ingame, I was thinking of using TWorld and TArea(inside the TWorld) hehe


Apollonius(Posted 2007) [#9]
I gotta say, I'm having trouble understanding some parts completely, I tried to make my own example:
SuperStrict
Graphics 800,600,0

Global startup:TRoom=New TRoom
startup.Buttons=New TButton[1]

startup.Buttons[0]=New TButton
startup.Buttons[0].Create(10,10,70,15,"Click Now") 


While Not KeyHit(KEY_ESCAPE)

	startup.UpdateRoom()

Flip; Cls
Wend; End

Type TRoom
	Field Buttons:TButton[]
	Method UpdateRoom()
		For Local i:Int = 0 To Buttons.length-1
			Buttons[i].Update()
		Next
	End Method
End Type

Type TButton
	Field Text:String
	
	Field xpos:Int
	Field ypos:Int
	Field Width:Int
	Field Height:Int
	
	Field Clicked:Int=False
	
	Method Create(xstart:Int, ystart:Int, wstart:Int, hstart:Int, tstart:String)
		xpos=xstart
		ypos=ystart
		Width=wstart
		Height=hstart
		text=tstart
	End Method
	
	Method Update()
		' Clicked
		If(MouseX()>xpos)And(MouseX()<xpos+Width)And(MouseY()>ypos)And(MouseY()<ypos+Height)Then
			If MouseHit(1)=True Then
				Clicked=True
			EndIf
		EndIf
		If Clicked=True Then Text="Clicked"
		
		Draw()
	End Method
	
	Method Draw()
		SetColor(100,100,100)
		DrawRect xpos, ypos, Width, Height
		SetColor(255,255,255)
		DrawText Text,xpos,ypos
	End Method
End Type


Ok this works, now here's teh first place I'd need more explication on:

startup.Buttons=New TButton[1]
startup.Buttons[0]=New TButton

First one seems to create a new TButton Object. But isn't it the startup.Buttons being the array? TButton isnt an array its an object why is there a [1]

As for teh second line it stores a TButton object into the first Row of the array.

-------
The Next part I'm having trouble with is the
For Local i:Int = 0 To Buttons.length-1

Button.length gives you the number of rows within a array I think? At first the -1 was confusing me but then I though 1 entry total length 1 but Array line 0.. cuz 0,1,2,3.. So yeah I understand why -1 now .. hehe

edited
Love this:
Global startup:TRoom=New TRoom
startup.Buttons=New TButton[5]

For Local i:Int = 0 To startup.Buttons.length-1
startup.Buttons[i]=New TButton
Next

startup.Buttons[0].Create(10,10,90,15,"Click Now") 
startup.Buttons[1].Create(10,30,90,15,"Click Now") 
startup.Buttons[2].Create(10,50,90,15,"Click Now") 
startup.Buttons[3].Create(10,70,90,15,"Click Now") 
startup.Buttons[4].Create(10,90,90,15,"Click Now") 


EDITED
Even more Practice, I made two Rooms, if you click all the buttons in the first room it will go to the next room! :)
(or you can cheat by pressing enter)

SuperStrict
Graphics 800,600,0

'--------------------
' FIRST ROOM: STARTUP
Global startup:TRoom=New TRoom
startup.Buttons=New TButton[5]

For Local i:Int = 0 To startup.Buttons.length-1
startup.Buttons[i]=New TButton
Next

startup.Buttons[0].Create(10,10,90,15,"Click Now") 
startup.Buttons[1].Create(10,30,90,15,"Click Now") 
startup.Buttons[2].Create(10,50,90,15,"Click Now") 
startup.Buttons[3].Create(10,70,90,15,"Click Now") 
startup.Buttons[4].Create(10,90,90,15,"Click Now") 

'--------------------
' SECOND ROOM: SECOND
Global second:TRoom=New TRoom
second.Buttons=New TButton[2]

For Local i:Int = 0 To second.Buttons.length-1
second.Buttons[i]=New TButton
Next

second.Buttons[0].Create(10,10,90,15,"Click Now") 
second.Buttons[1].Create(110,10,90,15,"Click Now") 

'--------------------
' VARIABLES
Global CurrentRoom:TRoom=startup:TRoom


While Not KeyHit(KEY_ESCAPE)

	CurrentRoom.UpdateRoom()

Flip; Cls
Wend; End

Type TRoom
	Field Buttons:TButton[]
	Method UpdateRoom()
		Local totalB:Int
		For Local i:Int = 0 To Buttons.length-1
			Buttons[i].Update()
			
			If(Buttons[i].Clicked=True)Then
				totalB:+1
				If(totalB=Buttons.length)Then
					CurrentRoom=second:TRoom
				EndIf
			
			EndIf
		Next
		
		If KeyHit(KEY_ENTER) Then CurrentRoom=second:TRoom
	End Method
End Type

Type TButton
	Field Text:String
	
	Field xpos:Int
	Field ypos:Int
	Field Width:Int
	Field Height:Int
	
	Field Clicked:Int=False
	
	Method Create(xstart:Int, ystart:Int, wstart:Int, hstart:Int, tstart:String)
		xpos=xstart
		ypos=ystart
		Width=wstart
		Height=hstart
		text=tstart
	End Method
	
	Method Update()
		' Clicked
		If(MouseX()>xpos)And(MouseX()<xpos+Width)And(MouseY()>ypos)And(MouseY()<ypos+Height)Then
			If MouseHit(1)=True Then
				Clicked=True
			EndIf
		EndIf
		If Clicked=True Then Text="Clicked"
		
		Draw()
	End Method
	
	Method Draw()
		SetColor(100,100,100)
		DrawRect xpos, ypos, Width, Height
		SetColor(255,255,255)
		DrawText Text,xpos,ypos
	End Method
End Type



TomToad(Posted 2007) [#10]
startup.Buttons=New TButton[1]
startup.Buttons[0]=New TButton

When startup is created, you have a field called Buttons which is an array of TButtons, but it hasn't been initialized with a dimension yet.
Startup.Buttons=new TButtons[1] tells the program that you now want Buttons to be initialized with a size of 1. You are not assigning it a specific TButton, but telling it to allocate an array with a dimension of 1 for TButtons.
Startup.Buttons[0] = New TButton now assigns element 0 of the array to an actual TButton object, so now you can use the object in your program.
Another example here, using Ints and TImages:
Local IntArray:Int[]
IntArray = New Int[10] 'Make IntArray 10 elements long
IntArray[0] = 4 'assign a value to IntArray[0]

Local ImageArray:TImage[] 'an array of images
ImageArray = new TImage[10] 'Make ImageArray 10 elements long
ImageArray[0] = New TImage ' assign a TImage to ImageArray[0]



Czar Flavius(Posted 2007) [#11]
If you're doing a -1 thingy on a For loop, you can use Until

So
For Local i:Int = 0 Until second.Buttons.length
is the same as
For Local i:Int = 0 To second.Buttons.length-1


It just makes things a little less cluttered :)


Apollonius(Posted 2007) [#12]
hehe nice.

For a practice, I'm trying to design what you would call a "Simple GUI" for my game. Basicly it's 4 type objects, TWindow, TButton, TTextfield and TTextview. This should be good practice, I called it "QGI" which means Quick Game Interface.

QGI.bmx just needs to be included into a project for it to work. But I've been having "mouse Over" Problems with my button object...

I feel my button doesn't light up fast enough so I tried to use "Flip 0", it did improve it however it feels as though my style of coding or teh way I coded it is making it slow.

So maybe you could check how good and optimised my code is, it's quite readable.

Ok first file is the main.bmx:


QGI File


I'm only working with the TWindow and TButton, I haven't worked really on the others yet.

I appreciate the help Czar Flavius!


Czar Flavius(Posted 2007) [#13]
Try using [ codebox ] instead of [ code ] then you get nice scroll bars on your code : )


Apollonius(Posted 2007) [#14]
Done, so you see the mouse over button things is not really optimised and I wonder how can I optimise them to make the mouse over effect faster?


tonyg(Posted 2007) [#15]
The speed seems OK for me.
You've duplicated some code in the QGI_TButton
draw() method but that shouldn't matter.
The other thing you need to do is store off mousex() and mousey() values to check against.
You might want to consider images which can be checked using a collision layer for all the buttons.


Apollonius(Posted 2007) [#16]
Yeah I though the duplication of the Draw Method could slow it down, but then I couldn't figure out another way that would improve it.

as for
"The other thing you need to do is store off mousex() and mousey() values to check against."

What do you mean? (kinda lost with that sentence)


tonyg(Posted 2007) [#17]
Test mousex() and mousey() once per loop and
return the values into variables:
local mx:int=mousex()
local my:int=mousey()
You might consider creating a mouse object to hold this kind of data.
You're not doing enough in your update() to cause anything to slowdown so it could be a driver issue. Try GL driver and see what happens. Try omitting the drawline stuff and see what happens.
There's nothing I can see wrong with the code itself.

<edit> P.S. Have you bought Bmax yet?


Apollonius(Posted 2007) [#18]
Haven't ever tried OpenGL so I'm scared to dive into it right now :o

To the EDIT
Maybe I have maybe I haven't ;D


tonyg(Posted 2007) [#19]
Haven't ever tried OpenGL so I'm scared to dive into it right now :o


You simply add
Setgraphicsdriver glmax2ddriver()
just before your graphics statement. As long as you're using native Bmax commands it does the rest for you.

Maybe I have maybe I haven't ;D

OK, I'll check again each time you post.


Apollonius(Posted 2007) [#20]
Seems to run way better with the GLMax2DDriver() thingy. This is great, does it mean it can run on mac now, since it's using openGL drivers? :o


tonyg(Posted 2007) [#21]
If you're using native Bmax commands only then it's very possible it'll compile and run on Mac.


Apollonius(Posted 2007) [#22]
I'm looking around but I can't find.. how can you destroy an object? I tried Delete but, no good?


tonyg(Posted 2007) [#23]
The object will be destroyed when there are no more references to it.


Apollonius(Posted 2007) [#24]
If KeyHit(KEY_ENTER) Then test.Buttons[0]=Null

Wouldn't that remove the reference to it? i got an error :S


Czar Flavius(Posted 2007) [#25]
What error?

Setting all references to it to Null should delete the object.


Apollonius(Posted 2007) [#26]
If KeyHit(KEY_ENTER) Then test.Buttons[0]=Null


	Method Update()
		' Buttons
		For Local i:Int = 0 To Buttons.Length-1
			If Not Button[i]=Null Then
			Buttons[i].Update()
			EndIf
		Next


Error's at the Update() so i added a if not NULL.. then.. but that didn't help either it makes an error at it now lol.


Czar Flavius(Posted 2007) [#27]
You're calling it Button and ButtonS is that the problem? What is the actualy error message you are receiving?


Apollonius(Posted 2007) [#28]
Sorry for the late reply, Czar Flavius. I wasn't at home for a few days.

Thanks for pointing that out it missed an "s" as soon as I corrected that everything worked.