Ich mache gerade einen RPG Hack und slash in Java mit nur den Standardbibliotheken.Überlappung von Buttons mit Leinwand für Mauseingabe
Für diese Spiele hatte ich eine CustomButton
Klasse in einem unabhängigen Paket, das ich einfach kopieren und in fast alle meine Spiele einfügen und dann einige spielspezifische Änderungen vornehmen.
Dies ist die Klasse ::
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import objects.Collectable;
public final class CustomButton implements MouseListener {
// private BufferedImage image;
private String text = "";
private boolean pressed = false;
private int x;
private int y;
private int width;
private int height;
private Color currentColor, defaultColor, hoverColor, pressColor;
private Point mousePoint = new Point(0, 0);
private ButtonListener btnListener = null;
private Canvas canvasObject;
private BufferedImage image;
private BufferedImage darkImage;
private String actionCommand = "default";
private Collectable object;
private boolean enabled;
/*
* private CustomButton(Canvas canvasObject,JFrame frame) { this.x=100;
* this.y=100; this.width=100; this.height=100;
*
* canvasObject.addMouseListener(this); currentColor=new Color(255,255,255);
* defaultColor=new Color(255,255,255); hoverColor=new Color(255,255,255);
* pressColor=new Color(255,255,255); }
*/
public CustomButton(int x, int y, int width, int height, Canvas canvasObject) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.canvasObject = canvasObject;
canvasObject.addMouseListener(this);
currentColor = Color.GREEN;
currentColor = new Color(255, 255, 255);
defaultColor = new Color(255, 255, 255);
hoverColor = new Color(255, 255, 255);
pressColor = new Color(255, 255, 255);
enabled = true;
}
public CustomButton(int x, int y, int width, int height, Canvas canvasObject, BufferedImage image,
Collectable object) {
this.image = image;
this.darkImage = darkenImage(image);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
canvasObject.addMouseListener(this);
currentColor = Color.GREEN;
currentColor = new Color(255, 255, 255);
defaultColor = new Color(255, 255, 255);
hoverColor = new Color(255, 255, 255);
pressColor = new Color(255, 255, 255);
this.canvasObject = canvasObject;
this.object = object;
enabled = true;
}
public void render(Graphics g) {
if (image == null) {
g.setColor(currentColor);
if (!pressed)
g.fillRect(this.x, this.y, width, height);
else
g.fill3DRect(this.x, this.y, width, height, true);
g.setColor(Color.BLACK);
g.drawString(text, this.x + 10, this.y + 15);
} else {
if (enabled) {
g.drawImage(image, x, y, width, height, null);
} else {
g.drawImage(darkImage, x, y, width, height, null);
}
}
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
public void tick() {
mousePoint = getMouseLocation();
changeColor();
}
private Point getMouseLocation() {
int x = 0;
int y = 0;
try {
x = (int) (canvasObject.getMousePosition().getX());
y = (int) (canvasObject.getMousePosition().getY());
} catch (NullPointerException nl) {
}
return new Point(x, y);
}
public void changeColor() {
if (!pressed) {
if (getBounds().contains(mousePoint))
currentColor = hoverColor;
else
currentColor = defaultColor;
} else {
currentColor = pressColor;
}
}
public void addButtonListener(ButtonListener btnListener) {
this.btnListener = btnListener;
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
if (enabled) {
if (btnListener != null) {
if (getBounds().contains(mousePoint)) {
ButtonID id = ButtonID.UNDETERMINABLE;
if (e.getButton() == MouseEvent.BUTTON1) id = ButtonID.LEFT;
if (e.getButton() == MouseEvent.BUTTON2) id = ButtonID.RIGHT;
btnListener.buttonClicked(new ButtonEvent(id, object, actionCommand));
}
}
}
}
public void mousePressed(MouseEvent e) {
if (getBounds().contains(mousePoint)) pressed = true;
}
public void mouseReleased(MouseEvent e) {
pressed = false;
}
public void setActionCommand(String actionCommand) {
this.actionCommand = actionCommand;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public void setDefaultColor(Color c) {
defaultColor = c;
}
public void setHoverColor(Color c) {
hoverColor = c;
}
public void setPressColor(Color c) {
pressColor = c;
}
public Collectable getObject() {
return object;
}
public void setObject(Collectable object) {
this.object = object;
}
public void destroy() {
canvasObject.removeMouseListener(this);
}
public void disable() {
enabled = false;
}
public void enable() {
enabled = true;
}
public boolean isEnabled() {
return enabled;
}
private BufferedImage darkenImage(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
image = deepCopy(image);
WritableRaster raster = image.getRaster();
for (int xx = 0; xx < width; xx++) {
for (int yy = 0; yy < height; yy++) {
int[] pixels = raster.getPixel(xx, yy, (int[]) null);
pixels[0] -= 50;
pixels[1] -= 50;
pixels[2] -= 50;
pixels[0] = Math.max(pixels[0], 0);
pixels[1] = Math.max(pixels[0], 0);
pixels[2] = Math.max(pixels[0], 0);
raster.setPixel(xx, yy, pixels);
}
}
return image;
}
private BufferedImage deepCopy(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
}
Wie Sie wahrscheinlich aus der mouseClicked()
Methode, die ein Ereignis an den ButtonListener
class.The ButtonListener
Schnittstelle deklariert wird auch im Paket gesendet wird, sehen können.
Diese Schaltfläche wird auf der Zeichenfläche selbst gezeichnet. In der Levelmap befindet sich beispielsweise eine Schaltfläche in der unteren rechten Ecke, die beim Klicken das Inventar öffnet. Diese Schaltfläche heißt btn_INV
.
Bis jetzt habe ich Eingaben für das Bewegen des Spielers durch die Tastatur genommen. Aber ich plane, keyInput zur Mauseingabe zu ändern, wo der Spieler zu der Fliese sich bewegt, auf die der Benutzer klickt.
Dafür habe ich eine Klasse machen muß, sagen MouseInput
die MouseListener
implementiert .Jetzt das Problem, dass, wenn ich btn_INV
klicken, wird nicht nur die Taste ein Ereignis erzeugen, sondern auch, weil die Taste tatsächlich auf der Leinwand gezeichnet , die MouseInput
Klasse wird auch ein Ereignis betreffs der Fliese erhalten, zu der der Spieler sich bewegen will. Jetzt dachte ich, dass wenn die MouseInput
Klasse eine MouseEvent
erhält, es mit den Knöpfen überprüfen wird, als wenn es einen Mausklick auf der Leinwand gibt , die Tasten immer wird informiert, obwohl es keine ButtonEvent
erzeugen kann, wie Sie aus dem Code sehen können.Aber das ist eine ziemlich schlechte Methode und sehr ineffizient.So will ich eine andere Methode dafür.
HINWEIS: Ich dachte, eine andere Leinwand für die Anzeige der HUD und der btn_INV
und andere solche Schaltflächen erstellen, aber das löst nicht wirklich das Problem so gut wie umgehen.
Vielen Dank für Ihre Zeit und Beratung.Ich werde mein a = Programm entsprechend ändern, wie das, was Sie erwähnt haben, gültig ist. Eine Sache würde ich sagen, dass die 'btn_INV' nur den' GameState' ändert, also ist es egal wenn ich diese Methode während des Ausführens irgendeines anderen Updates auf dem Hauptspielthread anrufe. Jedoch, was Sie über den 'MouseListener'-Faden sagten, gerade einige" ActionCommands "zu schaffen, ist ein guter Punkt und ich werde versuchen, es zu implementieren. Danke. –