欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

仿写:《飞翔的小鸟》游戏代码部分

程序员文章站 2024-03-18 19:50:40
...

代码部分


简单论述:代码注释可能有点乱,里面有些参数是可以改变的,例如:计分的坐标,窗口的大小等。一共有三个状态,可以添加状态和功能。期待一起交流。资料归本人解释所有。

主页类

package cn.ayxy;

import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.ForkJoinPool.ManagedBlocker;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BirdGame extends JPanel{
    //启动飞翔的小鸟游戏的方法  
    /*声明变量*/
    Bird bird;//鸟类
    Column column1;//柱子类1 前一根
    Column column2;//柱子类2 后一根
    Ground groud;//地面类
    BufferedImage background;//创建BufferedImage对象    
    int score;//分数
    boolean gameOver;//判断是否结束
    BufferedImage gameOverImage;//背景图片
    //游戏结束属性
    int state;//游戏的状态
    //公开的权限 (访问权限)  静态不可改变的  常量变量名 一定要大写
    public static final int START = 0;//游戏初始状态
    public static final int RUNNING = 1;//
    public static final int GAME_OVER = 2;//游戏结束状态
    //游戏属性图片
    BufferedImage stateImage;


    public static void main(String[] args) throws Exception {   //有个抛出异常Exception
        /*创建一个窗体*/
        JFrame frames = new JFrame("NineFruit");//加入字符串 给窗口一个名字         
        BirdGame game = new BirdGame();//
        frames.add(game);//把画放入画框
        //设置窗体大小
        frames.setSize(440,670);        
        //设置窗口显示中间
        frames.setLocationRelativeTo(null);
        //用户关闭窗口时,做的操作
        frames.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        /*setDefaultCloseOperation();是用来设定窗口被关闭时(比如点击了右上角的”x”)的行为。
        EXIT_ON_CLOSE:结束窗口所在的应用程序。在窗口被关闭的时候会退出JVM。*/
        //设置窗口显示
        frames.setVisible(true);
        //地面动起来
        game.action();
    }
    //地面移动
            public void action()throws Exception{//移动方法 地面
                //写一个监听事件
                MouseListener l = new MouseAdapter() {
                    //鼠标按下的方法  void表示没有返回值
                    @Override
                    public void mousePressed(MouseEvent e) {
                        // 获得点击
                        //bird.flappy();//调用鸟类的飞翔
                        //抛出异常 抛给 Java编译器 自己处理
                        try {
                            switch (state) {
                            case GAME_OVER://结束状态
                                //二次赋值  容器
                                column1 = new Column(1);
                                column2 = new Column(2);
                                bird = new Bird();
                                score = 0;//分数
                                state = START;
                                break;
                            case START://启动状态
                                //二次赋值  容器
                                state = RUNNING;
                                break;
                            case RUNNING://运行的状态
                                bird.flappy();//运行调动飞翔方法
                                break;
                            }

                        } catch (Exception e2) {
                            // TODO: handle exception
                            e2.printStackTrace();
                        }
                    }
                };
                //将 l 挂接到面板上 
                addMouseListener(l);
                while(true){
//                  //什么时候可以飞
//                  if (!gameOver) {//当为false 可以飞  或  gameOver == false
//                      //游戏没有结束的时候飞
//                      groud.step();//重新绘画                 
//                      column1.step();//移动第一个柱子
//                      column2.step();//移动第二个柱子
//                      bird.step();//鸟移动
//                      bird.fly();//鸟挥动翅膀
//                  }
//                  //判断是否碰撞
//                  if (bird.hlt(groud) || bird.hlt(column1)|| bird.hlt(column2)) {//碰到地面  或者碰到 第一个柱子 和第二个柱子
//                      gameOver = true;//如果碰撞 就真的gameover
//                  }
//                  
//                  //计分逻辑
//                  if (bird.x == column1.x || bird.x ==  column2.x ) {
//                      score++;//每次分数加         
//                  }   
                //
                switch (state) {
                case START://启动
                    groud.step();
                    bird.fly();//小鸟飞翔状态
                    break;
                case RUNNING://启动
                    groud.step();
                    column1.step();
                    column2.step();
                    bird.fly();//鸟飞翔动
                    bird.step();
                    //积分
                    if (bird.x == column1.x || bird.x == column2.x ) {
                        score++;
                    }
                    //碰撞
                    if (bird.hlt(column1) || bird.hlt(column2) || bird.hlt(groud)) {
                        //碰撞 第一个柱子 或者 第二个柱子 或者 地面
                        state = GAME_OVER;//游戏状态为结束
                    }
                }
                    repaint();
                    //就是1 秒 看到 多少 这是每秒30
                    Thread.sleep(1000/30);                  
                }               
            }
    //重写paint 方法  制作一个画笔
    public void paint(Graphics g){//这个Graphics 是画笔参数
            //绘制背景
        g.drawImage(background, 0, 0, null);//最后一个参数  相当于一个检查者  查看背景图片是否改变
        /*
         * g.drawImage(img, x, y, width, height, observer)
         *   
         *   第一个参数  是背景  
         *   第二个参数  是横坐标
         *   第三个参数  是纵坐标
         *   第四个参数  是检查者
         */
            //绘制柱子
        /*拿第一根柱子的X坐标 减去 第一根柱子的宽2分之1
         *拿第一根柱子的Y坐标 减去 第一根柱子的高2分之1
         */
        g.drawImage(column1.image, column1.x - column1.width / 2,column1.y - column1.height / 2,null);
        g.drawImage(column2.image, column2.x - column2.width / 2, column2.y - column2.height / 2, null);
            //绘制地面
        g.drawImage(groud.image, groud.x, groud.y, null);
            //绘制小鸟
        //改一下画笔 API方法 旋转绘图坐标
        Graphics2D g2 = (Graphics2D)g;//把之前的画笔强制转换成这个新的  ## g的值不变
        //开始反转
        //把鸟的X  Y坐标翻转  这个度  有一个向上,向下的动作(变过以后,再变回来)
        g2.rotate(-bird.alp, bird.x, bird.y);//负角度 小鸟的头变

        //X坐标 减去 宽度的二分子一  *根柱子的坐标一样
        g.drawImage(bird.image, bird.x - bird.width / 2, bird.y - bird.height / 2, null);
        //再变回来
        g2.rotate(bird.alp, bird.x, bird.y);//小鸟的头在变过来
        //  里面的三个参数   字体 样式  大小
        Font f = new Font(Font.SANS_SERIF, Font.BOLD, 40);//属性 不带括号  方法 带括号
        g.setFont(f);       
        //绘制分数
        g.drawString(""+score, 40, 60);//分数转换字符串 X Y 显示位置  做为背景色
        g.setColor(Color.WHITE);//字体的颜色为白色
        g.drawString(""+score, 40-3, 60-3);
        //游戏结束的画面
        switch (state) {
        case GAME_OVER:
            g.drawImage(gameOverImage, 0, 0, null);
            break;
        case START:
            g.drawImage(stateImage, 0, 0, null);
            break;
        }
    }   
    //添加构造方法,或者构造器,或者构造函数。
    /*
     * 第一次赋值 叫初始化
     * 第二次赋值 是赋值
     * 自动调用
     * 类是类型 不真实存在 需要对象
     */
    public BirdGame() throws Exception{// 抛出异常Exception最大异常
        /*
         * 这里有一个错误1 
         * column1 = new Column(1);//这里传参数1
         * column2 = new Column(2);//这里传参数2 
         * 修改 是在 柱子类 里面
         */ 
        /*初始化*/
        state = START;//游戏初始状态
        stateImage = ImageIO.read(getClass().getResource("start.png"));//加入游戏结束图片

        bird = new Bird();
        groud = new Ground();
        column1 = new Column(1);//这里传参数1
        column2 = new Column(2);//这里传参数2
        //这里是把图片加载进来 添加的是背景图片"图片的名字"
        background = ImageIO.read(getClass().getResource("bg.png"));
        gameOver = false;
        gameOverImage = ImageIO.read(getClass().getResource("gameover.png"));//获取结束图片
    }
}

