user2441221
user2441221

Reputation: 23

Key Listener and Graphics do not agree

So hey I'm trying to make a simple game based on the light cycles from Tron. It has 3 classes: the driver with the main method(LightCycleRunner), a LightCycle class that stores the coordinates and direction of each light cycle, and the class that draws and processes the movements after drawing the background. Everything worked fine except that the key listeners wouldn't listen until after the game is over. I tried to solve this by making a new thread to run the game while so the key listener will still listen, but now my graphics aren't being recognized. What are your opinions?

This is LightCycleRunner.java

import java.awt.Event;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class LightCycleRunner extends JFrame{

    /**
     *@param WIDTH the width of the window.
     *@param HEIGHT the height of the window.
     */
    private static final int WIDTH = 617;
    private static final int HEIGHT = 639;


    public LightCycleRunner()
    {
        super("Light Cycles");
        addKeyListener(this);
        setSize(WIDTH,HEIGHT);
        Grid obj = new Grid();
        getContentPane().add(obj);
        obj.giveCycles(cycle1, cycle2);
        setFocusable(true);
        setVisible(true);
    }

    public static void main( String args[] )
    {
        run();
    }
    public void run() {
            LightCycleRunner run = new LightCycleRunner();
            window = this.getGraphics();
        }

    public boolean handleEvent(Event e) {
        if (e.id == Event.KEY_PRESS) {
            System.out.println("pressed!!!!!!!!!!");
        } else if (e.id == Event.KEY_RELEASE) {
            System.out.println("pressed!!!!!!!!!!");
        }
        return false;
    }
}

This is Grid.java

import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.*;

public class Grid extends Canvas implements KeyListener, Runnable{

    final int FRAME_WIDTH = 600;
    final int FRAME_HEIGHT = 600;
    final int SQUARE_WIDTH = 20;
    final int SQUARE_HEIGHT = 20;
    final long WAITING_TIME = 300;
    Grid griddy = new Grid();
    Graphics window = griddy.getGraphics();
    griddy.paint(Graphics griddy);

    //to determine if the lightcycle will crash or not
    private boolean[][] instanceGrid = new boolean[30][30];
    //the two light players will control these light cycles
    LightCycle redCycle = new LightCycle(0,0,15);
    LightCycle blueCycle = new LightCycle(2,29,15);

    public void Grid(){
        setSize(FRAME_WIDTH,FRAME_HEIGHT);
        setBackground(Color.black);
        addKeyListener(this);
        setVisible(true);
        setFocusable(true);
    }

    public void giveCycles(LightCycle c1, LightCycle c2){
        redCycle = c1;
        blueCycle = c2;
    }

    public void run(){
        paint(this.getGraphics());
    }

