2016-09-30 126 views
0

我目前正在使用标准库在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); 
    } 

} 

正如你可能会从一个事件被发送到ButtonListener class.The ButtonListener接口在包也宣告了mouseClicked()方法见。

此按钮绘制在画布本身上。例如,在等级图中,右下角有一个按钮,点击时会打开库存。让此按钮被称为btn_INV

到现在为止,我一直在通过键盘移动播放器的输入。但是我打算将keyInput更改为鼠标输入,其中播放器将移动到用户点击的图块。

对于我必须做的一类,说MouseInput实现MouseListener。现在的问题是,当我点击btn_INV,不仅将按钮生成一个事件,而且,因为按钮实际上是在画布上绘制,MouseInput班也会得到关于玩家想要移动的瓦片的事件。现在,我认为当MouseInput类获得MouseEvent时,它将检查按钮,因为每当在画布上点击鼠标时,尽管它可能不会生成ButtonEvent,但您可以从代码中看到按钮始终为。但是,这是一种相当糟糕的方法,效率非常低。因此,我需要另一种方法。

注意:我想创建另一个画布显示HUD和btn_INV和其他这样的按钮,但这并没有真正解决问题,绕过它。

回答

1

我认为有两种方法来解决这个问题:

  • 第一个将是你的游戏画面分割成两个部分:一部分为按钮,另一个用于瓷砖,这样你就可以测试whilecatching一个MouseEvent,如果点击位于瓷砖上或没有。请注意,瓷砖可以放置在新的按钮上。这个解决方案很容易实现,但是你将无法在你的瓷砖区域放置按钮。

  • 第二个将创建一个“ButtonManager”。你的游戏类将有这个按钮管理器,它将监听鼠标事件,然后发送到按钮。按钮不会直接收听此事件。他们会一个接一个地说,如果点击是在他们的边界上,并且如果没有按钮被触发,这意味着点击发生在瓷砖上。这种方法实现起来有点难,但是可以让你创建一个按钮的优先级,所以按钮可以让我的边界相交!

希望它对你有所帮助!

1

一般来说,像按钮侦听器这样的概念在应用程序中使用,而不是游戏。

游戏一般与游戏循环一起工作,游戏循环将有更新和绘制阶段。在更新阶段,用户输入被捕获(以及更多检查,而不是被捕获,但我会在一会儿得到)并进行解释。

所以你只需要一个大的鼠标监听器,然后检查看看哪个按钮可能被按下,或者如果鼠标在游戏区域内,所以角色应该得到移动命令。

当然,从技术上讲,鼠标监听器不应该直接做任何事情,因为它绑定到摆动线程。它应该只是改变一些变量(如:“鼠标左键放下,位置是x,y”),然后在更新阶段检查,然后实际上它将与它一起工作。这样,你就不再依赖于摆动线程(这对游戏来说并不理想),而且 - 几乎同样重要 - 你的游戏逻辑是完全可预测的。

但是,您仍然必须确保您的绘制方法被定期调用,并且实际上绘制了什么以及何时需要它绘制。除了这个问题之外,所以我不会详细讨论它。

请记住,即使摆动不只是一些神奇的构造。当点击鼠标时,摆动也会遍历你拥有的所有元素,看看他们中的一个是否应该得到一个事件。如果你编写自己的按钮,那也是你必须要做的。

给每个按钮它自己的鼠标监听器只会让你感到困惑,你的游戏越大。它也将摧毁你的游戏循环,因为无论你现在在做什么,鼠标事件都可以在任何时候抛出并捕获。如果你的游戏逻辑发生在一个独立的线程中(它应该),那么甚至有可能在你处理某些事情时得到一个事件。这会搞砸你的结果。

这也可能会导致一些非常奇怪的一次性错误,您不明白并且无法重现。所以要非常小心。

+0

谢谢你的时间和建议。我会改变我的a =程序,因为你所提到的是有效的。但我要说的一件事是'btn_INV'只改变'GameState',所以它并不重要如果我在主游戏线程上执行某些其他更新时调用该方法。然而,对于刚刚创建一些“ActionCommands”的'MouseListener'线程而言,这是一个很好的观点,我会尽力实现它。谢谢。 –