Jump to content
  • Advertisement
CyberFlash

Optimization How to Click and Unclick an object based on where the mouse is.. in GML

Recommended Posts

Howdy!

First of, I think what I'm trying to do is going to be super duper simple and I'm just missing one key piece of information.... So the best way to illustrate/explain my end goal is to look at Bloons Tower Defense 3 (It probably exists in a lot of other examples also)... When you grab a tower from the menu and place it, It's 'highlighted'/'selected' and you can see the upgrade information... Okay I can do that... Mouse Left Pressed - Clicked = true; and then Draw - //Upgrade Info ...

My question is how to deactivate that selection.. I was thinking it would be a simple If ! clicking on the tower... which makes sense.. If you're clicking but its not on the object you want to turn it off.. cool BUT what if you are attempting to click the upgrade button on the menu??? That is NOT the object but you DO want to keep it selected... This is what I'm trying to achieve.. And I don't know how to explain it...

I was thinking that I could do a trigger like
 

if clicked = true {
  		if (!mouse_x >= 50 && !mouse_x <= 100) && (!mouse_y >= 50 && !mouse_y <= 100){ //Example Coordinates - Pretend this is upgrade button
          if (mouse_check_button_pressed(mb_left)){ //Clicking Left Button
          		clicked = false;
        	}
        }
}

And this is where I'm getting stuck... Like I want to click the object and have it trigger clicked = true; I've got that, that happens.. I now want to have it so if you are NOT clicking the object and NOT clicking the upgrade button (this is drawn via a sprite so I'm using coordinates) then I want clicked to go false....

I just feel like all the && && && && is wrong... is there any sort of command that could be called that means like 'anything else' ? I'm thinking that might not work either though to be honest as I want to be able to click the upgrade button... 

Maybe having the use of 'or' could apply here.. maybe having the coordinates of 'self' (this will be triggered by one tower that has been clicked not all towers at same time obviously,,,) and the coordinates of where the upgrade button will be in the same line so like

If you are NOT clicking tower or NOT clicking upgrade button then clicked = false?? 

I feel that would be it... I'm just not sure.. Any ideas? I'm not used to trying to share code so I might have made a mess above. But I hope this helps explain what I'm trying to achieve.

 

Also I'm stuck outside for a while so I'm having a nightmare of a time just trying to think of this but not able to test it right now!!! 

Share this post


Link to post
Share on other sites
Advertisement

Sorry if I'm miss-understanding the question. Are you wanting to click and select a tower for building, and if you select another tower have your current selection deactivated and activate the tower which you clicked instead?

Share this post


Link to post
Share on other sites

Yes and No... That is a part of it BUT the difficulty I'm having is like this:

When clicked = true, I am going to display some upgrade information, based on that tower, on the menu... So I want the tower to remain selected if you were to click your upgrade stuff..

If you click another tower I want the original tower to be set to false and the new tower set to true where the upgrade information is now current for the new tower. I've got no problem displaying the information and keeping it current per instance, That is behind my clicked=true.. its just being able to turn clicked on and off at the right times that I am struggling with. 

Did that help clarify?

Share this post


Link to post
Share on other sites

I would do something simple like putting a switch case inside your "OnClick" trigger.

switch (ClickedObject)
{
case tower:
	turn off all other tower menus
	turn this one on
	break;
case towermenubutton:
	execute menu button code
	turn off all menus(if applicable)
	break;
case otherwise:
	do nothing? or? whatever else you need to handle with clicks.
	break;
}

As long as it doesn't get too big or complicated it should be perfectly functional, and way easier to read/debug than a pile of IFs. ;)

https://docs.yoyogames.com/source/dadiospice/002_reference/001_gml language overview/401_12_switch.html

Share this post


Link to post
Share on other sites
2 minutes ago, Septopus said:

than a pile of IFs. ;)

Yeahh something like this!! I wasn't liking all my IFs :P I just gotta remember how the Case Switchy thing works now!... 

So the ClickedObject would be my condition that 'this' tower got clicked right? That's my trigger for all of this? Or would that be triggered by 'any' click and then only IF my tower was clicked it'd trigger the first case? I think that's how it works isn't it? Like its possible to execute multiple cases if the price is right?

So I think for my otherwise (If it isn't clicking the tower OR the upgrade section) I want it to do nothing, would just having break; be okay for that so it just breaks out of the cycle there? 

I've hardly spent time with Cases but I remember learning a while ago to use a case for character movements because it can trigger multiple at the same time? Or one after the other kinda thing?

 

Share this post


Link to post
Share on other sites

The way I wrote it, the switch is expecting to see the "object" you clicked on.  But that could be anything you devise.  The switch could just check x,y pos of the click against coordinates you have stored in an array/etc. and then act accordingly.  It all depends on how you keep track of objects/devise the logic. ;)

It really also depends on WHERE you put the switch-case statement(what object it's attached to and whatnot, I think gamemaker works like that anyhow)..  Been a long time since I played with it.

Yep, the switch functionality is pretty flexible, if you pile the cases up without a break they will all trigger.

e.g. 
 

Switch (something){
case this:
case that:
  print "this and/or that";
break;
case other:
 print "other";
break;
case default:
 print "something entirely different";
break;
}

Lots of other little tricks you can do too. ;)

The switch will only match a condition, just like an IF, so if none of  the conditions are true, or the state not present in the switch, it won't do anything. ;)

 

Share this post


Link to post
Share on other sites

Oh yeah perfect! I see the document link now! Awesome! This looks like what I need to use! :D Thank you!! 🤔

