2017-06-11 2 views
0

こんにちは私は自分のゲームの一時停止メニューを作成し、キーボードの矢印キーでそれをナビゲートします。私の質問は、どうすればマウスでナビゲートして、矢印キーを使わずにボタンをクリックすることができるのですか?ここキーボードではなくマウスでボタンを選択

はコードです:

public class InGameMenu implements KeyListener { 

private String[] string = { "Resume Game", "Options", "Save Game", "Load Game", "Exit Game" }; 
private String[] optionStrings = { "Help", "Back" }; 

public static int selected = 0; 
private int space = 25; 

public int width = 800; 
public int height = 600; 

public static boolean isInMenu = true; 
public static boolean isInOptions = false; 
public static boolean saving = false; 
public static boolean loading = false; 

public InGameMenu() { 

} 

public void tick() { 

} 

public void render(Graphics g) { 

    g.setColor(new Color(0, 0, 0, 90)); 
    g.fillRect(0, 0, Component.width, Component.height); 
    if (isInMenu) { 
     g.setColor(Color.LIGHT_GRAY); 
     if (saving) { 
      g.drawString("Saving", Component.width/2/Component.pixelSize - (int) (Component.width/25), 35); 
     } 
     if (loading) { 
      g.drawString("Loading", Component.width/2/Component.pixelSize - (int) (Component.width/25), 35); 
     } 

     for (int i = 0; i < string.length; i++) { 
      if (selected == i) { 
       g.setColor(Color.RED); 
      } else { 
       g.setColor(Color.WHITE); 
      } 
      g.drawString(string[i], Component.width/2/Component.pixelSize - (int) (Component.width/17.5), Component.height/8 + (i * space)); 
     } 
    } else if (isInOptions) { 
     for (int i = 0; i < optionStrings.length; i++) { 
      if (selected == i) { 
       g.setColor(Color.RED); 
      } else { 
       g.setColor(Color.WHITE); 
      } 
      g.drawString(optionStrings[i], Component.width/2/Component.pixelSize - (int) (Component.width/17.5), Component.height/8 + (i * space)); 

     } 
    } 

} 

public void keyPressed(KeyEvent e) { 
    int key = e.getKeyCode(); 
    if (isInMenu) { 
     if (key == KeyEvent.VK_UP) { 
      selected--; 
      if (selected < 0) { 
       selected = string.length - 1; 
      } 
     } 
     if (key == KeyEvent.VK_DOWN) { 
      selected++; 
      if (selected > string.length - 1) { 
       selected = 0; 
      } 
     } 
     if (key == KeyEvent.VK_ENTER) { 
      if (selected == 0) { 
       Component.isInMenu = false; 
      } else if (selected == 1) { 
       isInMenu = false; 
       isInOptions = true; 
       selected = 0; 
      } else if (selected == 2) { 
       saving = true; 
       SaveLoad.save(); 
       saving = false; 
      } else if (selected == 3) { 
       loading = true; 
       SaveLoad.load(); 
       loading = false; 
      } else if (selected == 4) { 
       System.exit(0); 
      } 
     } 
    } else if (isInOptions) { 
     if (key == KeyEvent.VK_UP) { 
      selected--; 
      if (selected < 0) { 
       selected = optionStrings.length - 1; 
      } 
     } 
     if (key == KeyEvent.VK_DOWN) { 
      selected++; 
      if (selected > optionStrings.length - 1) { 
       selected = 0; 
      } 
     } 
     if (key == KeyEvent.VK_ENTER) { 
      if (selected == 0) { 
       System.out.println("HELP"); 
      } else if (selected == 1) { 
       isInOptions = false; 
       isInMenu = true; 
      } 
     } 
    } 

} 

public void keyReleased(KeyEvent e) { 

} 

public void keyTyped(KeyEvent e) { 

} 

} 

答えて

1

あなたもMouseListenerを実装することができます。

