GUI编程实战--贪吃蛇

GUI编程实战--贪吃蛇

参考:遇见狂神说

https://space.bilibili.com/95256449

界面绘制

  • 帧:如果时间片足够小,就是动画,一秒30帧。连起来是动画,拆开是静态的图片
  • 键盘监听
  • 定时器 Timer

package com.ssl.Snake;

import javax.swing.*;

//游戏的主启动类
public class StartGame {

    public static void main(String[] args) {
        JFrame frame = new JFrame("基于java-GUI的贪吃蛇小游戏");

        frame.setBounds(50,50,900,800);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setResizable(false);  //大小不可变

        //正常游戏界面都应该在面板上!
        frame.add(new GamePanel());
    }
}
package com.ssl.Snake;

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 headURL = Data.class.getResource("statics/head.png");
    public static ImageIcon head = new ImageIcon(headURL);
    public static URL leftURL = Data.class.getResource("statics/left.png");
    public static ImageIcon left = new ImageIcon(leftURL);

    public static URL rightURL = Data.class.getResource("statics/right.png");
    public static ImageIcon right = new ImageIcon(rightURL);

    public static URL upURL = Data.class.getResource("statics/up.png");
    public static ImageIcon up = new ImageIcon(upURL);

    public static URL downURL = Data.class.getResource("statics/down.png");
    public static ImageIcon down = new ImageIcon(downURL);

    public static URL foodURL = Data.class.getResource("statics/food.png");
    public static ImageIcon food = new ImageIcon(foodURL);

    public static URL bodyURL = Data.class.getResource("statics/body.png");
    public static ImageIcon body = new ImageIcon(bodyURL);

}
package com.ssl.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.security.Key;
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;

    //游戏当前状态   开始/停止
    boolean isStart;

    //游戏速度
    int speed = 100;
    //定时器
    Timer timer = new Timer(speed,this);   //100ms执行一次

    //食物的坐标  x:25:850 y:150:725
    int foodx;
    int foody;

    Random random = new Random();

    //游戏失败
    boolean isfall = false;

    //成绩
    int score;

    //构造器
    public GamePanel(){
        init();
        //获得焦点和键盘事件
        this.setFocusable(true);   //获得焦点事件
        this.addKeyListener(this);
    }

    public void init(){
        //初始化长度为3
        length=3;
        snakeX[0]=100; snakeY[0]=200;  //脑袋坐标
        snakeX[1]=75; snakeY[1]=200;  //第一个身体
        snakeX[2]=50; snakeY[2]=200;  //第二个身体
        fx = "R";
        isStart = false;
        speed=100;
        timer.start();//定时器

        //把食物随机放上
        foodx = 25 + 25 * random.nextInt(34);
        foody = 150 +25 * random.nextInt(24);

        score = 0;
    }

    //绘制面板,游戏中所用东西都用这个画笔来画。
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);  //清屏,不用会闪烁

        //绘制静态的面板
        this.setBackground(Color.WHITE);
        Data.head.paintIcon(this,g,0,0);  //广告栏

        g.fillRect(25,150,850,600);//默认的游戏界面

        //画积分
        g.setColor(Color.BLACK);
        //设置字体
        g.setFont(new Font("微软雅黑",Font.BOLD,20));

        //放入字
        g.drawString("长度:"+length,750,50);
        g.drawString("得分:"+score,750,100);


        //画食物
        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){
            g.setColor(Color.WHITE);
            //设置字体
            g.setFont(new Font("微软雅黑",Font.BOLD,40));

            //放入字
            g.drawString("按下空格开始游戏",300,400);
        }

        //如果游戏失败
        if(isfall){
            g.setColor(Color.RED);
            //设置字体
            g.setFont(new Font("微软雅黑",Font.BOLD,40));

            //放入字
            g.drawString("游戏失败,按下空格重新开始",150,400);
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    //键盘的监听事件
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();   //获得键盘的按键
        if(keyCode == KeyEvent.VK_SPACE){    //如果按下的是空格键
            if(isfall){
                //重新开始
                isfall = false;
                init();
            }else{
                isStart = !isStart;
            }
            repaint();
        }
        //小蛇移动
        if(keyCode == KeyEvent.VK_UP && (fx.equals("R")||fx.equals("L")) ){
            fx="U";
        }else if(keyCode == KeyEvent.VK_DOWN && (fx.equals("R")||fx.equals("L"))){
            fx="D";
        }else if(keyCode == KeyEvent.VK_LEFT && (fx.equals("U")||fx.equals("D")) ){
            fx="L";
        }else if(keyCode == KeyEvent.VK_RIGHT && (fx.equals("U")||fx.equals("D"))){
            fx="R";
        }

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    //事件监听  通过固定的事件刷新 1s 10次
    @Override
    public void actionPerformed(ActionEvent e) {
        //如果游戏是开始状态,就让小蛇动起来
        if(isStart && isfall == false){

            //吃食物
            if(snakeX[0]==foodx && snakeY[0]==foody){
                length++;
                foodx = 25 + 25 * random.nextInt(34);
                foody = 150 +25 * random.nextInt(24);
                //变速
                speed= speed - 1;
                score+=10;
            }

            //身体的移动  后一节变到前一节
            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;
            }else if(fx.equals("L")){
                snakeX[0]=snakeX[0]-25;
            }else if(fx.equals("U")){
                snakeY[0]=snakeY[0]-25;
            }else if(fx.equals("D")){
                snakeY[0]=snakeY[0]+25;
            }

            //边界判断
            if(snakeX[0]>850){
                snakeX[0]=25;
            }
            if(snakeX[0]<25){
                snakeX[0]=850;
            }
            if(snakeY[0]>725){
                snakeY[0]=150;
            }
            if(snakeY[0]<150){
                snakeY[0]=725;
            }

            //失败判定,撞到自己就算失败
            for(int i=1;i<length;i++){
                if(snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i])
                    isfall=true;
            }

            repaint();

        }
        if(speed<50){
            speed=50;
        }
        timer.start();//定时器
    }
}
posted @ 2022-09-29 17:36  林每天都要努力  阅读(69)  评论(1)    收藏  举报