• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
langQ
博客园    首页    新随笔    联系   管理    订阅  订阅
04 贪吃蛇

贪吃蛇

帧,如果时间片足够小,就是动画 一秒30帧 60帧
连起来是动画,拆开就是静态的图片!

键盘监听
定时器Timer

重点:

 
处理是一个一个加上去的,逐步完善的!
不是一下就都实现的。
 

StartGame.java

package com.mysoft.snake;

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

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

    public StartGame()  {
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();

        frame.setBounds(10, 10, 900, 720);
        frame.setResizable(false);//窗口大小不可变
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        //正常游戏界面都应该在面板上
        frame.add(new GamePanel());

        frame.setVisible(true);
    }
}
Data.java

package com.mysoft.snake;

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

//数据中心
public class Data {
    //相对路径 tx.jpg
    //绝对路径 / 相对于当前的项目
    public static URL headerURL = Data.class.getResource("static/header.png");
    public static ImageIcon header = new ImageIcon(headerURL);

    public static URL upURL = Data.class.getResource("static/up.png");
    public static URL downURL = Data.class.getResource("static/down.png");
    public static URL leftURL = Data.class.getResource("static/left.png");
    public static URL rightURL = Data.class.getResource("static/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 = Data.class.getResource("static/body.png");
    public static ImageIcon body = new ImageIcon(bodyURL);

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

}
GamePanel.java

package com.mysoft.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
    String fw;//初始方向

    //食物的坐标
    int foodx;
    int foody;
    Random random = new Random();

    int score;


    //游戏当前的状态:开始,停止
    boolean isStart = false;//游戏是不是开始!

    //游戏失败
    boolean isFail = false; //游戏失败状态

    //定时器 以ms为单位  1000ms=1秒
    Timer timer = new Timer(100,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;//第二个身体的坐标
        fw = "R";//初始方向向右
        score = 0;

        //把食物随机分布在界面上
        foodx = 25 + 25 * random.nextInt(34);
        foody = 75 + 25 * random.nextInt(24);
    }

    //绘制面板,我们游戏中的所有东西,都是用这个画笔来画
    @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, 650);//默认的游戏界面

        //画积分
        g.setColor(Color.white);
        g.setFont(new Font("MS ゴシック", Font.BOLD, 18));//设置字体
        //g.drawString("积分是:" + String.valueOf(score * 10), 700, 50);
        g.drawString("长度:" + length, 750, 35);
        g.drawString("得分:" + score, 750, 50);

        //画食物
        Data.food.paintIcon(this, g, foodx, foody);

        //把小蛇画上去
        //Data.right.paintIcon(this,g,snakeX[0],snakeY[0]);//蛇头初始化向右,需要通过方向来判断
        switch (fw) {
            case "U":
                Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化,需要通过方向来判断
                break;
            case "D":
                Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case "L":
                Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            case "R":
                Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
                break;
            default:
                Data.right.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("MS ゴシック", Font.BOLD, 32));//设置字体
            g.drawString("按下空格开始游戏", 300, 300);
        }

        if (isFail) {
            g.setColor(Color.red);
            g.setFont(new Font("MS ゴシック", Font.BOLD, 32));//设置字体
            g.drawString("游戏失败,按下空格重新开始", 300, 300);
        }


    }


    @Override
    public void keyTyped(KeyEvent e) {

    }

    //键盘的监听事件
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        System.out.println("keyPressed=> " + keyCode);
        //if (keyCode == KeyEvent.VK_SPACE) {
        //    isStart = !isStart;//取反
        //}
        if (keyCode == KeyEvent.VK_SPACE) {
            if (isFail) {
                //重新开始
                isFail = false;
                init();
            } else {
                isStart = !isStart;
            }
            repaint();
        }

        //小蛇移动
        if (keyCode == KeyEvent.VK_UP) {
            if (!fw.equals("D")) {
                fw = "U";
            }
        } else if (keyCode == KeyEvent.VK_DOWN) {
            if (!fw.equals("U")) {
                fw = "D";
            }
        } else if (keyCode == KeyEvent.VK_LEFT) {
            if (!fw.equals("R")) {
                fw = "L";
            }
        } else {
            //fw = "R";
            if (!fw.equals("L")) {
                fw = "R";
            }
        }
        repaint();
    }

    //事件监听---需要通过固定事件来刷新,比如:1秒=10次
    @Override
    public void keyReleased(KeyEvent e) {

    }

    //事件监听---需要通过固定事件来刷新,1s=10次
    @Override
    public void actionPerformed(ActionEvent e) {
        if (isStart && !isFail) {//如果游戏是开始状态,就让小蛇动起来!
            //吃食物
            if (snakeX[0] == foodx && snakeY[0] == foody) {
                //长度 + 1
                length++;
                //分数加10
                score += 10;
                //再次随机食物
                foodx = 25 + 25 * random.nextInt(34);
                foody = 75 + 25 * random.nextInt(24);
            }

            //移动
            for (int i = length-1; i > 0; i--) {//后一节移动到前一节的位置 snakeX[1] = snakeX[0];
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }
            //走向 (头移动)
            if (fw.equals("U")) {
                snakeY[0] = snakeY[0] - 25;
                if (snakeY[0] < 75) {//边界判断
                    snakeY[0] = 650;
                }
            } else if (fw.equals("D")) {
                snakeY[0] = snakeY[0] + 25;
                if (snakeY[0] > 650) {//边界判断
                    snakeY[0] = 75;
                }
            } else if (fw.equals("L")) {
                snakeX[0] = snakeX[0] - 25;
                if (snakeX[0] < 25) {//边界判断
                    snakeX[0] = 850;
                }
            } else if (fw.equals("R")) {
                snakeX[0] = snakeX[0] + 25;
                if (snakeX[0] > 850) {//边界判断
                    snakeX[0] = 25;
                }
            }
            //snakeX[0]=snakeX[0]+25;

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

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

            repaint();//重画页面

        }


    }
}

实行效果:

posted on 2024-04-14 15:48  嚯嚯go  阅读(17)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3