Calling For Java Help, Part Deux

View previous topic View next topic Go down

Calling For Java Help, Part Deux

Post by reboundstudent on Wed Apr 08, 2015 7:58 pm

Sorry to take advantage of you nice folks again, but I am desperate. My professor is yet again ignoring my emails, and I cannot figure out why something is happening in my code.

For background: our project is to take the program my professor wrote, and add enhancements/bug fixes. One of the enhancements is to ask the user at the beginning of the game if they'd like to turn on/off warp walls and mazes.

In the original program, the "start screen" is a very simple Graphics draw. I feel more comfortable with GUIs than I do Graphics, and couldn't figure out how to "draw" radio buttons, so I decided I'd implement a GUI. Simple, right? NOPE. Whenever I try to run my program, the GUI just "flashes" and rebuilds itself over and over again until I have dozens of Java windows on top of each other. I just do not get why. Is it because there are Graphic repaints going on in other classes? Anybody run into this before?

(The code is quite extensive: https://github.com/farleymd/Snake)

Below is the main class that "starts" the game:

Code:
public class DrawSnakeGamePanel extends JPanel {
   
   private static int gameStage = SnakeGame.BEFORE_GAME;  //use this to figure out what to paint
   
   private Snake snake;
   private Kibble kibble;
   private Score score;

   
   DrawSnakeGamePanel(Snake s, Kibble k, Score sc){
      this.snake = s;
      this.kibble = k;
      this.score = sc;
   }
   
   public Dimension getPreferredSize() {
        return new Dimension(SnakeGame.xPixelMaxDimension, SnakeGame.yPixelMaxDimension);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);     

        /* Where are we at in the game? 4 phases..
        * 1. Before game starts
        * 2. During game
        * 3. Game lost aka game over
        * 4. or, game won
        */

        gameStage = SnakeGame.getGameStage();
       
        switch (gameStage) {
        case 1: {
           displayInstructions(g);
           break;
        }
        case 2 : {
           displayGame(g);
           break;
        }
        case 3: {
           displayGameOver(g);
           break;
        }
        case 4: {
           displayGameWon(g);
           break;
        }
        }
       
       
       
    }

   private void displayGameWon(Graphics g) {
      // TODO Replace this with something really special!
      g.clearRect(100,100,350,350);
      g.drawString("YOU WON SNAKE!!!", 150, 150);
      
   }
   private void displayGameOver(Graphics g) {

      g.clearRect(100,100,350,350);
      g.drawString("GAME OVER", 150, 150);
      
      String textScore = score.getStringScore();
      String textHighScore = score.getStringHighScore();
      String newHighScore = score.newHighScore();
      
      g.drawString("SCORE = " + textScore, 150, 250);
      
      g.drawString("HIGH SCORE = " + textHighScore, 150, 300);
      g.drawString(newHighScore, 150, 400);
      
      g.drawString("press a key to play again", 150, 350);
      g.drawString("Press q to quit the game",150,400);      
             
   }

   private void displayGame(Graphics g) {
      displayGameGrid(g);
      displaySnake(g);
      displayKibble(g);   
   }

   private void displayGameGrid(Graphics g) {

        //SnakePanelGUI snakePanelGUI = new SnakePanelGUI();

      int maxX = SnakeGame.xPixelMaxDimension;
      int maxY= SnakeGame.yPixelMaxDimension;
      int squareSize = SnakeGame.squareSize;

      g.clearRect(0, 0, maxX, maxY);

      g.setColor(Color.RED);

      //Draw grid - horizontal lines
      for (int y=0; y <= maxY ; y+= squareSize){
         g.drawLine(0, y, maxX, y);
      }
      //Draw grid - vertical lines
      for (int x=0; x <= maxX ; x+= squareSize){
         g.drawLine(x, 0, x, maxY);
      }
   }

   private void displayKibble(Graphics g) {

      //Draw the kibble in green
      g.setColor(Color.GREEN);

      int x = kibble.getKibbleX() * SnakeGame.squareSize;
      int y = kibble.getKibbleY() * SnakeGame.squareSize;

      g.fillRect(x+1, y+1, SnakeGame.squareSize-2, SnakeGame.squareSize-2);
      
   }

   private void displaySnake(Graphics g) {

      LinkedList<Point> coordinates = snake.segmentsToDraw();

      //Draw head in grey
      g.setColor(Color.LIGHT_GRAY);
      Point head = coordinates.pop();
      g.fillRect((int)head.getX(), (int)head.getY(), SnakeGame.squareSize, SnakeGame.squareSize);

      //Draw rest of snake in black
      g.setColor(Color.BLACK);
      for (Point p : coordinates) {
         g.fillRect((int)p.getX(), (int)p.getY(), SnakeGame.squareSize, SnakeGame.squareSize);
      }

   }

   private void displayInstructions(Graphics g) {

        SnakeStartGUI snakeStartGUI = new SnakeStartGUI();
        //This is my GUI right here

        g.drawString("Press any key to begin!",100,200);
        g.drawString("Press q to quit the game",100,300);
       }
}

