2016-09-30 129 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'線程而言,這是一個很好的觀點,我會盡力實現它。謝謝。 –