JAVA贪吃蛇游戏2.0版本
程序员文章站
2023-12-23 19:51:27
...
package com.test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Random;
public class SnakeGameFrame {
public static void main(String[] args){
new SnakeGameFrame();
}
public SnakeGameFrame(){
Frame app=new Frame("贪吃蛇");
app.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
app.setLocation(100,100);
GamePanel drawB=new GamePanel();
app.add(drawB,BorderLayout.CENTER);
app.pack();
app.setResizable(false);
app.setVisible(true);
drawB.gameStart();
}
}
class Food{
public Point location;
public Point size;
private GamePanel gameP;
private Snake snk;
private Random rand;
public Food(GamePanel gp,Snake sk){
gameP=gp;
snk=sk;
rand=new Random();
location=new Point(Math.abs(rand.nextInt()%gameP.width),Math.abs(rand.nextInt()%gameP.height));
size=new Point(sk.diameter,sk.diameter);
}
public void update() {
if ((Math.abs((snk.x + snk.diameter / 2) - (location.x + size.x / 2)) < snk.diameter) &&
(Math.abs((snk.y + snk.diameter / 2) - (location.y + size.y / 2)) < snk.diameter)) {
location = new Point(Math.abs(rand.nextInt() % gameP.width), Math.abs(rand.nextInt() % gameP.height));
if (snk.length < Snake.MAXLENGTH) {
snk.length++;
}
}
}
public void draw(Graphics g){
g.setColor(Color.black);
g.fillRect(location.x, location.y, size.x, size.y);
}
}
class Snake{
GamePanel gamePanel;
private Point[] body;
public static final int MAXLENGTH=20;
private int head;
private int tail;
public int length;
private int speed;
public int x;
public int y;
public int diameter;
public Snake(GamePanel gp){
gamePanel=gp;
body=new Point[MAXLENGTH];
head=-1;
tail=-1;
length=1;
speed=10;
diameter=10;
}
public void update() {
int direction=gamePanel.getDirection();
switch (direction) {
case GamePanel.SOUTH:
y += speed;
break;
case GamePanel.NORTH:
y -= speed;
break;
case GamePanel.EAST:
x += speed;
break;
case GamePanel.WEST:
x -= speed;
break;
}
if (x > gamePanel.width) {
x = -diameter;
}
if (y > gamePanel.height) {
y = -diameter;
}
if (x < -diameter) {
x = gamePanel.width;
}
if (y < -diameter) {
y = gamePanel.height;
}
head = (head + 1) % body.length;
tail = (head + body.length - length + 1) % body.length;
body[head] = new Point(x, y);
}
public void draw(Graphics g) {
g.setColor(Color.blue);
if (length > 1) {
int i = tail;
while (i != head) {
g.fillOval(body[i].x, body[i].y, diameter, diameter);
i = (i + 1) % body.length;
}
}
g.setColor(Color.red);
g.fillOval(body[head].x, body[head].y, diameter, diameter);
}
}
class GamePanel extends Panel implements Runnable,KeyListener{
private static final long serialVersionUID = 1L;
public int width;
public int height;
public int incre=1;
private Image im;
private Graphics dbg;
private Thread gamethread;
private static final int FPS=30;
private boolean running=false;
private boolean isPaused=false;
private int direction;
public static final int NORTH=0;
public static final int SOUTH=1;
public static final int WEST=2;
public static final int EAST=3;
private Snake sk;
private Food fd;
public GamePanel(){
width=300;
height=300;
setPreferredSize(new Dimension(width,height));
sk=new Snake(this);
fd=new Food(this,sk);
setFocusable(true);
requestFocus();
addKeyListener(this);
}
public void gameStart() {
if (!running) {
gamethread = new Thread(this);
gamethread.start();
}
}
public void gameStop() {
running = false;
}
public void gamePaint() {
Graphics g;
try {
g = this.getGraphics();
if (g != null && im != null) {
g.drawImage(im, 0, 0, null);
}
g.dispose();
} catch (Exception e) {
}
}
public void gameRender() {
if (im == null) {
im = createImage(width, height);
if (im == null) {
System.out.println("im is null");
} else {
dbg = im.getGraphics();
}
}
dbg.setColor(Color.white);
dbg.fillRect(0, 0, width, height);
sk.draw(dbg);
fd.draw(dbg);
// line.draw(dbg);
}
public void gameUpdate() {
if (!isPaused) {
sk.update();
fd.update();
}
}
public void run() {
long t1,t2,dt,sleepTime;
long period=1000/FPS; //计算每一次循环需要的执行时间,单位毫秒
t1=System.nanoTime(); //保存游戏循环执行前的系统时间,单位纳秒
while(true){
gameUpdate();
gameRender();
gamePaint();
t2= System.nanoTime() ; //游戏循环执行后的系统时间,单位纳秒
dt=(t2-t1)/1000000L; //本次循环实际花费的时间,并转换为毫秒
sleepTime = period - dt;//计算本次循环剩余的时间,单位毫秒
if(sleepTime<=0) //防止sleepTime值为负数
sleepTime=2;
try {
Thread.sleep(sleepTime); //让线程休眠,由sleepTime值决定
} catch (InterruptedException ex) { }
t1 = System.nanoTime(); //重新获取当前系统时间
}
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
if (keycode == KeyEvent.VK_P) {
isPaused = !isPaused;
System.out.println("key is P");
}
if (!isPaused ) {
switch (keycode) {
case KeyEvent.VK_DOWN:
direction = SOUTH;
System.out.println("key is down" + direction);
break;
case KeyEvent.VK_UP:
direction = NORTH;
System.out.println("key is up" + direction);
break;
case KeyEvent.VK_RIGHT:
direction = EAST;
System.out.println("key is right" + direction);
break;
case KeyEvent.VK_LEFT:
direction = WEST;
System.out.println("key is left" + direction);
break;
}
}
}
public void keyReleased(KeyEvent e) {
}
public int getDirection() {
return direction;
}
}