"check for a keyboard event and then compares that to the cases listed" in their example on that page, I'm worried that I've misunderstood.. Like if they're clicking left and clicking down it'd perform the left and down case... So if I click my tower, it'll perform the tower code display action BUT if I click on the upgrade button on the menu 'case 2' will it stop doing case 1 because i did NOT click on my tower ? Or will case 1 remain active until told otherwise? -- I mean I'm maybe asking If I should put both the actions of case 1 into case 2 as well? 

I'm thinking if I put this into the step event or mouse left pressed event of my 'mastercontroller' object whilst each tower object will have a clicked = false; upon create -- It should only trigger this to be true for that one that is clicked.. OR place this in the tower object and have the switch be told to look for mouse click of 'self' (I could maybe tell it to record it's own x and y prior to activating the switch... then the switch could maybe look for/read the tower at those coordinates? )

I'm so confused in such a way that I don't know what's confusing me -.- I feel like as i'm typing it i'm 'getting it' then suddenly I wanna just write ahhh I dunno!!! lol ... 

I am thinking that maybe I can lose the 'clicked' true/false thing and just go straight to triggering a script straight from the case which will handle the display stuff then not having a break between case 1 and case 2 so both should be okay with each other? case 2 would handle my actual upgrade whilst case 1 is displaying? Or make case 2 display and upgrade (because case 2 is actually clicking the upgrade) case 1 is clicking the tower so only displaying, case 3 would need to not draw anything

 

but how do i turn this whole thing off when I click elsewhere? If I was to click a new tower or even just a random place on the map (I dunno why but maybe someone wants to turn off the upgrade display... Is this what Case 3 would be? (any idea what would be good to write to say if you're not clicking tower and you're not clicking the upgrade area... would this be triggered just by any click?) 

Share this post


Link to post
Share on other sites

Yep, a switch would be a good approach for this problem. :) Nice @Septopus

11 minutes ago, CyberFlash said:

but how do i turn this whole thing off when I click elsewhere? If I was to click a new tower or even just a random place on the map (I dunno why but maybe someone wants to turn off the upgrade display... Is this what Case 3 would be? (any idea what would be good to write to say if you're not clicking tower and you're not clicking the upgrade area... would this be triggered just by any click?) 

I'm not sure if you're using actual raw X Y cords for mouse checks instead of a dynamic bounding box setup, but what I've done in the past is set up bounding boxes for everything and if the mouse is clicked but no collision is detected everything toggles off.

Since you're checking if the mouse is within an x, y location, I would suggest going ahead is setting up bounding boxes for anything clickable then you can cycle through these options in logic to see if the mouse is actually over an object when clicking or in an empty space.

Share this post


Link to post
Share on other sites
1 minute ago, Rutin said:

bounding boxes for anything clickable

I'm wondering now, Would it be worth giving things a value like clickable = 0 and clickable = 1... And then test if clickable = 1 .... I say this because my enemies and bullets will have bounding boxes but shouldn't be clickable.. I was going to 'draw' my entire menu as a sprite and then using a bunch of different X Y cords dictate certain things like highlighting towers, clicking towers depends on X Y of mouse, Displaying the price info only shows if mouse is within a certain area (happens per each 'tower' << Not the actual object tower just a drawn sprite in a certain place).. So i've used X Y quite a bit for the 'important' stuff... I figured this would be better than a bunch of extra objects 😧 

Technically only my towers would want to be the 'clickable' things as my upgrade section is just drawn there as a sprite not an object so perhaps I could check if Mouse is clicking/colliding with Towers One Two or Three... 

I feel like I'm getting this wrong again... 

Maybe I should do something like !position_meeting(x, y, self); to check if its not clicking itself && !position_meeting(x, y, objUpgrade);

and then make a blank object to just place over menu as part of the case 1 & 2 ? 

So this would be if mouse click not on self and not on upgrade -- deactivate, disable, clicked=false, etc etc 

and then go back to the use of clicked = true to trigger drawing (I just remembered that if I do this in my 'step' event, I cannot draw anything anyway so I can't draw via the case's as Game Maker demands you use a 'draw' event so I could just use the cases to trigger clicked = true and false, then in draw, if its true I can draw for days, if its false stop drawing, everything else goes like normal... 

 

I suppose position_meeting(x, y, self); could be my trigger for the switch entirely IF placed inside the left button pressed event so its like another IF before the big IF :P I just gotta test it out and mess around, I think I have a better understanding now! The 'switch' stuff is definitely where I need to be.....

Share this post


Link to post
Share on other sites
1 minute ago, CyberFlash said:

I'm wondering now, Would it be worth giving things a value like clickable = 0 and clickable = 1... And then test if clickable = 1

I wouldn't worry about that too much, that's where the case default -> do nothing, or the no matching object in the switch comes in.  It can fire the click handler for every bounding box, but it doesn't have to execute code if the bounding box isn't one you are checking against.  Can your code return an ID# or a Name, or something unique for the bounding box it hit?  If so, just switch based on that.

1 minute ago, CyberFlash said:

.... I say this because my enemies and bullets will have bounding boxes but shouldn't be clickable.. I was going to 'draw' my entire menu as a sprite and then using a bunch of different X Y cords dictate certain things like highlighting towers, clicking towers depends on X Y of mouse, Displaying the price info only shows if mouse is within a certain area (happens per each 'tower' << Not the actual object tower just a drawn sprite in a certain place).. So i've used X Y quite a bit for the 'important' stuff... I figured this would be better than a bunch of extra objects 😧 

Generally speaking extra objects are only bad where they cause extra processing, or extra confusion/complexity.  If they are going to simplify your code/life/everything, then USE MORE OF THEM ;)  (that's my philosophy anyhow)

 

Also, if you are switching based on object identifier instead of X,Y position, it frees you to make your object positions more dynamic/not be something you have to keep track of after you handle placement, if you wanted. ;)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!