Solved - How do I stop a mouse click from effecting two objects at once.

1 favourites
From the Asset Store
Hand-painted tiles, objects, animated objects, and background to build a colorful Mayan civilization environment.
  • I have an object on Layer 0 (called "obstacle") that responds to a left mouse click.

    I have another object on Layer 1 (called "turn") that also responds to a left mouse click.

    The problem is, if "turn" is on top of "obstacle", when I click on "turn", "obstacle" triggers as well (even though it is hidden underneath).

    How do I stop both objects from triggering at the same time and just use the object that is visible and my mouse is touching?

    Tagged:

  • 1-You could add a second condition is visible:

    On touched object

    Object isVisible

    2-You can set the other layer interactive to false if the objects are on different layers

    3-If Both objects are on the same object type you could use system "Pick top instance"

    4-You could put them in a family and filter them

  • Put all your click-able objects into a family, then you can setup your events like:

    On click FAMILY

    Pick top instance of FAMILY

    You can find "pick top instance" within an object, like Sprite>Pick top/bottom, or Family>Pick top/bottom.

  • Families seems like the best solution, but I must be doing something wrong.

    I created a family called towers and put all my tower objects into it.

    This is my event:

    But now, when I click on it, every instance of "Turn" is rotating, not just the one I clicked on.

    Any idea, what I am doing wrong?

  • Families seems like the best solution, but I must be doing something wrong.

    I created a family called towers and put all my tower objects into it.

    This is my event:

    But now, when I click on it, every instance of "Turn" is rotating, not just the one I clicked on.

    Any idea, what I am doing wrong?

    You are applying the Action to the "Turn" object instead of the one that you pick in the Towers family, that's why it applies the action to all the Turn objects because there was none picked on the conditions therefore it applies the action to all instances of Turn.

    Select the "Towers" family instead to apply the rotate action

  • I feel very dumb and I'm not sure what I'm doing wrong now.

    I made the change you suggested and now it is only rotating that one tower called "Turn", but it's back to also calling the code on the left click below it.

    Here is the relevant code bock:

    Here is an image from the game:

    So, what should happen is:

    - If you left click on an "Obstacle" object (which is not in the Families, "Towers") it will add a new "Turn" object. This currently works.

    - If you left click on a "Turn" object (which is in the Families, "Towers") it will rotate the turn. This works now too. But, it's also creating another instance of the "Turn" object.

    I need clicking on the "Turn" Object to only kick off that code, even though the "Obstacle" object is right underneath it.

    Thanks for any guidance.

  • I feel very dumb and I'm not sure what I'm doing wrong now.

    No worries there are no dumb questions, especially when you are new to Construct. Ask any questions you need.

    You need to put the obstacle in the family swell and then make just 1 one click event then you can compare which object it is and do your actions accordingly:

    Example:

    On family Clicked:
    Pick Top Instance:
    -----System Compare: Family.ObjectTypeName = Obstacle:----> Create Turn
    -----Else: Rotate 90
    
  • Really appreciate your patience (I'm used to more traditional programming and I guess I haven't fully grasped events yet).

    Anyway, I think I added the check for the ObjectTypeName correctly (see image):

    But, where the heck does the Else go? I can't even find an else statement in the events sheet.

  • Really appreciate your patience (I'm used to more traditional programming and I guess I haven't fully grasped events yet).

    Anyway, I think I added the check for the ObjectTypeName correctly (see image):

    But, where the heck does the Else go? I can't even find an else statement in the events sheet.

    On family Clicked:
    Pick Top Instance:
    ---Subevent: System Compare: Family.ObjectTypeName = Obstacle:----> Create Turn
    ---Subevent: Else: Rotate 90
    

    This "-----" below means a subevent.

  • Like this:

  • Like this:

    That did it!

    You made my day. Thank you so much.

    Edited: Just wanted to add, thank you for teaching me about families and sub-events. I think I understand both concepts now and I was able to use that new knowledge to enhance and streamline my code. Very cool!

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • I don't think adding Obstacle to the Family 'Towers' is the best fix because it's not a tower. When you want to apply other events in future to 'all towers' it will apply it to Obstacle as well which is the black empty square, you don't really want this. A Family should contain only related object types.

    example : you want to destroy all Towers to refresh the game, so you use destroy Family'Towers' it will destroy all the black squares too.

    The reason you are having the problem is because it creates the object on a click, then immediately runs the next event which is to rotate on click. A better fix would be to lock out the rotate event on towers that were recently created, perhaps with a 'state' variable. When you release mouse click you can set the variable to allow the tower to be rotated.

  • The reason you are having the problem is because it creates the object on a click, then immediately runs the next event which is to rotate on click. A better fix would be to lock out the rotate event on towers that were recently created, perhaps with a 'state' variable. When you release mouse click you can set the variable to allow the tower to be rotated.

    lionzThis seems like great advice.

    Is a "state" variable the same a global variable?

    Also, where in the order would the release mouse click code go?

  • It would be an instance variable at the family level, also called a family instance variable, so on the family object Towers you can add an instance variable 'stamped' for example. Then in a general event (order doesn't matter), you can add 'on mouse click release' and 'Towers.stamped=0', set Towers.stamped to 1 (0 is default).

    Another way to do the same functionality without using mouse click is to have an event 'Family Towers on created' - wait 0.1 seconds, set Towers.stamped to 1.

    Then returning to your original event for rotating, you add a condition 'Towers.stamped=1', means it won't be rotated at the same time it is created but on second click it is possible. You can then remove the black square from the family also.

  • MessMess

    Families were created to solve many problems, like Picking and treating many different objects as a single object to simplify the code and the Picking and the number of events that you would normally need.

    In your case, it's a perfectly valid solution and simple, as that is what it was designed for, you just need to follow the advice that was given which is to put the objects in a separate Family that you will just use for clickable objects so you shouldn't have any problem if you followed the advice.

    4-You could put them in a family and filter them

    Put all your click-able objects into a family, then you can setup your events like:

    More info about Families:

    https://www.construct.net/en/make-games/manuals/construct-3/project-primitives/objects/families?utm_campaign=C3Editor&utm_source=browser&utm_medium=r391&utm_term=OpenManualLink&utm_content=ProjectBar-FamiliesHelp

    There are no restrictions on how many families you can create in the c3 paid version.

    Are there more solutions?

    Yes

    Do you have to use families?

    Not necessary, you can use the method you like the most and which it resolves your issue in the most simplistic and logical manner. So Families is just one of them. There are other solutions without families.

    It would be an instance variable at the family level, also called a family instance variable, so on the family object Towers you can add an instance variable 'stamped' for example. Then in a general event (order doesn't matter), you can add 'on mouse click release' and 'Towers.stamped=0', set Towers.stamped to 1 (0 is default).

    Another way to do the same functionality without using mouse click is to have an event 'Family Towers on created' - wait 0.1 seconds, set Towers.stamped to 1.

    Then returning to your original event for rotating, you add a condition 'Towers.stamped=1', means it won't be rotated at the same time it is created but on second click it is possible. You can then remove the black square from the family also.

    None of your solutions solved the problems he had lol

    Honestly, they dont make any sense if you look from the perspective of the context that he needs to solve. ))

    The Issues he was trying to solve:

    He has two totally different and independent events:

    1-If you click any obstacle that has no tower --------> Spawn a Turn object which I assume is a (Tower)

    2-If you click in a Tower --------> Rotate the tower 90 degrees clockwise (Probably to fire enemies at different angles)

    It would be an instance variable at the family level, also called a family instance variable, so on the family object Towers you can add an instance variable 'stamped' for example. Then in a general event (order doesn't matter), you can add 'on mouse click release' and 'Towers.stamped=0', set Towers.stamped to 1 (0 is default).

    There are many issues with this solution:

    -You dont pick correctly the target "Tower" which you need to use the "On Mouse Click On Tower" to know to who you need to apply the action Rotate, so your events are not clear as to which Towers are applying the Rotations. Because without Clicking the Tower you can never know to which tower you need to rotate.

    -"On Mouse Release"

    Is gonna fire the Rotate Events and conditions checks each time a "Mouse-Click" is released.

    He doesn't need that as he wants instead to just rotate the Tower explicitly when you touch it, not every time you release the Mouse click.

    Another way to do the same functionality without using mouse click is to have an event 'Family Towers on created' - wait 0.1 seconds, set Towers.stamped to 1.

    The same issue:

    -The Picking is wrong as it doesn't need to rotate the objects that are created, just the ones you select with "On Mouse Click On Tower"

    therefore there is no way to change this condition so you have to use "On Mouse Click On Tower" and you have to make sure that both triggers (Towers & Obstacle) dont trigger at the same time.

    Then returning to your original event for rotating, you add a condition 'Towers.stamped=1', means it won't be rotated at the same time it is created but on second click it is possible. You can then remove the black square from the family also.

    -This is just personal but:

    I would recommend you always run your events under a Trigger whenever you have the opportunity, which in this case we have under "On Mouse Click On Tower"

    [b]-"On Mouse Click On Tower": [/b]
    Will only trigger on user input and it will run the events only once
    
    [b]-'Towers.stamped=1',[/b]
    This checks "every tick" 
    Every Tower if (is = 1) 
    Unnecessary just to rotate when you can do the events under a trigger which will run only "On triggered" and it will run the action to just the clicked tower.
    

    This avoids scenarios such as:

    Imagine you have a big layout with hundreds of Towers, it will:

    Check "every tick"

    Every Tower if (is = 1)

    Wasting resources is unnecessary just to make a simple rotation.

    Benefits of adding the actions under a Trigger:

    -You keep all your actions under just one event which makes it easy to manage instead of having separate events and conditions. Also, it makes it easier to debug when you have a bug as you have everything under one event.

    -Save resources

    -Avoid unnecessary waits, as if you keep adding them in any trivial matter just to solve simple issues such as this which doesn't need any waits you could end up in the future in a big messy code and potential bugs when you try to add new features etc... Which could be hard to track.

    Alternatives Solutions:

    If for any reason you dont want to use families. Remove the obstacle from the family.

    There are many ways you could archive this:

    1-Just add a condition blocker to the obstacle:

    Note:

    Make sure that the Tower is at least 1 pixel smaller than the obstacle to work, otherwise if both are the same size then it will trigger true if it overlaps neighbours Towers on different tiles, so by setting the tower to 1 pixel smaller it avoids false triggers from the neighbours.

    An alternative you could just make the Tower collision box 1 pixel smaller if you need to keep both (obstacle & Tower) the same size.

    2-You could keep track of the obstacles that have a Tower by adding a boolean like for example "Has_Tower"

    -On your event that you spawn the Tower --------> Set Obstacle.Has_Tower = True

    Then these events:

    There are probably many more ways, but in short, don't be scared to use families as they are a very powerful feature in Construct that you will need to do from advanced things to simplify your events etc...

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)