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;}@Overridepublic 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.将缓冲区数据写入混频器源数据行*/@Overridepublic 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;}@Overridepublic 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() {@Overridepublic 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;//障碍的listprivate 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;}@Overridepublic 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;}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {int code = e.getKeyCode();if (code == KeyEvent.VK_SPACE) {golden.jump();}}@Overridepublic 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() {@Overridepublic 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();}
}

奔跑吧恐龙----基于JavaSwing的一个跑酷游戏相关推荐

  1. 如何使用c++制作一个跑酷游戏

    1.游戏引擎和开发环境的选择 如今市面上有很多成熟的游戏引擎可供选择,例如 Unity.Unreal Engine.Cocos2d-x 等.这些引擎均提供了完整的游戏开发框架,可以省去很多底层开发的工 ...

  2. 基于JavaSwing开发蜘蛛纸牌游戏 课程设计 大作业源码

    基于JavaSwing开发蜘蛛纸牌游戏:   (大作业) 开发环境: Windows操作系统 开发工具: Eclipse+Jdk 运行效果图: 基于JavaSwing开发蜘蛛纸牌游戏:   (大作业) ...

  3. 基于JavaSwing开发联机坦克游戏(服务器+客户端) 课程设计 大作业

    基于JavaSwing开发联机坦克游戏(服务器+客户端):   (大作业) 开发环境: Windows操作系统 开发工具: MyEclipse+Jdk 运行效果图: 基于JavaSwing开发联机坦克 ...

  4. 基于JavaSwing开发坦克大战游戏(单人或双人版) 课程设计 大作业 毕业设计

    基于JavaSwing开发坦克大战游戏(单人或双人版):   (大作业/毕业设计) 开发环境: Windows操作系统 开发工具: MyEclipse/Eclipse+Jdk 运行效果图:  基于Ja ...

  5. 基于JavaSwing开发中国跳棋游戏带论文 课程设计 大作业 毕业设计

    基于JavaSwing开发中国跳棋游戏:   (大作业/毕业设计) 开发环境: Windows操作系统 开发工具:Eclipse+Jdk 运行效果图:  基于JavaSwing开发中国跳棋游戏:    ...

  6. 基于JavaSwing开发魔塔小游戏 课程设计 大作业

    基于JavaSwing开发魔塔小游戏:   (大作业) 开发环境: Windows操作系统 开发工具: Eclipse+Jdk1.6 运行效果图: 基于JavaSwing开发魔塔小游戏:   (大作业 ...

  7. 用pygame编写一个跑酷游戏

    奔跑吧~小忍者 游戏运行后的效果 游戏初始运行状态 运行时候的状态 结束状态 初始化创建游戏界面 from loadImg import * import random# 窗口大小 SCREENSIZ ...

  8. 基于JavaSwing的简单的动作类游戏

    FightGame 介绍 借用拳皇和冒险岛素材的基于JavaSwing的动作类游戏. JDK 1.9 运行截图: 动态演示: 安装教程 下载本项目后导入eclipse即可. 存在问题 目前该游戏仍然存 ...

  9. 【Cocos2dx】跑酷游戏

    下面将用Cocos2dx完成一个跑酷游戏,跑酷游戏从头到尾包括美工完全可以一个人完成,就是比较耗费时间,只能达到能玩的程度而已. 做出来的跑酷游戏如下所示: 玩家能做的就只有一个动作,触摸屏幕,触摸屏 ...

最新文章

  1. CCF NOI1040 除法游戏
  2. otsu阈值分割算法_图像分割之大津算法(OTSU)
  3. fzu 1686(DLX 重复点覆盖)
  4. Google Palette算法详解以及OC化
  5. 如何快速成长为技术大牛?
  6. solaris 10 安装oracle 10g
  7. 【Linux系统编程】信号 (下)
  8. spring 注释_Spring核心注释
  9. 《JEECG_v3 开发手册》文档发布通知
  10. 我的世界手机版javaui材质包_传奇世界中变版手机版下载-传奇世界中变版手机版最新下载...
  11. java在线打开xml文件_java实现简单解析XML文件功能示例
  12. Windows系统镜像、PE系统下载地址大全
  13. python的pygame模拟太阳-地球-月亮-金星等动态示意图代码分析
  14. innodb_buffer_pool_reads、innodb_buffer_pool_read_requests分析与innodb 缓存命中率计算
  15. Axure实战——实现登录注册功能
  16. 自然语言处理NLP 2022年最新综述:An introduction to Deep Learning in Natural Language Processing
  17. Flutter绘制指南05-图形的路径添加
  18. 灵活自定义 PDF转换成Word转换器下载
  19. 什么是顶级域名?有哪些分类?
  20. Java Web前端到后台常用框架介绍

热门文章

  1. 正大国际期货:做期货交易,怎么样才能成功?
  2. 《终结拖延症》读书笔记,作者威廉·克瑙斯
  3. 视频教程-沐风老师Scratch3.0快速入门视频课程-其他
  4. 台式电脑显示屏显示html,台式机电脑屏幕突然出现彩色条纹原因及解决方法
  5. 坠落的蚂蚁【思维/模拟】
  6. 解决Windows莫名其妙地从休眠状态唤醒的问题
  7. 项目管理流程之人员管理阶段一
  8. 有多少“垃圾”App藏在你的手机里?
  9. 数商云B2B商城系统订货功能为新能源汽车行业赋能,打造高质量发展生态圈
  10. Android 智能遥控器源码,基于Android手机的智能遥控器设计