Creating a main menu with a mouse listener

539 views Asked by At

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
1

There are 1 answers

0
MadProgrammer On

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 a MouseMotionListener 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 is 0x0. It will also tell you when something occurs, so you don't need to constantly poll for the information

I would, instead, have a JFrame, probably using a CardLayout 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