小鸟类

package cn.ayxy;

import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

/*  这个是小鸟类
 * 
 * X Y这个是鸟类的中心点坐标
 */
public class Bird extends JPanel{
    BufferedImage image;//图片
    int x,y,width,height;//横,纵,宽,高
    int size;//表示小鸟的大小,用于检测碰撞的使用,表示正方形的边长       
    //继续增加属性 用于计算鸟的位置
     double g;//重力加速度
     double t;//两次位置时间的间隔
     double v0;//初始上抛速度
     double s;//时间t以后的位移
     double alp;//弧度,鸟的倾角
     double speed;//当前的上抛速度
    //定义一个数组 是鸟的动画帧
     BufferedImage[] images;
     int index;//这个变量是数组元素的下标 从0开始

    //构造器
    public Bird() throws Exception{//抛出异常 Exception最大异常
        image = ImageIO.read(getClass().getResource("0.png"));//添加图片
        width = image.getWidth();
        height = image.getHeight();
        size = 40;//小鸟的大小
        x = 132;//小鸟在屏幕的距离
        y = 280;
        //初始化 定义的
        g = 4;//真实的不是这 是9.4
        v0 = 20;//初速度
        t = 0.25;//两次位置的时间隔
        speed = v0;//当前的上抛速度
        s = 0;//t时间以后的位移
        alp = 0;//鸟的倾角
        //初始化
        images = new BufferedImage[8];//定义了一个8张的图片数组
        for (int i = 0; i < images.length; i++) {//数组填值
            //添加图片 ,i=0,1,2,3,4,5,6,7
            images[i] = ImageIO.read(getClass().getResource(i+".png"));
            /*+ 一个意思是加减乘除 另一个是连接符*/         
        }
        index = 0;
    }
    //小鸟飞翔的方法
    public void fly(){
        //下标递增
        index++;
        //图片 挥动的比较慢自然
        image = images[index / 12 % 8];//翅膀挥动的频率        
    }
    //添加一个移动方法
    public void step(){//没有返回值的移动方法
        double v0 = speed;
        s = v0 * t + g * t * t / 2;//公式计算上抛的位移 物理公式
        y = (int) (y - s);//这里强制类型转换  浮点型 转换成整型  物理公式
        double v = v0 - g * t;//公式 计算下次的速度
        speed = v;//*鸟不会移动  
        //计算倾斜角度  数学公式
        /*调用API里面的反正切函数*/
        alp = Math.atan(s/8);//假设 距离是8 (可以改)
    }
    public void flappy() {
        // TODO Auto-generated method stub
        //设置一下重新向上飞
        speed = v0;//初始速度 赋值给当前速度
    }
    //碰撞的方法
    public boolean hlt(Ground ground){//碰撞地面 
        //当小鸟的中心坐标 + 2分之1的小鸟坐标 > 地面的Y坐标
        boolean hlt = y + size / 2 > ground.y;//前面是小鸟的Y坐标  小鸟的大小  地面的Y坐标    
        if (hlt) {
            //将小鸟放置地面
            y = ground.y - size / 2;//小鸟放到地面的上面  这里减 是显示  如果加 是小鸟被埋。。。
        }
        return hlt;//如果碰撞 返回true 没有false

    }

