Parent Child..
BlitzMax Forums/BlitzMax Programming/Parent Child..
| ||
| don't think I have ever tried this before so will ask here before I do. I need to code or have the ability in a game to parent an object to another, essentially little guy walks around and picks stuff up, I want to parent the stuff to his hands/claws/jaws so that when I move guy, the stuff goes with and I dont need to worry about it until I drop it on the ground again. thoughts? |
| ||
| This is quite easy if you're using an object based structure. Your guy object should have the fields to define him (position, image reference, whatever else) and an array/list/dictionary/etc. to hold references to the stuff he's carrying (if he can just cary one thing then you just need a field for that rather than a list obviously). The guy then has a draw method that draws him and loops through anything he's carrying and draws that offset by his position. When he picks something up it should be removed from your list of stuff on the ground, or however else you're referencing that stuff to draw it when it's not being carried. If you're not using OOP, you will want a list (or other grouping) of stuff being carried by your guy to serve a similar purpose. Hope that helps get you started. |
| ||
| I hadd'nt thought of it like that. I did it like that last time, although my ant type didnt have a field for stuff it was holding, instead I had a field in my food type called holder which I set to the instance of ant which picked it up, when drawing the food being held I then just did a loop to draw all food, and when one was found during that loop to be held I did a second look to find the ant, get its position and then draw the food. I'm not sure which way is better, my method kept all food in a single list so stuff was not being copied or moved from list to list all the time, but I can see some benefit to having all food thats being held in its own list of objects, what do you think would be faster I wonder, there could be a lot of food on the ground and a lot of ants picking it up regularly. Also what I really had trouble with last time and what prompted this post is the specifics on positioning of the held object. in my b3d code I just draw the food on the ant, but this time around I want to actually put the food in the ants mouth, then when I rotate the ant I want the food to stay in its mouth, its the math behind this that has me stumped all that sin and cos stuff hurts my brain. So.. type ant field x,y..... field holding : true or false end type ants=list of all ants. type food field x,y.... field heldby end type food = list of all food. where as soon as an ant picks up a bit of food, I set that foods heldby=ants.ant and I set ant holding to true. or would I be faster having a seperete list of items being held and whos holding them. Last edited 2011 |
| ||
| the b3d code I wrote was more of an AI simulation with 4 queens which spawned workers who got food, and then when enough food was gathered spawned soldiers which looked for other ants to kill, there were after about 30 minutes hundreds of ants, on screen picking up lots of food and fighter so which ever way is fastest I'll use. |
| ||
I would suggest a different approach. Not necesarily better than the ima747 one:
Class ParentableObj
Field _x:Float
Field Parent:ParentableObj
Method DrawPosX:Float()
If Parent <> Null then
Return Parent.DrawPosX()+_x
Else
Return _x
EndIf
End Method
End Class
You could do the same for the _y coordinate, rotation, etc. This way, you can handle complex chains of objects and they will be always related to their parents (wich will be related to the parents of the parents, etc.) EDIT: The only problem of this design, is that you'll have to be careful to prevent cyclic parenting. If you do, you'll run out of stack, but it would be a bug in the code anyway. Last edited 2011 |
| ||
| You could handle it any way that makes sense to you: MOB->Things it's holding or Thing->Being held by I generally prefer objects having a list of stuff they hold for the reason that it's easier to figure out what an object is holding (just look, rather than loop through ALL objects looking for the one it's holding on to). Also it helps with off screen optimizations (if the MOB is not drawn you can skip looking at all the things it's holding too) but it's really down to what makes the most sense given the structure of your game... you can of course have both. An object can have a list of things it's holding, and something being held can have a reference to the thing it's holding... Ziggy's example is easily applied as an extension of either method to further simplify drawing and your class structures. In practice I would use something along those lines, but if you're not into sub-classing, or your game is structurally simple enough that you don't want to go that extra step then you could skip it... again, whatever makes the most sense to you. Last edited 2011 |
| ||
| First of all I haddnt thought of stuff being out of screen and being held, old code was single screen but the new code will have much bigger play area, so thats a major plus for creating or keep a list of all objects being held. As for the parenting I only ever at least at this point need to parent 1 object to 1 ant, and only worker ants, picking up a bit of food,water,egg,etc. so I should only ever need to parent one object to one ant. ziggy, your code Return Parent.DrawPosX()+_x, I get it your grabbing the x from its parent and adding its own x but how would that be done with rotation ? for example say my ant is facing north walks up and grabs a bit of food, then it turns 1 degree at a time to face south and walks off with the food in its mouth, how would you get the foods position relative to the ants head or a spot just in front of the ants head. I know there should be a simple sin cos routine to get the local position relative to the ants x,y but my math stinks. |
| ||
| I would have the ant refering to the food and the food also refering to the ant. If you do this you need to be aware it's a circular reference. This means when you want to delete an object, it must have a remove method which sets anything which could be circular to null. |
| ||
| Yeah thats why I was just having the ant with a true or false boolean to say if its holding something or not, and the food type manages whos holding what. but I might flip that around and have the ant manage what its holding and the food or object type just have the boolean to say its being held or not which I would use to push and pop those objects off the main list and onto the holding list. im gona use this little bit of test code to sort out the parenting of a leaf object to the mouth of an ant. ![]() ![]()
Strict
Framework brl.glmax2d
Import brl.freeaudioaudio
Import brl.linkedlist
Import brl.math
Import brl.random
Import brl.wavloader
Import brl.bmploader
Import brl.pngloader
Import brl.tgaloader
Import brl.jpgloader
Import brl.oggloader
SetGraphicsDriver GLMax2DDriver()
Global GFX_Width :Int = 1024
Global GFX_Height :Int = 768
Graphics GFX_Width , GFX_Height , 0
SetBlend MASKBLEND | ALPHABLEND
'HideMouse
Global antSpriteSheet:TImage = LoadAnimImage("ants.png" , 35 , 35 , 0 , 4)
SetImageHandle antSpriteSheet , 17 , 17
Global leafSprite:TImage = LoadImage("leaf.png")
SetImageHandle leafSprite,7,5
Global Time:Int=0
Global AnimationRate:Int=100
Global AnimationFrame : Int =0
Global Rot:Int
Const Walking:Int = 1
Const Still:Int = 2
Global Ants:TList = CreateList()
Type TAnt
Field x:Float
Field y:Float
Field angle:Float
Field x_vel:Float
Field y_vel:Float
Field speed:Float
Field state:Int
End Type
For Local looper:Int = 1 To 1
Local newant:TAnt = New TAnt
newant.x = 500+Rand(-500,500)
newant.y = 500+Rand(-500,500)
newant.angle = 12
newant.x_vel = 0
newant.y_vel = 0
newant.speed = 3
newant.state = still
ListAddLast(Ants,newant)
Next
Repeat
Cls
If MilliSecs() - time => AnimationRate
AnimationFrame:+ 1
If AnimationFrame => 4 Then AnimationFrame = 0
time=MilliSecs()
End If
If MouseHit(2)
For Local rant:Tant = EachIn Ants
rant.x = 500+Rand(-500,500)
rant.y = 500 + Rand( - 500 , 500)
Next
End If
For Local myant:Tant = EachIn Ants
If MouseDown(1)
myant.state=walking
Else
myant.state=still
End If
Select myant.state
Case still
rot = -ATan2(MouseX()-myant.x,MouseY()-myant.y)
myant.angle = rot
myant.x_vel = Cos(rot) * myant.speed
myant.y_vel = Sin(rot) * myant.speed
Case walking
rot = -ATan2(MouseX()-myant.x,MouseY()-myant.y)
myant.angle = rot
myant.x_vel = Sin(rot) * myant.speed
myant.y_vel = Cos(rot) * myant.speed
myant.x :- myant.x_vel
myant.y :+ myant.y_vel
End Select
SetRotation myant.angle
DrawImage(antSpriteSheet,myant.x,myant.y,AnimationFrame)
SetRotation 1
Next
Flip
Until KeyHit(KEY_SPACE) Or AppTerminate()
|

