Wow, I never even considered doing a Rectangle.
I’ll try that here in a few guys.
Thanks,
Jev.
Wow, I never even considered doing a Rectangle.
I’ll try that here in a few guys.
Thanks,
Jev.
Still not working.
Here’s my code.
package net.kemoy.G581G.gui;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import net.kemoy.G581G.Art;
import net.kemoy.G581G.Core;
public class Button extends Rectangle {
public static final long serialVersionUID = 1L;
public Point mse = new Point(0, 0);
BufferedImage button;
public Button(String msg, int x, int y) {
setBounds(x, y, Art.b1.getWidth(), Art.b1.getHeight());
System.out.println(getBounds());
button = Art.b1;
String mval = msg;
Graphics g = Core.display.getGraphics();
g.drawImage(button, x, y, null);
Fonts.drawString(mval, x + 20, y + 20);
}
public Button() {
}
public void tick() {
if (contains(new Point(mse))) {
button = Art.b2;
System.out.println("Woohoo!");
}
}
}
It can detect the location and size now, but now I’m having issues with the mouse coordinates.
Is mse the mouse coords? B/c You never modify it…
‘mse’ is the point of the mouse coordinates that are collected in my input class.
Make sure that your mse and the rectangle you test for intersection are using the same coordinate system, i.e. J2D’s upper-left corner being 0,0 and y increasing downwards.
Also, I don’t see why you need to copy mse each tick(), unless you are trying to do some kind of thread safety, which if that is the case, you are going about it wrong.
Instead of extending rectangle i would rather just keep a field that contains rectangle
^This^
As Wesley said, your ‘mse’ variable is never updated (at least not in the code you posted). Your tick function is referencing the class level variable which is stuck at [0,0].
My approach to doing something like this is to create a base control class that contains the basic properties (visible, dimension, render point, etc) a “contains” function to check for mouse events, and an abstract render method then just extend/override the base class for your more specific classes. It may be a bit of an overkill if you’re just looking to add a couple of buttons to your main menu, but it makes implementing other controls such as progress bars, input controls, check boxes, and the like a lot easier (and more fun) in the long run. Your mileage may vary, but this approach has been serving me well while I’ve been developing my GUI library over the past couple of months. 8)
Edit: Just realized that your ‘mse’ variable is public. Are you updating this variable directly from outside of the button class? :o If that’s the case, have you tried tracing what value it’s set to on each tick? One other note, since ‘mse’ is already a Point, there’s really no need to create a new point in your tick method for the contains check. Just use the ‘mse’ variable directly.
It’s updated in my input class only when the mouse moves. It’s not being constantly set.
public void mouseMoved(MouseEvent e) {
if (game.state == 1) {
butt.mse.x = e.getX();
butt.mse.y = e.getY();
} else if (game.state == 0) {
}
}
}
Oh wow, that was a huge mess-up.
I wasn’t modifying it, I thought I was.
I got everthing down, now I just need the detection going.
Here’s the current code I have. It’s not working.
if (butt.contains(Button.mse)) {
Button.button = Art.b2;
System.out.println("Woohoo!");
}
*Note, I moved the detection to the input class.
Why are you having “butt” do the bounds checking, and why are you suddenly referencing the member variables of your button class as if they’re static? Assuming “butt” is a globally referenced object (it’s hard to tell because your posted code doesn’t seem to contain all the important bits), shouldn’t the code be more along the lines of:
public void tick() {
if (butt.contains(mse)) {
button = Art.b2;
System.out.println("Woohoo!");
}
}
This would still appear to be incorrect since “butt” would have to have it’s bounds altered in creative ways each time it wanted to do a contains check with a control. In this scenario, you really want the button to determine whether the mouse point is currently inside of it instead of the input class being responsible for the contains check (like your earlier code had it):
public class Button extends Rectangle {
public Point mse = new Point(0, 0);
BufferedImage button;
/* ... SNIP ... */
public void tick() {
if (contains(butt.mse)) {
button = Art.b2;
System.out.println("Woohoo!");
}
}
}
Posting your input class would probably help to net some better answers.
It extends rectangle, and the contains method isn’t static.
Is tick() getting called? That’s the next thing to check if that code isn’t running.
Really, I think you should use the model that most gui systems use (including Swing names here, as you are probably familiar with them):
Component/Container - If you make the distinction, Container is a Component that can have child Components. Or you can just make all Components able to have children.
Components implement EventListeners - the EventListener methods do the handling of events
If there is a tick() or render() method on Component, it will call tick() or render() on all its children, and so on until the the whole scene graph is updated/rendered.
Might take a half hour to setup, and another to transfer, but I think you will have less headaches later, esp. if you go much further than buttons.
I’m assuming we’re talking about your input handler. The “static” comment was referring to this part of your code:
if (butt.contains(Button.mse))
“mse” would have to be a static member of the Button class for the above to make sense. Ideally, your Button class would look something like:
public class Button extends Rectangle {
public static final long serialVersionUID = 1L;
BufferedImage button;
public Button(String msg, int x, int y) {
setBounds(x, y, Art.b1.getWidth(), Art.b1.getHeight());
System.out.println(getBounds());
button = Art.b1;
String mval = msg;
}
public render(Graphics g) {
g.drawImage(button, x, y, null);
Fonts.drawString(mval, x + 20, y + 20);
}
public boolean tick(Point mse) {
if (contains(mse)) {
// Change to the hovered
button = Art.b2;
System.out.println("Woohoo!");
return true;
}
button = Art.b1;
return false;
}
}
Then your input handlers mouse move event would look something like this:
public void mouseMoved(MouseEvent e) {
if (game.state == 1) {
// Get a reference to your button here...we'll call it theButton in this case.
theButton.tick(e.getPoint());
} else if (game.state == 0) {
// Do something else...
}
}
The boolean on the tick event can be omitted if you’re only using one button. If you’re using more, then it becomes useful when iterating over multiple button objects (as in Slyth2727’s scenario) to determine if the event has been processed by a particular button thus ending the iteration loop.
BurntPizza’s recommendations are also solid and pretty much how my GUI controls are implemented as well. It adds a bit of complexity in the short term, but makes things far easier in the long term. Delving into the source for Java’s Component class may also provide some enlightenment/ideas for how to implement your controls.
For better design and flexibility, a UI button should not inherit from a rectangle class, but use it.
A button is not a rectangle but can have the shape of a rectangle.
Alright, I got that down.
The detection still won’t work.
Also, I feel like the tick method should constantly be running. If I only use it when the mouse is moved, there can be a delay so the coordinates aren’t exact.
The tick method should definitely be constantly checked. However if you have a million buttons (which I have a hard time imagining why you would but still) that will be bad. What I had was a Gui class which basically held and array of all of that gui’s buttons. Then in my main class I had a Gui displayedGui that, in the update loop, called displayedGui.drawGui() which drew and updated (tick()) the buttons.
Here’s what I did for my game, though I used a polygon (hexagonal) rather than a rectangle.
Rectangle rectangle = new Rectangle(xLoc, yLoc, width, height);
public boolean contains(Point point)
{
if (rectangle.contains(point)) return true;
return false;
}
put a “hover” boolean in your Button object. I’d probably make this instance variable ‘volatile’.
have your MouseMotionListener include the following code:
public void mouseMoved(MouseEvent arg0)
{
button.setHover(button.contains(arg0.getPoint());
}
You may have to do same for mouseDragged(). This should keep the state of the button current.
Maybe a setup like the above will work for your game.
Hey. I did a whole UI system I did in java2D if you want to look. Here is a just the button class.
http://www.java-gaming.org/?action=pastebin&id=709
Stop writing code for a second and think of what a button needs.
Is the button active? can it test for events?
Is the mouse over the button?
Is the mouse pressed?
Is the mouse released when it is still over the button?
How do we know when the mouse is over the button?
You probably already thought of these but now think of how you will code them. Once you have an idea, hop to it and make some buttons.
Rectangle rect = new Rectangle(0, 0, 50, 50);
if (mx > rect.x && my > rect.y && mx < (rect.x + rect.width) && my < (rect.y + rect.height)) {
do stuff
}
You do realize that your example re-invents the wheel. The Rectangle’s contains method does pretty much the same thing.
Rectangle rect = new Rectangle(0, 0, 50, 50);
if (rect.contains(mx, my) {
// do stuff
}
Other than that, the checks should be “>=” and “<=” otherwise you miss intersections with the border pixels.