Thanks for any help you can give me, I am desperate.
avatar
reboundstudent

Posts : 458
Reputation : 261
Join date : 2014-10-01

View user profile

Back to top Go down

Re: Calling For Java Help, Part Deux

Post by sky on Wed Apr 08, 2015 10:15 pm

nevermind


Last edited by sky on Thu Apr 09, 2015 11:56 am; edited 1 time in total (Reason for editing : next poster fixed the problem, can't figure out how to delete my post)
avatar
sky

Posts : 97
Reputation : 53
Join date : 2014-10-01

View user profile

Back to top Go down

Re: Calling For Java Help, Part Deux

Post by Izmuth on Thu Apr 09, 2015 4:10 am

When you see new windows getting opened in Java, there are only a few culprits: the main one is places where you're using setVisible on a Frame.
In this case, this is indeed the culprit: Every time you call new SnakeStartGUI() it opens a new window.

Spoiler:

Code:

+    public SnakeStartGUI(){
+        super("Snake!");
+        setContentPane(rootPanel);
+        pack();
+        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        setVisible(true);
+        setSize(new Dimension(SnakeGame.xPixelMaxDimension, SnakeGame.yPixelMaxDimension));
+
+    }

And you call new SnakeStartGUI every time your program needs to update its graphics:

Spoiler:

Code:

   private void displayInstructions(Graphics g) {

        SnakeStartGUI snakeStartGUI = new SnakeStartGUI();
        //This is my GUI right here

        g.drawString("Press any key to begin!",100,200);
        g.drawString("Press q to quit the game",100,300);
       }

Every time you open a new window, it has to update graphics, resulting in a new window, etc. etc.

I would personally, since I agree that graphics suck and Swing GUIs rock, implement it like this:
Spoiler:

Code:


MasterPanel extends JPanel
{
        MasterPanel()
        {
                setLayout(new BorderLayout())
                add(new snakeStartPanel(this));
        }
        public void startGame(boolean turnOnMazes)
       {
                removeAll();
                add(new DrawSnakeGamePanel(turnOnMazes));
       }
}
snakeStartPanel extends JPanel
{
      MasterPanel parent;
      snakeStartPanel(MasterPanel parent)
      {
              this.parent=parent;
       }
//GUI STUFFFFFFFF like buttons,checkboxes,etc. etc.
      public void buttonPressed()
      {
           parent.startGame(isMazeCheckBoxChecked());
       }
}

Then you've seperated the Graphics from the Swing GUI components cleanly and you don't have to worry about any weird interactions.
avatar
Izmuth

Posts : 141
Reputation : 76
Join date : 2014-10-02

View user profile

Back to top Go down

Re: Calling For Java Help, Part Deux

Post by reboundstudent on Thu Apr 09, 2015 3:53 pm

So I've been struggling to understand this and I'm afraid I just..... don't. Where would the MasterPanel go? Would it become an entirely new class in itself? Which probably makes sense, but I am having a fuck-hard time separating out graphics and GUI. Every time I try, I keep getting NullPointer errors. I feel resigned to just having everything in one class. Could you explain a little bit more how this fits into the overall code design?

Sorry for being obtuse; my brain is just about on the verge of exploding.
avatar
reboundstudent

Posts : 458
Reputation : 261
Join date : 2014-10-01

View user profile

Back to top Go down

Re: Calling For Java Help, Part Deux

Post by Izmuth on Thu Apr 09, 2015 5:57 pm

Damn, seems like the code is a lot more complicated than I thought on my first read through :/

MasterPanel should be a stand-alone class, yes. I'm terribly unsure now whether my solution would increase readability, but I've added it to give you an idea how it could be accomplished.

You run SnakeGame right? You could adopt that class by changing this bit:

Spoiler:
Code:
private static void createAndShowGUI() {
       //Create and set up the window.
       snakeFrame = new JFrame();
       snakeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
       snakeFrame.setSize(xPixelMaxDimension, yPixelMaxDimension);
       snakeFrame.setUndecorated(true); //hide title bar
       snakeFrame.setVisible(true);
       snakeFrame.setResizable(false);
 
       snakePanel = new DrawSnakeGamePanel(snake, kibble, score);
       snakePanel.setFocusable(true);
       snakePanel.requestFocusInWindow(); //required to give this component the focus so it can generate KeyEvents
 
       snakeFrame.add(snakePanel);
       snakePanel.addKeyListener(new GameControls(snake));
 
       setGameStage(BEFORE_GAME);
 
       snakeFrame.setVisible(true);
    }

To this bit:


Spoiler:
Code:
private static void createAndShowGUI() {
       //Create and set up the window.
       snakeFrame = new JFrame();
       snakeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
       snakeFrame.setSize(xPixelMaxDimension, yPixelMaxDimension);
       snakeFrame.setUndecorated(true); //hide title bar
       snakeFrame.setVisible(true);
       snakeFrame.setResizable(false);
 
       snakePanel = new DrawSnakeGamePanel(snake, kibble, score);

//SnakePanel is not added to the frame yet, first a masterPanel is added to seperate AWT graphics from Swing GUI. When the game is started, SnakePanel will be added to the MasterPanel.

                snakeFrame.add(new MasterPanel(snakePanel,new GameControls(snake)));
 
       setGameStage(BEFORE_GAME);
 
       snakeFrame.setVisible(true);
    }

MasterPanel class:
Spoiler:
Code:

public MasterPanel extends JPanel
{
        DrawSnakeGamePanel gamePanel;
        GameControls controls;
        MasterPanel(DrawSnakeGamePanel gamePanel, GameControls controls)
        {
                this.gamePanel=gamePanel;
                this.controls=controls;
                setLayout(new BorderLayout())
                SnakeStartPanel startPanel = new SnakeStartPanel(this);
                add(startPanel);
        }
        public void startGame(boolean turnOnMazes)
      {
                removeAll();
                gamePanel.setMazes(turnOnMazes);
                add(gamePanel);
       gamePanel.setFocusable(true);
                gamePanel.requestFocusInWindow();

       gamePanel.addKeyListener(controls);
      }
}

SnakeStartPanel class:
Spoiler:
Code:

public SnakeStartPanel extends JPanel
{
      MasterPanel parent;
      SnakeStartPanel(MasterPanel parent)
      {
              this.parent=parent;
              setFocusable(true);
              requestFocusInWindow();
              addKeyListener(new KeyListener(){
    
                   public void keyPressed(KeyEvent ev) {
                                  startGame();
                        }
              });
      }
//GUI STUFFFFFFFF like buttons,checkboxes,etc. etc.
      public void startGame()
      {
          parent.startGame(isMazeCheckBoxChecked());
      }
}
avatar
Izmuth

Posts : 141
Reputation : 76
Join date : 2014-10-02

View user profile

Back to top Go down

View previous topic View next topic Back to top


 
Permissions in this forum:
You cannot reply to topics in this forum