Okay so I am creating a simple aiming game based off of the game: CS:GO and I have been having issues regarding the creation of the main menu and the use of a MouseListener on it. Here is the Game class which contains the enum for the state of the game:
/*
* This code is protected under the Gnu General Public License (Copyleft), 2005 by
* IBM and the Computer Science Teachers of America organization. It may be freely
* modified and redistributed under educational fair use.
*/
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.Timer;
/**
* An abstract Game class which can be built into Pong.<br>
* <br>
* The default controls are for "Player 1" to move left and right with the
* 'Z' and 'X' keys, and "Playr 2" to move left and right with the 'N' and
* 'M' keys.<br>
* <br>
* Before the Game begins, the <code>setup</code> method is executed. This will
* allow the programmer to add any objects to the game and set them up. When the
* game begins, the <code>act</code> method is executed every millisecond. This
* will allow the programmer to check for user input and respond to it.
*
* @see GameObject
*/
public abstract class Game extends JFrame {
private boolean _isSetup = false;
private boolean _initialized = false;
private ArrayList _ObjectList = new ArrayList();
private static Timer _t;
public static enum STATE{
MENU,
MENU1,
GAME
};
public static STATE State = STATE.MENU;
//
/**
* <code>true</code> if the 'Z' key is being held down
*/
private boolean p1Left = false;
/**
* <code>true</code> if the 'X' key is being held down.
*/
private boolean p1Right = false;
/**
* <code>true</code> if the 'N' key is being held down.
*/
private boolean p2Left = false;
/**
* <code>true</code> if the 'M' key is being held down.
*/
private boolean p2Right = false;
/**
* Returns <code>true</code> if the 'Z' key is being pressed down
*
* @return <code>true</code> if the 'Z' key is being pressed down
*/
public boolean RKeyPressed() {
return p1Left;
}
/**
* Returns <code>true</code> if the 'X' key is being pressed down
*
* @return <code>true</code> if the 'X' key is being pressed down
*/
public boolean XKeyPressed() {
return p1Right;
}
/**
* Returns <code>true</code> if the 'N' key is being pressed down
*
* @return <code>true</code> if the 'N' key is being pressed down
*/
public boolean NKeyPressed() {
return p2Left;
}
/**
* Returns <code>true</code> if the 'M' key is being pressed down
*
* @return <code>true</code> if the 'M' key is being pressed down
*/
public boolean MKeyPressed() {
return p2Right;
}
/**
* When implemented, this will allow the programmer to initialize the game
* before it begins running
*
* Adding objects to the game and setting their initial positions should be
* done here.
*
* @see GameObject
*/
public abstract void setup();
/**
* When the game begins, this method will automatically be executed every
* millisecond
*
* This may be used as a control method for checking user input and
* collision between any game objects
*/
public abstract void act();
/**
* Sets up the game and any objects.
*
* This method should never be called by anything other than a <code>main</code>
* method after the frame becomes visible.
*/
public void initComponents() {
getContentPane().setBackground(Color.black);
setup();
for (int i = 0; i < _ObjectList.size(); i++) {
GameObject o = (GameObject)_ObjectList.get(i);
o.repaint();
}
_t.start();
}
/**
* Adds a game object to the screen
*
* Any added objects will have their <code>act</code> method called every
* millisecond
*
* @param o the <code>GameObject</code> to add.
* @see GameObject#act()
*/
public void add(GameObject o) {
_ObjectList.add(o);
getContentPane().add(o);
}
/**
* Removes a game object from the screen
*
* @param o the <code>GameObject</code> to remove
* @see GameObject
*/
public void remove(GameObject o) {
_ObjectList.remove(o);
getContentPane().remove(o);
}
/**
* Sets the millisecond delay between calls to <code>act</code> methods.
*
* Increasing the delay will make the game run "slower." The default delay
* is 1 millisecond.
*
* @param delay the number of milliseconds between calls to <code>act</code>
* @see Game#act()
* @see GameObject#act()
*/
public void setDelay(int delay) {
_t.setDelay(delay);
}
/**
* Sets the background color of the playing field
*
* The default color is black
*
* @see java.awt.Color
*/
public void setBackground(Color c) {
getContentPane().setBackground(c);
}
/**
* The default constructor for the game.
*
* The default window size is 400x400
*/
public Game() {
setSize(1280, 720);
getContentPane().setBackground(Color.BLACK);
getContentPane().setLayout(null);
JMenuBar menuBar = new JMenuBar();
JMenu menuFile = new JMenu("File");
JMenuItem menuFileExit = new JMenuItem("Exit");
menuBar.add(menuFile);
menuFile.add(menuFileExit);
setJMenuBar(menuBar);
setTitle("Mid Peek");
addKeyListener(new KeyAdapter()
{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
System.out.println("ENTER key pressed");
State=STATE.GAME;
startGame();
}
}
});
// Add window listener.
addWindowListener (
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
menuFileExit.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
);
_t = new Timer(1, new ActionListener() {
public void actionPerformed(ActionEvent e) {
act();
for (int i = 0; i < _ObjectList.size(); i++) {
GameObject o = (GameObject)_ObjectList.get(i);
o.act();
}
}
});
addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
char pressed = Character.toUpperCase(e.getKeyChar());
switch (pressed) {
case 'Z' : p1Left = true; break;
case 'X' : p1Right = true; break;
case 'N' : p2Left = true; break;
case 'M' : p2Right = true; break;
}
}
public void keyReleased(KeyEvent e) {
char released = Character.toUpperCase(e.getKeyChar());
switch (released) {
case 'Z' : p1Left = false; break;
case 'X' : p1Right = false; break;
case 'N' : p2Left = false; break;
case 'M' : p2Right = false; break;
}
}
});
}
/**
* Starts updates to the game
*
* The game should automatically start.
*
* @see Game#stopGame()
*/
public static void startGame() {
_t.start();
}
/**
* Stops updates to the game
*
* This can act like a "pause" method
*
* @see Game#startGame()
*/
public void stopGame() {
_t.stop();
}
/**
* Displays a dialog that says "Player 1 Wins!"
*
*/
public void p1Wins() {
_WinDialog d = new _WinDialog(this, "Player 1 Wins!");
d.setVisible(true);
}
/**
* Displays a dialog that says "Player 2 Wins!"
*
*/
public void p2Wins() {
_WinDialog d = new _WinDialog(this, "Player 2 Wins!");
d.setVisible(true);
}
/**
* Gets the pixel width of the visible playing field
*
* @return a width in pixels
*/
public int getFieldWidth() {
return getContentPane().getBounds().width;
}
/**
* Gets the pixel height of the visible playing field
*
* @return a height in pixels
*/
public int getFieldHeight() {
return getContentPane().getBounds().height;
}
class _WinDialog extends JDialog {
JButton ok = new JButton("OK");
_WinDialog(JFrame owner, String title) {
super(owner, title);
Rectangle r = owner.getBounds();
setSize(200, 100);
setLocation(r.x + r.width / 2 - 100, r.y + r.height / 2 - 50);
getContentPane().add(ok);
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
_WinDialog.this.setVisible(false);
}
});
}
}
}
And here is the actual coding is done as the Game class is taken from a Pong game example:
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class GlobalOffensive extends Game{
JLabel rifleOverlay;
JLabel rifleShooting1;
JLabel rifleShooting2;
JLabel pistolOverlay;
JLabel pistolShooting1;
JLabel pistolShooting2;
JLabel backImage;
JLabel Terrorist;
JLabel menu1;
static JLabel open = new JLabel();
private static Menu menu;
private static int timer = 0;
Player p;
Terrorists t;
Terrorists t1;
Terrorists t2;
Terrorists t3;
Terrorists t4;
private static int spawnLimit = 1;
private static int numBots = 0;
private static int spawnTime;
MouseEvent e;
public void setup(){
menu = new Menu();
ImageIcon menu = new ImageIcon("menu1.jpg");
menu1 = new JLabel(menu);
menu1.setSize(1280, 720);
if (State==STATE.MENU || State==STATE.MENU1){
add(menu1);
}
if (State==STATE.GAME){
p = new Player(4, 3);
t = new Terrorists();
//t1 = new Terrorists(100,50);
//t2 = new Terrorists(100,50);
//t3 = new Terrorists(100,50);
//t4 = new Terrorists(100,50);
ImageIcon background = new ImageIcon("DustMid.jpg");
ImageIcon overlay = new ImageIcon("m414mask.png");
ImageIcon bot = new ImageIcon("Terrorist");
Toolkit toolkit = Toolkit.getDefaultToolkit();
Image image = toolkit.getImage("Crosshair.png");
//Creating bot
Terrorist = new JLabel(bot);
Terrorist.setSize(50,100);
add(Terrorist);
//Creating the gun overlay and setting the background
rifleOverlay = new JLabel(overlay);
rifleOverlay.setSize(1280,720);
add(rifleOverlay);
backImage = new JLabel(background);
backImage.setSize(1280, 720);
add(backImage);
//setting the cursor to the cross hair when it is over the background image or the overlay
backImage.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
Cursor c = toolkit.createCustomCursor(image , new Point(backImage.getX(),
backImage.getY()), "Crosshair");
backImage.setCursor (c);
rifleOverlay.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
Cursor d = toolkit.createCustomCursor(image , new Point(rifleOverlay.getX(),
rifleOverlay.getY()), "Crosshair");
rifleOverlay.setCursor (d);
//ImageIcon rifleShooting = new ImageIcon("rifleShooting2.png");
//rifleShooting2 = new JLabel(rifleShooting);
//rifleShooting2.setSize(1280, 720);
//add(rifleShooting2);
}
}
public void act(){
if (State==STATE.GAME){
setDelay(10);
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int x = (int) b.getX();
int y = (int) b.getY();
//Rifle follows mouse movement
if (x != 0){
rifleOverlay.setLocation(x-700, 0);
repaint();
}
//Spawn bot
if (numBots <= spawnLimit && timer%60 == 0){
t.spawn();
numBots += 1;
System.out.println("Bot spawned");
spawnTime = timer;
Terrorist.setLocation(549, 404);
repaint();
}
//Shoots the player after set amount of time
if ((timer - spawnTime)%200 == 0){
t.shoots(p);
System.out.println("Bot fired");
}
//Bot disappears after set amount of time
if ((timer - spawnTime)%210 == 0){
System.out.println("Bot ran away");
t.lifeTime(t);
}
//Ammo
if (p.getCurrentAmmo() == 0){
p.reload();
System.out.println("Out of Ammo");
}else if (p.getCurrentAmmo() > 0){
//To fire bullet
if (XKeyPressed() == true){
p.shotsFired(true);
System.out.println("Player fired");
//if(XKeyPressed() == false){
// p.shotsFired(false);
//}
//rifleShooting2.setLocation(x-700, 0);
//repaint();
}
}else if (RKeyPressed() == true){
p.reload();
}
Robot r = null;
try {
r = new Robot();
} catch (AWTException e1) {
// TODO Auto-generated catch block
System.out.println("An error of sorts");
e1.printStackTrace();
}
//If terrorist fires, player takes damage
//if (t.shoots(p) == true){
// p.health(true);
//}
//Game ends if player dies
if (p.dies() == true){
stopGame();
}
timer ++;
}
}
public static void main(String[] args) {
GlobalOffensive p = new GlobalOffensive();
p.initComponents();
p.pack();
p.setVisible(true);
p.setSize(1280, 720);
p.getContentPane().setBackground(Color.BLACK);
}
}
//Spawn location coordinates
//404y
//549x
//526y
//1133x
//301y
//297x
//413
//696
MouseInfo
is NOT the best choice for monitoring mouse activity, it provides location in screen coordinates, not local/component coordinates, which is really going to mess with you.Instead, you should be making use of a
MouseListener
(and maybe aMouseMotionListener
depending on your needs) registered to the component that you're interested in managing.See How to Write a Mouse Listener for more details.
A
MouseListener
will automatically translate the mouse coordinates into local (the component) context so that the top/left position is0x0
. It will also tell you when something occurs, so you don't need to constantly poll for the informationI would, instead, have a
JFrame
, probably using aCardLayout
a "menu" panel and a "game" panel. This way, you can separated the functionality of the two and isolate the responsibility into their own classes.I think you'll also find the key bindings API will work more reliably then
KeyListener
. See How to Use Key Bindings