用Java实现的跑酷小游戏

前言

自学java前期做的小项目,主要灵感来源于天天跑酷和大家耳熟能详的flappy bird小游戏,当然在运行过程中也有许多瑕疵,欢迎指正

结构

1.显示窗口,绘制人物与背景

2.点击鼠标,人物即可跳跃

3.随机出现障碍物,检测撞击到障碍物人物死亡

4.人物成功避开障碍物积分加1

代码

1.背景包Ground

package game;

import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;

/*
 地面
 */
public class Ground {
    //图片
    BufferedImage image1,image2;
    //位置
    int x1,x2;
    //宽高
    int width,height;
    //初始化地面
    public Ground() throws Exception{
        image1=ImageIO.read(getClass().getResource("/images/ground1.png"));
        image2=ImageIO.read(getClass().getResource("/images/ground1.png"));
        x1=0;
        x2=674;
    }
    //向左移动一步
    public void step() {
        x1-=2;
        x2-=2;
        //地面滚动拼接
        if(x1<=-674) {
            x1=674;
        }else if (x2<=-674) {
            x2=674;
        }
    }
}
 

2.人物包Human 

在这里人物跳跃我用一个极其笨拙的方法,随时间人物y坐标变化,因为原本使用抛物线运动的时候人物容易闪烁掉帧,在加上比较匆忙没有用双缓冲,大佬们有什么好的建议尽管说

package game;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;

/*
 人物
 */
public class Human {
    //图片
    BufferedImage image;
    //位置
    int x,y;
    //最低位置,即地面
    public static final int LOW_Y = 320;
    //宽高
    int width,height;
    //边框
    int size;
    //一组图片,记录人物的动画帧
    BufferedImage[] images;
    //动画帧数组的下标
    int index;
    //初始化人物
    public Human() throws Exception{
        //初始化基本参数
        image =ImageIO.read(getClass().getResource("/images/r0.PNG"));
        width=image.getWidth();
        height=image.getHeight();
        //初始化位移参数
        x=130;
        y=320;
        size=30;
        //初始化动画
        images=new BufferedImage[6];
        for(int i=0;i<6;i++) {
            images[i] = ImageIO.read(getClass().getResource("/images/r" + i + ".PNG"));
        }
        index=0;
    }


    //移动一步
    public void step() {
        index++;
        image=images[(index/12)%6];

    }
    //向上跳跃
    public void jump() throws Exception {
       Timer timer=new Timer();
       timer.schedule(new Task(timer),200,120);
    }
    class Task extends TimerTask{
        private Timer timer;
        public Task(Timer timer) {
            this.timer = timer;
        }
        int i = 0;

        @Override
        public void run() {
            i++;
            if (i<=3){
                y-=30;
            }else if(i>3 & i<=8) {
                //
            }else if(i>8 & i<=11) {
                y += 30;
            }else if (i==12) {
                this.timer.cancel();
            }
        }
    }


    //检测人物是否撞到障碍物
    public boolean hit(Obstacle obstacle) {
        //先检测是否在障碍物的范围内
        if(x+size>obstacle.x && x<obstacle.x+size) {
            //再检测是否撞到障碍
            if(y+height>obstacle.y+size && y+size<obstacle.y+ obstacle.height) {
                return true;
            }else {
                return false;
            }
        }
        return false;
    }

}

 3.障碍包Obstacle

package game;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Obstacle {
    //图片
    BufferedImage image;
    //位置
    int x,y;
    //宽高
    int width,height;
    //随机数
    int index;
    //障碍之间的距离
    int distance;
    //随机数工具
    Random random=new Random();
    /*
      初始化第N个障碍
     */
    public Obstacle(int n) throws Exception{
        index= random.nextInt(2);
        switch (index) {
            case 0:
                image = ImageIO.read(getClass().getResource("/images/b0.PNG"));
                y=200;
                break;
            case 1:
                image = ImageIO.read(getClass().getResource("/images/s0.png"));
                y=350;
                break;
        }
        width=image.getWidth();
        height=image.getHeight();
        distance= random.nextInt(3)*100+200;
        x=700+(n-1)*distance;
    }
    //向左移动一步
    public void step() {
        x-=2;
        if(x+width<=0) {
            x= random.nextInt(3)*50+700;
        }
    }
}

4.主函数RunningGame 

