我的问题是" Game Over"图形显示在游戏开始时,但我希望它只显示蛇何时进入自身。
这是我到目前为止所做的:
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferStrategy;
import java.util.*;
import javax.swing.JFrame;
public class Snake extends JFrame implements KeyListener {
private static final long serialVersionUID = 1L;
private boolean gameOver;
private int windowWidth = 800;
private int windowHeight = 600;
private LinkedList<Point> snake;
private int dx;
private int dy;
private Random generator = new Random();
private Point food;
private int points;
public static void main(String[] args) {
new Snake();
}
public Snake() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(windowWidth, windowHeight);
this.setResizable(false);
this.setLocation(100, 100);
this.setVisible(true);
this.createBufferStrategy(2);
this.addKeyListener(this);
initGame();
while(true) {
long start = System.currentTimeMillis();
gameLoop();
while(System.currentTimeMillis()-start < 40) {
//do nothing
}
}
}
private void initGame() {
// game variables initialized here
snake = new LinkedList<Point>();
snake.addFirst(new Point(20,20));
growSnake(5);
dx = 0;
dy = 0;
food = new Point(10,10);
points = 0;
}
private void gameLoop() {
// game logic
// move the snake
moveSnake(dx, dy);
// check if snake has eaten food
if(snake.getFirst().equals(food)) {
moveFood();
growSnake(3);
points++;
}
// go through walls
if (snake.getFirst().x <= 0){
snake.getFirst().x = windowWidth/10;//go left, wrap right
}
else if (snake.getFirst().x >= windowWidth/10){
snake.getFirst().x = 0;//go right, wrap left
}
else if (snake.getFirst().y <= 0){
snake.getFirst().y = windowHeight/10;//go top, wrap bottom
}
else if (snake.getFirst().y >= windowHeight/10){
snake.getFirst().y = 0;//go bottom, wrap top
}
// check if the snake has hit itself
for(int n = 1; n < snake.size(); n++) {
if(snake.getFirst().equals(snake.get(n))) {
initGame();
gameOver = true;
}
}
drawFrame();
}
private void drawFrame() {
// code for drawing
BufferStrategy bf = this.getBufferStrategy();
Graphics g = null;
try {
g = bf.getDrawGraphics();
// clear the back buffer (just draw a big black rectangle over it)
g.setColor(Color.BLACK);
g.fillRect(0, 0, windowWidth, windowHeight);
drawSnake(g);
drawFood(g);
drawPoints(g);
if (gameOver == true){
gameEnd(g);
}
} finally {
g.dispose();
}
// Shows the contents of the backbuffer on the screen.
bf.show();
//Tell the System to do the Drawing now, otherwise it can take a few extra ms until
//Drawing is done which looks very jerky
Toolkit.getDefaultToolkit().sync();
}
private void drawSnake (Graphics g) {
for(int n = 0; n < snake.size(); n++) {
g.setColor(Color.RED);
Point p = snake.get(n);
g.fillOval(p.x*10, p.y*10, 10, 10);
}
}
private void moveSnake(int dx, int dy) {
for(int n = snake.size()-1; n >= 1; n--) {
snake.get(n).setLocation(snake.get(n-1));
}
snake.getFirst().x += dx;
snake.getFirst().y += dy;
}
private void growSnake (int n) {
while(n > 0) {
snake.add(new Point(snake.getLast()));
n--;
}
}
private void moveFood() {
food.x = generator.nextInt((windowWidth/10)-4)+2;
food.y = generator.nextInt((windowHeight/10)-5)+3;
}
private void drawFood(Graphics g) {
g.setColor(Color.BLUE);
g.fillOval(food.x*10, food.y*10, 10, 10);
}
private void drawPoints(Graphics g) {
g.setColor(Color.GRAY);
g.drawString("points: " + points, 10, 40);
}
private static final Font FONT_LARGE = new Font("Times New Roman", Font.BOLD, 40);
private void gameEnd(Graphics g){
if (gameOver == true){
g.setColor(Color.RED);
g.setFont(FONT_LARGE);
g.drawString("Game Over",300, 320);
}
}
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == 37) {//left
dx = -1;
dy = 0;
} else if(key == 38) {//up
dx = 0;
dy = -1;
} else if(key == 39) {//right
dx = 1;
dy = 0;
} else if(key == 40) {//down
dx = 0;
dy = 1;
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
}
有什么想法吗?
答案 0 :(得分:2)
我看到几个问题:
getGraphics()
获得的Graphics对象来绘制GUI。此Graphics对象将不会持久存在,这可能会导致绘图不一致。protected void paintComponent(Graphics g)
覆盖方法进行绘制。我相信更多会来......
答案 1 :(得分:2)
private void growSnake (int n) {
while(n > 0) {
snake.add(new Point(snake.getLast()));
n--;
}
}
因为在开始时蛇的唯一元素是Point(20,20)
snake.add(new Point(snake.getLast()));
创建一条仅包含相同点的蛇。所以
growSnake(5);
在initGame()内创建5个与头部相同的点。
然后,在
private void moveSnake(int dx, int dy) {
for(int n = snake.size()-1; n >= 1; n--) {
snake.get(n).setLocation(snake.get(n-1));
}
snake.getFirst().x += dx;
snake.getFirst().y += dy;
}
分别用dx和dy改变X和Y的值。问题是,它们的初始值都是0,因此蛇的头部不会移动。只有按下
键后才能更改dx和dy值public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == 37) {//left
dx = -1;
dy = 0;
// and so on
所以,总而言之 - 将dx或dy的默认值更改为1,这样蛇就会从游戏开始时移动。
还有一件事。你可以“向后移动”你的蛇 - 如果你的蛇向右移动并按下左键 - 你的蛇将会自己吃掉它的头部 - 游戏结束。
答案 2 :(得分:1)
因为在新游戏的第一次运动中,蛇的“头部”位置与身体的位置相同。所以......这个:
if(snake.getFirst().equals(snake.get(n)))
应该是:
if(snake.getFirst().equals(snake.get(n)) && snake.size() > 6)
这样,只有在蛇开始移动时才会验证条件(考虑初始大小为5)。