贪吃蛇小游戏

206 阅读4分钟

将图片加载进来

运用到对象的思想,把图片路径变成对象,把图片变成对象:

package game;

import com.sun.jndi.toolkit.url.UrlUtil;

import javax.swing.*;
import java.net.URL;

/*
    用于获取游戏中所涉及到图片。
* */
public class images {
//    将图片所在的路径封装成一个对象:
   public static URL bodyURL = images.class.getResource("/images/body.png");
    public static URL foodURL = images.class.getResource("/images/food.png");
    public static URL upURL = images.class.getResource("/images/up.png");
    public static URL downURL = images.class.getResource("/images/down.png");
    public static URL leftURL = images.class.getResource("/images/left.png");
    public static URL rightURL = images.class.getResource("/images/right.png");
    public static URL imgURL = images.class.getResource("/images/img.png");
//    将图片封装成程序中的一个对象
    public  static ImageIcon bodyImg = new ImageIcon(bodyURL);
    public  static ImageIcon foodImg = new ImageIcon(foodURL);
    public  static ImageIcon upImg = new ImageIcon(upURL);
    public  static ImageIcon downImg = new ImageIcon(downURL);
    public  static ImageIcon leftImg = new ImageIcon(leftURL);
    public  static ImageIcon rightImg = new ImageIcon(rightURL);
    public  static ImageIcon imgImg = new ImageIcon(imgURL);
}

创建窗体,也是游戏的启动程序

设置窗口的标题

在屏幕的位置

窗体的大小

打开关闭窗体时关闭程序

窗体大小不可改变

package game;

import javax.swing.*;
import java.awt.*;

public class StartGame {
//    这是一个main方法,启动程序的入口:
public static void main(String[] args) {

//    创建一个窗口:
    JFrame jf = new JFrame();
//    给窗体传建一个标题:
    jf.setTitle("第一次的尝试:贪吃蛇小游戏 by GuiPengCheng");
//    设置窗体大小不可调节
    jf.setResizable(false);
//    关闭窗口的同时,程序要关闭:
    jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//    创建面板:
    GamePanel gamePanel = new GamePanel();
//    写入窗体:
    jf.add(gamePanel);
//    设置窗体坐标:窗体大小   默认情况下窗体是隐藏的:
    int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    int height = Toolkit.getDefaultToolkit().getScreenSize().height;
    jf.setBounds((width-800)/2,(height-800)/2,800,800);
    jf.setVisible(true);

}
}

创建面板

首先要继承java的面板类:Jpanel 才能实现其功能

package game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;

//继承了JPanel以后,才能实现其功能
public class GamePanel extends JPanel {
    //    相当于一个图形版本的main启动方法
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
//        填充背景颜色:
        this.setBackground(new Color(151, 234, 162));
//        画顶部图片:
//        this是指当前画板,g是指使用的画笔
        images.imgImg.paintIcon(this,g,18,10);
//        调节画笔颜色:
        g.setColor(new Color(239, 226, 141, 255));
//        画一个矩形:
        g.fillRect(2,65,780,700);
}

画一个静态小蛇,改变蛇头方向

在面板类中定义小蛇的各参数,再定义小蛇如何运动。

以下代码仅仅是小蛇的:

先初始化蛇头和蛇身,放在x和y的数组里,保存的是相当于窗口的坐标。

然后蛇长,蛇头

蛇长在每次吃食物是都会增加,蛇身在改变字符时switch判断,进行图片的调整。

蛇身的循环是依据蛇长判断的。

//        初始化一个小蛇:
int[] snakeX = new int[200];
int[] snakeY = new int[200];
int length;//蛇长;
String direction; //蛇头方向

//--------------------------------------------

 public void init(){
//            初始化蛇头:
        snakeX[0]=175;
        snakeY[0]=275;
//            初始化第一节
        snakeX[1]=150;
        snakeY[1]=275;
//            初始化第二节
        snakeX[2]=125;
        snakeY[2]=275;
//        初始化蛇长
        length =3;
//        蛇头方向
        direction = "R";//u,d,l,r
 }

// -----------------------------------------------
//        画蛇:
//        1.蛇头
//        images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);
        switch (direction){
            case "R" :images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
            case "L" :images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
            case "D" :images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
            case "U" :images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]);break;
        }
//        2.身子
//        images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]);
//        images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]);
        for (int i = 1; i < length; i++) {
            images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]);
        }

加入监听,空格判断开始

加入构造器,和定义一个初始化方法,方法用来存储初始化的数值,以后每次开始运行程序,构造器会先调用初始化数据的方法。

