Why you should name types?
Blitz3D Forums/Blitz3D Beginners Area/Why you should name types?
| ||
(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. |
| ||
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... |
| ||
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. |
| ||
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 :) |
| ||
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. |
| ||
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 ;) |
| ||
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???) |
| ||
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. |
| ||
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!) |
| ||
@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. |
| ||
"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? :-) |
| ||
that was just an example of good programming practice, what if he had 10 million particles and used 3 seperate loops huh? ;-P |
| ||
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... |
| ||
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... |
| ||
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 |
| ||
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). |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
the name isn't useless... try thisGraphics 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. |
| ||
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. |
| ||
this is a useful idea |
| ||
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 ^^ |