最近,在 Stack Overflow 的一些人的帮助下(我非常感谢他们),我完成了自己的 Java 游戏 Tron 重制。但是,发生了一些事情,现在游戏不会结束,因为我为测试玩家是否交叉路径而制作的列表在路径交叉时没有返回 x 和 y 坐标。这是代码(问题区域已评论):
package tron;
import javax.swing.*;
import java.util.Random;
import java.awt.Graphics2D;
import java.awt.*;
import java.awt.BasicStroke;
import java.awt.event.*;
import java.awt.geom.Path2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
public class Tron extends JPanel{
private static Point player = new Point(40, 40);
private static Point lastTurn = new Point(player);
private static Point cpu = new Point(360, 330);
private static Point cpuTurn = new Point(cpu);
static int timer = 0;
static Point RANGE = new Point(400, 400);
public static int size = 1;
public static int move = 1;
public static int dir = 1;
public static int cpu_dir = 2;
public static Path2D path;
public static Path2D path2;
public Random random = new Random();
public Random random2 = new Random();
static List playerlist = new ArrayList();
static List cpulist = new ArrayList();
static final Tron m = new Tron();
static final JFrame frame = new JFrame("1P Tron");
public static void main(String[] args){
frame.setSize(RANGE.x,RANGE.y);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(m);
m.setBackground(Color.black);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
path = new Path2D.Float();
path2 = new Path2D.Float();
path.moveTo(player.x, player.y);
path2.moveTo(cpu.x, cpu.y);
Action actionRight = new AbstractAction(){
public void actionPerformed(ActionEvent actionRightEvent){
dir = 1;
lastTurn = new Point(player);
};
};
Action actionLeft = new AbstractAction(){
public void actionPerformed(ActionEvent actionLeftEvent){
dir = 2;
lastTurn = new Point(player);
};
};
Action actionUp = new AbstractAction(){
public void actionPerformed(ActionEvent actionUpEvent){
dir = 3;
lastTurn = new Point(player);
};
};
Action actionDown = new AbstractAction(){
public void actionPerformed(ActionEvent actionDownEvent){
dir = 4;
lastTurn = new Point(player);
};
};
KeyStroke right = KeyStroke.getKeyStroke("RIGHT");
KeyStroke left = KeyStroke.getKeyStroke("LEFT");
KeyStroke up = KeyStroke.getKeyStroke("UP");
KeyStroke down = KeyStroke.getKeyStroke("DOWN");
InputMap inputMap = m.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(right, "RIGHT");
inputMap.put(left, "LEFT");
inputMap.put(up, "UP");
inputMap.put(down, "DOWN");
m.getActionMap().put("RIGHT", actionRight);
m.getActionMap().put("LEFT", actionLeft);
m.getActionMap().put("UP", actionUp);
m.getActionMap().put("DOWN", actionDown);
}
public void endGame(){ //problems with "if, else if" statements
Component temporaryLostComponent = null;
if(cpulist.contains(player)){
dir = 0;
JOptionPane.showMessageDialog(temporaryLostComponent, "You Lose");
WindowEvent close = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
}else if(playerlist.contains(cpu)){
dir = 0;
JOptionPane.showMessageDialog(temporaryLostComponent, "You Win!");
WindowEvent close = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
}else if(player.x == cpu.x && player.y == cpu.y){
dir = 0;
JOptionPane.showMessageDialog(temporaryLostComponent, "Game Over");
WindowEvent close = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(close);
}
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
draw(g);
try{
p1_move(m);
cpu_move();
}catch(InterruptedException jk){
Component temporaryLostComponent = null;
JOptionPane.showMessageDialog(temporaryLostComponent, "Timer exception, Thread.sleep()");
}
}
@SuppressWarnings("unchecked")
public void p1_move(Tron m) throws InterruptedException{
if(dir == 1){
if(player.x > 390){
player.x = -5;
path.moveTo(0, player.y);
};
Thread.sleep(27);
player.x += 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}else if(dir == 2){
if(player.x < 0){
player.x = 395;
path.moveTo(400, player.y);
};
Thread.sleep(27);
player.x -= 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}else if(dir == 3){
if(player.y < 0){
player.y = 370;
path.moveTo(player.x, 400);
};
Thread.sleep(27);
player.y -= 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}else if(dir == 4){
if(player.y > 369){
player.y = 0;
path.moveTo(player.x, 0);
};
Thread.sleep(27);
player.y += 5;
playerlist.add(player);
path.lineTo(player.x, player.y);
path.moveTo(player.x, player.y);
m.repaint();
endGame();
}
}
@SuppressWarnings("unchecked")
public void cpu_move() throws InterruptedException{
if(cpu_dir == 1){
if(cpu.x > 390){
cpu.x = -5;
path2.moveTo(0, cpu.y);
};
cpu.x += 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else if(cpu_dir == 2){
if(cpu.x < 0){
cpu.x = 395;
path2.moveTo(400, cpu.y);
};
cpu.x -= 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else if(cpu_dir == 3){
if(cpu.y < 0){
cpu.y = 370;
path2.moveTo(cpu.x, 400);
};
cpu.y -= 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else if(cpu_dir == 4){
if(cpu.y > 369){
cpu.y = 0;
path2.moveTo(cpu.x, 0);
};
cpu.y += 5;
cpulist.add(cpu);
path2.lineTo(cpu.x, cpu.y);
path2.moveTo(cpu.x, cpu.y);
timer += 1;
}else{
cpu_dir = random.nextInt(4) + 1;
};
if(timer == ((cpu_dir * 4) + 25)){
if(cpu_dir == 1){
cpu_dir = random.nextInt(2) + 3;
cpuTurn = new Point(cpu);
timer = 0;
}else if(cpu_dir == 2){
cpu_dir = random.nextInt(2) + 3;
cpuTurn = new Point(cpu);
timer = 0;
}else if(cpu_dir == 3){
cpu_dir = random.nextInt(2) + 1;
cpuTurn = new Point(cpu);
timer = 0;
}else if(cpu_dir == 4){
cpu_dir = random.nextInt(2) + 1;
cpuTurn = new Point(cpu);
timer = 0;
}else{
cpu_dir = random.nextInt(4) + 1;
cpuTurn = new Point(cpu);
timer = 0;
};
}
}
public void draw(Graphics g){
Graphics2D g2 = (Graphics2D) g.create();
g.setColor(Color.BLUE);
g.fillRect(player.x, player.y, size, size);
g2.setColor(Color.BLUE);
g2.setStroke(new BasicStroke(5));
g2.draw(path);
g2.draw(new Line2D.Float(lastTurn, player));
g.setColor(Color.ORANGE);
g.fillRect(cpu.x, cpu.y, size, size);
g2.setColor(Color.ORANGE);
g2.draw(path2);
g2.draw(new Line2D.Float(cpuTurn, cpu));
}
}
我根据您的建议和其他人对我的代码进行了一些(好的,很多)更改:
//package Tron.Stable;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Tron {
public static void main(String[] args) {
new Tron();
}
public Tron() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Tron");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
private int cpu_xVelocity;
private int cpu_yVelocity;
private int xVelocity;
private int yVelocity;
protected static int CPU_DIR = 1;
protected static final int PLAYER_SIZE = 0;
protected static final int DELTA = 4;
protected static int CPU_DELTA = -4;
public static int timer = 0;
private Point player;
private Point cpu;
private Point lastTurn;
private Point cpuTurn;
private Path2D playerPath;
private Path2D cpuPath;
private final Random random = new Random();
static CpuVelocityAction cpu_Vel;
public TestPane(){
setBackground(Color.BLACK);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");
am.put("left", new VelocityAction(-DELTA, 0));
am.put("right", new VelocityAction(DELTA, 0));
am.put("up", new VelocityAction(0, -DELTA));
am.put("down", new VelocityAction(0, DELTA));
cpu_xVelocity = CPU_DELTA;
xVelocity = DELTA;
player = new Point(40, 40);
cpu = new Point(360, 360);
lastTurn = new Point(player);
cpuTurn = new Point(cpu);
playerPath = new Path2D.Float();
cpuPath = new Path2D.Float();
playerPath.moveTo(40, 40);
cpuPath.moveTo(360, 360);
Timer playerTimer = new Timer(20, new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
player.x += xVelocity;
if (player.x > getWidth()){
playerPath.lineTo(getWidth(), player.y);
playerPath.moveTo(0, player.y);
player.x = 0;
lastTurn = new Point(player);
}
if (player.x + PLAYER_SIZE < 0){
playerPath.lineTo(0, player.y);
playerPath.moveTo(getWidth() - 1, player.y);
player.x = getWidth() - 1;
lastTurn = new Point(player);
}
player.y += yVelocity;
if (player.y > getHeight()){
playerPath.lineTo(player.x, getHeight());
playerPath.moveTo(player.x, 0);
player.y = 0;
lastTurn = new Point(player);
}
if (player.y + PLAYER_SIZE < 0){
playerPath.lineTo(player.x, 0);
playerPath.moveTo(player.x, getHeight() - 1);
player.y = getHeight() - 1;
lastTurn = new Point(player);
}
if(CPU_DIR == 1){
cpu_Vel = new CpuVelocityAction(CPU_DELTA, 0);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
}else if(CPU_DIR == 2){
cpu_Vel = new CpuVelocityAction(-CPU_DELTA, 0);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
}else if(CPU_DIR == 3){
cpu_Vel = new CpuVelocityAction(0, CPU_DELTA);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
}else if(CPU_DIR == 4){
cpu_Vel = new CpuVelocityAction(0, -CPU_DELTA);
cpu_xVelocity = cpu_Vel.cpu_xDelta;
cpu_yVelocity = cpu_Vel.cpu_yDelta;
};
if(timer == (CPU_DIR + 25)){
if((CPU_DIR == 1) | (CPU_DIR == 2)){
CPU_DIR = ((random.nextInt(2)) + 3);
}else if((CPU_DIR == 3) | (CPU_DIR == 4)){
CPU_DIR = ((random.nextInt(2)) + 1);
}
};
timer += 1;
cpu.x += cpu_xVelocity;
if (cpu.x > getWidth()){
cpuPath.lineTo(getWidth(), cpu.y);
cpuPath.moveTo(0, cpu.y);
cpu.x = 0;
cpuTurn = new Point(cpu);
}
if (cpu.x + PLAYER_SIZE < 0){
cpuPath.lineTo(0, cpu.y);
cpuPath.moveTo(getWidth() - 1, cpu.y);
cpu.x = getWidth() - 1;
cpuTurn = new Point(cpu);
}
cpu.y += cpu_yVelocity;
if (cpu.y > getHeight()){
cpuPath.lineTo(cpu.x, getHeight());
cpuPath.moveTo(cpu.x, 0);
cpu.y = 0;
cpuTurn = new Point(cpu);
}
if (cpu.y + PLAYER_SIZE < 0){
cpuPath.lineTo(cpu.x, 0);
cpuPath.moveTo(cpu.x, getHeight() - 1);
cpu.y = getHeight() - 1;
cpuTurn = new Point(cpu);
}
repaint();
}
});
playerTimer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setStroke(new BasicStroke(6));
g2d.setColor(Color.BLUE);
g2d.draw(playerPath);
g2d.draw(new Line2D.Float(lastTurn, player));
g2d.drawRect(player.x - (PLAYER_SIZE / 2), player.y - (PLAYER_SIZE / 2), PLAYER_SIZE, PLAYER_SIZE);
g2d.setColor(Color.ORANGE);
g2d.draw(cpuPath);
g2d.draw(new Line2D.Float(cpuTurn, cpu));
g2d.drawRect(cpu.x - (PLAYER_SIZE / 2), cpu.y - (PLAYER_SIZE / 2), PLAYER_SIZE, PLAYER_SIZE);
}
public class VelocityAction extends AbstractAction{
private final int xDelta;
private final int yDelta;
public VelocityAction(int xDelta, int yDelta){
this.xDelta = xDelta;
this.yDelta = yDelta;
};
@Override
public void actionPerformed(ActionEvent e){
xVelocity = xDelta;
yVelocity = yDelta;
lastTurn = new Point(player);
playerPath.lineTo(player.x, player.y);
}
}
public class CpuVelocityAction extends AbstractAction{
private final int cpu_xDelta;
private final int cpu_yDelta;
public CpuVelocityAction(int cpu_xDelta, int cpu_yDelta){
this.cpu_xDelta = cpu_xDelta;
this.cpu_yDelta = cpu_yDelta;
};
@Override
public void actionPerformed(ActionEvent e){
cpu_xVelocity = cpu_xDelta;
cpu_yVelocity = cpu_yDelta;
cpuTurn = new Point(cpu);
cpuPath.lineTo(cpu.x, cpu.y);
}
}
}
}
虽然我还没有实现一个系统来测试与对手线的碰撞,但我最初的问题是,我在将我的 cpu 播放器转换为使用挥杆计时器时遇到了很多问题(我讨厌使用那些,顺便说一句,这就是为什么我试图Thread.sleep()
在我的原始代码中工作)。基本上,cpu只是不工作。它要么完全吓坏了,到处都是这些对角线,要么只是保持直线前进并且从不转弯。我几乎可以肯定,这与我为使 cpu 决定如何转动而放置的随机数生成器无关,那么在写这篇文章时我还搞砸了什么?谢谢您的帮助。