    public void paint(Graphics window){
        /*
         *Draws Grid
         */
        window.setColor(Color.black);
        window.fillRect(0,0,600,600);
        //vertical lines
        window.setColor(Color.gray);
        for(int x = 0; x <= FRAME_WIDTH; x+=SQUARE_WIDTH){  
            window.drawLine(x,0,x,600);
        }
        //horizontal lines
        for(int y = 0; y <= FRAME_HEIGHT; y+=SQUARE_HEIGHT){
            window.drawLine(0,y,600,y);
        }

        //starting positions
        //red Cycle
        instanceGrid[redCycle.getY()][redCycle.getX()] = true;
        //blue Cycle
        instanceGrid[blueCycle.getY()][blueCycle.getX()] = true;

        public static void main(String[]args)
    {

        JFrame jp1 = new JFrame();
        Grid a=new Grid ();
        jp1.getContentPane().add(a, BorderLayout.CENTER);
        jp1.setSize(new Dimension(500,500));
        jp1.setVisible(true);

    }

        /*
         *Process pieces
         */
        new Thread() {
            public void run(){
                while(redCycle.isAlive()&&blueCycle.isAlive()){
                    //waiting period
                    System.out.println("***cycle started***");
                    this.getGraphics() = window;

                    try{
                        Thread.sleep(WAITING_TIME);
                    }
                    catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    //testing instanceGrid[][] for bugs
                    for(int row = 0; row < instanceGrid[0].length; row++){
                        for(int column = 0; column < instanceGrid.length; column++){
                            if(instanceGrid[row][column])
                                System.out.print("-");
                            else System.out.print("0");
                        }
                        System.out.println();
                    }
                    //red checks for obstructions
                    boolean redObstructed = false;
                    try{
                        switch(redCycle.getDirection()){
                            case 0: if(instanceGrid[redCycle.getY()][redCycle.getX()+1] == true)
                                //System.out.println(redCycle.getX()+1+","+redCycle.getY());
                                redObstructed = true; break;
                            case 1: if(instanceGrid[redCycle.getY()-1][redCycle.getX()] == true)
                                //System.out.println(redCycle.getX()+","+(redCycle.getY()-1));
                                redObstructed = true; break;
                            case 2: if(instanceGrid[redCycle.getY()][redCycle.getX()-1] == true)
                                //System.out.println(redCycle.getX()-1+","+redCycle.getY());
                                redObstructed = true; break;
                            case 3: if(instanceGrid[redCycle.getY()+1][redCycle.getX()] == true)
                                //System.out.println(redCycle.getX()+","+redCycle.getY()+1);
                                redObstructed = true; break;
                        }
                    }
                    catch(IndexOutOfBoundsException e){
                        redObstructed = true;
                    }


                    //kill red if crashed
                    if (redObstructed == true)
                        redCycle.kill();

                    //move and draw trails
                    if(redCycle.isAlive()){
                        //move
                        window.setColor(Color.red);
                        int x = redCycle.getX()*20+1;
                        int y = redCycle.getY()*20+1;
                        window.fillRect(x,y,SQUARE_WIDTH-1,SQUARE_HEIGHT-1);
                        redCycle.move();
                        instanceGrid[redCycle.getY()][redCycle.getX()] = true;
                        //window.drawLine(x1,y1,x2,y2);
                        x = redCycle.getX()*20+1;
                        y = redCycle.getY()*20+1;   

                        switch(redCycle.getDirection()){
                            case 0:
                                //update instanceGrid[][]
                                //draw triangle pointing right
                                //window.drawString("0",35,35);
                                window.drawLine(x,y,x,y+18);
                                window.drawLine(x,y,x+18,y+9);
                                window.drawLine(x,y+18,x+18,y+9);
                            break;
                            case 1:
                                //draw triangle pointing up
                                //window.drawString("1",35,35);
                                window.drawLine(x+9,y,x,y+18);
                                window.drawLine(x,y+18,x+18,y+18);
                                window.drawLine(x+9,y,x+18,y+18);
                            break;
                            case 2:
                                //draw triangle pointing left
                                //window.drawString("2",35,35);
                                window.drawLine(x+18,y,x+18,y+18);
                                window.drawLine(x,y+9,x+18,y);
                                window.drawLine(x,y+9,x+18,y+18);
                            break;
                            case 3:
                                //draw triangle pointing down
                                //window.drawString("3",35,35);
                                window.drawLine(x,y,x+18,y);
                                window.drawLine(x,y,x+9,y+18);
                                window.drawLine(x+18,y,x+9,y+18);
                            break;
                        }
                            //draw trails
                    }

                    boolean blueObstructed = false;
                    try{
                        switch(blueCycle.getDirection()){
                            case 0: if(instanceGrid[blueCycle.getY()][blueCycle.getX()+1] == true)
                                blueObstructed = true; break;
                            case 1: if(instanceGrid[blueCycle.getY()-1][blueCycle.getX()] == true)
                                blueObstructed = true; break;
                            case 2: if(instanceGrid[blueCycle.getY()][blueCycle.getX()-1] == true)
                                blueObstructed = true; break;
                            case 3: if(instanceGrid[blueCycle.getY()+1][blueCycle.getX()] == true)
                                blueObstructed = true; break;
                        }
                    }
                    catch(IndexOutOfBoundsException e){
                        blueObstructed = true;
                    }
                    if(blueObstructed == true)
                        blueCycle.kill();
                    if(blueCycle.isAlive()){
                        //move
                        window.setColor(Color.blue);
                        int x = blueCycle.getX()*20+1;
                        int y = blueCycle.getY()*20+1;
                        window.fillRect(x,y,SQUARE_WIDTH-1,SQUARE_HEIGHT-1);
                        blueCycle.move();
                        instanceGrid[blueCycle.getY()][blueCycle.getX()] = true;
                        //window.drawLine(x1,y1,x2,y2);
                        x = blueCycle.getX()*20+1;
                        y = blueCycle.getY()*20+1;

                        switch(blueCycle.getDirection()){
                            case 0:
                                //update instanceGrid[][]
                                //draw triangle pointing right
                                //window.drawString("0",35,35);
                                window.drawLine(x,y,x,y+18);
                                window.drawLine(x,y,x+18,y+9);
                                window.drawLine(x,y+18,x+18,y+9);
                            break;
                            case 1:
                                //draw triangle pointing up
                                //window.drawString("1",35,35);
                                window.drawLine(x+9,y,x,y+18);
                                window.drawLine(x,y+18,x+18,y+18);
                                window.drawLine(x+9,y,x+18,y+18);
                            break;
                            case 2:
                                //draw triangle pointing left
                                //window.drawString("2",35,35);
                                window.drawLine(x+18,y,x+18,y+18);
                                window.drawLine(x,y+9,x+18,y);
                                window.drawLine(x,y+9,x+18,y+18);
                            break;
                            case 3:
                                //draw triangle pointing down
                                //window.drawString("3",35,35);
                                window.drawLine(x,y,x+18,y);
                                window.drawLine(x,y,x+9,y+18);
                                window.drawLine(x+18,y,x+9,y+18);
                            break;
                        }
                            //draw trails
                    }
                    if(!(blueCycle.isAlive()||redCycle.isAlive())){
                        window.setColor(Color.white);
                        window.drawString("TIE",200,300);
                        System.out.println("TIE!");
                    }
                    else if(!blueCycle.isAlive()){
                        window.setColor(Color.white);
                        window.drawString("RED WINS!",200,300);
                        System.out.println("RED WINS!");
                    }
                    else{
                        window.setColor(Color.white);
                        window.drawString("BLUE WINS!",300,300);
                        System.out.println("BLUE WINS!");
                    }
                }
            }
        }.start();
    }
     /**
     *changes the direction of the light cycles according to which key was pressed
     */  
    public void keyPressed(KeyEvent e) {
        //System.out.println("KEY PRESSED");
        if(e.getKeyCode() == KeyEvent.VK_W)
        {redCycle.setDirection(1);
        System.out.println("RED UP");}
        else if(e.getKeyCode() == KeyEvent.VK_A)
        {redCycle.setDirection(2);
        System.out.println("RED LEFT");}
        else if(e.getKeyCode() == KeyEvent.VK_S)
        {redCycle.setDirection(3);
        System.out.println("RED DOWN");}
        else if(e.getKeyCode() == KeyEvent.VK_D)
        {redCycle.setDirection(0);
        System.out.println("RED RIGHT");}
        else if(e.getKeyCode() == KeyEvent.VK_UP)
        {blueCycle.setDirection(1);
        System.out.println("BLUE UP");}
        else if(e.getKeyCode() == KeyEvent.VK_LEFT)
        {blueCycle.setDirection(2);
        System.out.println("BLUE LEFT");}
        else if(e.getKeyCode() == KeyEvent.VK_DOWN)
        {blueCycle.setDirection(3);
        System.out.println("BLUE DOWN");}
        else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
        {blueCycle.setDirection(0);
        System.out.println("BLUE RIGHT");}
    }

