学习链接:狂神说Java–1小时开发贪吃蛇小游戏
(定义数据,画上面板,监听事件(键盘/事件))
1、首先一个游戏主启动类StartGame类,里面放一个JFrame窗口及其大小位置设置,关闭设置,这里设置窗口大小不可变,以防拉伸导致游戏图标变形,相关的具体操作都在相应类中进行!
2、正常的游戏界面应在面板上!因此定义一个GamePanel类进行操作,首先是重写了painComponent(Graphics p)方法,游戏中的所有东西都是用这支画笔来画!首先是绘制静态的面板,设置面板颜色为白色。
3、接着把游戏图片素材放入static字典中,放入游戏开发包下,定义一个Data类,在其中获取存放游戏图片的地址,并把它们变为图标,接着在花瓣上画上头部广告栏、矩形(默认黑色)的游戏界面。
4、绘制静态的的小蛇,在GamePanel类中定义小蛇的数据结构!
然后写初始化方法init()方法初始化静态小蛇的长度、位置及其初始方向,再在构造器中调用init()方法,接着把小蛇画入面板中!(要判断头的方向!),身体用for循环画。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wzjij3il-1622175043668)(…/…/AppData/Roaming/Typora/typora-user-images/image-20210528090620469.png)]
6、空格键控制游戏开始与停止!设置键盘监听!直接在GamePanel类中实现KeyListener接口!按下空格键–>状态取反,重画repaint(),再init()函数中设置焦点事件和添加键盘监听。
7、小蛇动起来,Timer定时器!在GamePanel类中实现ActionListener接口即可。游戏一开始就启动定时器!接着写出小蛇移动的位置坐标处理,上下左右移动,头部、身体坐标如何变化,最后repaint()重画页面。这样子小蛇可以自己动了。但我们需要通过键盘监听上下左右键来控制小蛇的移动!身体移动是一样的,我们只需要判断移动方向,把头的位置坐标找好就行!
8、小蛇吃食物长大啦~,定义食物的坐标并在init()中初始化
吃食物即是头部坐标和食物坐标重合,小蛇长度+1,再次生成随机的食物,吃完食物再画身体!
package com.xiao.lesson07_game;
import javax.swing.*;
//游戏的主启动类
public class StartGame {
public static void main(String[] args) {
JFrame frame = new JFrame("贪吃蛇");
//正常游戏界面应在面板上
frame.add(new GamePanel());
frame.setBounds(10,10,900,720);
frame.setResizable(false);//大小不可变
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
package com.xiao.lesson07_game;
import javax.swing.*;
import java.net.URL;
//数据中心
public class Data {
//相对路径“tx.jpg
//绝对路径:/ 相当于当前的项目
//头+身体+食物
public static URL headerURL=Data.class.getResource("statics/header.png");
public static ImageIcon header=new ImageIcon(headerURL);
public static URL bodyURL=Data.class.getResource("statics/body.png");
public static ImageIcon body=new ImageIcon(bodyURL);
public static URL foodURL=Data.class.getResource("statics/food.png");
public static ImageIcon food=new ImageIcon(foodURL);
//上下左右
public static URL upURL=Data.class.getResource("statics/up.png");
public static URL downURL=Data.class.getResource("statics/down.png");
public static URL leftURL=Data.class.getResource("statics/left.png");
public static URL rightURL=Data.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);
}
package com.xiao.lesson07_game;
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
String fx; //初始方向
//食物的坐标(随机!)
int foodX; //正常食物
int foodY;
Random random=new Random();//随机
int score; //成绩
boolean isStart=false;// 游戏当前状态:开始/停止,默认停止
boolean isFail=false; //游戏失败状态
//定时器,以毫秒为单位
Timer timer=new Timer(100,this); //100ms执行一次
//构造器
public GamePanel() {
init();
//获得焦点和键盘监听
this.setFocusable(true); //获得焦点事件
this.addKeyListener(this); //获得键盘监听器
timer.start();//游戏一开始定时器就启动
//食物坐标得在游戏界面,小蛇才能吃到!
foodX=25+25*random.nextInt(34);
foodY=75+25*random.nextInt(24);
score=0;
}
//小蛇初始化方法
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"; //初始方向向右
}
//绘制面板,游戏中的所有东西,都是用这支画笔来画!
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //清屏
//绘制静态的面板
this.setBackground(Color.WHITE);
Data.header.paintIcon(this, g, 25, 11);//画上头部广告栏
g.fillRect(25, 75, 850, 600); //画矩形=》游戏界面
//画积分
g.setColor(Color.WHITE);
g.setFont(new Font("微软雅黑",Font.BOLD,18));
g.drawString("长度:"+length,775,30);
g.drawString("分数:"+score,775,50);
//画食物
Data.food.paintIcon(this,g,foodX,foodY);
//把小蛇画上去,得判断初始方向!
if (fx.equals("R")) {
Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化向右
} else if (fx.equals("L")) {
Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化向右
} else if (fx.equals("U")) {
Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化向右
} else if (fx.equals("D")) {
Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化向右
}
for (int i = 1; i < length; i++) {
Data.body.paintIcon(this,g,snakeX[i],snakeY[i]);//身体
}
//游戏状态
if(isStart==false){
g.setColor(Color.WHITE);//设置画笔颜色
g.setFont(new Font("微软雅黑",Font.BOLD,40));//设置字体
g.drawString("按下空格键开始游戏!",250,380); //写游戏提示
}
if(isFail){
g.setColor(Color.WHITE);//设置画笔颜色
g.setFont(new Font("微软雅黑",Font.BOLD,40));//设置字体
g.drawString("Score:"+score,230,330);
score=0;
g.setColor(Color.RED);//设置画笔颜色
g.drawString("失败,按下空格键重新开始!",230,380); //写游戏提示
}
}
//键盘监听事件:键盘按压,控制游戏开始、停止
@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="U";
}else if(keyCode==KeyEvent.VK_DOWN){
fx="D";
}else if(keyCode==KeyEvent.VK_LEFT){
fx="L";
}else if(keyCode==KeyEvent.VK_RIGHT){
fx="R";
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
//事件监听--需要通过固定事件来刷新,1s=10次,Timer
@Override
public void actionPerformed(ActionEvent e) {
//如果游戏是开始状态,就让小蛇动起来
if(isStart && isFail==false) {
//吃食物,坐标重合
if((snakeX[0]==foodX && snakeY[0]==foodY)){
length++; //小蛇长长了!
score+=10;
//食物再次随机生成!
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) {
snakeX[0] = 25;
} //边界判断
} else if (fx.equals("L")) {
//左移
snakeX[0] = snakeX[0] - 25;
if (snakeX[0] < 25) {
snakeX[0] = 850;
}
} else if (fx.equals("U")) {
//上移
snakeY[0] = snakeY[0] - 25;
if (snakeY[0] < 75) {
snakeY[0] = 650;
}
} else if (fx.equals("D")) {
//下移
snakeY[0] = snakeY[0] + 25;
if (snakeY[0] > 650) {
snakeY[0] = 75;
}
}
//失败判定:撞到自己
for (int i = 1; i < length; i++) {
if(snakeX[0]==snakeX[i] && snakeY[0]==snakeY[i]){
isFail=true;
}
}
repaint();//重画页面
}
timer.start();
}
}
14、优化(未实现!)
游戏优化暂没有实现!慢慢来吧~