Teenagers in Pygrr - setting up parenting
Parenting is a pretty useful thing when it comes to game development. It allows you to link objects together, so that they'll inherit movement and everything. It's basically like sticking two or more objects together.
The structure of families in coding is referred to as a "hierarchy", as there can be multiply levels of children, starting from the "root" object. For example, I'm going to use indentation to show you an example of a hierarchy.
Root objectAnother grandchild!
Third child
If I move an object left, all of the objects underneath it in the hierarchy (that is, successors of that object) will also move left by the same amount. Change travels down in a hierarchy, applying to all of the object's children, and then their children, and so on and so forth.
It should be pretty simple to code this... spoiler: it wasn't
Well, movement was quite easy to code, just rotation was the thing that was... Interesting! As you can see here, I've hooked up a gun to the player, and when the player moves, so does the gun! Awesome stuff...
import pygrr
pygrr.create_window()
player = pygrr.Polygon(model=pygrr.Model.rectangle(50, 100), outline_width=5, tag="Player")
gun_model = pygrr.Model.from_file("gun_new.pygrr", scale=4.5)
gun = pygrr.Polygon(model=gun_model, parent=player, tag="Gun")
gun.set_outlinewidth(5)
bullet_model = pygrr.Model.rectangle(2, 4)
while True: # game loop!
player_speed = 50 * pygrr.deltatime
for obj in pygrr.objects:
if obj.get_tag() == "Bullet":
obj.move_forward(500 * pygrr.deltatime)
if pygrr.Input.key("left"):
player.move_left(player_speed)
if pygrr.Input.key("right"):
player.move_right(player_speed)
if pygrr.Input.key("up"):
player.move_up(player_speed)
if pygrr.Input.key("down"):
player.move_down(player_speed)
gun.point_towards(pygrr.Input.mouse_x(), pygrr.Input.mouse_y())
if pygrr.Input.mouse_down("left"):
bullet = pygrr.Polygon(position=gun.get_position(), model=bullet_model, fill_color="black", tag="Bullet", rotation=gun.get_rotation())
bullet.move_forward(55)
gun.rotate_left(5)
pygrr.next_frame()
Here's the code for that. Pretty simple stuff! You might have noticed, but I've adding a new structure to Pygrr - tags and objects. You can tag an object, and then in the game loop, iterate through (scan through) all objects, applying change to some object if it's tag is what you want, or anything like that.
The code in there that does this is:
for obj in pygrr.objects:
if obj.get_tag() == "Bullet":
obj.move_forward(500 * pygrr.deltatime)
Cool stuff! Now, let's do the rotation.
Well, I'm an idiot. I need to add a function "rotate_around", so that they rotate around their parent's anchor!
Here's the moment when I spent ages getting so many errors, spending hours rewriting this new function... Here's a compilation of some bugs!
4 hours, 5 rewrites later, I found myself at a stopping point. There was no reason my code shouldn't work! Then I read it all through again, and realised. I missed a single minus symbol. One single symbol, that's all it was! Fun(!)...
Well, here we go, it works now!
Only a few functions left to add here! Added to get:
obj.get_localposition()
obj.get_localx()
obj.get_localy()
obj.get_localrotation()
These just return the values in relation to their parent! Also, in every function such as "move", there is an optional parameter defaulted to True called "inherit". This chooses whether or not to apply the change to the children!
We've also added:
obj.apply_position(inherit=True, inherit_level=1)
obj.apply_rotation(inherit=True, inherit_level=1)
obj.apply_visibility(inherit_level=255)
obj.apply_all(inherit_level, inherit) # calls all of the above functions
Parameter "inherit_level" states how many levels of children to apply change to.
Parameter "inherit" states whether or not to inherit change in children below inherit_level (like normal inherit parameter!).
Now, this is all well and good, but how do I actually parent objects to one another? I'm glad you asked!
When you create an object, you can pass in the optional "parent" parameter, to set parent, or the optional "children" array, to add children. If you want to do it later on, there's a few functions to help you out!
obj.get_parent() # returns object's parent
obj.get_children() # returns object's children
obj.unchild() # removes object from their parent
obj.add_child(new_child) # adds child to object
obj.remove_child(child) # removes child from object
obj.set_parent(new_parent) # sets object's parent
And that's done! All we need now is collision and documentation, and the alpha is ready to go!
Isaac, over and out...