iii
iii

Reputation: 626

Color Class Not Changing Colors

I'm working on a Simon Says game. One problem I'm having is that after the first level, my colors will not change/light up. I traced the code and included print statements to make sure the code was working correctly as well.

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

 public class SimonShape extends JFrame implements KeyListener {


private int width;
private int height;
private int x;
private int y;
private int TURN = 45;


private int level = 1;

//speed of the light up sequence
private int lightUpSpd = 500;

//chooses random color based on numbers 0-3
private int random;

//keeps track of user inputs 
private int compCounter = 0;

ArrayList<Integer> comp = new ArrayList<Integer>();


private Color blue = Color.BLUE.darker();
private Color red = Color.RED.darker();
private Color yellow = Color.YELLOW.darker();
private Color green = Color.GREEN.darker();


public SimonShape (int width, int height, int x, int y)
{


    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;


    JLabel label = new JLabel();


    setSize(800,800);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setVisible(true);



    label.setFocusable(true);
    label.setOpaque(true);
    label.addKeyListener(this);
    this.add(label);
    setVisible(true);
    label.requestFocusInWindow();


    randomColorChange();
}


private void randomColorChange()
{
    try
    {
        JOptionPane.showMessageDialog(this, "Level " + level);
        random = (int) (Math.random() * 4);
        comp.add(random);

        //light up sequence
        for (int i = 0; i < level; i++)
        {

            if (comp.get(i) == 0)
            {
                green = green.brighter();
                System.out.println("light");
                repaint();
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                green = green.darker();
                repaint();
            }

            else if (comp.get(i) == 1)
            {
                red = red.brighter();
                repaint();
                System.out.println("light");
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                red = red.darker();
                repaint();
            }

            else if (comp.get(i) == 2)
            {
                blue = blue.brighter();
                repaint();
                System.out.println("light");
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                blue = blue.darker();
                repaint();
            }

            else {

                yellow = yellow.brighter();
                repaint();
                System.out.println("light");
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                yellow = yellow.darker();
                repaint();
            }

            Thread.sleep(lightUpSpd/2);
        }


    }
        catch (InterruptedException e){
            e.printStackTrace();
        }

}

public void keyPressed(KeyEvent e)
{   

    if (e.getKeyCode() == KeyEvent.VK_DOWN)
    {
        blue = blue.brighter();
        repaint();
    }
    if (e.getKeyCode() == KeyEvent.VK_LEFT)
    {
        red = red.brighter();
        repaint();
    }
    if (e.getKeyCode() == KeyEvent.VK_UP)
    {
        green = green.brighter();
        repaint();
    }
    if (e.getKeyCode() == KeyEvent.VK_RIGHT)
    {
        yellow = yellow.brighter();
        repaint();
    }

}


public void keyReleased(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_UP)
    {
        green = green.darker();
        repaint();

        if (0 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;
                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect, end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }

    if (e.getKeyCode() == KeyEvent.VK_DOWN)
    {
        blue = blue.darker();
        repaint();

        if (2 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;

                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect; end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }

    if (e.getKeyCode() == KeyEvent.VK_RIGHT)
    {
        yellow = yellow.darker();
        repaint();

        if (3 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;
                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect; end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }

    if (e.getKeyCode() == KeyEvent.VK_LEFT)
    {
        red = red.darker();
        repaint();
        //user.add(1);
        if (1 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;
                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect; end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }
}

public void keyTyped(KeyEvent e) {}

public void paint(Graphics g)
{

    Graphics2D g2 = (Graphics2D) g;


    // Blue Section
    g2.setStroke(new BasicStroke(1.0f));
    g2.setPaint(blue);
    g2.fill(new Arc2D.Double(x,y,width,height,180+TURN,90,Arc2D.PIE));

    // Red Section
    g2.setStroke(new BasicStroke(2.0f));
    g2.setPaint(red);
    g2.fill(new Arc2D.Double(x,y,width,height,90+TURN,90,Arc2D.PIE));

    // Yellow Section
    g2.setStroke(new BasicStroke(2.0f));
    g2.setPaint(yellow);
    g2.fill(new Arc2D.Double(x,y,width,height,-90+TURN,90,Arc2D.PIE));

    // Green Section
    g2.setStroke(new BasicStroke(2.0f));
    g2.setPaint(green);
    g2.fill(new Arc2D.Double(x,y,width,height,360+TURN,90,Arc2D.PIE));

}
}

Upvotes: 2

Views: 211

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

It looks like you're trying to write a Swing GUI as a linear console program, and I'm surprised that it works at all. If you don't mind, please let me offer some suggestions:

  1. Don't draw directly in a JFrame's paint method as this can mess up your GUI's graphics. You don't call the JFrame's super.paint(g) method, and so it wouldn't surprise me if your program develops strange hard to debug painting problems and artifacts, since you then break the painting chain at a very critical juncture.
  2. Instead if you must draw with Graphics, do so in the paintComponent override of a JPanel.
  3. Don't call Thread.sleep(...) as you're doing in a Swing GUI, since if you don't understand Swing threading rules and take care, you risks putting the entire GUI to sleep. Instead if you need a time delay, use a Swing Timer.
  4. This is an event-driven GUI program, and so there's no place for the for loop that advances levels. Instead let the user interact with the GUI, and base the GUI's responses by the state of the GUI without a linear programming type for loop. This is one of the hardest concepts to grasp when learning event-driven programming, but is a critical concept.
  5. DRY: don't repeat yourself. You have much repetitive code that can easily be consolidated into methods, and doing so will make your code much easier to debug and enhance.
  6. Use Key Bindings rather than a KeyListener since this way you don't have to use the kludge of forcing the focus to go to your JFrame or a JPanel.
  7. Wherever possible, try to separate out your program logic from the view (the GUI). Create a model class or classes, one that is totally independent from the GUI, and then create a GUI around those classes. This too will make it much easier to enhance and debug your program. Strive to make the GUI as dumb as possible, leaving all the brains to the model. Later you could consider creating a "Control" to handle communication between the two.

Just playing with some code. No where near a complete solution...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Arc2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.swing.*;

public class SimonGui {
   private static void createAndShowGui() {
      final SimonPanel simonPanel = new SimonPanel(600, 600, 1000);

      // create a list or random directions, just to test the GUI
      Random random = new Random();
      final List<Direction> dirList = new ArrayList<>();
      for (int i = 0; i < 15; i++) {
         int randomDirIndex = random.nextInt(Direction.values().length);
         Direction randomDir = Direction.values()[randomDirIndex];
         dirList.add(randomDir);
      }          

      JFrame frame = new JFrame("SimonGui");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(simonPanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);

      // display the colors from the random list of directions, 
      // but wait 400 msecs to allow time for the GUI to display
      new Timer(400, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            // have JPanel display the colors in the list
            simonPanel.displayDirectionList(dirList);

            // then stop this timer (timer should run just once)
            ((Timer) e.getSource()).stop();
         }
      }).start();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class SimonPanel extends JPanel {
   private static final int GAP = 10;
   private int displayColorDelay;
   private int prefW;
   private int prefH;
   private Map<Direction, Shape> dirShapeMap = new LinkedHashMap<>();
   private Direction activeDir = null;
   private Timer displayColorTimer;

   public SimonPanel(int prefW, int prefH, int displayColorDelay) {
      this.prefW = prefW;
      this.prefH = prefH;
      this.displayColorDelay = displayColorDelay;

      int x = GAP;
      int y = GAP;
      int width = prefW - 2 * GAP;
      int height = prefH - 2 * GAP;
      int degree = 45;
      for (Direction direction : Direction.values()) {
         Shape shape = new Arc2D.Double(x, y, width, height, degree, 90, Arc2D.PIE);
         dirShapeMap.put(direction, shape);
         degree += 90;
      }

      setKeyBindings();
   }

   public void displayDirectionList(List<Direction> dirList) {
      displayColorTimer = new Timer(displayColorDelay, new DisplayColorTimerListener(dirList));
      displayColorTimer.start();
   }

   private void setKeyBindings() {
      Map<Direction, Integer> dirToKeyMap = new HashMap<>();
      dirToKeyMap.put(Direction.NORTH, KeyEvent.VK_UP);
      dirToKeyMap.put(Direction.WEST, KeyEvent.VK_LEFT);
      dirToKeyMap.put(Direction.SOUTH, KeyEvent.VK_DOWN);
      dirToKeyMap.put(Direction.EAST, KeyEvent.VK_RIGHT);

      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      for (Direction dir : Direction.values()) {
         int keyCode = dirToKeyMap.get(dir);
         boolean keyReleased = false; // key pressed
         KeyStroke pressedKeyStroke = KeyStroke.getKeyStroke(keyCode, 0, keyReleased);
         inputMap.put(pressedKeyStroke, pressedKeyStroke.toString());
         actionMap.put(pressedKeyStroke.toString(), new KeyBindingAction(dir, keyReleased));

         keyReleased = true; // key released
         KeyStroke releasedKeyStroke = KeyStroke.getKeyStroke(keyCode, 0, keyReleased);
         inputMap.put(releasedKeyStroke, releasedKeyStroke.toString());
         actionMap.put(releasedKeyStroke.toString(), new KeyBindingAction(dir, keyReleased));
      }

   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(prefW, prefH);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      for (Direction direction : dirShapeMap.keySet()) {
         Color color = (activeDir == direction) ? direction.getActiveColor() : direction.getPassiveColor();
         g2.setColor(color);
         g2.fill(dirShapeMap.get(direction));
      }
   }

   private class KeyBindingAction extends AbstractAction {
      private Direction dir;
      private boolean keyReleased;

      public KeyBindingAction(Direction dir, boolean keyReleased) {
         this.dir = dir;
         this.keyReleased = keyReleased;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         // TODO: action depending on direction and if key is pressed or released
      }
   }

   private class TurnOffListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         activeDir = null;
         repaint();
      }
   }

   private class DisplayColorTimerListener implements ActionListener {
      private List<Direction> directionList;
      private int counter = 0;
      private Timer turnOffTimer;

      public DisplayColorTimerListener(List<Direction> directionList) {
         this.directionList = directionList;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         Timer timer = (Timer) e.getSource();
         if (counter == directionList.size()) {
            activeDir = null;
            timer.stop();
         } else {
            activeDir = directionList.get(counter);
            counter++;

            // so there's a time gap in the display, so that same colors will 
            // be distinct
            int turnOffDelay = (3 * timer.getDelay()) / 4; // turn off 3/4 time into display
            turnOffTimer = new Timer(turnOffDelay, new TurnOffListener());
            turnOffTimer.setRepeats(false);
            turnOffTimer.start();
         }
         repaint();         
      }
   }
}

enum Direction {
   NORTH(Color.blue),
   WEST(Color.yellow),
   SOUTH(Color.red),
   EAST(Color.green);

   private Color color;

   private Direction(Color color) {
      this.color = color;
   }

   public Color getColor() {
      return color;
   }

   public Color getPassiveColor() {
      return color.darker();
   }

   public Color getActiveColor() {
      return color.brighter();
   }

}

Upvotes: 5

Related Questions