Types yet again again again
Blitz3D Forums/Blitz3D Beginners Area/Types yet again again again
| ||
If I have a 'type' within another type's field, is there any means to associate other instances of this secondary type to the primary? I know this can be achieved with a separate field which contains a value which can identify the first type, but this would be a slower process with large numbers of instances. To explain a little more clearly: Imagine the setup: Const GENDER_MALE=1 Const GENDER_FEMALE=0 Const ANIMAL_DOG=0 Const ANIMAL_FISH=1 Const ANIMAL_CAT=2 Const ANIMAL_SPIDER=3 Const ANIMAL_RABBIT=4 Const ANIMAL_TYRANNOSAUR=5 Type owner Field Name$ Field Gender Field pets.pet End Type Type Pet Field name$ Field animal.animals End Type Type animals Field animaltype Field name$ Field legs End Type JohnOwner.Owner = New Owner JohnOwner\Name$="John Smith" JohnOwner\Gender=GENDER_MALE JohnOwner\Pets.Pet= New Pet JohnOwner\Pets\Name$="Kittie" JohnOwner\Pets\animal.animals=New animals JohnOwner\Pets\animal\animaltype=ANIMAL_CAT JohnOwner\Pets\animal\name$="Siamese" JohnOwner\Pets\animal\legs = 4 But what if John has more than one pet? JohnOwner\Pets.Pet= New Pet JohnOwner\Pets\Name$="Spot" JohnOwner\Pets\animal.animals=New animals JohnOwner\Pets\animal\animaltype=ANIMAL_DOG JohnOwner\Pets\animal\name$="Sheepdog" JohnOwner\Pets\animal\legs = 4 Just overwrites the 'Cat' info. Is therwe a way to add a "sheepdog" as John's pet without either: a) Making a 2ndary "John" instance of Owner b) Adding a new field to "Pet" to identify the Owner.Owner as "John"? |
| ||
There are several ways to solve this. I would use this construction: The child objects are linked together by adding a field that points to the next object in the series. |
| ||
Actually I would go with a linked list...Type TOwner Field name$ Field firstPet.TPet End type Type TPet Field name$ Field NextPet.TPet Field Owner.TOwner End Type This way its fast and easy to get all the pets that an owner owns and all the pets know who they below to. |
| ||
Haha .. that is a good idea indeed. It also works in Java, C++ and BMax. |
| ||
Thanks guys, so it seems either way will still require iterating through to find common references, i.e. Warner's "For o.TOwner = Each TOwner" and Skully's use of the Owner.Owner field. There's no means of having these links 'internally'? The reason for my asking is because the situation may arise that (continnuing the owner/pet example) I may have around 50 owners, each with a few hundred pets, many of these pets may have the same names and be the same type of creature. I am unsure as yet whether to make use of parent/child entity relationships as certain details pertaining to the pets may refer to child entities of another sort :S |
| ||
No, I think you are misreading the code. The line 'For o.TOwner = Each TOwner' is just used in the example. It isn't used to find out which pets belong to who. Instead, this part: p.TPet = o\firstPet While p <> Null Print " Pet = " + p\name$ p = p\nextPet Wend Iterates through all pets that belong to 'o'. That was the whole idea: to create something along the lines of this: (Imaginary code) For p.Pet = Each Pet In o.Owner print p\Name$ + " belongs to " + o\Name$ Next Google a bit for linked list. Here is a picture to illustrate how they work: ![]() |
| ||
Woops! I forgot a critical element...Type TOwner Field name$ Field firstPet.TPet End type Type TPet Field name$ Field NextPet.TPet Field PrevPet.TPet Field Owner.TOwner End Type Function AddTPet(o.TOwner,name$) p.Tpet=o\FirstPet if p<>null then repeat if p\NextPet=null then ; initialize TPet code p\NextPet=new TPet p\NextPet\name=name p\NextPet\Owner=o Exit End If until o\NextPet=null else o\FirstPet=new TPet o\FirstPet\name=name o\FirstPet\Owner=o End if End Function Function DeleteTPet(p.TPet) If p\PrevPet<>null then p\PrevPet\NextPet=p\NextPet If p\NextPet<>null then p\NextPet\PrevPet=p\PrevPet End If End If Delete p End function |
| ||
Hey, has anybody seen my cat? He was here two seconds ago .. |
| ||
Is this your cat? *Hands over road kill* |
| ||
Thanks, sorry Warner yes, I did misunderstand, thanks for the info though, I can follow that no problem. Now I just need to consider whether to create a linked list instance and add to it as new "pets" are added to "owners" or whether to only populate it when it is required and tghus take the time then to retrieve all the data. |
| ||
I know exactly what you mean Malice. It would be handy if you could create a type list, just for that object. Kind of like a second dimension in an array, that is only accessed by the one first slot. Something like: Type owner field name$ Type pet field name$ End Type End type Then do something like: For p.owner.pet = each owner.pet ;loop through each owners lists of pets next or temp.owner = first owner for temp.owner.pet = each pet ; loop through the FIRST owners pets next That would be handy :) |
| ||
I didnt know blitz 3D can do thisType owner field name$ Type pet field name$ End Type End type [ |
| ||
Is this your cat? *Hands over road kill* Nope :/ |
| ||
HotShot2005, it can't. |
| ||
Yeah, sorry. I was meaning, i wish you could :) |
| ||
I'm sure one of the pet monkeys talks... |
| ||
But you _can_ do this, to get types within type. (Substitute your own variables for 100) Type Jpathpoint Field x,z End Type Type Jseq Field startframe Field endframe End Type Type JChar Field label$ Field seq.Jseq[100] Field pathpoint.Jpathpoint[100] End Type Dim char.JChar(100) For z = 0 To nNumChars char(z) = New JChar For cnt = 0 To 100 char(z)\seq.Jseq[cnt] = New Jseq Next For cnt = 0 To 100 char(z)\pathpoint.Jpathpoint[cnt] = New Jpathpoint Next Next Access using something like: char(num)\pathpoint[p]\x = 10 |
| ||
Or you can do it using a bank, and storing in the bank a list of type handles, then simply iterate through the bank one int at a time to get the handles of all the pets: IE type person field petbank end type type pet field petname end type ;now for a specific person with a bunch of pets attached do this: ;we'll call our person instance 'human' if human\petbank<>0 then ;human has a bank containing all their pets for offset=0 to banksize(human\petbank)-4 step 4 mypet.pet=object.pet(peekint(human\petbank,offset)) if mypet.pet<>null then ;this is one of my many pets endif next endif |
| ||
SO, your basically just using object handle? I do that with arrays. For simplicity sake, it would be easier to have a linked list, directly connected with another, that no other linked list object could access. I know you can do this with types and arrays, however i didn't realise you could go so deep with it :) Thanks John. I guess i'm woried mainly about the memory requirements when you start using arrays for large projects. |
| ||
Well John & Matty, I'm having a little trouble 'visualising' what's happening there. I'm still not 100% on how to use "Object" and "Handle" commands, though I figured they might feature in this somewhere. Which is the "best" (i.e. most efficient) way to to do this considering some 50 people and over a hundred 'pets' each? As for the Banks... Aren;t banks actually gonna be less memory than a separate Type, considring the bank would just be the 'raw' int's rather than excess info concerning the types and fields etc. ? |
| ||
With fifty people and a hundred pets each... use array fields in the owner type. Five or ten thousand "wasted" array spaces isn't going to be a noticeable memory hit, and access will be an order of magnitude (literally) faster than using banks or linked-lists - much more efficient if performance is your priority. |
| ||
Totally agree with Yasha, so long as you are storing raw info/flags, and not whole meshes, then arrays are incredibly fast. |
| ||
Okay thanks for that. The main reason I approached this with Types rather than arrays was because the number of 'pets' and 'owners' are completely variable but I reckon I can set a top limit and if the 'wasted' array space isn't likely to be an issue, that's all good. |