GUI编程入门到游戏实战(二)

实战——贪吃蛇小游戏

  • 帧:如果时间片足够小,就是动画,一秒30帧 60帧,连起来是动画;拆来就是静态的图片
  • 键盘监听
  • 定时器Timer
package com.song.snake;

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

public class Data {

    //绝对路径与相对路径
    //相对路径 / 相当于当前的项目
    public static URL headURL = Data.class.getResource("statics/header.png");
    public static ImageIcon header = new ImageIcon(headURL);
    public static URL bodyURL = Data.class.getResource("statics/body.png");
    public static ImageIcon body = new ImageIcon(bodyURL);
    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 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 foodURL = Data.class.getResource("statics/food.png");
    public static ImageIcon food = new ImageIcon(foodURL);


}

package com.song.snake;

import com.song.lesson04.JPanelDemo;
import javafx.scene.input.KeyCode;

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;

/*
整体设计思路:
1)先设计变量或者数据结构
2)进行初始化数据或状态
3)面板画上去
4)事件(键盘)监听,改变状态
 */


//游戏面板;通过键盘接口,实现监听键盘;通过定时器接口,实现
public class GamePanel extends JPanel implements KeyListener, ActionListener {

    //定义蛇的数据结构
    int length;//蛇的长度
    int[] snakeX = new int[600];//蛇的X坐标
    int[] snakeY = new int[600];//蛇的Y坐标
    String fx;//方向

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

    //成绩
    int score;

    //游戏当前的状态:Start Stop
    boolean isStart;

    //游戏失败判断
    boolean isFail = false;

    //定时器  以ms为单位  1000ms=1s
    Timer timer = new Timer(100, this);//100毫秒执行一次

    //构造器
    public GamePanel() {
        init();
        //获得焦点和键盘事件
        this.setFocusable(true);//获得焦点事件
        this.addKeyListener(this);//获得键盘监听事件
        timer.start();//游戏一开始,定时器就要启动
    }

    //初始化方法
    public void init() {
        length = 3;//初始蛇的长度为3(包含头
        //一个小格子长度是25
        snakeX[0] = 100;
        snakeY[0] = 100;//脑袋的坐标
        snakeX[1] = 75;
        snakeY[1] = 100;//第一个身体的坐标
        snakeX[2] = 50;
        snakeY[2] = 100;//第二个身体的坐标
        fx = "right";//初始方向向右
        isStart = false;//初始默认不开始

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

        //成绩初始为0
        score = 0;
    }


    //绘制面板——游戏中的所有东西都通过这个画笔来画
    @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, 20));
        g.drawString("长度" + length, 750, 35);
        g.drawString("分数" + score, 750, 55);

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

        //把小蛇画上去

        //初始小蛇头朝向右,要通过方向来判断
        if (fx.equals("right")) {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("up")) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("left")) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (fx.equals("down")) {
            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("按下空格开始游戏", 300, 300);
        }
        //游戏失败状态显示
        if (isFail == true) {
            g.setColor(Color.RED);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("游戏失败,按下空格重新开始", 300, 300);//空格双重作用
        }

    }


    //键盘监听事件
    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();//获得键盘按键是哪一个
        //开始、停止
        if (keyCode == KeyEvent.VK_SPACE) {//如果按下的是空格键;//空格双重作用——暂停开始;重新开始
            if (isFail == false) {//游戏正常运行的暂停开始
                isStart = !isStart;//取反操作!!!!!!!!!!
            } else {//游戏失败的重新开始
                isFail = false;
                init();//重新开始,初始化
            }
            repaint();//值有变化后,就要重新画

        }
        //小蛇移动
        if (keyCode == KeyEvent.VK_UP) {
            fx = "up";
        } else if (keyCode == KeyEvent.VK_DOWN) {
            fx = "down";
        } else if (keyCode == KeyEvent.VK_LEFT) {
            fx = "left";
        } else if (keyCode == KeyEvent.VK_RIGHT) {
            fx = "right";
        }


    }

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

            //吃食物
            if (snakeX[0] == foodx && snakeY[0] == foody) {
                length++;//长度+1
                score = score + 10;//分数+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];
            }
            //一个小格子长度是25,脑袋移动一格是25;还需要判断脑袋移动的方向
            if (fx.equals("right")) {
                snakeX[0] = snakeX[0] + 25;
                //边界判断
                if (snakeX[0] > 850) {
                    snakeX[0] = 25;
                }
            } else if (fx.equals("left")) {
                snakeX[0] = snakeX[0] - 25;
                //边界判断
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            } else if (fx.equals("up")) {
                snakeY[0] = snakeY[0] - 25;
                //边界判断
                if (snakeY[0] < 75) {//有广告位
                    snakeY[0] = 650;
                }
            } else if (fx.equals("down")) {
                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;
                    break;
                }
            }


            //变完后,重画
            repaint();
        }
        timer.start();//定时器开启

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }
}




package com.song.snake;

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

//游戏的主启动类
public class StartGame extends JFrame {
    public StartGame() {
        Container container = getContentPane();

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

        this.setBounds(100, 100, 900, 720);//宽和高是计算得出的
        this.setResizable(false);//设置窗口大小不可变
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new StartGame();
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值