あなたはMouseListenerからこれらのメソッドを追加することができます。

public void mousePressed(MouseEvent e) { 

    if(e.getSource() == button1) 
    { 
     isInMenu = false; 
     isInOptions = true; 
     selected = 0; 
    } 
    if(e.getSource() == button2) 
    { 
     saving = true; 
     SaveLoad.save(); 
     saving = false; 
    } 
    if(e.getSource() == button3) 
    { 
     loading = true; 
     SaveLoad.load(); 
     loading = false; 
    } 
    if(e.getSource() == button4) 
    { 
     System.exit(0); 
    } 
} 

public void mouseReleased(MouseEvent e) { 

} 

public void mouseEntered(MouseEvent e) { 

} 

public void mouseExited(MouseEvent e) { 

} 

public void mouseClicked(MouseEvent e) { 

} 
+1

'getButton'はマウスボタンが押された*を指定します。 *プレスがどこで発生したかは決まっていません。これをテストしましたか?どのアイテムが選択されたかはどのように決定されますか? –

+0

@VinceEmighニースキャッチ!申し訳ありません。私はそれを修正します。 –

+0

ヒント: 'Font'を使って' FontMetrics'を使って[テキストを測定する]ようにしてください(http://docs.oracle.com/javase/tutorial/2d/text/measuringtext.html)。メトリックの 'getWidth'と' getHeight'とテキストの 'x'と' y'の位置を使って、マウスがその領域をクリックしたかどうかを調べることができます。 –

0

まず、あなたがテキストの境界(xywidthheight)を取得する必要があります。

g.drawString(string[i], Component.width/2/Component.pixelSize - (int) (Component.width/17.5), Component.height/8 + (i * space)); 
// x = Component.width/2/Component.pixelSize - (int) (Component.width/17.5) 
// y = Component.height/8 + (i * space) 

あなたはFont#getStringBounds(String, FontRenderContext)経由widthheightを決定することができます:あなたはすでにxyを持って

マウスがテキストの上にマウスを移動した場合

FontRenderContext renderContext = new FontRenderContext(null, true, true); 
Font font = new Font("Arial", Font.PLAIN, 14); 
String labelText = "Start"; 

Rectangle2D labelBounds = font.getStringBounds(labelText, renderContext); 
int labelWidth = (int) labelBounds.getWidth(); 
int labelHeight = (int) labelBounds.getHeight(); 

境界を決定するのに必要とされていますクリックが発生したとき。

次に、各メニュー項目の境界を維持する必要があります。

現在のところ、名前はstringoptionStringsでのみ維持されています。メニュー項目ごとにxywidthheightを維持する必要があります。

すべてのメニュー項目それぞれが自分の名前、サイズと位置を持っているので、これらのプロパティで構成さ新しいタイプを作成することが容易になります代わりにString[]

public class Label {  
    private String name; 
    private Font font; 
    private int x, y; 
    private int width, height; 

    public Label(String name, Font font, int x, int y, int width, int height) { 
     this.name = name; 
     this.font = font; 
     this.x = x; 
     this.y = y; 
     this.width = width; 
     this.height = height; 
    } 
} 

を、あなたはLabel[]を持つことができます。より高いレベルの機能だためListを使用するpreferrableだが:

その後
public class InGameMenu implements MouseListener { 
    private List<Label> labels; 

    public void mousePressed(MouseEvent event) { 
     int x = event.getX(); 
     int y = event.getY(); 

     labels.forEach(label -> { 
     // if (mouse hovering over label) 
     //  ... 
     }); 
    } 
} 

、あなたはマウスの位置は、ラベルの位置内にあるかどうかを決定しなければなりません。

式は非常に単純です:

// checks if mouse intersects with label on X axis 
intersectsHorizontally := mouseX > labelX && mouseX < labelX + labelWidth; 

// checks if mouse intersects with label on Y axis 
intersectsVertically := mouseY > labelY && mouseY < labelY + labelHeight; 

// if both conditions above are true, mouse is hovering over label 

これはあなたのLabelを与えることであろう実装するための最も簡単な方法は、containsPoint(int x, int y)振る舞いオブジェクト:

public class Label { 
    private int x, y; 
    private int width, height; 

    //... 

    public boolean containsPoint(int pointX, int pointY) { 
     boolean containsHorizontally = pointX > x && pointX < x + width; 
     boolean containsVertically = pointY > y && pointY < y + height; 

     return containsHorizontally && containsVertically; 
    } 
} 

今、あなたは簡単にマウスがあるかどうかを判断することができます特定のラベルにカーソルを合わせる:

public void mousePressed(MouseEvent event) { 
    int x = event.getX(); 
    int y = event.getY(); 

    labels.forEach(label -> { 
     if(label.containsPoint(x, y)) { 
      //... 
     } 
    }); 
} 

最後に、ラベルがクリックされたと判断する必要があります

これについては多くの方法があります。代わりにList、あなたは独立して、ラベルを維持し、それぞれをチェックすることができ:

public class InGameMenu implements MouseListener { 
    private Label startLabel; 
    private Label loadLabel; 

    public InGameMenu(Label startLabel, Label loadLabel) { 
     this.startLabel = startLabel; 
     this.loadLabel = loadLabel; 
    } 

    public void mousePressed(MouseEvent event) { 
     int x = event.getX(); 
     int y = event.getY(); 

     if(startLabel.containsPoint(x, y)) { 
      //start game 
     } else if(loadLabel.containsPoint(x, y)) { 
      //load game 
     } 
    } 
} 

しかしInGameMenuは、それが持っているすべてのラベルについて知っていることを余儀なくされ、ラベルを追加することが苦痛なように、これは、動的ではありません。

FontRenderContext renderContext = ...; 
Font font = ...; 

// start label 
String labelText = "Start"; 
Rectangle2D labelBounds = font.getStringBounds(labelText, renderContext); 
int x = ...; 
int y = ...; 
int width = (int) labelBounds.getWidth(); 
int height = (int) labelBounds.getHeight(); 
Label label = new Label(labelText, font, labelX, labelY, labelWidth, labelHeight); 

// list of all labels for menu 
List<Label> labels = new ArrayList<>(); 
labels.add(label); 

InGameMenu menu = new InGameMenu(labels); 

を、それがクリックされたときにラベルオブジェクトが私たちに教えています

より良いアプローチは、上記の例はやっているように、InGameMenuの外にすべてLabelオブジェクトを作成することです。私たちは、ラベルがクリックされた場合に発生させるInGameMenuためLabelclick()方法を与えることによってこれを行うことができます:あなたはLabelオブジェクトを作成するときに

public class Label {  
    private String name; 
    private Font font; 
    private int x, y; 
    private int width, height; 
    private Runnable onClick; 

    public Label(String name, Font font, int x, int y, int width, int height, Runnable onClick) { 
     this.name = name; 
     this.font = font; 
     this.x = x; 
     this.y = y; 
     this.width = width; 
     this.height = height; 
     this.onClick = onClick; 
    } 

    public void click() { 
     onClick.run(); 
    } 

    //... 
} 

public class InGameMenu implements MouseListener { 
    private List<Label> labels; 

    public InGameMenu(List<Label> labels) { 
     this.labels = labels; 
    } 

    public void mousePressed(MouseEvent event) { 
     int x = event.getX(); 
     int y = event.getY(); 

     labels.forEach(label -> { 
      if(label.containsPoint(x, y)) 
       label.click(); 
     }); 
    } 
} 

はその後、コールバック関数を受け入れるようにLabelを許可しますあなたは外部のデータを使用するアクションを与えることができます(GameStateManagerなど):

Runnable onClick =() -> System.out.println("Start button was clicked!"); 

Label label = new Label("Start", ..., onClick); 
関連する問題