include ".bb" is this how you load levels???

Blitz3D Forums/Blitz3D Beginners Area/include ".bb" is this how you load levels???

AvestheFox(Posted 2004) [#1]
Okay... Ive decided to make my game by placing each level and their commands in seperate .bb files, someone had told me once that this was neccesary.. but my question.. how do I load these levels into my game.. and into their proper order?

Do I use the "include" command?


Sledge(Posted 2004) [#2]
There might be a small case for organising your project files this way if each of your levels is vastly different, but as a method to load in each level one by one during gameplay you are on the wrong track with this.

The contents of an included file get pasted into the source at the point the include command is called... like a massive macro. The clue really is in the name... if you "include" files a.bb, b.bb and c.bb then your exe will include all of their contents. You can flit between their sections of code, of course, but there would be no loading after the fact... they're already there.

Level loading should typically involve you sitting down and formalising exactly what it is your core game code will have to deal with and how the data for each level will be expressed, then formulating a loading routine to generate the world from the data for the engine (and, if you're sensible, a level editor and matching save routine). The "include" command doesn't really enter into it.


jfk EO-11110(Posted 2004) [#3]
What Sledge said. First of all, your game need to be capabl of releasing everything from memory that was part of a level. THe easiest way would be to use a textfile that holds all information it needs to load a level: MEsh filenames, Positions, Rotations, Scalings, 3Dsound Filenames, positions etc. (assuming you want to make a 3D game), You engine would then read the textfile and load, position, rotate and scale the level content one by one. In the same time it will store all entity handles in an array or as types, so you will be able to free them at the end of the level using a single for loop that will release all stuff and make space for the next level. Then you only have to reset all global game variables to their intial value and then you can load the next level, using the same loading function like with level one.


AvestheFox(Posted 2004) [#4]
okay..I think I understand what your talking about here... so let's say for example.. I have this code in the main program...
Graphics3D 520,340
SetBuffer BackBuffer()

Const WLD=1
Const PLR=2
Const COINS=3

light=CreateLight()

camera=CreateCamera()
Camerapoint=CreateSphere()
HideEntity camerapoint

player=CreateSphere()
PositionEntity player,0,5,0
EntityType player,PLR	

coin=CreateCylinder()
ScaleEntity coin,1,0.1,1
TurnEntity coin,90,0,45
EntityColor coin,255,255,0
EntityType coin,COINS
HideEntity coin

Collisions PLR,WLD,2,2
Collisions PLR,COINS,2,2

While Not KeyHit(1)

If KeyDown(200) MoveEntity player,0,0,0.3 
If KeyDown(208) MoveEntity player,0,0,-0.3  
If KeyDown(203) MoveEntity player,-0.3,0,0 
If KeyDown(205) MoveEntity player,0.3,0,0 

;Camera control
PositionEntity camera,EntityX(player,1),EntityY(player,1)+5,EntityZ(player,1)-20
PointEntity camera,player

;Jump and Gravity control
gravity#=.03 
jumpvel#=.9 

If jumping=0 Then TranslateEntity player,0,-.9,0

If jumping=0 
If KeyDown(54) Then yvel#=jumpvel# jumping=1 
EndIf 
If jumping=1 
yvel#=yvel#-gravity# 
by#=by#+yvel# 
EndIf 

If by#<1 Then by#=1 yvel#=0 jumping=0 

speed#=speed#*.99 
MoveEntity player,0,yvel#,speed# 

;Collisions with coins
If CountCollisions(player) > 0 Then 
    If EntityCollided(player, COINS) > 0 Then
        FreeEntity EntityCollided(player, COINS)
        UpdateWorld()
    EndIf
EndIf

UpdateWorld
RenderWorld

Flip
Wend

End
then I place the following code into a text file:
world=CreatePlane()

cube1=CreateCube()
cube2=CreateCube()
cube3=CreateCube()
cube4=CreateCube()

PositionEntity cube1,5,1,10
PositionEntity cube2,-5,1,10
PositionEntity cube3,5,1,20
PositionEntity cube4,-5,1,20

EntityColor world,0,0,200
EntityColor cube1,255,0,0
EntityColor cube2,0,255,0
EntityColor cube3,0,0,255
EntityColor cube4,0,0,0

EntityType world,WLD
EntityType cube1,WLD
EntityType cube2,WLD
EntityType cube3,WLD
EntityType cube4,WLD

;coins >>
PositionEntity coin,-10,1,15
ShowEntity coin
CopyEntity coin
PositionEntity coin,-5,1,15
ShowEntity coin
CopyEntity coin
PositionEntity coin,0,1,15
ShowEntity coin
CopyEntity coin
PositionEntity coin,5,1,15
ShowEntity coin
CopyEntity coin
PositionEntity coin,10,1,15
ShowEntity coin
then I can somehow load it into the main program???


WolRon(Posted 2004) [#5]
I'm not sure that Sledge and jfk made themselves clear so I will give it a try.

.bb files (typically) contain CODE.

files that contain your level data would (typically) be something else (i.e. .b3d, .lvl, .L01, .L02, L03, etc.)

You COULD, if you wanted to, use .bb files for your level data but that's not what they were intended for.

Here's an example:
Graphics 640, 480, 0, 1
SetBuffer BackBuffer()
Include "Init.bb"
LoadLevel(level)

;main loop
While Not KeyHit(1)
  Include "PlayerInput.bb"
  Include "UpdateAI.bb"
  If levelwon = True
    level = level + 1
    LoadLevel(level)
    ResetGame()
  EndIf
  Include "Drawscreen.bb"
  Flip
Wend
End

Function LoadLevel(lvl)
  ;assuming that your level files are named with a .lvl? extension
  ;like .lvl1 or .lvl2 for example
  levelmesh = LoadMesh("MyGame.lvl" + lvl)
End Function

Function ResetGame()
  ;resets all game data for the next level
End Function
And the Init.bb" file could for instance contain some CODE like this:
player = LoadMesh("player.x")
cam = CreateCamera(player)
MoveEntity cam, 0, 1, -3
light = CreateLight()
level = 1
;etc.
and the other included files would also contain CODE.


AvestheFox(Posted 2004) [#6]
Ah! Now I see... so I was right about the second part ^^

thanks for the help.. I'll play around with what's given here


AvestheFox(Posted 2004) [#7]
is there a certain way I have to code the .lvl file for it to work? I cant seem to get the level to load like it should


Sledge(Posted 2004) [#8]
Level files should contain data only, not commands. Your core code must be flexible enough to read the data from the level files and build each level accordingly. For a simple example, your level file might read...

3,1,3,2,0,0,0,10,0,0,2,4,4


...in order to describe three cubes, the first 1 unit in size and positioned at 0,0,0; the second 3 units in size and positioned at 10,0,0; the third two units in size and positioned at 2,4,4. Do you see how those things relate to the data?

Your loading routine has to be able to parse that information from data file (where using commas to separate entries can come in handy... there are other standards others might suggest instead) and construct the level accordingly. If it were a different level, you'd read in a different file, describing an alternate arangement of cubes (or polygons, textures, enemy locations, script triggers etc) and the central code would build that instead.

You really need familiarise yourself with Blitz's file I/O commands - they form the basis for all this stuff.


AvestheFox(Posted 2004) [#9]
hehe.. I'm even more confused.. though I'm sure I'll learn how all this stuff works... is there a more simple way of transfering your levels into that data string?.. or does this all have to be coded by hand?


Sledge(Posted 2004) [#10]
Well it's just an example. For actual level geometry you'd normally use a dedicated modeller and save out either a .x or .b3d file (and your data file would refer to each component model and describe how they fit together and are populated). But as each and every game is different - yes, you basically have to devise a custom system that fits your needs. It's quite a leap to go from typing out your levels long-hand (ie entity by entity) to formulating a system that will build them from data... it takes forward thinking because your core code has to be flexible and your loader extensible.


is there a more simple way of transfering your levels into that data string?


When you're experimenting it's probably quickest to write the data by hand (if nothing else it reduces the chance of bugs); once you're commited to a sufficiently large project it's then more likely that knuckling down and writing a level editor and save routine will be worthwhile.

The biggest question to be asking yourself is "Do I actually need a level loader?" If your game is only modestly sized then it may be much more expedient to simply "hard-code" everything into the main source code. Just remember that the "right" way is the way that enables you to get the job done.

If you take nothing else from this thread, though, understand that a Blitz exe can't interpret and run .bb files... it would be like expecting your Word Processor to understand C++ just because that's the language it was written in.


AvestheFox(Posted 2004) [#11]
well concidering I'll be piecing together my level models in AC3D, I know I wont have to be using default Blitz cubes to build each little nuke and cranny of my worlds... my big concern would be positioning power ups, collectables.. enemy positions, also each objects movements and interactions (which would all be worked through the main program I'm assuming)... it's not the big stuff I'm worried about.. it's the little things


WolRon(Posted 2004) [#12]
It's really not as hard as you think.

YOU decide what kind of program you are making. Therefore YOU decide what information your program needs to load.

As Sledge suggested above, if your program needs to create a few cubes and needs to know the cubes dimensions and locations, then thats the type of data that you would need to store.


Here, I will show you an example. I made a Pitfall II clone a year ago. I also added an additional cavern for the player to explore if they completed the first so I built a LoadLevel function to load in the levels.

The Pitfall II game is a large underground cavern which can basically be represented by an array 8 units wide by 30 units deep.

At each location of the cavern (array), my program needed to know what was at that location. So I built a level editor that stored each locations specific data in to a file. I created a type that contained the following elements:
type of graphic
water at that location?
left_blocked?
right_blocked?
type of animal at that location (0 for none)
ladder at that location?
checkpoint at that location?
background_image
treasure at that location?

Then the editor just stored each of those type fields to the file in order while running through the array top/bottom, left/right.

In my main program I created the "level" type that would store the data at each location: (Note that the term 'level' being used here is not meant as in an entire game level but as in a 'platform')
Type Level
	Field graphic			;0=nothing 1=ladderhole 2=hole-in-middle 3=left 4=right 5=ladderhole+2holes
					;6=flat 7=ground 8=treetops 9=water 10=skyline 11=other-treetops 12=other-skyline
	Field water			;0=not 1=true(graphic needs to be set to 3 or 4)
	Field left_blocked		;0=not 1=solid 2=checkered
	Field right_blocked		;0=not 1=solid 2=checkered
	Field animal			;0=not 1=bat 2=bird 3=scorpion 4=frog 5=eel 6=mouse(treasure has to be 6 also)
	Field ladder			;0=not 1=ladder in middle
	Field checkpoint		;0=not 1=true
	Field background_image		;0=not 1=water 2=trees 3=treetops 4=ground 5=other-trees
	Field treasure			;0=not 1=gold(right) 2=gold(left) 3=cat 4=girl 5=ring 6=mouse(animal has to be 6 also)
End Type

and then I created an array of types:
Dim Board.Level(8, 30)
;8 screens across x 30 levels high (including sky as a level)


My main program used this function to load one of the levels:
Function LoadLevelData(level)
	;fill level data
	If level = 2
		l$ = "2"
	Else
		l$ = ""
	EndIf
	; Open the file to Read
	filein = ReadFile("level"+l$+"data\leveldata")
	If filein = 0 Then RuntimeError("Pitfall II - Error: Can't read level data. Reinstall program.")
	For xiter = 1 To 8
		For yiter = 1 To 30
			; Read the data from the file
			Board.Level(xiter, yiter) = New Level
			Board(xiter, yiter)\graphic = ReadByte( filein )
			Board(xiter, yiter)\water = ReadByte( filein )
			Board(xiter, yiter)\left_blocked = ReadByte( filein )
			Board(xiter, yiter)\right_blocked = ReadByte( filein )
			Board(xiter, yiter)\animal = ReadByte( filein )
			Board(xiter, yiter)\ladder = ReadByte( filein )
			Board(xiter, yiter)\checkpoint = ReadByte( filein )
			Board(xiter, yiter)\background_image = ReadByte( filein )
			Board(xiter, yiter)\treasure = ReadByte( filein )
			If Board(xiter, yiter)\treasure > 2
				If Board(xiter, yiter)\treasure < 6
					NumTreasures = NumTreasures + 1
				EndIf
			EndIf
		Next
	Next
	; Close the file once reading is finished
	CloseFile( filein )
	Return NumTreasures
End Function


First it loads the appropriate file;
then it goes into a loop (1-30 high, 1-8 across);
at each iteration of the loop it creats a type instance for that location of the cavern;
it then loads in each type field for that location;
it increments a treasure variable for me if there is any treasure at that location so that when the entire level is loaded my program knows how many treasure pieces need to be collected;
when done loading everything it closes the file;
at the end of the function it returns the number of treasures that were loaded.


AvestheFox(Posted 2004) [#13]
I pretty much see how this works now.. so I'm thinking about building me a level editing tool to help make the files I need... anyone who'd like to help me... you may IM me at

AIM = Ryuu Silverfox
MSN = Aves_fox@... (hoping I'm right on that
Yahoo = Ryuu_silverfox

thanks for your help and info so far

thanks to:
WolRon
Sledge
jfk


jfk EO-11110(Posted 2004) [#14]
I never IM. But I suggest to do it this way:

Make your Level Editor capable of displaying a File Request Box. So you can choose a Mesh file. After chosing a meshfile, the Editor will load this meshfile right away. You will then be able (well you have to code this, it's the editors functionality) to select the Mesh, rotate it, scale it, position it in 3D.
The editor should store all information about the Meshes you used to load in an array, or in a type structure. Most people will tell you to use types, but personally I prefere an Array. It doesn't really matter.

Basicly you first need to sit down and think about what parameters for every mesh you want to be able to set in the editor. This means you are "wrapping" the entity. Make a list like:

filename (includes path)
name (a string you can use to give it a name)
x#
y#
z#
xscale#
yscale#
zscale#
pitch#
yaw#
roll#
alpha#
pickmode
collision type
optional texture
texture flag
optional texture 2
texture flag
optional texture 3
texture flag
optional texture 4
texture flag
EntityFX


and maybe a lot more. you need to take some time to make a list that contains everything that could be important one day. study the Docs, esp. the Entity Properties section.

Then you should define a default value for all parameters. The paramters are initialized with these.

You need some kind of GUI to edit the values. Position and rotation and scaling may work with some kind of mousedriven tool. other things may be common GUI Forms.

Anyway, after creating and adjusting a scene made of several meshes, you will be able to save all parameters to a file.

Now that you have all the parameters, it's easy to open the file and read out all parameters, then load and restore the scene as you just saved it before.

Example:

re=readfile("level.lvl")
while not eof(re)
 l$=readline(re) ; mesh filename
 if filetype(l$)<>1
  runtimeerror "Cannot load "+l$
 endif
 m=loadmesh(l$)
 x#=readline(re)
 y#=readline(re)
 z#=readline(re)
 positionentity m,x,y,z
 xs#=readline(re)
 ys#=readline(re)
 zs#=readline(re)
 scaleentity m,xs,ys,zs
 ...and so on
wend
closefile re


Using Readline and Writeline for all parameters makes things much easier for you and you will also be able to visually check a .lvl files content by watching it with notepad. You can easily use a floating point variable to read in a line, the value will automaticly be converted to a number, although Readline returns a String. It's a simple and flexible method that will allow to store both, strings and numbers.

just make sure you will read the same number of lines from the file as you used to saved. And of course you also need to store the parameters in an array or in types while loading, to be able to free everything from memory later, when you want to load the next level.


jfk EO-11110(Posted 2004) [#15]
Uh, BTW. i still don't know if you are talkin about a 2D game ir a 3D game, anyway, this was about 3D.


AvestheFox(Posted 2004) [#16]
it was 3D, man.. thanks


jfk EO-11110(Posted 2004) [#17]
I have released a slim version of my editor for the prject plasma some time ago, you may have a look:
http://www.melog.ch/dl/pledit05.zip

uh, it may be a bit confusing that the loader example is reading the level file twice: the first time to determine how many game objects have to be loaded (since it's using DIMed Arrays, it should know that number so it won't have to reserve more Memory than required), and the second time that actually will load the level.


AvestheFox(Posted 2004) [#18]
hey thanks, man.. I'll give this a look and play around with it ^_^

again.. thanks bunches