Loop, Type and General Game Structure?

BlitzMax Forums/BlitzMax Beginners Area/Loop, Type and General Game Structure?

Apollonius(Posted 2007) [#1]
I've been wondering how to structure my game. I've been told that all objects(types) must be created before the loop, but won't that be overloading? And take time?

Why not just create the objects as you need it? and then destroy them?

My idea of a game structure would be as follow (although it did not work at all)

Graphics 800,600,0

' Set Transparency
SetBlend(ALPHABLEND)

' Globals & Constants
Global gm_room	:Int 	= 0
Global gm_donce	:Int 	= 0
Global gm_exit	:Int 	= 0

' Included Files
Include "textfields.bmx"
Include "buttons.bmx"

While Not KeyHit(KEY_ESCAPE)

Select gm_room
	Case 0
		' DO ONCE
		If gm_donce = 0 Then
		
			Local test1:Tbutton=New Tbutton
			test1.create(10,10,"test")
			
			gm_donce = 1
		EndIf
		
		' LOOP
		test1.Update()
End Select



Flip; Cls
Wend
End

Types not included in the above, i dont see the point. Anyway I get an error which probably means I can't create un object in the loop.

I have a hard time picturing how to structure my game with multiple rooms.. like intro, menu, stage1..stage2?

If you could give me some help with this, it would be very appreciated!


Who was John Galt?(Posted 2007) [#2]
You are on the right tracks with what you have. Creating and destroying type instances in the loop is fine, in fact this is the best way for spawning and killing monsters, bullets etc as you need them. Of course, your type declarations should be outside this loop, although even this may not matter, but it would not be good coding style. I wouldn't bother with a big case/select for room in your loop. When a new room is entered, call a 'new room' function that creates all the creatures etc for the room, then your main loop can be generic, just updating all the objects you have.

No glaring errors in what I can see above.


Apollonius(Posted 2007) [#3]
By type declaration do you mean:
Local test1:Tbutton=New Tbutton
test1.create(10,10,"test")

or do you mean the type structure? Which is outside the loop in one of the included files.

But if you mean the piece of code above then if I declare all the type instances before the loop won't that over-crowd the memory for no reason? Shouldnt it only be declared when you need it like

Let's say you have the room 1 and room 2... Won't you just wana declare the type instance you currently need in the current room and then destroy it when you leave the room... so like if ur in room 1, you have 3 events..
@ creation of the room,
@ loop of the room,
@ end of the room(whenever you change room),
so you create all your type instance at the room start and then destroy all the instances at the end of the room?

Won't that save performance and memory usage?

Then I guess i could argue that the type instances wont be already present at the room's creation thus could hinder the game but then again you could make a loading... depending if you have a huge quantity or not.

Anyway I'm jsut speculating since I've never made a game because I couldn't get past the game structure, dunno how to structure everything for perfection.

EDITED
btw the error i was talking about is
"Identifier test1 not found"
so yeah there is an error in there :o


TomToad(Posted 2007) [#4]
btw the error i was talking about is
"Identifier test1 not found"
so yeah there is an error in there :o


That's because you are declaring test1 as local to the If/End if structure, but you are trying to access the type outside of that structure.
You need to declare the type before the if/end if, or if you are using the type other than in the Case 0: then you need to declare it before the select.

While Not KeyHit(KEY_ESCAPE)
Local test1:TButton 'declare it here

Select gm_room
	Case 0
                'Alternatively, you can declare test1 here if it wont be used outside of Case 0
		' DO ONCE
		If gm_donce = 0 Then
		
			test1=New Tbutton 'This will create a new TButton and the GC will destroy the old one.
			test1.create(10,10,"test")
			
			gm_donce = 1
		EndIf
		
		' LOOP
		test1.Update()
End Select



Flip; Cls
Wend
End



Apollonius(Posted 2007) [#5]
I tried to use that way of doing things but I got an error:
Unhandled Exception: Attempt to access field or method of null object.

What does that mean?


@Nomen: What do you mean by:
I wouldn't bother with a big case/select for room in your loop.
When a new room is entered, call a 'new room' function that creates all the creatures etc for the room, 
then your main loop can be generic, just updating all the objects you have.


I dont understand, could you show me what you mean?


Who was John Galt?(Posted 2007) [#6]
It means you are trying to call a method or set or read a field in a type variable that does not have a type instance associated with it. i.e. A return from the New function has not been assigned to it.


Apollonius(Posted 2007) [#7]
It works if I set it to global instead of local... for some odd reason..

the error was caused at "test1.Update()" yet i changed nothing from previous it works out of the loop as local but only works in the loop as global... hmm

confusing


Czar Flavius(Posted 2007) [#8]
Are you basically asking, should you load the entire level/world into memory, or only load the parts needed for the next area upon entry and discard the data for the previous area?

Also for a simple first game I wouldn't worry too much about memory usage. Modern computers have plenty to spare.


Apollonius(Posted 2007) [#9]
Yes I am asking should I load parts as needed into memory like types... and how to structure such a fest using "rooms" like intro, menu, room1, room2.. ect and loading such things by room only so it won't take much memory.

Because If I load evrything before the loop wont that like hog the system while it's loadign everything which kinda sucks no?

( Let's say i were to make an rpg(practicing so i get to that point)


Czar Flavius(Posted 2007) [#10]
Where is the room data stored, a file on the harddrive? If it is then the size of the file can give you an indication of how much memory it would take in-game. I'd guess it would be a few kilobytes in size, but even if it's several megabytes (which I doubt!) I'd still say it would be easier to just load the entire data into memory once, and not bother with loading as you go along.

Since you're learning how to make a game, it can be tempting to make everything as efficent as possible. Don't worry about that just yet. Learn how to get a game working first, and how to optimise it later ;) I say just do which ever is easiest for you to implement right now.

(Another thought, after leaving a room, won't you need to keep track of which monsters have been killed/wounded?)


Apollonius(Posted 2007) [#11]
Well, I was thinking of making this old zelda style game of my own. Basicly, the room data such as buttons and menu would be types so I doubt I'll store them in a file for now. I'm putting it all in the source file thingy.

My main concerne is how to structure my code to do what I want. Let me tell you about how I see things right now:

I've been told to declare everything before loops so at first I thought if that's so, should I make a loop for every room and so declare everything before those loops.

Then I tried and it didn't work so well. So i thought of another way:

I though I would separate my rooms in the loop with a select case statements like ROOM_ID = 0,1,2,3... ect case 0, case 1.. ect. And then to declare my stuff.. since it's a loop and declaring should only be done once(so they say) then I need to make something that's only executed once in my loop code to declare the things I havent declared and after the room is past just destroying them.

Even that gave me problems, we I declare stuff, it says I haven't declared it when I did and stuff like that. Seems not to work quite accurately, /sob.

(as for keeping track of monster killed and wounded I though of using type.. but then again.. I guess that should stay in the memory uh lol, if I destroy everything after the room then it's not keeping track of them, I understand what you mean)

But what about not needing to keep track of buttons, textfields.. ect (which is a re-usable type I can use everywhere in my code thus not needing to retype any code) So I could destroy them to free some space but then when I re-enter the room I need to re-declare it so if not in the loop there's no way to redeclare it?

Overthinking my stuff :S
I appreciate the help Czar


Czar Flavius(Posted 2007) [#12]
Ok if i were going to do it I would do it like this. (I am by no means an expert though!)

Have a room type to contain all the information you need. Then create an instance of each room and store them in an array. If you're not using a file to store them then hardcode them in a source file.

For example
Local/Global/Whatever room:TRoom[roomNum] = New TRoom
For Local i:Int = 0 Until RoomNum
   room[i] = new TRoom
Next

room[0].name = "Room 1"
room[0].background = Image1
'etc. your monsters will probably be either a list or array
room[0].monsterNum = 3
room[0].monster = New TMonster[room[0].monsterNum]
For Local i:Int = 0 Until room[0].monsterNum
   room[0].monster[i] = New TMonster
Next
room[0].monster[0].health = 100
'and so on


This way is a bit wordy, which is where an editor program or making a way to load from a file can be helpful, but it should get the job done. I suggest you only prepare a room or 2 at first to test this way will work, rather than design your whole game only to discover this way doesn't work or something!

Then in your main game loop you'll have a current room variable pointing to one of the rooms stored in data. I'll call this thisRoom:TRoom.

Now you simply say thisRoom = room[0] to set that to the current room, or thisRoom = room[1] for the second room.

Now instead of having a separate case for each room, you can write a generalised loop for any room. Yay!

So to draw monsters, you'd put this in a loop (or make it into a method to call from the loop)

For Local I:Int = 0 Until thisRoom.monsterNum
   thisRoom.monster[i].draw()
   thisRoom.monster[i].updateOrSomething()
Next


Or a cleverer way

For Local tempMonster:TMonster = EachIn thisRoom.monster
   tempMonster.draw()
   tempMonster.updateOrSomething()
Next


Persumably your rooms will consist of doors to other rooms. In that case you'll want an array of doors for each room, and each doorhaving a value to which room it leads. So changing room is as easy as this:

'assuming doors are stored as a type with fields for
'destination, keys etc
Method openDoor()
  thisRoom = room[destination] 'could be say 5, assumes your room list and thisRoom are global
End Method

'in your main loop
If thisRoom.door[whichDoor].unlocked = True
   thisRoom.door[whichDoor].openDoor()
End If


I hope this clears things up a bit, and gives you new ideas on your game's designs. If anybody has any better ideas, I'd love to hear them ;)


Apollonius(Posted 2007) [#13]
Oh! Oh! Why didn't I think of that? I mean,
monster=type..
button=type...
textfield=type....

So why not rooms? That's logical no? lol. As soon as you showed me room = type... it gave me plenty more ideas! :o

Types, in types.. so basicly I can add in all the controles for the room inside it's own type.. creating instances of all rooms.

Very very interesting... I'll play with it later after work. And post back how everything goes :D

Thanks!


Czar Flavius(Posted 2007) [#14]
Yep. It might help to plan it out on paper first. You have an array of room types. Each room also has an array/list of doors, monsters and items and so forth. Simply switch the current room and then you don't need to treat each seperately.