您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

奔跑吧恐龙----基于JavaSwing的一个跑酷游戏

1.游戏功能

随机出现障碍物,人物可以通过向上跳进行避免,游戏结束后出现分数,对难度进行一定的控制:当分数>1000时难度升级,当分数>4000时,难度再进行升级,并存在音乐播放功能。

2.具体实现

2.1 model

(1)Dinosaur类

游戏人物。主要有构造方法,移动方法、跳跃方法,获取边界方法用于碰撞检测。

构造方法:加载图片、定义人物的x,y坐标

step():主要是通过变换恐龙的图片来达到走路的动作

jump():跳跃

move():移动方法通过是否处于跳跃状态分成两种

剩下的一些为getset方法

package com.study.dinosaur.model;

import com.study.dinosaur.service.FreshThread;
import com.study.dinosaur.service.Sound;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/***
 * 恐龙类
 */
public class Dinosaur {
    public BufferedImage image;   //主图片
    public BufferedImage image1,image2,image3;   //跑步图片
    public int x,y;//坐标
    private int jumpValue=0;   //跳跃的增变量
    private boolean jumpState=false;   //跳跃状态
    private int stepTimer=0;      //踏步计时器
    private final int JUMP_HIGHT=120;   //跳起的最大高度
    private final int LOWEST_Y=415;    //落地的最低坐标
    private final int FREASH= FreshThread.FRESH;      //刷新时间

    /**
     * 构造函数
     * @throws IOException
     */
    public Dinosaur() throws IOException {
        x=50;
        y=LOWEST_Y;
        image1= ImageIO.read(new File("D:\\JavaProject\\JavaGames\\dinosaur\\image\\dinosaur1.png"));
        image2= ImageIO.read(new File("D:\\JavaProject\\JavaGames\\dinosaur\\image\\dinosaur2.png"));
        image3= ImageIO.read(new File("D:\\JavaProject\\JavaGames\\dinosaur\\image\\dinosaur3.png"));
    }

    /***
     * 踏步向前移动
     */
    public void step(){
        //每过250毫秒就更换一张图片
        int tmp=stepTimer/250 %3;
        switch (tmp){
            case 1:
                image=image1;
                break;
            case 2:
                image=image2;
                break;
            default:
                image=image3;  //没有奔跑的图片
        }
        stepTimer+=FREASH;
    }

    /**
     * 跳跃的动作
     */
    public void jump(){
        if(!jumpState){
            Sound.jump();
        }
        jumpState=true;
    }

    /**8
     * 移动
     * 1.向前走
     * 2.跳跃
     */
    public void move(){
        step();
        if(jumpState){
            if(y>=LOWEST_Y){
                jumpValue=-4;
            }
            if(y<=LOWEST_Y-JUMP_HIGHT){
                jumpValue=4;
            }
            y+=jumpValue;
            if(y>=LOWEST_Y){
                jumpState=false;
            }
        }
    }

    public Rectangle getFootBounds() {
        return new Rectangle(x + 25, y + 100, 45, 44);
    }

    public Rectangle getHeadBounds() {
        return new Rectangle(x + 55, y + 50, 50, 25);
    }

    public BufferedImage getImage() {
        return image;
    }

    public void setImage(BufferedImage image) {
        this.image = image;
    }

    public BufferedImage getImage1() {
        return image1;
    }

    public void setImage1(BufferedImage image1) {
        this.image1 = image1;
    }

    public BufferedImage getImage2() {
        return image2;
    }

    public void setImage2(BufferedImage image2) {
        this.image2 = image2;
    }

    public BufferedImage getImage3() {
        return image3;
    }

    public void setImage3(BufferedImage image3) {
        this.image3 = image3;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getJumpValue() {
        return jumpValue;
    }

    public void setJumpValue(int jumpValue) {
        this.jumpValue = jumpValue;
    }

    public boolean isJumpState() {
        return jumpState;
    }

    public void setJumpState(boolean jumpState) {
        this.jumpState = jumpState;
    }

    public int getStepTimer() {
        return stepTimer;
    }

    public void setStepTimer(int stepTimer) {
        this.stepTimer = stepTimer;
    }

    public int getJUMP_HIGHT() {
        return JUMP_HIGHT;
    }

    public int getLOWEST_Y() {
        return LOWEST_Y;
    }

    public int getFREASH() {
        return FREASH;
    }
}

(2)Obstacle类

障碍主要有仙人掌和石头两类,在构造方法中利用random进行随机生成;

isLive():主要是判断此时障碍是否还在当前游戏面板内,方便碰撞检测

package com.study.dinosaur.model;

import com.study.dinosaur.view.BackgroundImage;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

/**
 * 障碍类
 */
public class Obstacle {