构造器用来(监听键盘输入,实现动作),

 //        写一个构造器:
    public GamePanel(){
        init();
//        将焦点定位在面板上
        this.setFocusable(true);
//        加入监听
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                int KeyCode = e.getKeyCode();
                switch (KeyCode){
                    case KeyEvent.VK_SPACE:  //监听空格
                    {
                        if(Die){
                            init(); //恢复初始状态
                            Die = false;
                        }
                        else {
                            Start = !Start;
                            repaint();//调用下面的图形启动器方法
                        }
                    };break;
                    case KeyEvent.VK_UP:
                    {
                        direction = "D";//向上
                    };break;
                    case KeyEvent.VK_DOWN:
                    {
                        direction = "U";//向下
                    };break;
                    case KeyEvent.VK_LEFT:
                    {
                        direction = "L";//向左
                    };break;
                    case KeyEvent.VK_RIGHT:
                    {
                        direction = "R";//向右
                    };break;

                }

            }
        });
    }

小蛇动起来

需要在构造器中创建一个定时器,每100毫秒监听一次交互事件

动起来的前提条件是游戏开始,并且小蛇活着

然后蛇头是在不同的方向加减25

蛇身是循环递减,把前一项的值赋给后一项,实现蛇蛇的前进

然后对蛇的出界进行一个修订

启动定时器

//        初始化定时器
        timer = new Timer(100, new ActionListener() {
//            事件监听:
//            每100毫秒监听一次动作,放在下面那个方法里
            @Override
            public void actionPerformed(ActionEvent e) {
                if(Start&&Die ==false){//游戏开始并且小蛇活着
//                    蛇身
                    for (int i = length-1; i >0; i--) {
                        snakeX[i]=snakeX[i-1];
                        snakeY[i]=snakeY[i-1];
                    }
//                    蛇头
                    switch (direction){
                        case "R":snakeX[0] +=25;break;
                        case "L":snakeX[0] -=25;break;
                        case "U":snakeY[0] +=25;break;
                        case "D":snakeY[0] -=25;break;

                    }
//                    防止蛇超出边界
                    if(snakeX[0]>800){
                        snakeX[0]=25;
                    }
                    if(snakeX[0]<25){
                        snakeX[0]=800;
                    }
                    if(snakeY[0]<100){
                        snakeY[0]=700;
                    }
                    if(snakeY[0]>700){
                        snakeY[0]=100;
                    }
                    repaint();//刷新界面
                }


        });


//        定时器必须要启动
        timer.start();

吃食物

使用Rodam随机生成数字,来实现食物在界面的随机显示

在吃食物时,蛇头的坐标和食物的坐标完全吻合,此时食物改变位置

画积分,画倒计时

在吃食物时,每完成一次,积分数据改变,并且由于定时器的刷新界面,把积分数据实时的现实在面板上

//                检测碰撞动作:蛇吃食物
                time = time-0.06;
                if((int) time == 0 ){
                    foodX = ((new Random().nextInt(30)+1)*25);
                    foodY = ((new Random().nextInt(24)+4)*25);
                    time = 7;
                }

                if(snakeX[0] == foodX && snakeY[0] == foodY){
//                    蛇长度+1
                    length++;
//                    食物随机改变,每过二十秒刷新 也就是十二次
                    foodX = ((new Random().nextInt(30)+1)*25);
                    foodY = ((new Random().nextInt(24)+4)*25);
                    time = 7;
//                    吃上食物积分加十;
                    score +=10;
                }

死亡判定

蛇头跟任意蛇身坐标相等

//            死亡判断:
for (int i = 1; i < length; i++) {
    if(snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]){
        Die = true;
    }
 画食物:
        images.foodImg.paintIcon(this,g,foodX,foodY);

//        画积分:
        g.setColor(new Color(0x1515EE));
        g.setFont(new Font("微软雅黑",Font.BOLD,40));
        g.drawString("积分:"+score,390,40);
//        倒计时:
        g.setColor(new Color(0x1515EE));
        g.setFont(new Font("微软雅黑",Font.BOLD,40));
        g.drawString("倒计时:"+Math.round(time),60,40);
//        判断游戏的启动状态
        if(Start == false && Die == false) {
            g.setColor(new Color(0x0B77F8));
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("点击空格开始游戏", 250, 330);
        }

//        死亡
        if(Die) {
            g.setColor(new Color(0xE30A0A));
            g.setFont(new Font("微软雅黑", Font.BOLD, 25));
            g.drawString("你输了,按空格重新开始", 250, 330);
        }

打jar包