    public void keyReleased(KeyEvent e) {
        //System.out.println("KEY RELEASED");
    }

    public void keyTyped(KeyEvent e) {
        //System.out.println("KEY TYPED");
    }

}

This is LightCycle.java

import java.awt.event.*;

public class LightCycle{

    /* Cardinal directions
     * 0 = right
     * 1 = up
     * 2 = left
     * 3 = down 
     */
     /**
      *@param direction the cardinal direction the light cycle is facing (0=right, 1=up).
      *@param x the x coordinate from the left of the grid; 0 being the leftmost column.
      *@param y the y coordinate from the top of the grid; 0 being the top row.
      *@param alive whether or not the lightcycle has crashed or not
      */
    int direction;
    int x;
    int y;
    boolean alive = true;

    public LightCycle() {
        direction = 1;
        x = 0;
        y = 0;
    }

    /**
     *@param d the beginning direction the light cycle is facing
     *@param x1 the starting x coordinate.
     *@param y1 the starting y coordinate.
     */
    public LightCycle(int d, int x1, int y1) {
        direction = d;
        x = x1;
        y = y1;
    }


    /**
     *Changes the direction the light cycle is facing
     *@param d the new direction the light cycle will travel.
     */
    public void setDirection(int d){
        direction = d;
    }

   /**
    *changes either the x or y coordinates by 1 according to the direction 
    */
    public void move(){
        switch(direction){
            case 0: x++; break;
            case 1: y-- ; break;
            case 2: x--; break;
            case 3: y++; break;
        }
    } 
    /**
     *Sets alive to false.
     */
    public void kill(){
        alive = false;
    }

