我正在制作Simon说的游戏。我遇到的一个问题是,在第一级之后,我的颜色不会改变/亮起。我跟踪代码并包含print语句以确保代码也正常工作。
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));
}
}
答案 0 :(得分:5)
看起来你正在尝试将Swing GUI编写为线性控制台程序,我很惊讶它的工作原理。如果您不介意,请让我提供一些建议:
super.paint(g)
方法,所以如果你的程序发展得很难调试绘画问题和工件,那就不会让我感到惊讶,因为你在一个非常关键的时刻打破了绘画链。Thread.sleep(...)
,因为如果您不了解Swing线程规则并注意,则可能会使整个GUI处于睡眠状态。相反,如果您需要延时,请使用Swing Timer。只是玩一些代码。没有完全解决方案......
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();
}
}