package game;


/*
  游戏界面
 */
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class RunningGame extends JPanel {
    // 背景图片
    BufferedImage background;
    // 开始图片
    BufferedImage startImage;
    BufferedImage humanImage;
    // 结束图片
    BufferedImage gameOverImage;
    // 地面
    Ground ground;
    // 障碍物
    Obstacle obstacle1, obstacle2;
    // 人物
    Human human;
    // 游戏分数
    int score;
    // 游戏状态
    int state;

    // 状态常量
    public static final int START = 0;// 开始
    public static final int RUNNING = 1;// 运行
    public static final int GAME_OVER = 2;// 结束

    /*
      初始化游戏
     */
    public RunningGame() throws Exception {
        // 导入背景图片
        background = ImageIO.read(getClass().getResource("/images/bg0.png"));
        // 导入开始、结束图片
        startImage = ImageIO.read(getClass().getResource("/images/start.png"));
        gameOverImage = ImageIO.read(getClass().getResource("/images/gameover.png"));
        humanImage = ImageIO.read(getClass().getResource("/images/ren.PNG"));

        // 导入地面、障碍、人物
        ground = new Ground();
        obstacle1 = new Obstacle(1);
        obstacle2 = new Obstacle(2);
        human = new Human();

        // 初始化分数
        score = 0;
        // 初始化状态
        state = START;

    }

    /*
     绘制界面
     */
    public void paint(Graphics g) {
        // 绘制背景
        g.drawImage(background, 0, 0, null);
        // 绘制地面
        g.drawImage(ground.image1, ground.x1, 360, null);
        g.drawImage(ground.image2, ground.x2, 360, null);

        // 绘制障碍物
        g.drawImage(obstacle1.image, obstacle1.x, obstacle1.y, null);
        g.drawImage(obstacle2.image, obstacle2.x, obstacle2.y, null);

        // 绘制人物
        g.drawImage(human.image, human.x, human.y, null);

        // 绘制分数
        Font f = new Font(Font.MONOSPACED, Font.BOLD, 40);
        g.setFont(f);
        g.drawString("" + score, 40, 60);
        g.setColor(Color.WHITE);
        g.drawString("" + score, 40 - 3, 60 - 3);

        // 绘制开始与结束界面
        switch (state) {
            case START:
                g.drawImage(startImage, 50, -120, null);
                g.drawImage(humanImage,440,70,null);
                break;
            case GAME_OVER:
                g.drawImage(gameOverImage, 150, -80, null);
                break;
        }
    }

    // 开始游戏
    public void action() throws Exception {

        MouseListener l = new MouseAdapter() {
            // 鼠标按下事件
            public void mousePressed(MouseEvent e) {
                try {
                    switch (state) {
                        case START:
                            // 在开始时,点击鼠标则转为运行状态。
                            state = RUNNING;
                            break;
                        case RUNNING:
                            // 在运行时,点击鼠标则人物向上跳
                            human.jump();
                            break;
                        case GAME_OVER:
                            // 在结束时,点击鼠标则重置数据,返回开始界面。
                            obstacle1 = new Obstacle(1);
                            obstacle2 = new Obstacle(2);
                            human = new Human();
                            score = 0;
                            state = START;
                            break;
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };

        addMouseListener(l);

        // 不断的移动与重绘
        while (true) {
            switch (state) {
                case START:
                    // 地面及背景向左移动一步
                    human.step();
                    ground.step();
                    break;
                case RUNNING:
                    //整个画面移动
                    ground.step();
                    obstacle1.step();
                    obstacle2.step();
                    human.step();
                    // 计算分数
                    if (human.x == obstacle1.x || human.x == obstacle2.x) {
                        score++;
                    }
                     //是否发生碰撞
                    if (human.hit(obstacle1) || human.hit(obstacle2)) {
                        state = GAME_OVER;
                        break;
                    }
            }

            // 重新绘制界面
            repaint();
            // 休眠 1000/60 毫秒
            Thread.sleep(1000 / 60);
        }

    }

    /*
     启动方法
     */
    public static void main(String[] args) throws Exception {
        JFrame frame = new JFrame();
        RunningGame game = new RunningGame();
        frame.add(game);
        frame.setSize(700, 480);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        game.action();

    }
}

下面是运行界面截图

 

 

  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值