Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [Solved] Detecting clicks on custom Buttons/Objects  (Read 2452 times)
0 Members and 1 Guest are viewing this topic.
Offline fermixx

Senior Newbie





« Posted 2009-08-29 21:56:09 »

Hi dudes, i was wondering how to do this. Well i can imagine a way, but i think it's too "brute".

Lets explain thigs a little bit better:

Basically i have a program where you have a canvas (passive rendered) and you can add there squares or circles. So you choose the shape and then click on the canvas to draw it where you want. But when you draw the shape, your mose goes back to its normal behaviour (i.e. dont draw anything). But the idea is that when you click an existing shape, you can modify its radius, width and or height.

So basically i was thinking in a big arrayList with all my shapes (with their boundary rectangle) and when the user clicks on the canvas retrieve the coords of the mouse and check
1  
2  
if (mouse.x < shape.x + shape.width && mouse.x > shape.x && mouse.y < shape.y + shape.width && mouse.y > shape.y)
          finallyYouClickedTheF***ingShape(shape);


So you guys that are smarter and have more imagination, should this be OK for rectangles and or circles? Keep in mind that the rectangles can be rotated in any angle (hopefully i dont need to do any trig here Tongue)

Could i create a rectangle surrounding the mouse and use the intersects function ? Does this function only consider rectangles at 0º ?


Any suggestions on how to implement this?

Thanks in advance




RTS game or a big rock-paper-sissors ?
Online Riven
« League of Dukes »

JGO Overlord


Medals: 606
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2009-08-29 22:03:22 »

You can use the inverse of the AffineTransform you use for Rectangle you render -- to transform your mouse-coordinates. Then check the coords for intersection with the untransformed Rectangle.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline fermixx

Senior Newbie





« Reply #2 - Posted 2009-08-29 22:55:41 »

You can use the inverse of the AffineTransform you use for Rectangle you render -- to transform your mouse-coordinates. Then check the coords for intersection with the untransformed Rectangle.


So i should straighten up the rectangle (return it to 0º) and then check with that big " if " if the mouse is in the straighten up rectangle? this with all my rectangles in the arrayList PER CLICK?

This is a small image of my biggest doubt with this solution:



