GML [SOLVED] Collision with ONLY one object and nothing else

Dan1

Member
Hey everyone,

So I'm at a bit of a loss with how to code this:

Basically, I'm building a management/building kind of game and one of the building objects HAS to be in collision with a conveyor belt in order to build it but can't be in collision with ANYTHING else (any other machines already on the conveyor belt) - but without playing around with adjusting solids and parent objects (as they do all act quite differently), I'm not sure what the best way is to detect if the item is in collision only with the conveyor belt object and nothing else in order to say it can be built.

The detection is done via a control object that uses the mouse_x and mouse_y positions (rounded to a 32x32 grid)

Ideally I don't want to use the collision mask either as I've had to give each of the machine objects a very small collision mask for a different reason entirely and changing that would mess up a different bit.

This image might better explain what I'm trying to achieve here



Any ideas how to accomplish this would be much appreciated! :)
 

TheouAegis

Member
Is the conveyor belt an object itself or a tile?

Perform two collision checks. First check if it's on a conveyor belt. Then check if there are any other instances too close to it.
 

Dan1

Member
The Conveyor belt is an object - wouldn't checking for other objects automatically detect the conveyor belt as well though?
 

FrostyCat

Redemption Seeker
Why are you avoiding parent objects? It's common in GM to have parent objects that contain absolutely no code (i.e. their children define all of their own behaviours), just so that they can be grouped in a collision check. Had you done that, this would be an easy way out:
Code:
if (place_meeting(x, y, obj_conveyor) && !place_meeting(x, y, obj_machine)) {
  // Can build here
}
 

Dan1

Member
Why are you avoiding parent objects? It's common in GM to have parent objects that contain absolutely no code (i.e. their children define all of their own behaviours), just so that they can be grouped in a collision check. Had you done that, this would be an easy way out:
Code:
if (place_meeting(x, y, obj_conveyor) && !place_meeting(x, y, obj_machine)) {
  // Can build here
}
Thanks for the advice, I tend to use parent objects when objects are similar but many of the machines on the conveyor act very differently and need to be treated differently, I could do !place_meeting for every conveyor object but this might take some time
 

samspade

Member
I would start using parents as FrostyCat suggested. It's one of the primary purposes of inheritance and you're missing out on major advantages by not doing so.

In fact, the way I read your response is essentially: "I could do what you suggested (which would accomplish what I want in one line of code) but I could also not do that (without giving any reason as to why I wouldn't) and instead do it a much more complicated way which will take more time." Obviously, that's not what you actually said and I'm not trying to say you were rude or anything, just that you seem to be rejecting the simple, and commonly used, solution to your problem without providing any reason not to use it.

There are other options, but they're all worse. The second best option I can think of is you can check for how many conveyor instances the new instance would be in collision with, and then you can check for (with collision list) how many total instance it is in collision with and if the number is greater than the number of conveyor belts, then it's hitting something else. Not only would this be more complicated to code, it would also introduce more edge cases such as what if there are 'objects' maybe effects, buttons, etc, that shouldn't matter for placement?
 

Dan1

Member
I would start using parents as FrostyCat suggested. It's one of the primary purposes of inheritance and you're missing out on major advantages by not doing so.

In fact, the way I read your response is essentially: "I could do what you suggested (which would accomplish what I want in one line of code) but I could also not do that (without giving any reason as to why I wouldn't) and instead do it a much more complicated way which will take more time." Obviously, that's not what you actually said and I'm not trying to say you were rude or anything, just that you seem to be rejecting the simple, and commonly used, solution to your problem without providing any reason not to use it.

There are other options, but they're all worse. The second best option I can think of is you can check for how many conveyor instances the new instance would be in collision with, and then you can check for (with collision list) how many total instance it is in collision with and if the number is greater than the number of conveyor belts, then it's hitting something else. Not only would this be more complicated to code, it would also introduce more edge cases such as what if there are 'objects' maybe effects, buttons, etc, that shouldn't matter for placement?
My main reason for not parenting them is because there is a lot of differences between how all of the different machines behave so setting one as a parent would make them all act differently based on coding for other aspects of the game.
However, now that I think about it, if I had a controller object as a parent rather than one of the existing conveyor belt machines, that could work so when I check for a collision with the controller object, it would include the children objects
 

samspade

Member
My main reason for not parenting them is because there is a lot of differences between how all of the different machines behave so setting one as a parent would make them all act differently based on coding for other aspects of the game.
However, now that I think about it, if I had a controller object as a parent rather than one of the existing conveyor belt machines, that could work so when I check for a collision with the controller object, it would include the children objects
If you did it as FrostyCat suggested, that isn't true. You don't need to put code in the parent object. You make a completely blank object with no events, no code, no sprite, nothing, and you assign children to it.

Incredibly basic example. If you have an object named animal_parent with a child named obj_cat and a child named obj_fish where obj_cat and obj_fish have entirely different code and animal_parent is completely empty of everything the following will work:

Code:
///destroy all animals
with (animal_parent) {
    instance_destroy();
}

///select any animal
if (position_meeting(mouse_x, mouse_y, animal_parent)) {
    //code
}

//etc.
This works going down as many levels as you want.
 

Dan1

Member
If you did it as FrostyCat suggested, that isn't true. You don't need to put code in the parent object. You make a completely blank object with no events, no code, no sprite, nothing, and you assign children to it.

Incredibly basic example. If you have an object named animal_parent with a child named obj_cat and a child named obj_fish where obj_cat and obj_fish have entirely different code and animal_parent is completely empty of everything the following will work:

Code:
///destroy all animals
with (animal_parent) {
    instance_destroy();
}

///select any animal
if (position_meeting(mouse_x, mouse_y, animal_parent)) {
    //code
}

//etc.
This works going down as many levels as you want.
I see what you guys are getting at now - I misunderstood as setting one of the existing objects as the parent which would confuse things but yeah, I can make a blank controller object and set the rest as the children of this object then do the collision detection from that instead, good idea! :)
 
Top