程序不大,收获良多
材料也上传了,在资源中。
java是面向对象的语言,所以使用每个对象时候,它必须是在一个类中,被封装起来的。(正因如此才可以导入图片,将图片编译)
package com.msb.demo1;
import javax.swing.*;
import java.net.URI;
import java.net.URL;
/**
* @Auther:zhangjj
* @Date:2021/4/1 - 04-01-8:48
* @Description:com.msb.demo1
* @version:1.0
*/
public class Images {
public static URL bodyURL = Images.class.getResource("/Images/body.png");
public static ImageIcon body = new ImageIcon(bodyURL);
public static URL downURL = Images.class.getResource("/Images/down.png");
public static ImageIcon down = new ImageIcon(downURL);
public static URL foodURL = Images.class.getResource("/Images/food.png");
public static ImageIcon food = new ImageIcon(foodURL);
public static URL headerURL = Images.class.getResource("/Images/header.png");
public static ImageIcon header = new ImageIcon(headerURL);
public static URL leftURL = Images.class.getResource("/Images/left.png");
public static ImageIcon left = new ImageIcon(leftURL);
public static URL rightURL = Images.class.getResource("/Images/right.png");
public static ImageIcon rihgt= new ImageIcon(rightURL);
public static URL upURL = Images.class.getResource("/Images/up.png");
public static ImageIcon up = new ImageIcon(upURL);
public static URL sprURL = Images.class.getResource("/Images/sup.png");
public static ImageIcon spr = new ImageIcon(sprURL);
}
将图片编译完成之后,就可以将他应用到程序之中
首先创建一个窗口作为游戏的“家”——游戏要在窗口内运行
此时涉及到一个类:JFrame---具体内容自行在SDK中学习查看
package com.msb.demo1;
import javax.swing.*;
import java.awt.*;
/**
* @Auther:zhangjj
* @Date:2021/4/1 - 04-01-9:18
* @Description:com.msb.demo1
* @version:1.0
*/
public class StartGme {
public static void main(String[] args) {
//创建窗口
JFrame jf =new JFrame();
//设置标题
jf.setTitle("贪吃蛇游戏");
//调取方法直接获取
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
//设置窗体的弹出坐标,对应窗体的大小
int wandh =800;
//jf.setBounds(570,140,800,800);//570=(1940-800)/2;140=(1080-800)/2
jf.setBounds((width-wandh)/2,(height-wandh)/2,wandh,wandh);
//设置窗口不可调解
jf.setResizable(false);
jf.setBackground(new Color(114, 2, 255));
//关闭窗口的同时关闭程序
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE/* =3 */);
//创建面板
GamePaneTest gp1 = new GamePaneTest();
//将面板添加到窗口
jf.add(gp1);
//让窗口显示
jf.setVisible(true);
}
}
窗口创建好之后,游戏在窗口中哪里运行也是个问题,所以我们再建一个类,在这类重在建立一个面板,游戏在面板中运行(面板也是一个类我们要创建新面板就得继承内部类:JPanel---》具体内容SDK中自行查找学习)
将类定义完毕之后,添加到窗口的之中---》位置自定
注:在定义这个新类的时候又有两个点
一丶监视器
对键盘的监视器:addKeyListener
将键盘上的摁键当做是参数传入的的时候,其实是传入了一个int型的数
二丶定时器
从程序开始到程序中断的一种方式:Timer
package com.msb.demo1;
import sun.security.util.Length;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
/**
* @Auther:zhangjj
* @Date:2021/4/1 - 04-01-21:22
* @Description:com.msb.demo1
* @version:1.0
*/
public class GamePaneTest extends JPanel {
//定义蛇的初始长度
int Length = 3;
//定义两个数组
//蛇的X轴坐标
int[] SnakeX = new int[500];
//蛇的Y轴坐标
int[] SnakeY = new int[500];
//定义游戏状态--》暂停、开始
boolean isStart = false;
//蛇头方向
String direction;
//加入时间监听器
Timer timer,timer0;
//定义食物的X,Y坐标
int foodX,foodY ;
//定义积分
int score;
//定义一个boolean确定小蛇状态
boolean isDie =false;
//定义一个彩蛋出现时间
int surTimestart,surTimeEnd;
//彩蛋的X,Y
int surX,surY;
int[] sp1 = new int[4];
int[] sp2 = new int[4];
//定时器的时间
int times;
int time ;
public void inin(){
//蛇的初始长度
Length = 3;
SnakeX[0] = 175;
SnakeY[0] = 275;
SnakeX[1] = 150;
SnakeY[1] = 275;
SnakeX[2] = 125;
SnakeY[2] = 275;
direction = "R";//'L' 'R' 'U' 'D'
foodX = 300;
foodY = 200;
surX =600;surY=15;
score = 0;
surTimestart = surTimeEnd =2000;
times =0;
time =0 ;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//填充背景颜色
this.setBackground(new Color(64, 219, 188, 255));
//画头部图片
Images.header.paintIcon(this,g,0,0);
//改变画笔颜色
g.setColor(new Color(63, 4, 191, 225));
//绘制游戏界面
g.fillRect(10,70,770,690);
//画蛇头
if(direction == "R"){
Images.rihgt.paintIcon(this,g,SnakeX[0],SnakeY[0]);
}
if(direction == "L"){
Images.left.paintIcon(this,g,SnakeX[0],SnakeY[0]);
}
if(direction == "U"){
Images.up.paintIcon(this,g,SnakeX[0],SnakeY[0]);
}
if(direction == "D"){
Images.down.paintIcon(this,g,SnakeX[0],SnakeY[0]);
}
//优化为循环画身子
for (int i = 1; i < Length; i++) {
Images.body.paintIcon(this,g,SnakeX[i],SnakeY[i]);
}
//画食物
Images.food.paintIcon(this,g,foodX,foodY);
//画积分
g.setColor(new Color(243, 4, 4));
g.setFont(new Font("微软雅黑",Font.BOLD,20));
g.drawString("积分"+score,700,50);
//画彩蛋
Images.spr.paintIcon(this,g,surX,surY);
//游戏暂停时显示提示
if(isStart == false){
g.setColor(new Color(243, 4, 4));
g.setFont(new Font("微软雅黑",Font.BOLD,100));
g.drawString("空格开始游戏",100,400);
}
//游戏结束画面
if(isDie == true){
g.setColor(new Color(243, 4, 4));
g.setFont(new Font("微软雅黑",Font.BOLD,60));
g.drawString("游戏结束"+","+"空格重新开始",100,400);
}
}
//构造器
public GamePaneTest() {
inin();
//将焦点定位在当前操作面板上
this.setFocusable(true);
//加入监听器
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int keyCode = e.getKeyCode();
/*System.out.println(keyCode);*/
if(keyCode == KeyEvent.VK_SPACE){
if(isDie){
inin();
isDie = false;
}
else {
isStart = !isStart;
repaint();
}
}
//监听即将改变的方向输出键
if(keyCode ==KeyEvent.VK_LEFT&&!"R".equals(direction )){
direction = "L";
repaint();
}
if(keyCode ==KeyEvent.VK_RIGHT && !"L".equals(direction)){
direction = "R";
repaint();
}
if(keyCode ==KeyEvent.VK_UP&&!"D".equals(direction)){
direction = "U";
}
if(keyCode ==KeyEvent.VK_DOWN&&!"U".equals(direction)){
direction = "D";
}
}
});
//对定时器初始化
timer0 = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
timer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(isStart&&isDie==false){
//后一节身子走到前一节身子的位置
for (int i = Length-1; i > 0; i--) {
SnakeX[i] = SnakeX[i-1];
SnakeY[i] = SnakeY[i-1];
}
//改变蛇头
if("R".equals(direction)){
SnakeX[0] +=25;
}
if("L".equals(direction)){
SnakeX[0] -=25;
}
if("U".equals(direction)){
SnakeY[0] -=25;
}
if("D".equals(direction)){
SnakeY[0] +=25;
}
//改变蛇的速度
//防止蛇逃出界面
if(SnakeX[0]>750){
SnakeX[0] = 25;
}
if(SnakeY[0]<100){
SnakeY[0] = 725;
} if(SnakeX[0]<25){
SnakeX[0] = 750;
}
if(SnakeY[0]>725){
SnakeY[0] = 100;
}
//检测碰撞动作---》吃的动作:因为每 100s画一次
//没有彩蛋时
if(SnakeX[0]==foodX&&foodY == SnakeY[0]){
Length++;//蛇长加一
/*
*算法解析:foodX=25*(int)(30*(Math.random()+1))
random = [0.0,1.0)--->[1,30]
* 1.30*random=[0.0,30.0)
* 2.int(random)=[0,29]
* 3.int(random+1)=[1,30]
* */
foodX = 25*(int)(15*(Math.random()+1));//x必须是25到725的25的倍数
foodY = 25*(new Random().nextInt(20)+4);//Y必须是100到725的25的倍数
/*System.out.println(foodX);
System.out.println(foodY);*/
score +=10;
}
if((SnakeX[0]==surX+25&&SnakeY[0]==surY+25)||(SnakeX[0]==surX+25&&SnakeY[0]==surY)||(SnakeX[0]==surX&&SnakeY[0]==surY+25)||(SnakeX[0]==surX&&SnakeY[0]==surY)){
Length+=5;
surX =surY =2000;
score +=50;
}
//死亡判断
for (int i = 1; i < Length; i++) {
if(SnakeX[0]==SnakeX[i]&&SnakeY[0]==SnakeY[i]){
isDie = true;
}
}
//彩蛋时间
surTimestart +=timer.getDelay();
if(surTimestart%8000==0){
surX = 25*(new Random().nextInt(20)+2);
surY = 25*(new Random().nextInt(20)+1);
time =surTimestart;
times =1;
surTimeEnd +=timer.getDelay();
}
if(times==1){
if ((surTimestart-time)%2000==0&&surTimestart-time!=0){
//System.out.println(time);
time = 0;times=0;
surX =600; surY =15;
}
}
repaint();//界面重绘
}
}
});
//定时器启动
timer.start();
}
}