(just in case the image is not displayed properly, here it is: http://img19.yfrog.com/img19/5720/doubtsketch.jpg)



Anyways thanks for the super fast reply

RTS game or a big rock-paper-sissors ?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Riven
« League of Dukes »

JGO Overlord


Medals: 606
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2009-08-29 23:32:19 »

It's the other way around:

You have this original rect, and you rotate (transform) it with the AffineTransform, then draw it.

When you receive a mouse-input, you take the inverse of the AffineTransform, and transform your mouse-coords, these are now in the 'local transform' of the transformed rect. So when they are in the same transform, you can simply call rect.inside(point) to see whether the transformed mouse-coords are in the transformed-rect

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline fermixx

Senior Newbie





« Reply #4 - Posted 2009-08-30 01:11:39 »

Well i think im starting to understand the point. What i should do is to move not the rectangle or the mouse coords but the whole coordinate system like in this image (or something like that?):



(link to image: http://img195.yfrog.com/img195/5070/newcoordsystem.jpg)


But how to rotate the whole coord system / transform the mouse coords?

Thanks again

PS: sorry if im getting you nervous, im a big noob

RTS game or a big rock-paper-sissors ?
Online Riven
« League of Dukes »

JGO Overlord


Medals: 606
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #5 - Posted 2009-08-30 01:25:42 »

AffineTransform trans = new AffineTransform();

// apply your rotations

Rectangle rect = ...;

g.setTransform(trans);
g.draw(rect);

Point mouseGlobal = ...;
Point mouseLocal = new Point();
trans.inverseTransform(mouseGlobal, mouseLocal);

boolean inside = rect.inside(mouseLocal);

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Nate

JGO Kernel


Medals: 129
Projects: 3
Exp: 14 years


Esoteric Software


« Reply #6 - Posted 2009-08-30 01:35:14 »

Try this...



Do your mouse detection using the red "Original box" and "Rotated mouse"

Offline fermixx

Senior Newbie





« Reply #7 - Posted 2009-08-30 01:49:54 »

Do your mouse detection using the red "Original box" and "Rotated mouse"

that seems logical to me.

Anyways im gonna give a try to what Riven said. When he told me to swap the coords, i was thinking it was going to be a real pain in the a**. God bless the huge libraries Sun created for us, it saves you a lot of mental hassle.


By the way, no one mentioned how to detect which rectangle was clicked. I guess i need to check it for every rectangle on screen (creating a new transform with the current angles for that rectangle and then do the inverse transform for the mouse coords), true?


Just by curiosity, when you add an action listener to your swing component, how does swing detect which button was clicked? Does it check the mouse coords with all the components in the canvas, lets say for example, buttons ?

RTS game or a big rock-paper-sissors ?
Offline Nate

JGO Kernel


Medals: 129
Projects: 3
Exp: 14 years


Esoteric Software


« Reply #8 - Posted 2009-08-30 03:11:04 »

Anyways im gonna give a try to what Riven said.
I believe Riven and I have said the same thing.

Offline Abuse

JGO Coder


Medals: 10


falling into the abyss of reality


« Reply #9 - Posted 2009-08-30 03:39:56 »

that seems logical to me.

Anyways im gonna give a try to what Riven said. When he told me to swap the coords, i was thinking it was going to be a real pain in the a**. God bless the huge libraries Sun created for us, it saves you a lot of mental hassle.

Quote
By the way, no one mentioned how to detect which rectangle was clicked. I guess i need to check it for every rectangle on screen (creating a new transform with the current angles for that rectangle and then do the inverse transform for the mouse coords), true?

You can (and for the sake of efficiency, probably should) store the AffineTransform instance, rather than recreate it every time your code is executed in a render or mouse event.

Quote
Just by curiosity, when you add an action listener to your swing component, how does swing detect which button was clicked? Does it check the mouse coords with all the components in the canvas, lets say for example, buttons ?

Essencially, yes - though obviously AWT's tree structure reduces the complexity of this search, so it doesn't necessarily have to search the bounding box of every visible component.

One small suggestion - instead of creating a customized Button, I think you'd instead do better to create a customized Container that supports rotation.

That way you will be able to create rotated instances of any component, not just Buttons.
You would also be able to nest rotations, and do all the other funky things a scenegraph-like structure allows.

Ofcourse, this suggestion is only applicable if you are using the AWT/Swing component system for managing these Buttons you are talking about.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline fermixx

Senior Newbie





« Reply #10 - Posted 2009-08-30 04:20:24 »

You can (and for the sake of efficiency, probably should) store the AffineTransform instance, rather than recreate it every time your code is executed in a render or mouse event.

I'll have stored of course coords, width, height and rotation angle of each shape. Do you suggest that i should create an affine transform and store it in each object?

Or you mean using the same affine transform for all rectangles but updating it with the correct angle for each rect?


Another question, lets say i have two rectangles, A rotated 45º and B rotated 85º.
When the user clicks inside the canvas i'll do:

1  
2  
3  
4  
trans.rotate(45);  //trans is an already created AffineTransform
//some stuff here
trans.inverseTransform(mouseGlobal, mouseLocal);
boolean inside = rect.inside(mouseLocal);


And then for shape B:

1  
2  
3  
4  
trans.rotate(85);  
//some stuff here
trans.inverseTransform(mouseGlobal, mouseLocal);
boolean inside = rect.inside(mouseLocal);


But im not sure if rotating 85º will be added to the existing 45º in the affineTransform. Should i straighten up the affine transform first ?

version straightening up after check:

1  
2  
3  
4  
5  
trans.rotate(45);  //trans is an already created AffineTransform
//some stuff here
trans.inverseTransform(mouseGlobal, mouseLocal);
boolean inside = rect.inside(mouseLocal);
trans.rotate(-45); //going back to 0 degrees



Is that right?





One small suggestion - instead of creating a customized Button, I think you'd instead do better to create a customized Container that supports rotation.


Well they are just shapes for a map editor. The idea is that you can draw shapes into the map (the canvas) with an specified width, height and angle (at a specific location of course). But if you want to edit something, i thought clicking on the shape to edit it would be the best way to find the exact shape you want to edit. I dont know if i should call them Buttons

RTS game or a big rock-paper-sissors ?
Offline fermixx

Senior Newbie





« Reply #11 - Posted 2009-09-08 02:30:19 »

It was done by doing this:

the mouseListener goes throught the whole arrayList of shapes and for each one it calls shape.checkClick(point p)
where p are the mouse coordinates.

Well the circle was easy because pithagoras already did the job (distance <= radius^2)

Here's the code for the rectangles:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
public boolean checkClick (Point p){
        AffineTransform aft = new AffineTransform ();
        aft.rotate(Math.toRadians(angle), x, y);
        Point pDst = new Point();

        aft.inverseTransform(p, pDst);
       
        Rectangle rect = new Rectangle (x-width/2,y-height/2,width,height);
        //i do x-width/2 because the coordinates (x,y) are the center of the shape (not top left corner)

        selected = rect.contains(pDst); //selected is a boolean value that indicates the shape was selected
                                                  //i need it for later usage
   
        return selected;
    }


This is because the rects are stored without rotation (i guess its not possible store them rotated). They are rotated in render time (just before drawing) so i keep the original x,y, width and height. Thats why i've only had to modify the mouse coordinates


Its really accurate, considering that i've used integers for everything (no floats for angle or coordinates)

The only problem using integers is that when i rotate it several times (anchoring it from its center) it slightly moves some pixels. But nothing big considering that im cutting decimals without rounding or anything

Thanks for all your replies

RTS game or a big rock-paper-sissors ?
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (64 views)
2014-04-15 18:08:23

BurntPizza (62 views)
2014-04-15 03:46:01

UprightPath (75 views)
2014-04-14 17:39:50

UprightPath (58 views)
2014-04-14 17:35:47

Porlus (76 views)
2014-04-14 15:48:38

tom_mai78101 (101 views)
2014-04-10 04:04:31

BurntPizza (161 views)
2014-04-08 23:06:04

tom_mai78101 (256 views)
2014-04-05 13:34:39

trollwarrior1 (209 views)
2014-04-04 12:06:45

CJLetsGame (216 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!