Why you should name types?

Blitz3D Forums/Blitz3D Beginners Area/Why you should name types?

bobbo(Posted 2004) [#1]
(BitzPlus)
What's the point of giving a name to types?
First, I thought I could use them to build a structure and then create differetn instances... But this is not true.
The For... Each loop will check all instances regardless of the name... Is it normal?

Example:

Type SPRITE 
	Field LOCX 
	Field LOCY 
	Field CURRENTFRAME	
	Field MAXFRAME	
End Type 

For temp = 1 To 20

	cats.sprite = New sprite 
	cats\LOCX = Rand(100)
	cats\LOCY = Rand(200)
        cats\CURRENTFRAME= Rand(1,8)-1
	cats\MAXFRAME= 8
		
Next 

For temp = 1 To 20

	zombies.sprite = New sprite 
	zombies\LOCX = Rand(100)
	zombies\LOCY = Rand(200)
        zombies\CURRENTFRAME= Rand(1,18)-1
	zombies\MAXFRAME= 18
		
Next 

For zombies.sprite= Each sprite

        Print zombies\LOCY

Next



This will print both cats and zombies...

And if you try a new name:


For zombies.sprite= Each sprite

        Print zombies\LOCY

Next



It will print all sprite collection again!

I have already found workarounds for this, but don't you think that it is not logic? Each instance of a type should be a different collection.


bobbo(Posted 2004) [#2]
Sorry, the secodn example should have been:

For newFantasyname.sprite= Each sprite

        Print newFantasyname\LOCY

Next


It prints all the content of both cats and zombies...


SopiSoft(Posted 2004) [#3]
well, the For...Each loop just loops through all the same types in Blitz's typelist regardless of what instance-name it has...so the only solution would be to use some sort of flagging, but you probabaly already have done that since you said you've found a workaround.

...but the syntax actually says exactly what it does:
For obj.typename = Each typename ....*Each* -> typname.
so...each instance of the given type.


bobbo(Posted 2004) [#4]
Yes, that's exactly what I did.
But it is a bad programming technique IMHO (flags everywhere...).
Well, BlitzPlus is damn fast so I should not complain...
I think they should explain this better in the docs :)


sswift(Posted 2004) [#5]
A type is a linked list. Each type you create is a seperate linked list.

When you go ThisEnemy.Enemy = New Enemy, what you are doing is adding an Enemy to the list of enemies, and assigning a pointer to that particular enemy to the variable ThisEnemy.

If you want a list of cats and a list of dogs, then you can either go:

Type Cat
Blah
End Type

Type Dog
Blah
End Type

Or, you can go:
Type Animal
Field Species
blah
End Type

Then you can pass any animal to a function which deals with animals, and use a case statement to dtermine which specific type of animal you are dealing with.

In addition, you can create a variable FirstCast.Animal, and store the pointer to the first cat that is in the list of animals. You can also store LastCat.Animal. Then, you can easily loop through only the cats in your list, though you must use a repeat or a while loop to do so. I think... I'm pretty sure you can't go For ThisCat.Cat = FirstCat to LastCat. Though it would certainly be nice if you could, and I don't see any reason why you should not be able to, from a language design standpoint.


bobbo(Posted 2004) [#6]
Thanks for the tips sswift, I will certainly try your ideas.
I want to be perfectly sure about what i am doing with Types before starting to code my brand new vertical shoot'em up ;)


_PJ_(Posted 2004) [#7]
On this subject, I am curious as to when checking against types, does it eat up memory or anything the amount of different for/next associations you create...

what I mean is, imagine I have a type for a player bulleet.

at one point, when fire is pressed, I make the new bullets so I use

MyNewBullet.Bullet=New Bullet

Then, later in the program I want all my bullets that have been fired to move, so I use something like

For MoveBullets.Bullet = Each Bullet

Then I wish to check if my bullets have run out of range, hit an enemy or a wall etc. so I check again with another For/Next

For COllisionBullet.Bullet = Each Bullet

Of course each iteration will take time, but are there any other bad points with this?

Is it possible to use the same label each time (DoSOmethingWithBullet.Bullet) or do everything related to that type in the one for/next loop???)


sswift(Posted 2004) [#8]
I use the same type names all the time. Every functiont hat deals with bullets accepets a parameter caleld ThisBullet.Bullet. And every tine I need to loop through my list of bullets I'll use ThisBullet.Bullet for that as well. Or I'll use something else.

All ThisBullet.Bullet is is a pointer. It can hold a pointer to any bullet you want it to. Treat it exactly the same as you would an integer. Use it for as many different values as you like. Values in this case being pointers to bullets in your bullet type.

And no there is no good reason to combine multiple loops into one, unless it makes your code neater.


_PJ_(Posted 2004) [#9]
Hmm yeah thinking about it... it's much clearer having separate loops - much easier to identify for de-bugging etc.

Thanks Sswift ;-)

------------EDIT--------

(can't spell!)


SopiSoft(Posted 2004) [#10]
@malice:
if you create lets say, 100 instances of type 'bullet', and you use 3 seperate loops then you are looping 300 times...while if you do all the movement/checking for collisions/out of range checking in just 1 loop you only have to loop through 100 bullets instead of 300 which saves you a lot of calculation time.


sswift(Posted 2004) [#11]
"you only have to loop through 100 bullets instead of 300 which saves you a lot of calculation time."

I can loop through 10 million pixels per frame and you're worried about 300 bullets vs 100? :-)


SopiSoft(Posted 2004) [#12]
that was just an example of good programming practice, what if he had 10 million particles and used 3 seperate loops huh? ;-P


_PJ_(Posted 2004) [#13]
Luckily I haven't ;-)

Although Type iterations are so quick there shouldn't be any problems, I am kind of curious now and might run some trials. I wonder how much difference is made with the time for types that contain Fields which are mesh/sprite handles compared to other raw data...


bobbo(Posted 2004) [#14]
I am exploring the potential if banks now.
I decided that arrays are limited (only globals), so I am using banks for storing level data and maybe I will use types for simple alien waves... But I wonder if banks are faster than types (especially becuase I can use byte and short)... In that case I am going to use only banks.
Maybe the code is less readable, but I am looking for the highest speed and I hate global variables...


Neo Genesis10(Posted 2004) [#15]
I rather prefer the idea of using one loop myself. It can be much tidier and faster. A perfect example of this was when I was running collision checks on conveyor belts for 'Trouble'. I had previously used 2 loops and the slowdown was horrendous (and this is a 2D game on a 3Ghz PC!). Squashing it into one loop solved all my woes.

Besides, if you use one loop you can call functions within that loop to run anything you need to...
For m.mytype = Each mytype
	collision_type = MoveBullet( m )
	If collision_type > 0
		DoCollision( m, collision_type )
		Destroy( m )
	EndIf
Next



PowerPC603(Posted 2004) [#16]
I tried the upper most example and changed the name in the last For-loop to this:

For a.sprite= Each sprite 
	Print a\LOCY
Next 


I think Sintetik was asking: why should you give a name to the type, as it doesn't matter what name you give?

In my example, the variable "a" (or type instance) didn't exist or doesn't get declared.
But Blitz doesn't give me an error on it.

So you could create this program:

Type SPRITE 
	Field LOCX 
	Field LOCY 
	Field CURRENTFRAME 
	Field MAXFRAME 
End Type 

For temp = 1 To 5 
	cats.sprite = New sprite 
	cats\LOCX = Rand(100) 
	cats\LOCY = Rand(200) 
	cats\CURRENTFRAME= Rand(1,8)-1 
	cats\MAXFRAME= 8 
Next 

For a.sprite= Each sprite 
	Print a\LOCY
Next 


And it still does work.
In my opinion, there no need the give a type instance a name, like this:

cats.sprite = New sprite 


Why not just do:

New sprite


And use this routine to run through them:

For Each sprite 
	Print sprite.LOCY
Next 


This could make more sense (to me anyway).


bobbo(Posted 2004) [#17]
Yes PowerPC603, I was meaning exactly what you wrote.
No logic meaning with types: the names are useless.
Your examples are perfect.

Meanwhile, I finished my multi directional scrolling routines using banks: they are damn fast, I think I will never use types or arrays for the most important game routines.


Shambler(Posted 2004) [#18]
The only reason for needing a name I can see is if you have 2 nested For Each type loops.

As in http://www.blitzbasic.com/codearcs/codearcs.php?code=920

Other than that Blitz could assume that the type instance you want to access is

1) If you are in a For Each loop it is obvious which type instance you are talking about
2) If you just created a type then that is the one you are talking about so

New sprite
sprite.LOCY


means the LOCY field of the sprite type instance I just created.


tonyg(Posted 2004) [#19]
Even if you are using nested loops the names are irrelevant aren't they?
If I ALWAYS use my.DOG to declare types I can always use.
For type.DOG = each DOG
For type1.DOG = each DOG

Maybe it makes code a little more readable?
There was a thread on Blitzcoder where somebody listed about 10 reasons but I don't know whether we're supposed to product links to the other forum.


Shambler(Posted 2004) [#20]
The name is irrelevant in that you can call them whichever name you like but you need to give them different names otherwise it won't know which instance you are referring to.


PowerPC603(Posted 2004) [#21]
This isn't true, I think.

When you do this:

For temp = 1 To 5 
	cats.sprite = New sprite 
	cats\LOCX = Rand(100) 
	cats\LOCY = Rand(200) 
	cats\CURRENTFRAME= Rand(1,8)-1 
	cats\MAXFRAME= 8 
Next 


Doesn't this loop create 5 instances, each one with the name "cats" and of type "sprite"?

So you actually have 5 different type instances,
all called "cats.sprite".

Or am I wrong?

And the name doesn't matter.

Create this program:

; Initialize window
Graphics 640, 480, 0, 2

; Create a type, called "sprite" and assign some fields to it
Type SPRITE 
	Field LOCX 
	Field LOCY 
	Field CURRENTFRAME 
	Field MAXFRAME 
End Type 

; Create 5 instances of the "sprite"-type, each one called "cats", and give the fields some values
For temp = 1 To 5 
	cats.sprite = New sprite 
	cats\LOCX = Rand(100) 
	cats\LOCY = Rand(200) 
	cats\CURRENTFRAME= Rand(1,8)-1 
	cats\MAXFRAME= 8 
Next 

For SomeRandomName.sprite= Each sprite 
	Print SomeRandomName\LOCY
Next 

While Not KeyHit(1)
Wend

End


You will see that, when printing the fields, there's no instance created anywhere in the program called "SomeRandomName".

It just prints the field LOCY of any types of type "sprite",
not just the ones that have the name "SomeRandomName".
If the names of the type-instances were important,
then Blitz3D would complain that there were no instances created in the program with the name "SomeRandomName",
or if it didn't give an error, it would just print nothing.


Shambler(Posted 2004) [#22]
My comment about giving them different names was solely related to accessing types in a nested loop.

http://www.blitzbasic.com/codearcs/codearcs.php?code=920

Other than that the name doesn't matter, a For Each type loop will iterate through all instances of a type regardless of if they were created as cat/dog/fish.sprite.


GrrBrr(Posted 2004) [#23]
the name isn't useless... try this

Graphics 640, 480, 0, 2

; Create a type, called "sprite" and assign some fields to it
Type SPRITE 
	Field LOCX 
	Field LOCY 
End Type 

zombie.sprite = New sprite 
zombie\LOCX = 55
zombie\LOCY = 55 

; Create 5 instances of the "sprite"-type, each one called "cats", and give the fields some values
For temp = 1 To 5 
	cats.sprite = New sprite 
	cats\LOCX = 1
	cats\LOCY = 1 
Next   

;Print Out all Sprites
For SomeRandomName.sprite= Each sprite 
	Print SomeRandomName\LOCY
Next 
      
;Empty Line
Print 

; Only change one instance of the cats (the one with the pointer)
cats\LOCX = 22
cats\LOCY = 22

;Print Out all Sprites
For SomeRandomName.sprite= Each sprite 
	Print SomeRandomName\LOCY
Next 

;Empty Line
Print 

; Change the zombie (it doesn't need the pointer, only one zombie exists
zombie\LOCX = 99
zombie\LOCY = 99

;Print Out all Sprites
For SomeRandomName.sprite= Each sprite 
	Print SomeRandomName\LOCY
Next 

While Not KeyHit(1)
Wend

End


it prints out:

55
1
1
1
1
1

55
1
1
1
1
22

99
1
1
1
1
22


names aren't useless... theire only used seldom if you use types only for a collection of objects of the same sort. If you need a special object names are very useful.


Al Mackey(Posted 2004) [#24]
It helps to think of the variable name you give to an instance of a type as a pointer to that instance, and not the instance itself. If you re-assign that variable to a different instance (which is what you're doing when you do a For..Each) the original instance doesn't go away. Alternately, if you're creating an instance that you want to keep tabs on (for example, a special Player sprite), giving it its own unique variable name will allow you to do that.

You can also just copy these pointers from one variable to another, which is sometimes very useful. Also, pointers can point to no instance at all ("Null"). Let's say you want to find the sprite with the lowest Y coordinate:
Lowest.Sprite = Null
For Spr.Sprite = Each Sprite
  If (Lowest = Null)
    Lowest = Spr
  Else If (Spr\Y < Lowest\Y)
    Lowest = Spr
  End If
Next


"Lowest" will now point to the lowest sprite, or it will be Null if there are no sprites.

I realize I'm kind of rambling here.. just pointing out some of the things about Types that escaped me for a long time.


GrrBrr(Posted 2004) [#25]
this is a useful idea


ashmantle(Posted 2004) [#26]
Al Mackey hits the nail right on here..

Basicly you create a pointer to a particular item in the list:

Type Item
Field Contents
End Type


MyPointer.Item = New Item

This adds a new item to the item type AND returns the address of that type to the MyPointer variable.

This means that MyPointer contains an unique integer/address that points to the memory location of the particular type instance that was just created.

If we do this:
For x = 0 to 4

MyPointer.Item = New Item

Next

We have created 5 new items to the Item type list, and every time a new one is created, the MyPointer variable will contain its address.

If we type this:
MyPointer.Item = First Item

We assign MyPointer with the address of the first Item in the list.

You have noticed that I make sure to put .Item behind MyPointer every time..
I do this because I am creating local variables with the name MyPointer.. Every time you create a new variable that is going to be a type pointer, you have to typecast the variable.

So consider this:
Type Truck
Field Cargo
Field Fuel
End Type

Type Car
Field Fuel
End Type

Notice the difference between these different types.. the Truck type needs more memory than the Car type because it has one extra field.

Blitz needs to know this when you create a variable to use as a type pointer.

MyPointer.Truck will reserve the exact amount of memory needed for two fields.
MyPointer.Car will only reserve the memory for one field.


So the name of the variable/pointer doesn't really matter, just how you typecast it.
If you really wish for a real linked list with sublists, you can easily code it using blitz's types and typepointers.


I realize that this explaination is more of a ramble than a good way to teach something ^^