    //这是两个不同的方法 参数不一样 方法重载

    //小鸟碰撞柱子
    public boolean hlt(Column column){//碰撞到柱子

        //判断是否在柱子范围内
        if (x > column.x - column.width / 2 - size / 2 && x < column.width / 2 + column.x + size / 2) {//判断柱子的坐标
        //当 小鸟大小的二分之一 加上 柱子宽度二分之一  大于 柱子的中心点坐标
            if (y > column.y - column.gap / 2 +size / 2 && y < column.y + column.gap / 2 - size/ 2 ) {//判断柱子的缝隙
                return false;

            }
            return true;
        }

        return false;

    }

}

地面类

package cn.ayxy;

import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;


//这个是地面类
public class Ground extends JPanel{
    BufferedImage image;//图片
    int x;//横坐标
    int y;//纵坐标
    int width;//宽
    int height;//高
    //创造构造器
    public Ground() throws Exception{//抛出异常Exception最大异常
        image = ImageIO.read(getClass().getResource("ground.png"));//加入图片
        width = image.getWidth();//获取宽度
        height = image.getHeight();//获取高度
        x = 0;//赋值
        y = 500;        
    }
    //人眼1秒 看到大于24张图片 会看作动画
    //实现 地面运动
    public void step(){//写一个地面运动的类      
        x--;//每次减-      
        if (x == -109) {//当x等于-109(可修改) 时  给X重新赋值为0         
            x = 0;          
        }               
    }
}

柱子类

package cn.ayxy;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.management.ImmutableDescriptor;
import javax.swing.JPanel;
/*
 * 这个是柱子类
 * 
 * X  Y 这个是柱子中心坐标
 */
public class Column extends JPanel{
    BufferedImage image;//图片
    int x,y,width,height;//横,纵,宽,高
    int gap;//柱子之间的缝隙
    int distance;//两个柱子之间的距离
    Random rm = new Random();//创建随机数    
    /*添加一个有参构造器 错误1*/
    public Column(int n) throws Exception{
        //n 代表的是第几根柱子  抛出异常Exception  这里是最大的异常抛出        
        image = ImageIO.read(getClass().getResource("column.png"));//获取图片
        width = image.getWidth();//获取图片的宽
        height = image.getHeight();//获取图片的高
        gap = 144;//定义柱子的上下之间的距离  144 刚刚好  太大没有难度 太小难度太大
        distance = 245;//表示两个柱子之间的距离
        x = 550 + (n-1)*distance;//这里distance 两个之间的距离 是225 n-1 n 第几个柱子
        y = rm.nextInt(218) + 132;//生成一个0-218的整数  132-350之间浮动 到最上面为132 最下面350 就是上下浮动的距离     
    }
    //柱子的移动
    public void step(){
        x--;//X坐标一直减少
        if (x == -width / 2 ) {//柱子宽度的二分之一
            x = distance * 2 - width / 2;//移动到 边界 回去原始第二柱子的位置  第二个柱子 变成第一个
            y = y = rm.nextInt(218) + 132;          
        }
    }

}

效果部分显示图

仿写:《飞翔的小鸟》游戏代码部分
仿写:《飞翔的小鸟》游戏代码部分
仿写:《飞翔的小鸟》游戏代码部分
仿写:《飞翔的小鸟》游戏代码部分