    /**
     *@return the direction the cycle is currently facing.
     */
    public int getDirection(){
        return direction;
    }

    /**
     *@return the current x coordinate.
     */
    public int getX(){
        return x;
    }

    /**
     *@return the current y coordinate.
     */
    public int getY(){
        return y;
    }

    /**
     *@return whether or not the lightcycle has crashed
     */
    public boolean isAlive(){
        return alive;
    }

}

Upvotes: 2

Views: 213

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

To formalize my recommendations in my comment:

  • Don't mix AWT components with Swing components unnecessarily as
    • you will be mixing heavy and light weight components in one GUI which if not done correctly can lead to side effects
    • you will lose the advantage of Swing's default double-buffering.
  • Do your drawing in a JComponent's or JPanel's paintComponent(...) method, not a paint(...) method. Again, this will give you the advantage of Swing's default double buffering.
  • Don't get your Graphics object by calling getGraphics() on a component as this will return an evanescent object that will soon become null leading to unstable images. '
    • Much better to draw background images to a BufferedImage, but note that it is fine to call getGraphics() to get a Graphics object for the BufferedImage, but don't forget to dispose of it when done.
    • Then draw the BufferedImage in the paintComponent(...) override by calling drawImage(...) on the Graphics object that the JVM passes into the paintComponent(Graphics g) method's parameter.
  • Draw any short-lived or moving images in the paintComponent(...) method, again using the Graphics object given to you by the JVM.
  • Do not dispose of a Graphics object given to you by the JVM.
  • You almost never call paint(...) or paintComponent(...) directly. I've only done this myself when printing a component or when I need to do some very fancy graphics like those shown in the Filthy Rich Clients book.
  • Avoid use of KeyListeners as they are low-level constructs and require a component to have focus.
    • Better to use Key Bindings -- check out the tutorial for more on these.
    • If you must use KeyListeners, you must be sure to give the listened to component the focus.
  • Check out the Swing Graphics Tutorials
  • as well as thePainting in AWT and Swing article.

Upvotes: 2

Related Questions