我目前正在使用标准库在java中进行RPG破解和斜杠。
对于这些游戏,我在一个独立的软件包中创建了一个CustomButton
课程,我只是复制并粘贴在几乎所有的游戏中,然后进行一些特定于游戏的修改。
这是类::
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);
}
}
您可以从mouseClicked()
方法看到事件被发送到ButtonListener
类。ButtonListener
接口也在包中声明。
此按钮在画布上绘制。例如,在levelmap中,右下角有一个按钮,点击该按钮将打开库存。请将此按钮称为btn_INV
。< / p>
到目前为止,我一直在接受通过键盘移动播放器的输入。但我计划将keyInput更改为鼠标输入,播放器将移动到用户点击的图块。
为此,我必须创建一个类,说MouseInput
实现MouseListener
。现在的问题是当我点击btn_INV
时,按钮不仅会生成一个事件,而且此外,由于按钮实际上是在画布上绘制的,MouseInput
类也会得到一个关于玩家想要移动的图块的事件。现在,我认为当MouseInput
类获得时一个MouseEvent
,它会检查按钮,因为只要在画布上点击鼠标,按钮始终就会被通知,尽管它可能不会生成ButtonEvent
,你可以从代码中看到。但这是一个相当糟糕的方法而且非常低效。所以,我想要另一种方法。
注意:我想创建另一个用于显示HUD和btn_INV
以及其他此类按钮的画布,但这并没有像绕过它那样真正解决问题。
答案 0 :(得分:1)
我认为有两种方法可以解决这个问题:
第一个是将游戏画面分为两部分:一个用于按钮,另一个用于图块,因此如果点击位于图块上,您可以测试捕捉MouseEvent。请注意,瓷砖可以放在新按钮上。此解决方案易于实施,但您无法在瓷砖区域放置按钮。
第二个是创建“ButtonManager”。你的游戏类将有这个按钮管理器,它将监听鼠标事件并发送到按钮。按钮不会直接监听此事件。如果点击在他们的边界上,他们会一个接一个地说,如果没有按钮被触发,则意味着在瓷砖上发生了点击。这个方法实现起来有点困难,但是允许你在按钮之间创建一个优先级,所以按钮可以让i边界相交!
希望它能帮到你!
答案 1 :(得分:1)
一般来说,按钮侦听器等概念用于应用程序,而不是游戏。
游戏通常使用游戏循环,该游戏循环将具有更新和绘制阶段。在更新阶段,用户输入被捕获(嗯...比被捕获的更多检查,但我会稍等一下)并解释。
所以你只需要一个大鼠标监听器,然后检查可能会按下哪个按钮,或者鼠标是否在游戏区域内,这样角色就可以获得移动命令。
当然,从技术上讲,鼠标监听器不应该直接做任何事情,因为它绑定到swing线程。它应该只更改一些变量(例如:“鼠标左键按下,位置为x,y”),然后在更新阶段检查,然后实际使用它。这样,你就不再依赖于挥杆线程(这对于游戏来说并不理想),而且 - 几乎同样重要 - 你的游戏逻辑是完全可以预测的。
但是,您仍然需要确保定期调用绘制方法,并实际绘制您想要绘制的内容和时间。除了这个问题之外,所以我不会详细介绍它。
请记住,即使挥杆也不只是一些神奇的构造。单击鼠标时,swing也将遍历您拥有的所有元素,并查看其中一个元素是否应该获得事件。如果你自己编写按钮,那也是你必须要做的事情。
给每个按钮它自己的鼠标监听器只会让游戏变得越混乱。它还会破坏你的游戏循环,因为无论你现在正在做什么,鼠标事件都可以随时抛出和捕获。如果你的游戏逻辑发生在摆动的单独线程中(它应该),你甚至可能在处理某些事情时得到一个事件。哪会搞砸你的结果。
这也可能导致一些您不理解且无法重现的非常奇怪的一次性错误。所以要非常小心。