Class routine

Blitz3D Forums/Blitz3D Programming/Class routine

JoshK(Posted 2004) [#1]
Here is a good method for storing and handling objects. Types have two fundamental problems. First, a variable can only be one type class, unless you use the clunky Object() command. Second, types cannot store a variable array of subobjects, like a vertex list. This lets you store any structure in a regular old four-byte integer variable.

Here are the commands:

item=CreateItem(class)
"Class" is a constant, from 1 to infinity. Use CLASS_PLAYER, CLASS_MONSTER, etc.

Setl(item,parameter,value)
"parameter" is a constant, from 1 to infinity. Use PLAYER_HEALTH, MONSTER_LEVELOFSEETHINGRAGE, etc.

Getl(item,parameter) returns integers.

You can also use Setf(), Getf(), for floats.

CountItems(class)
How many items exist with that class.

GetItem(class,index)
Returns the item. Index is from 1 to CountItems().
This will probably be made into a lib.

Include "classes.bb"

Const CLASS_PLAYER=1
Const PLAYER_NAME=1
Const PLAYER_HEALTH=2
Const PLAYER_XPOSITION=3
Const PLAYER_YPOSITION=4
Const PLAYER_ZPOSITION=5

Const CLASS_MONSTER=2
Const MONSTER_HEALTH=1
Const MONSTER_XPOSITION=2
Const MONSTER_YPOSITION=3
Const MONSTER_ZPOSITION=4

Const CLASS_WEAPON=3
Const WEAPON_AMMO=1
Const WEAPON_RECOIL=2

For n=1 To 3
	player=createitem(CLASS_PLAYER)
	setl player,PLAYER_HEALTH,n
	setf player,PLAYER_XPOSITION,Rnd(0,100)
	setf player,PLAYER_YPOSITION,Rnd(0,100)
	setf player,PLAYER_ZPOSITION,Rnd(0,100)
	Next

player=GetItem(CLASS_PLAYER,2)
FreeItem player

sets GetItem(CLASS_PLAYER,1),PLAYER_NAME,"Adam"
sets GetItem(CLASS_PLAYER,2),PLAYER_NAME,"Joe"

For n=1 To CountItems(CLASS_PLAYER)
	player=getitem(CLASS_PLAYER,n)
	Print "Player "+n
	Print "Name: "+gets(player,PLAYER_NAME)
	Print "Health: "+getl(player,PLAYER_HEALTH)
	Print "X position: "+getf(player,PLAYER_XPOSITION)
	Print "Y position: "+getf(player,PLAYER_YPOSITION)
	Print "Z position: "+getf(player,PLAYER_ZPOSITION)
	Print ""
	Next

For n=1 To 2
	monster=createitem(CLASS_MONSTER)
	setl monster,MONSTER_HEALTH,Rnd(0,100)
	Next

For n=1 To CountItems(CLASS_MONSTER)
	monster=getitem(CLASS_MONSTER,n)
	Print "Monster "+n
	Print "Health:"+getl(monster,MONSTER_HEALTH)
	Print ""
	Next

WaitKey
End


classes.bb:
Global masterclassbuffer=CreateBank()

Const ITEM_HEADERLENGTH=4

Function CreateItem(class)
If BankSize(masterclassbuffer)<class*4
	ResizeBank masterclassbuffer,class*4
	Else
	classbuffer=PeekInt(masterclassbuffer,(class-1)*4)
	EndIf
If Not classbuffer
	classbuffer=CreateBank()
	PokeInt masterclassbuffer,(class-1)*4,classbuffer
	EndIf
item=CreateBank(ITEM_HEADERLENGTH)
PokeInt item,0,class
size=BankSize(classbuffer)
ResizeBank classbuffer,size+4
PokeInt classbuffer,size,item
Return item
End Function

Function CountItems(class)
If BankSize(masterclassbuffer)<class*4 Return 0
classbuffer=PeekInt(masterclassbuffer,(class-1)*4)
If classbuffer
	Return BankSize(classbuffer)/4
	Else
	Return 0
	EndIf
End Function

Function GetItem(class,index)
classbuffer=PeekInt(masterclassbuffer,(class-1)*4)
Return PeekInt(classbuffer,(index-1)*4)
End Function

Function FreeItem(item)
class=ItemClass(item)
classbuffer=PeekInt(masterclassbuffer,(class-1)*4)
For n=0 To (BankSize(classbuffer))/4-1
	If PeekInt(classbuffer,n*4)=item
		For m=n To (BankSize(classbuffer))/4-1-1
			PokeInt classbuffer,m*4,PeekInt(classbuffer,m*4+4)
			Next
		FreeBank item
		ResizeBank classbuffer,BankSize(classbuffer)-4
		Exit
		EndIf
	Next
End Function

Function ItemClass(item)
Return PeekInt(item,0)
End Function

Function Getl(item,parameter,defaultvalue=0)
If BankSize(item)<parameter*4+ITEM_HEADERLENGTH Return defaultvalue
Return PeekInt(item,(parameter-1)*4+ITEM_HEADERLENGTH)
End Function

Function Setl(item,parameter,value)
If BankSize(item)<parameter*4+ITEM_HEADERLENGTH ResizeBank item,parameter*4+ITEM_HEADERLENGTH
PokeInt item,(parameter-1)*4+ITEM_HEADERLENGTH,value
End Function

Function Getf#(item,parameter,defaultvalue#=0)
If BankSize(item)<parameter*4+ITEM_HEADERLENGTH Return defaultvalue
Return PeekFloat(item,(parameter-1)*4+ITEM_HEADERLENGTH)
End Function

Function Setf(item,parameter,value#)
If BankSize(item)<parameter*4+ITEM_HEADERLENGTH ResizeBank item,parameter*4+ITEM_HEADERLENGTH
PokeFloat item,(parameter-1)*4+ITEM_HEADERLENGTH,value
End Function

Function Gets$(item,parameter,defaultvalue$="")
If BankSize(item)<parameter*4+ITEM_HEADERLENGTH Return defaultvalue
sbank=PeekInt(item,(parameter-1)*4+ITEM_HEADERLENGTH)
If Not sbank Return defaultvalue
Return PeekString(sbank,0)
End Function

Function Sets(item,parameter,value$)
If BankSize(item)<parameter*4+ITEM_HEADERLENGTH
	ResizeBank item,parameter*4+ITEM_HEADERLENGTH
	Else
	sbank=PeekInt(item,(parameter-1)*4+ITEM_HEADERLENGTH)
	EndIf
If sbank
	ResizeBank sbank,Len(value)+1
	Else
	sbank=CreateBank(Len(value)+1)
	PokeInt item,(parameter-1)*4+ITEM_HEADERLENGTH,sbank
	EndIf
PokeString sbank,0,value
End Function



BulletMagnet(Posted 2004) [#2]
Fails here on: Return PeekString(sbank,0)" in your GetS function.

Result: "Function PeekString not found."


JoshK(Posted 2004) [#3]
Oh, you need my poke/peek string lib:

Global svar.s

ProcedureDLL PokeString(*bank,offset,value.s)
PokeS(*bank+offset,value)
EndProcedure

ProcedureDLL.l PeekString(*bank,offset)
svar=PeekS(*bank+offset)
ProcedureReturn @svar
EndProcedure


Rottbott(Posted 2004) [#4]
That looks a lot clunkier than Object() to me!


martonic(Posted 2004) [#5]
What is the "Object()" command? There is no mention of it in any of the Language or Command help files, as far as I can see. Thank you.


JoshK(Posted 2004) [#6]
Types are better for a small program. This is good for when you have an engine with a lot of structures, and structures that reference other structures.

I agree that typing out PLAYER_WHATEVER can get repetetive, but when you get to the point of a really massive engine, it's a tradeoff worth making. This is actually a LOT like how Blitz stores structures internally.

This is the kind of code I am using it for. Organization is more important for this than easiness:
Function LoadStaticMeshInstance(file$)
file=Lower(file)
For n=1 To countitems(CLASS_STATICMESHREFERENCE)
	staticmeshreference=getitem(CLASS_STATICMESHREFERENCE,n)
	If file=gets(staticmeshreference,STATICMESHREFERENCE_FILENAME)
		reference=staticmeshreference
		Exit
		EndIf
	Next

If Not reference
	mesh=LoadStaticMesh(file)
	If mesh
		reference=createitem(CLASS_STATICMESHREFERENCE)
		setl reference,STATICMESHREFERENCE_MESH,mesh
		sets reference,STATICMESHREFERENCE_FILENAME,file
		EndIf
	EndIf

If reference
	mesh=CopyEntity(gets(staticmeshreference,STATICMESHREFERENCE_MESH))
	staticmesh=createitem(CLASS_STATICMESH)
	setl staticmesh,STATICMESH_MESH,mesh
	setl staticmesh,STATICMESH_VIEWDISTANCE,8000
	Return staticmesh
	EndIf

End Function



BulletMagnet(Posted 2004) [#7]
Oh, you need my poke/peek string lib:


Got an active link for that?

Thanks,


Rimmsy(Posted 2004) [#8]
No, it's purebasic so he can't release it compiled.


dmaz(Posted 2004) [#9]
A lot of people seem to really like banks... I'm not one of them though. To each his own I guess.

I wrote a real nice linked list lib that's really simple use even with Handle() and Object().
http://www.blitzbasic.com/codearcs/codearcs.php?code=1117

Halo, serious question, why would you use your system over mine? I ask just because I'm wondering if there is something wrong or not liked about what I did?


JoshK(Posted 2004) [#10]
Actually, that function is not a wrapper of a PB function, so someone could post the DLL without a problem.

I don't know what yours does, and I hate types anyways.


dmaz(Posted 2004) [#11]
I don't know what yours does, and I hate types anyways.
well, it's just a linked list but it does use types. although it does allow for lists within lists etc...
Don't like types though, hmmm? you probably don't want to get into why? Well, I don't really like Mark's implementation here either. It was so much better in Blitz2 on the Amiga. As a matter of fact, my linked list lib was meant feel as close to that as possible.

It's good to know that Mark will be going back to separate lists in BlitzMax, can't wait.