GM:S 1.4 Destroying every part of ragdoll

Discussion in 'Programming' started by Matt93, Jul 7, 2016.

  1. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Hi fellow Game Makers!

    I'm using the physics system, and working on a project which has a ragdoll. This is made of 10 instances of a 'body' object, and 1 instance of a 'head' object. These are created in an obj_ragdoll_create object. My code for this is here:

    Code:
    head = instance_create(x, y-48, obj_ragdoll_head);
    body1 = instance_create(x, y-16, obj_ragdoll_body); //top of body
    body2 = instance_create(x, y+16, obj_ragdoll_body); //bottom of body
    physics_joint_revolute_create(body1, body2, x, y, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(body1, head, x, y-32, 0, 0, 0, 0, 0, 0, 1);
    
    plus = 12;
    leg1 = instance_create(x+plus, y+48, obj_ragdoll_body); //right leg
    leg2 = instance_create(x+plus, y+80, obj_ragdoll_body); //far right leg
    physics_joint_revolute_create(body2, leg1, x+plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg1, leg2, x+plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    leg1 = instance_create(x-plus, y+48, obj_ragdoll_body); //left leg
    leg2 = instance_create(x-plus, y+80, obj_ragdoll_body); //far left leg
    physics_joint_revolute_create(body2, leg1, x-plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg1, leg2, x-plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    
    arm1 = instance_create(x+plus, y-16, obj_ragdoll_body); //right arm
    arm2 = instance_create(x+plus, y+16, obj_ragdoll_body); //bottom right arm
    physics_joint_revolute_create(body1, arm1, x+plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm1, arm2, x+plus, y, -150, 150, 1, 0, 0, 0, 0);
    arm1 = instance_create(x-plus, y-16, obj_ragdoll_body); //left arm
    arm2 = instance_create(x-plus, y+16, obj_ragdoll_body); //bottom left arm
    physics_joint_revolute_create(body1, arm1, x-plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm1, arm2, x-plus, y, -150, 150, 1, 0, 0, 0, 0);
    
    instance_destroy();
    Obj_ragdoll_body and obj_ragdoll_head are parented to a ragdoll parent.

    When any part of the ragdoll collides with a 'hole' object, I want the entire ragdoll to be destroyed. The game involves catapulting ragdolls continuously towards this hole, so there will always be more than one in the room.

    Simply calling with (obj_ragdoll_body) instance_destroy causes all instances to be destroyed. Destroying the parent upon collision also doesn't seem to work. I have also tried looping through instance_nearest using the repeat function, but this also doesn't seem to work. Any ragdolls which miss the hole are just meant to stack up nearby, without being destroyed, so these can sometimes be the nearest instances.

    I'm quite stuck on this, as I don't just want the instances in collision to be destroyed, but all instances attached to it, without destroying the other ragdolls in the room.

    Any help would be really great. Thank you!
     
  2. Yal

    Yal GMC Memer GMC Elder

    Joined:
    Jun 20, 2016
    Posts:
    3,730
    You could create a local ds_list in the head (or a normal array would do as well), then store the IDs of all the body parts you create in that, and give all body parts a local variable with the head's ID. When a head collides with the hole, have it go through the list and destroy all instances whose IDs are in there; when a body part collides with the hole, run their head's collision event using a with statement with an event_execute() in it. IDs are unique, so you won't run into problems with two instances ever having the same.
     
    Cantavanda likes this.
  3. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Thank you for your reply. Is there any chance you could give me a hand with doing this in code? I'm still quite new to ds_lists!
     
  4. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    I have added this so far in obj_ragdoll_create. Am I on the right track?

    Code:
    head = instance_create(x, y-48, obj_ragdoll_head);
    body1 = instance_create(x, y-16, obj_ragdoll_body); //top of body
    body2 = instance_create(x, y+16, obj_ragdoll_body); //bottom of body
    physics_joint_revolute_create(body1, body2, x, y, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(body1, head, x, y-32, 0, 0, 0, 0, 0, 0, 1);
    
    plus = 12;
    leg1 = instance_create(x+plus, y+48, obj_ragdoll_body); //right leg
    leg2 = instance_create(x+plus, y+80, obj_ragdoll_body); //far right leg
    physics_joint_revolute_create(body2, leg1, x+plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg1, leg2, x+plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    leg1 = instance_create(x-plus, y+48, obj_ragdoll_body);
    leg2 = instance_create(x-plus, y+80, obj_ragdoll_body);
    physics_joint_revolute_create(body2, leg1, x-plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg1, leg2, x-plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    
    arm1 = instance_create(x+plus, y-16, obj_ragdoll_body);
    arm2 = instance_create(x+plus, y+16, obj_ragdoll_body);
    physics_joint_revolute_create(body1, arm1, x+plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm1, arm2, x+plus, y, -150, 150, 1, 0, 0, 0, 0);
    arm1 = instance_create(x-plus, y-16, obj_ragdoll_body);
    arm2 = instance_create(x-plus, y+16, obj_ragdoll_body);
    physics_joint_revolute_create(body1, arm1, x-plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm1, arm2, x-plus, y, -150, 150, 1, 0, 0, 0, 0);
    
    with(head) body_list = ds_list_create()
    
    with (head) ds_list_add(body_list, obj_ragdoll_create.body1, obj_ragdoll_create.body2,obj_ragdoll_create.arm1);
    
    instance_destroy();
     
  5. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    I don't understand why you can't use a simpler approach. Just destroy each body part (head, body, arm1/2, leg1/2) for the particular ragdoll you want to destroy.

    For example, I've made games with many ragdolls in the room at once. But if one of them falls out of the room, I destroy it.

    Code:
    with (head) instance_destroy();
    with (body) instance_destroy();
    ..
    ..
    with (leg2) instance_destroy();
    And since those names (head, body, leg2, etc.) are local to that particular ragdoll, then only those parts are destroyed. No other ragdolls are affected.
     
  6. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Thank you for getting back to me. Using this method is only working once though. One ragdoll gets destroyed, but then nothing happens to any other ones which collide with the hole.
     
  7. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    Then your problem goes beyond the ragdoll issue.

    How are you identifying each ragdoll? I mean, what "object" is associated with each ragdoll? One of its body parts? (that's the method I use)
    How are you detecting the collision with the hole? In the hole's collision event?
     
  8. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    I have an object for the ragdoll creation, called obj_ragdoll_create:

    Code:
    head = instance_create(x, y-48, obj_ragdoll_head);
    body1 = instance_create(x, y-16, obj_ragdoll_body); //top of body
    body2 = instance_create(x, y+16, obj_ragdoll_body); //bottom of body
    physics_joint_revolute_create(body1, body2, x, y, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(body1, head, x, y-32, 0, 0, 0, 0, 0, 0, 1);
    
    plus = 12;
    leg1 = instance_create(x+plus, y+48, obj_ragdoll_body); //right leg
    leg2 = instance_create(x+plus, y+80, obj_ragdoll_body); //far right leg
    physics_joint_revolute_create(body2, leg1, x+plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg1, leg2, x+plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    leg3 = instance_create(x-plus, y+48, obj_ragdoll_body);
    leg4 = instance_create(x-plus, y+80, obj_ragdoll_body);
    physics_joint_revolute_create(body2, leg3, x-plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg3, leg4, x-plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    
    arm1 = instance_create(x+plus, y-16, obj_ragdoll_body);
    arm2 = instance_create(x+plus, y+16, obj_ragdoll_body);
    physics_joint_revolute_create(body1, arm1, x+plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm1, arm2, x+plus, y, -150, 150, 1, 0, 0, 0, 0);
    arm3 = instance_create(x-plus, y-16, obj_ragdoll_body);
    arm4 = instance_create(x-plus, y+16, obj_ragdoll_body);
    physics_joint_revolute_create(body1, arm3, x-plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm3, arm4, x-plus, y, -150, 150, 1, 0, 0, 0, 0);
    Then a collision event in the hole object, one for obj_ragdoll body and one for obj_ragdoll_head:

    Code:
    with (obj_ragdoll_create.body1) instance_destroy();
    with (obj_ragdoll_create.body2) instance_destroy();
    with (obj_ragdoll_create.arm1) instance_destroy();
    with (obj_ragdoll_create.arm2) instance_destroy();
    with (obj_ragdoll_create.arm3) instance_destroy();
    with (obj_ragdoll_create.arm4) instance_destroy();
    with (obj_ragdoll_create.leg1) instance_destroy();
    with (obj_ragdoll_create.leg2) instance_destroy();
    with (obj_ragdoll_create.leg3) instance_destroy();
    with (obj_ragdoll_create.leg4) instance_destroy();
    with(obj_ragdoll_create.head) instance_destroy();
    
    I know it looks messy, but I'm going to clear it up once I've got it working. I think the issue is that obj_ragdoll_create isn't being destroyed when the limbs and head of each ragdoll get destroyed.
     
  9. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    The problem is that all the ragdoll instances use the obj_ragdoll_create object, right? So when you say with (obj_ragdoll_create.body_part), that affects all the ragdoll instances. Not just the one that collided.
     
  10. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Actually using your method, the first time, a single entire ragdoll gets destroyed upon collision. Any other ones in the room are left intact. It's just later ones where nothing happens at all upon collision?
     
  11. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    Not sure what's going on there... but it probably stems from referring to all the ragdolls in that "with" statement.

    Trying using the "other" variable in the hole's collision event.

    Code:
    with (other)
    { with (head) instance_destroy();
      with (arm) instance_destroy();
      etc.
    }
    That should identify only the head, arm, legs, etc that belong with the particular ragdoll that collided.
     
  12. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    But the body1, body2 etc variables are contained within obj_ragdoll_create. So I think using with(other) is going to throw an error, since those variables don't exist within the actual ragdoll_body and ragdoll_head objects? Thank you so much for your help with this so far!
     
  13. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    It depends on whether or not the obj_ragdoll_create objects are used for the instances associated with each ragdoll in the room. If they are just used once as a "creation controller" to create all the ragdolls, and then destroyed, then you're right.

    This is why I associate each ragdoll with a particular body part -- usually the body or head. Either way, you need to have a particular object associated with each ragdoll instance.
     
  14. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Okay I think that makes sense. The creation controller I have is just for creating the ragdolls. Is it possible to keep this, but still associate each ragdoll with, say, the head? And how would I do this?
     
  15. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    You could use the controller to define only the (say) ragdoll heads. And in the head object, put the rest of the code to create the body, arms, and legs. That way, those other body parts are named with variables local to each "head" instance. So when the head collides with the hole, you can use the "other" variable. And the body parts associated with that particular head can be referenced.

    That's the approach I sometimes use -- but with the body instead.

    Alternatively, you can set up an "ID" system so all the parts for a particular ragdoll share a common ID variable. i.e.,

    Code:
    arm = instance_create(etc);
    arm.ID = ID;  // ID defined by the creating object for that particular ragdoll
    
    leg = instance_create(etc);
    leg.ID = ID;  // ID defined by the creating object for that particular ragdoll, same for all parts.


    Then when any body part collides with the hole, you can use its ID to identify all the other body parts associated with that ragdoll. I've used this technique to identify all the links in a chain (out of many chains), so I could destroy that chain. I don't particularly recommend that approach here. It's overkill.

    The first approach I mentioned is very simple and doesn't cause any confusion in GM collision events.
     
  16. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Fantastic, thank you - I'm going to try and code this now. Just a question about how I would also do this so the same thing would happen if the ragdoll body collided with the hole. So that if any part of the ragdoll collides (rather than just the head), the entire ragdoll will be destroyed?
     
  17. Robert

    Robert Guest

    Forgive me if I am missing something as I didn't thoroughly read through all the replies, but I would only do the collision on the head and just assume that when there head collides it's time to destroy it, I'm not sure why you would need the body collision separate. I would also make your object that creates the rag dolls I just create the head, and then in the head object I would have that create the rest of the body and assign each part to a new variable in the head. This way the head acts as the individual object controller, if that makes sense. So when dealing with this ragdoll you only really deal with just the head for "managing" it.
     
  18. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Oh, I meant that I want it to count as a collision if the body collides with the hole as well. Otherwise it'll make my game significantly more difficult if you always have to get the ragdoll to collide on its head.
     
  19. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    @Robert, that's pretty much the same suggestion I just posted above. Use the head (or any part) as the ragdoll, and then define the other body parts within that.


    That's where the ID system can be used. That way, if you detect collision with other body parts (not just the head), then those other parts know which ragdoll they belong to. That way you can destroy that entire ragdoll when any one of its parts collides with the hole.

    You can also use parenting for this too -- if done correctly. I recommend giving each ragdoll a unique parent for all the parts. Not a universal parent for all the dolls.
     
    Last edited: Jul 7, 2016
  20. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Okay, I think I have nearly got this working! When the head collides with the hole, the ragdoll it belongs to is destroyed, leaving the others intact. I'm yet to tackle parenting, and/or using the id system for collision with any of its parts. The only thing now is, the head of my ragdoll has gone off angle.

    Obj_ragdoll_create:
    Code:
    instance_create(x, y, obj_ragdoll_head);
    instance_destroy();
    Obj_ragdoll_head:
    Code:
    head = self;
    body1 = instance_create(x, y-16, obj_ragdoll_body); //top of body
    body2 = instance_create(x, y+16, obj_ragdoll_body); //bottom of body
    physics_joint_revolute_create(body1, body2, x, y, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(body1, head, x, y-32, 0, 0, 0, 0, 0, 0, 1);
    
    plus = 12;
    leg1 = instance_create(x+plus, y+48, obj_ragdoll_body); //right leg
    leg2 = instance_create(x+plus, y+80, obj_ragdoll_body); //far right leg
    physics_joint_revolute_create(body2, leg1, x+plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg1, leg2, x+plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    leg3 = instance_create(x-plus, y+48, obj_ragdoll_body);
    leg4 = instance_create(x-plus, y+80, obj_ragdoll_body);
    physics_joint_revolute_create(body2, leg3, x-plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg3, leg4, x-plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    
    arm1 = instance_create(x+plus, y-16, obj_ragdoll_body);
    arm2 = instance_create(x+plus, y+16, obj_ragdoll_body);
    physics_joint_revolute_create(body1, arm1, x+plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm1, arm2, x+plus, y, -150, 150, 1, 0, 0, 0, 0);
    arm3 = instance_create(x-plus, y-16, obj_ragdoll_body);
    arm4 = instance_create(x-plus, y+16, obj_ragdoll_body);
    physics_joint_revolute_create(body1, arm3, x-plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm3, arm4, x-plus, y, -150, 150, 1, 0, 0, 0, 0);
    I was expecting to have to realign the whole body, since this code is in relation to the head now. But the rest of the body is the same - it's just the head which has its alignment set wrong? Do you have any idea why this would be happening?
    Screenshot 2016-07-07 14.21.03.png
     
  21. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Also, please would you be able to explain the ID system to me, as I can't seem to get it working? It won't allow me to set id as it's a read-only variable? I don't want to be a pain with this, it's just frustrating being so close!

    Update: I have done this in the obj_ragdoll_head create event

    Code:
    ID = id;
    
    head = self;
    body1 = instance_create(x, y-16, obj_ragdoll_body); //top of body
    body1.ID = ID
    body2 = instance_create(x, y+16, obj_ragdoll_body); //bottom of body
    body2.ID = ID
    physics_joint_revolute_create(body1, body2, x, y, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(body1, head, x, y-32, 0, 0, 0, 0, 0, 0, 1);
    
    plus = 12;
    leg1 = instance_create(x+plus, y+48, obj_ragdoll_body); //right leg
    leg1.ID = ID
    leg2 = instance_create(x+plus, y+80, obj_ragdoll_body); //far right leg
    leg2.ID = ID
    physics_joint_revolute_create(body2, leg1, x+plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg1, leg2, x+plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    leg3 = instance_create(x-plus, y+48, obj_ragdoll_body);
    leg3.ID = ID
    leg4 = instance_create(x-plus, y+80, obj_ragdoll_body);
    leg4.ID = ID
    physics_joint_revolute_create(body2, leg3, x-plus, y+32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(leg3, leg4, x-plus, y+64, -150, 150, 1, 0, 0, 0, 0);
    
    arm1 = instance_create(x+plus, y-16, obj_ragdoll_body);
    arm1.ID = ID
    arm2 = instance_create(x+plus, y+16, obj_ragdoll_body);
    arm2.ID = ID
    physics_joint_revolute_create(body1, arm1, x+plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm1, arm2, x+plus, y, -150, 150, 1, 0, 0, 0, 0);
    arm3 = instance_create(x-plus, y-16, obj_ragdoll_body);
    arm3.ID = ID
    arm4 = instance_create(x-plus, y+16, obj_ragdoll_body);
    arm4.ID = ID;
    physics_joint_revolute_create(body1, arm3, x-plus, y-32, 0, 0, 0, 0, 0, 0, 0);
    physics_joint_revolute_create(arm3, arm4, x-plus, y, -150, 150, 1, 0, 0, 0, 0);
    I think I'm on the right track, just need to work out what to do in the collision event.

    Update 2:
    I have now put this code into the hole collision event with obj_ragdoll_body:
    Code:
    with (obj_ragdoll_head).ID
    {
        with (body1) instance_destroy();
        with (body2)instance_destroy();
        with (arm1) instance_destroy();
        with (arm2) instance_destroy();
        with (arm3) instance_destroy();
        with (arm4) instance_destroy();
        with (leg1) instance_destroy();
        with (leg2) instance_destroy();
        with (leg3) instance_destroy();
        with (leg4) instance_destroy();
    }
    It destroys the right ragdoll, but then sometimes doesn't work if I've launched several at once?

    Update 3: I think(?) I've got it working. This is my code in the collision event of the hole object with obj_ragdoll_body:

    Code:
    with(other.ID)
    {
        with (body1) instance_destroy();
        with (body2) instance_destroy();
        with(arm1) instance_destroy();
        with (arm2) instance_destroy();
        with (arm3) instance_destroy();
        with (arm4) instance_destroy();
        with (leg1) instance_destroy();
        with (leg2) instance_destroy();
        with (leg3) instance_destroy();
        with (leg4) instance_destroy();
        with(head) instance_destroy();
    }
    Was this what you meant?
     
    Last edited: Jul 7, 2016
  22. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    795
    Yes, that's basically the idea. As long as "ID" refers to an instance, it works. In your example, I see that you set ID equal to the id of the ragdoll instance (the head, in your case). And you could equally well just say:

    bodypart.ID = id;

    Also, if you have problems with the with(other.ID) construction, you might have to break it apart:

    Code:
    with (other)
    { with (ID)
        { with (bodypart1) instance_destroy();
          with (bodypart2) instance_destroy();
         ..etc.
        }
    }
    
    And of course, you can avoid the "other" if the collision code is in the body part's collision event, instead of the hole's collision event. But you already know that.
     
  23. Matt93

    Matt93 Member

    Joined:
    Jun 25, 2016
    Posts:
    104
    Fantastic, thank you! I still haven't worked out how to get the head to align properly - but that is the ONLY thing left to do! If you have any ideas at all (if you'd be comfortable sharing how your ragdoll objects are set up to align?) that would be great. But thank you, you've helped me so much with this, and taught me some new things about gml. I really appreciate it.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice