一、概述
-
通过使用GUI编程完成窗口贪吃蛇的绘制,主要结合了事件监听、弹窗、按钮、面板、容器等多个知识点来进行结合而成,下面演示代码:
-
所需的广告页面路径一定要选择正确,否则无法导入图片
-
原图片
二、数据类Date(广告栏、贴纸、蛇头等部分)
package src.com.snake;
import javax.swing.*;
import java.net.URL;
//数据中心
public class Date {
//相对路径 tx.jps
//绝对路径 / 相当于当前的项目
public static URL headerURL = Date.class.getResource("statics/贪吃蛇广告.jpg");
public static ImageIcon header = new ImageIcon(headerURL);
public static URL upURL = Date.class.getResource("statics/up.png");
public static URL downURL = Date.class.getResource("statics/down.png");
public static URL leftURL = Date.class.getResource("statics/left.png");
public static URL rightURL = Date.class.getResource("statics/right.png");
public static ImageIcon up = new ImageIcon(upURL);
public static ImageIcon down = new ImageIcon(downURL);
public static ImageIcon left = new ImageIcon(leftURL);
public static ImageIcon right = new ImageIcon(rightURL);
//身体
public static URL bodyURL = Date.class.getResource("statics/body.png");
public static ImageIcon body = new ImageIcon(bodyURL);
//食物
public static URL foodURL = Date.class.getResource("statics/food.png");
public static ImageIcon food = new ImageIcon(foodURL);
}
三、面板GamePanel(主体类、包括监听器等)
package src.com.snake;
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 {
//定义蛇的数据结构
int length; //蛇的长度
int[] snakex = new int[600]; //蛇的x坐标 25*25
int[] snakey = new int[500]; //蛇的y坐标 25*25
//当前游戏的状态:开始 停止
boolean isStart = false; //默认为不开始
//当前蛇的状态:失败 未失败
boolean isFail = false; //默认为不是失败
String fx; //初始方向
//食物的坐标
int foodx;
int foody;
Random random = new Random();
//当前游戏的分数
int score;
//定时器 以毫秒为单位 1000ms = 1s
Timer timer = new Timer(150,this); //100毫秒执行一次!
//构造器
public GamePanel(){
init();
//获得焦点和键盘事件
this.setFocusable(true); //获取焦点事件
this.addKeyListener(this); //获得键盘监听事件
timer.start(); //游戏一开始定时器就启动
}
//初始化方法
public void init(){
length = 3;
snakex[0] = 100;snakey[0] = 100; //脑袋的坐标
snakex[1] = 75;snakey[1] = 100; //第一个身体的坐标
snakex[2] = 50 ;snakey[2] = 100; //第二个身体的坐标
fx = "R"; //初始方向向右
//初始化速度
timer.setDelay(150);
//把食物随机分布在界面上
foodx = 25+25*random.nextInt(34);
foody = 75+25*random.nextInt(24);
score = 0; //初始分数为0
}
//绘制画板,游戏种所有的东西,都是用这个画笔来画
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //清屏
//绘制静态面板
this.setBackground(Color.WHITE);
Date.header.paintIcon(this, g, 25, 10); //头部广告栏画上去
g.fillRect(25, 75, 850, 600); //默认的游戏界面
//把分数画上去
g.setColor(Color.RED);
g.setFont(new Font("宋体",Font.HANGING_BASELINE,20));
g.drawString("长度:"+length,400,95);
g.drawString("分数:"+score,400,120);
//画食物
Date.food.paintIcon(this,g,foodx,foody);
//把小蛇画上去
if (fx.equals("R")) {
Date.right.paintIcon(this, g, snakex[0], snakey[0]); //蛇头初始化向右,需要通过方向来判断
} else if (fx.equals("L")) {
Date.left.paintIcon(this, g, snakex[0], snakey[0]); //蛇头初始化向右,需要通过方向来判断
}else if (fx.equals("U")) {
Date.up.paintIcon(this, g, snakex[0], snakey[0]); //蛇头初始化向右,需要通过方向来判断
}else if (fx.equals("D")) {
Date.down.paintIcon(this, g, snakex[0], snakey[0]); //蛇头初始化向右,需要通过方向来判断
}
for (int i = 1; i <length ; i++) {
Date.body.paintIcon(this,g,snakex[i],snakey[i]); //第一个身体的坐标
}
//游戏状态
if (isStart==false){
g.setColor(Color.WHITE);
g.setFont(new Font("微软雅黑",Font.HANGING_BASELINE,40));
g.drawString("欢迎您,50元挑战者!按下空格键开始游戏!",50,500);
}
if (isFail){
g.setColor(Color.RED);
g.setFont(new Font("微软雅黑",Font.HANGING_BASELINE,35));
g.drawString("游戏失败啦!别放弃!请按下空格键重新开始!",25,500);
}
}
//键盘监听事件
@Override
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode(); //获得键盘按键是哪一个
if (keyCode == KeyEvent.VK_SPACE){ //如果按下的是空格键
if (isFail){
//重新开始
isFail = false;
init();
}else{
isStart = !isStart; //取反
}
repaint();
}
//小蛇移动
if (keyCode == KeyEvent.VK_UP && fx!="D"){ //如果按键按上键
fx = "U";
}else if (keyCode == KeyEvent.VK_DOWN && fx!="U"){ //如果按键按下键
fx = "D";
}else if (keyCode == KeyEvent.VK_LEFT && fx!="R"){ //如果按键按左键
fx = "L";
}else if (keyCode == KeyEvent.VK_RIGHT && fx!="L"){ //如果按键按右键
fx = "R";
}
}
//事件监听 -- 需要通过固定事件来刷新
@Override
public void actionPerformed(ActionEvent e) {
if (isStart && isFail == false){ //如果游戏是开始状态,就让小蛇动起来!
//吃食物
if (snakex[0]==foodx && snakey[0] ==foody){
//长度+5
length++;
repaint(); //重画页面
//分数加10
score = score+10;
//每吃到1颗食物,速度-1
timer.setDelay(150-length);
//再次随机食物
//把食物随机分布在界面上
foodx = 25+25*random.nextInt(34);
foody = 75+25*random.nextInt(24);
}
//移动
for (int i = length -1; i >0; i--) {
snakex[i] = snakex[i-1]; //向前移动一节
snakey[i] = snakey[i-1]; //向前移动一节
}
//走向
if (fx.equals("R")){
snakex[0] = snakex[0]+25;
if (snakex[0]>850){
isFail = true;
} //边界判断
}else if (fx.equals("L")){
snakex[0] = snakex[0]-25;
if (snakex[0]<25){
isFail = true;
} //边界判断
}else if (fx.equals("U")){
snakey[0] = snakey[0]-25;
if (snakey[0]<75){
isFail = true;
} //边界判断
}else if (fx.equals("D")){
snakey[0] = snakey[0] +25;
if (snakey[0]>650){
isFail = true;
} //边界判断
}
//失败判定,撞到自己
for (int i = 1; i < length ; i++) {
if (snakex[0]==snakex[i] && snakey[0] == snakey[i]){
isFail = true;
};
}
repaint(); //重画页面
}
timer.start(); //定时器开始!
}
//这两个方法是键盘监听事件接口延伸出来的 ,并未使用到
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
}
四、启动类StarGame
package src.com.snake;
import javax.swing.*;
//游戏的主启动类
public class StarGame {
public static void main(String[] args) {
JFrame frame = new JFrame("贪吃蛇Game");
frame.setBounds(10,10,900,720); //设置出现位置以及宽高
frame.setResizable(false); //窗口不可变
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //设置关闭事件
//正常的游戏都是在面板上
frame.add(new GamePanel());
frame.setVisible(true); //设置可见性
}
}
五、游戏效果图
以上的标题包括广告横条都可自行进行更换, 包括游戏参数也可自行调整,游戏还有许多BUG,可自行修复,如:蛇头转出屏幕,暂停提示与开头提示一致等等
注:文章仅做个人学习日记,不做学习建议,学习来源:狂神说