总体说一下,该游戏的制作一共涉及到3个类,分别为StartGame,GamePanel和Data,一个存放图片的statics文件夹。
1.创建小游戏主类StartGame
该类用于定义游戏外部大窗口,这里默认的绝对定位,因此窗口大小为静态定义,不能进行放大缩小,同时该类是游戏的入口。
import javax.swing.*;
//游戏的主启动类
public class StartGame {
public static void main(String[] args) {
JFrame frame = new JFrame("贪吃蛇小游戏");
frame.setBounds(10,10,925,800);
frame.setResizable(false); //窗口大小不可以改变
frame.add(new GamePanel());
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
2. 游戏主要模块
其中包含了数据的定义,画笔的绘画,键盘监听以及事件监听,实现该游戏的功能。
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 {
//定义蛇的数据结构
//定义小蛇的长度,头的方向,所在坐标X,Y轴的坐标,游戏的状态
int length;
String direction;
int[] snakeX = new int[100]; //坐标为 25 * 25
int[] snakeY = new int[100]; //坐标为 25 * 25
boolean isState ;
Timer timer = new Timer(100,this); //创建定时器
//定义食物坐标
int foodX;
int foodY;
//创建一个随机数
Random random = new Random();
//定义控制游戏失败的变量
boolean isFail;
//定义分数
int score;
//构造器
public GamePanel() {
init();
//获得焦点和键盘事件
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
this.addKeyListener(this); //获取键盘监听事件
this.setFocusable(true); //获取焦点事件
timer.start(); //开启定时器
}
//初始化小蛇
private void init(){
length = 3;
snakeX[0] = 100; snakeY[0] = 150 ;
snakeX[1] = 75; snakeY[1] = 150;
snakeX[2] = 50; snakeY[2] = 150;
isState = false;
direction = "right";
foodX = 25 + 25 * random.nextInt(34);
foodY = 125 + 25 * random.nextInt(24);
isFail = false;
score = 0;
}
//绘制面板, 我们游戏中的所有东西,都是用这个画笔来画
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //清屏
this.setBackground(Color.WHITE);
//绘制静态面板
Data.header.paintIcon(this,g,25,11);
g.fillRect(25,125,850,600);
//绘制分数
g.setColor(Color.BLACK);
g.setFont(new Font("微软雅黑",Font.BOLD,18));
g.drawString("长度"+length,750,50);
g.drawString("分数"+score,750,80);
//绘制食物
Data.food.paintIcon(this,g,foodX,foodY);
//绘制小蛇
//判断小蛇的方向
if(direction.equals("up")){
Data.up.paintIcon(this,g,snakeX[0],snakeY[0]);
}else if(direction.equals("right")){
Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);
}else if(direction.equals("down")){
Data.down.paintIcon(this,g,snakeX[0],snakeY[0]);
}else{
Data.left.paintIcon(this,g,snakeX[0],snakeY[0]);
}
//通过循环遍历出小蛇的身体长度
for(int i = 1; i<length; i++){
Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);
}
//设置游戏状态为停止时候的字体样式
if(isState == false){
g.setColor(Color.WHITE);
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.drawString("游戏已停止,点击开始",250,400);
}
if(isFail) {
g.setFont(new Font("微软雅黑",Font.BOLD,40));
g.setColor(Color.RED);
g.drawString("失败,游戏已经停止",250,400);
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_SPACE){
if(isFail){
//重新开始
init();
repaint();
} else{
isState = !isState;
repaint();
}
}
//控制小蛇方向
if(keyCode == KeyEvent.VK_UP){
direction = "up";
}else if(keyCode == KeyEvent.VK_RIGHT){
direction = "right";
}else if(keyCode == KeyEvent.VK_DOWN){
direction = "down";
}else if(keyCode == KeyEvent.VK_LEFT){
direction = "left";
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (isState && !isFail) { //游戏开始状态
//右移(后一节变到前一节的位置)
for (int i = length - 1; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
// 移动
if (direction.equals("up")) {
snakeY[0] -= 25;
if (snakeY[0] < 125) { snakeY[0] = 700; } //边界判断
} else if (direction.equals("right")) {
snakeX[0] += 25;
if (snakeX[0] > 850) { snakeX[0] = 25; } //边界判断
} else if (direction.equals("down")) {
snakeY[0] += 25;
if (snakeY[0] > 700) { snakeY[0] = 125; } //边界判断
} else if (direction.equals("left")) {
snakeX[0] -= 25;
if (snakeX[0] < 25) { snakeX[0] = 850; } //边界判断
}
repaint();
}
//小蛇吃食物边长
if(snakeX[0] == foodX && snakeY[0] == foodY){
length++;
score+= 10;
//重写生成食物
foodX = 25 + 25 * random.nextInt(34);
foodY = 125 + 25 * random.nextInt(24);
}
timer.start();
//游戏是否失败
for(int i = length; i>0;i--){
if(snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i]){
isFail = true;
}
}
}
@Override
public void keyReleased(KeyEvent e) {
}
}
3. Data类(数据集类)
用于收集我们小蛇的图片数据。
import javax.swing.*;
import java.net.URL;
public class Data {
//收集小蛇以及食物的信息
public static URL bodyUrl = Data.class.getResource("statics/body.png");
public static URL upUrl = Data.class.getResource("statics/up.png");
public static URL rightUrl = Data.class.getResource("statics/right.png");
public static URL downUrl = Data.class.getResource("statics/down.png");
public static URL leftUrl = Data.class.getResource("statics/left.png");
public static URL foodUrl = Data.class.getResource("statics/food.png");
public static URL headerUrl = Data.class.getResource("statics/banner.png");
//将收集到的这些信息放入我们的图像图标中
public static ImageIcon body = new ImageIcon(bodyUrl);
public static ImageIcon up = new ImageIcon(upUrl);
public static ImageIcon right = new ImageIcon(rightUrl);
public static ImageIcon down = new ImageIcon(downUrl);
public static ImageIcon left = new ImageIcon(leftUrl);
public static ImageIcon food = new ImageIcon(foodUrl);
public static ImageIcon header = new ImageIcon(headerUrl);
}
4.statics文件夹
用于存放游戏过程中用到的图片
5. 最终结果