目录
一、StartFrame 主类编写( main方法所在的类),
二、MyData 数据文件类编写(项目所需要用到的图片等其他的一些资源)
项目结构:
一、StartFrame 主类编写( main方法所在的类),
package com.sfy.greedySnake;
import javax.swing.*;
import java.awt.*;
//游戏开始窗口
public class StartFrame extends JFrame {
public static void main(String[] args) {
new StartFrame("贪吃蛇游戏");
}
public StartFrame(String title){
super(title);
this.setBounds(100,100,900,700);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
Container container = this.getContentPane();
container.setBackground(Color.WHITE);
GamePanel gamePanel = new GamePanel(); //实例化游戏面板
container.add(gamePanel);
}
}
二、MyData 数据文件类编写(项目所需要用到的图片等其他的一些资源)
package com.sfy.greedySnake;
import javax.swing.*;
import java.net.URL;
//图片数据
public class MyData {
//广告栏header
private static final URL HEADER = MyData.class.getResource("./static/header.jpg");
public static Icon header = new ImageIcon(HEADER);
//头
private static final URL UP = MyData.class.getResource("./static/up.png");
public static Icon up = new ImageIcon(UP);
private static final URL DOWN = MyData.class.getResource("./static/down.png");
public static Icon down = new ImageIcon(DOWN);
private static final URL LEFT = MyData.class.getResource("./static/left.png");
public static Icon left = new ImageIcon(LEFT);
private static final URL RIGHT = MyData.class.getResource("./static/right.png");
public static Icon right = new ImageIcon(RIGHT);
//身体
private static final URL BODY = MyData.class.getResource("./static/body.png");
public static Icon body = new ImageIcon(BODY);
//食物
private static final URL FOOD = MyData.class.getResource("./static/food.png");
public static Icon food = new ImageIcon(FOOD);
private MyData() {
}
}
三、GamePanel 游戏面板类编写
package com.sfy.greedySnake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
//游戏面板
public class GamePanel extends JPanel implements KeyListener, ActionListener {
private int length; //蛇长度
private int score; //分数
//蛇坐标
private int[] snakeX = new int[600]; //小蛇X轴
private int[] snakeY = new int[400]; //小蛇Y轴
//食物坐标
private int foodX; //食物X轴坐标
private int foodY; //食物Y轴坐标
Random random = new Random();//随机数类
//游戏状态
private boolean isStart; //是否开始
private boolean isFail; //是否失败
private String direction; //蛇头方向
Timer timer = new Timer(100,this); //计时器
public GamePanel() {
this.setFocusable(true); //获取焦点
this.addKeyListener(this);
timer.start(); //启动计时器
init(); //调用初始化方法
}
//面板初始化
public void init(){
length = 3; //初始化蛇长度
score = 0; //初始化分数
//游戏状态初始化
isStart = false; //true 开始 false 停止
isFail = false; //true 失败 false 未失败
direction = "R"; //初始化蛇头方向 R右
//初始化蛇坐标
snakeX[0] = 100; snakeY[0] = 125;
snakeX[1] = 75; snakeY[1] = 125;
snakeX[2] = 50; snakeY[2] = 125;
//初始化食物food坐标
foodX = 25 + 25 * random.nextInt(34);
foodY = 100 + 25 * random.nextInt(22);
}
//画图
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//画广告栏 header
MyData.header.paintIcon(this,g,25,25);
//画背景
g.fillRect(25,100,850,550);
//画头
switch (direction){
case "U": MyData.up.paintIcon(this,g,snakeX[0],snakeY[0]); break;
case "D": MyData.down.paintIcon(this,g,snakeX[0],snakeY[0]); break;
case "L": MyData.left.paintIcon(this,g,snakeX[0],snakeY[0]); break;
case "R": MyData.right.paintIcon(this,g,snakeX[0],snakeY[0]); break;
}
//画身体
for (int i = 1; i < length; i++) {
MyData.body.paintIcon(this,g,snakeX[i],snakeY[i]);
}
//画暂停文字
if(!isStart && !isFail){
g.setColor(Color.WHITE);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("点击空格开始游戏",300,300);
}
//画失败文字
if(isFail){
g.setColor(Color.RED);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("游戏失败!点击空格重新开始",180,300);
g.setFont(new Font("微软雅黑", Font.BOLD,35));
g.setColor(Color.GREEN);
g.drawString("最终长度:" + length,340,370);
g.drawString("最终得分:" + score,340,420);
}
//画食物food
MyData.food.paintIcon(this,g,foodX,foodY);
//画分数和长度
g.setFont(new Font("微软雅黑",Font.BOLD,16));
g.setColor(Color.WHITE);
g.drawString("长度:" + length,780,47); //长度
g.drawString("分数:" + score,780,67); //分数
repaint(); //重绘
}
//键盘按下监听事件
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
if(isFail){
init(); //初始化 重新开始
}else{
isStart = !isStart; //暂停
}
}
//监听方向键上下左右
if(isStart){
switch (e.getKeyCode()){
case KeyEvent.VK_UP: direction="U"; break;
case KeyEvent.VK_DOWN: direction="D"; break;
case KeyEvent.VK_LEFT: direction="L"; break;
case KeyEvent.VK_RIGHT: direction="R"; break;
}
}
repaint(); //重绘
}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyReleased(KeyEvent e) {}
//动作监听
@Override
public void actionPerformed(ActionEvent e) {
if(isStart && !isFail){
//小蛇移动
for (int i = length-1; i > 0; i--) {
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
//蛇头移动方向
switch (direction){
case "U": snakeY[0]=snakeY[0]-25; if(snakeY[0]<100){snakeY[0]=625;} break;
case "D": snakeY[0]=snakeY[0]+25; if(snakeY[0]>625){snakeY[0]=100;} break;
case "L": snakeX[0]=snakeX[0]-25; if(snakeX[0]<25){snakeX[0]=850;} break;
case "R": snakeX[0]=snakeX[0]+25; if(snakeX[0]>850){snakeX[0]=25;} break;
}
//断定失败
for (int i = 1; i < length; i++) {
if(snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i]){ //头和身体重合
isFail = true; //失败
}
}
//吃食物监听
if(snakeX[0]==foodX && snakeY[0]==foodY){
/**
* 注意:此处长度+1会出现左上角身体闪烁问题,目前原因不明!
*/
length++; //长度+1
score+=10; //分数+10
//重新生成食物坐标
foodX = 25 + 25 * random.nextInt(34);
foodY = 100 + 25 * random.nextInt(22);
}
}
}
}