    public int x,y;
    BufferedImage image;
    BufferedImage stone;
    BufferedImage cacti;
    private int speed;

    public Obstacle() throws IOException {
        stone= ImageIO.read(new File("D:\\JavaProject\\JavaGames\\dinosaur\\image\\rock.png"));
        cacti=ImageIO.read(new File("D:\\JavaProject\\JavaGames\\dinosaur\\image\\cacti.png"));
        Random random=new Random();
        if(random.nextInt(2)==0){
            image=cacti;
        }else{
            image=stone;
        }
        x=1024;
        y=560-image.getHeight();
        speed= BackgroundImage.SPEED;
    }


    public void move(){
        x-=speed;
    }

    public boolean isLive(){
        if(x<=-image.getWidth()){
            return false;
        }
        return true;
    }

    public Rectangle getBounds(){
        if (image==cacti){
            return new Rectangle(x,y,24,image.getHeight()-1);
        }
        return new Rectangle(x+5,y,32,28);
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public BufferedImage getImage() {
        return image;
    }

    public void setImage(BufferedImage image) {
        this.image = image;
    }

    public BufferedImage getStone() {
        return stone;
    }

    public void setStone(BufferedImage stone) {
        this.stone = stone;
    }

    public BufferedImage getCacti() {
        return cacti;
    }

    public void setCacti(BufferedImage cacti) {
        this.cacti = cacti;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    @Override
    public String toString() {
        return "Obstacle{" +
                "x=" + x +
                ", y=" + y +
                ", image=" + image +
                ", stone=" + stone +
                ", cacti=" + cacti +
                ", speed=" + speed +
                '}';
    }
}

2.2 Service

(1)MusicPlayer

主要是新开一个线程进行音乐的播放。

读取音乐文件后写入混频器源数据行:

 1.声明一个128k的缓冲区
 2.不断循坏将音乐文件读入缓冲区
 3.将缓冲区数据写入混频器源数据行

package com.study.dinosaur.service;

import javax.sound.sampled.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class MusicPlayer implements Runnable {
    File soundFile;
    Thread thread;
    boolean circulate;

    public MusicPlayer(String filePath, boolean circulate) throws FileNotFoundException {
        this.soundFile = new File(filePath);
        this.circulate = circulate;
        if(!soundFile.exists()){
            throw new FileNotFoundException(filePath+"文件未找到");
        }
    }

    /***
     * run()方法播放
     * 1.声明一个128k的缓冲区
     * 2.不断循坏将音乐文件读入缓冲区
     * 3.将缓冲区数据写入混频器源数据行
     */
    @Override
    public void run() {
        byte[] auBuffer=new byte[1024*128];
        do{
            AudioInputStream audioInputStream=null;
            SourceDataLine auline=null;
            try {
                //将音乐文件写入缓冲区
                audioInputStream= AudioSystem.getAudioInputStream(soundFile);
                AudioFormat  format=audioInputStream.getFormat();
                DataLine.Info info=new DataLine.Info(SourceDataLine.class,format);
                auline= (SourceDataLine) AudioSystem.getLine(info);
                auline.open(format);
                auline.start();
                int byteCount=0;
                while(byteCount!=-1){
                    //读取缓冲区文件
                    byteCount=audioInputStream.read(auBuffer,0,auBuffer.length);
                    //存在文件就写入
                    if(byteCount>=0){
                        auline.write(auBuffer,0,byteCount);
                    }
                }
            } catch (UnsupportedAudioFileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (LineUnavailableException e) {
                e.printStackTrace();
            }finally {
                //一定要执行的操作
                auline.drain();
                auline.close();
            }
        }while(circulate);
    }
   //开始播放
    public void play(){
        thread=new Thread();
        thread.start();
    }
   //停止播放
    public void stop(){
        thread.stop();
    }
}

(2)Sound类

音乐播放器类主要是启动musicPlayer,同时供游戏面板调用

package com.study.dinosaur.service;

import java.io.FileNotFoundException;

/***
 * 音乐播放器类
 */
public class Sound {
    public static final String DIR = "D:\\JavaProject\\JavaGames\\dinosaur\\music\\";
    public static final String BACKGROUND = "background.wav";
    public static final String JUMP = "jump.wav";
    public static final String HIT = "hit.wav";

    private static void play(String file, boolean circulate) {
        try {
            MusicPlayer player = new MusicPlayer(file, circulate);
            player.play();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void jump(){
        play(DIR+JUMP,false);
    }
    public static void hit(){
        play(DIR+HIT,false);
    }
    public static void background(){
        play(DIR+BACKGROUND,true);
    }

}

(3)计分模块

package com.study.dinosaur.service;

import java.io.*;
import java.util.Arrays;

/**8
 * 计分
 */

public class ScoreRecorder {
    private static final String SCOREFILE = "D:\\JavaProject\\JavaGames\\dinosaur\\data\\source";
    private static int[] scores = new int[3];

    public static void init(){
        //新建文件
        File file = new File(SCOREFILE);
        if (!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        FileInputStream fileInputStream = null;
        InputStreamReader reader = null;
        BufferedReader bufferedReader = null;

        try {
            fileInputStream = new FileInputStream(file);
            reader = new InputStreamReader(fileInputStream);
            bufferedReader = new BufferedReader(reader);
            String value = bufferedReader.readLine();
            if (!(value==null||"".equals(value))){
                String[] values = value.split(",");
                if (values.length<3){
                    Arrays.fill(scores,0);
                }else {
                    for (int i = 0; i < 3; i++) {
                        scores[i] = Integer.parseInt(values[i]);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if (bufferedReader != null) {
                    bufferedReader.close();
                    reader.close();
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void saveScore(){
        String value = scores[0]+","+scores[1]+","+scores[2];
        FileOutputStream fileOutputStream = null;
        OutputStreamWriter writer = null;
        BufferedWriter bufferedWriter = null;

        try{
            fileOutputStream = new FileOutputStream(SCOREFILE);
            writer = new OutputStreamWriter(fileOutputStream);
            bufferedWriter = new BufferedWriter(writer);
            bufferedWriter.write(value);
            bufferedWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try{
                if (bufferedWriter != null) {
                    bufferedWriter.close();
                    writer.close();
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void addNewScore(int score){
        int[] temp = Arrays.copyOf(scores,4);
        temp[3] = score;
        Arrays.sort(temp);
        scores = Arrays.copyOfRange(temp,1,4);
    }
    public static int[] getScores(){
        return scores;
    }
}

(4)刷新页面模块

package com.study.dinosaur.service;

import com.study.dinosaur.view.GamePanel;
import com.study.dinosaur.view.MainFrame;
import com.study.dinosaur.view.ScoreDialog;

import java.awt.*;
import java.io.IOException;


public class FreshThread extends Thread {
    public static final int FRESH = 20;
    public GamePanel gamePanel;

    public FreshThread(GamePanel gamePanel) {
        this.gamePanel = gamePanel;
    }

    @Override
    public void run() {
        while (!gamePanel.isFinish()) {
            gamePanel.repaint();
            try {
                Thread.sleep(FRESH);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Container c = gamePanel.getParent();
        while (!(c instanceof MainFrame)) {
            c = c.getParent();
        }
        MainFrame frame = (MainFrame) c;
        new ScoreDialog(frame);
        try {
            frame.restart();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

2.3 View层

 (1)主面板

package com.study.dinosaur.view;

import com.study.dinosaur.service.ScoreRecorder;
import com.study.dinosaur.service.Sound;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

public class MainFrame extends JFrame {
    public MainFrame() throws IOException {
        restart();
        setBounds(340,150,1024,720);
        setTitle("奔跑吧!小恐龙!");
        Sound.background();
        ScoreRecorder.init();
        addListener();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setVisible(true);
    }
    public void restart() throws IOException {
        Container c = getContentPane();
        c.removeAll();
        GamePanel gamePanel = new GamePanel();
        c.add(gamePanel);
        addKeyListener(gamePanel);
        c.validate();
    }
    private void addListener(){
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
              //  ScoreRecorder.saveScore();
            }
        });
    }
}

(2)游戏面板

package com.study.dinosaur.view;

import com.study.dinosaur.model.Dinosaur;
import com.study.dinosaur.model.Obstacle;
import com.study.dinosaur.service.FreshThread;
import com.study.dinosaur.service.ScoreRecorder;
import com.study.dinosaur.service.Sound;


import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 主要的游戏面板类
 */
public class GamePanel extends JPanel implements KeyListener {
    private BufferedImage image;
    private BackgroundImage background;
    private Dinosaur golden;
    private Graphics2D graphics2D;
    private int addObstacleTimer = 0;
    private boolean finish = false;
    //障碍的list
    private List<Obstacle> list =new ArrayList<Obstacle>();
    private final int FRESH = FreshThread.FRESH;
    private int score = 0;
    private int scoreTimer = 0;

    public GamePanel() throws IOException {
        image = new BufferedImage(1024, 720, BufferedImage.TYPE_INT_RGB);
        graphics2D = image.createGraphics();
        background = new BackgroundImage();
        golden = new Dinosaur();
        list.add(new Obstacle());
        FreshThread t = new FreshThread(this);
        t.start();
    }

    private void paintImage() throws IOException {
        //控制移动速度
        if (score > 1000) {
            BackgroundImage.SPEED = 5;
        }
        if (score > 4000) {
            BackgroundImage.SPEED = 7;
        }
        background.roll();
        golden.move();
        graphics2D.drawImage(background.image, 0, 0, 1024, 720, this);
        graphics2D.drawImage(golden.getImage(), golden.getX(), golden.getY(), this);
        if (addObstacleTimer >= 130 + Math.random() * 100 + 1000) {
            if (Math.random() * 100 > 60) {
                list.add(new Obstacle());
            }
            addObstacleTimer = 0;
        }
        for (int i = 0; i < list.size(); i++) {
            Obstacle obstacle = list.get(i);
            if (obstacle.isLive()) {
                obstacle.move();
                graphics2D.drawImage(obstacle.getImage(), obstacle.getX(), obstacle.getY(), this);
                if (obstacle.getBounds().intersects(golden.getFootBounds()) || obstacle.getBounds().intersects(golden.getHeadBounds())) {
                    Sound.hit();
                    gameOver();
                }
            } else {
                list.remove(i);
                i--;
            }
        }
        graphics2D.setColor(Color.BLACK);
        graphics2D.setFont(new Font("MS Song", Font.BOLD, 24));
        graphics2D.drawString(String.format("%6d", score), 900, 30);
        addObstacleTimer += FRESH;
        scoreTimer += FRESH;
        score += 1;
    }

    @Override
    public void paint(Graphics graphics) {
        try {
            paintImage();
        } catch (IOException e) {
            e.printStackTrace();
        }
        graphics.drawImage(image, 0, 0, this);
    }

    public void gameOver() {
        ScoreRecorder.addNewScore(score);
        finish = true;
    }

    public boolean isFinish() {
        return finish;
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if (code == KeyEvent.VK_SPACE) {
            golden.jump();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }
}

(3)计分器

package com.study.dinosaur.view;


import com.study.dinosaur.service.ScoreRecorder;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * Created by IntelliJ IDEA.
 *
 * @author : JarvisHsu
 * @create 2020/08/20 16:45
 */
public class ScoreDialog extends JDialog {
    public ScoreDialog(JFrame frame){
        super(frame,true);
        int[] scores = ScoreRecorder.getScores();
        JPanel scoreP = new JPanel(new GridLayout(4, 1));
        scoreP.setBackground(Color.white);
        JLabel title = new JLabel("得分排行榜", JLabel.CENTER);
        title.setFont(new Font("MS Song",Font.BOLD,20));
        title.setForeground(Color.RED);
        JLabel first = new JLabel("第一名:" + scores[2], JLabel.CENTER);
        JLabel second = new JLabel("第二名:" + scores[1], JLabel.CENTER);
        JLabel third = new JLabel("第三名:" + scores[0], JLabel.CENTER);
        JButton restart = new JButton("重新开始");
        restart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        scoreP.add(title);
        scoreP.add(first);
        scoreP.add(second);
        scoreP.add(third);

        Container c = getContentPane();
        c.setLayout(new BorderLayout());
        c.add(scoreP,BorderLayout.CENTER);
        c.add(restart,BorderLayout.SOUTH);

        setTitle("游戏结束");
        int width,height;
        width=height=200;
        int x = frame.getX()+(frame.getWidth()-width)/2;
        int y = frame.getY()+(frame.getHeight()-height)/2;
        setBounds(x,y,width,height);
        setVisible(true);
    }
}

(4)背景

package com.study.dinosaur.view;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * Created by IntelliJ IDEA.
 *
 * @author : JarvisHsu
 * @create 2020/08/20 16:45
 */
public class BackgroundImage {
    public BufferedImage image;
    private BufferedImage image1,image2;
    private Graphics2D graphics2D;
    public int x1,x2;
    public static int SPEED = 4;

    public BackgroundImage(){
        try {
            image1 = ImageIO.read(new File("D:\\JavaProject\\JavaGames\\dinosaur\\image\\background.png"));
            image2 = ImageIO.read(new File("D:\\JavaProject\\JavaGames\\dinosaur\\image\\background.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        image = new BufferedImage(1024,720,BufferedImage.TYPE_INT_RGB);
        graphics2D = image.createGraphics();
        x1 = 0;
        x2 = 1024;
        graphics2D.drawImage(image1,x1,0,null);
    }
    public void roll(){
        x1 -=SPEED;
        x2 -=SPEED;
        if (x1<=-800){
            x1=800;
        }
        if (x2<=-800){
            x2 = 800;
        }
        graphics2D.drawImage(image1,x1,0,null);
        graphics2D.drawImage(image2,x2,0,null);
    }
}

2.5 程序启动类

 

package com.study.dinosaur;

import com.study.dinosaur.view.MainFrame;

import java.io.IOException;

public class GameStart {
    public static void main(String[] args) throws IOException {
        new MainFrame();
    }
}


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进