Java实战项⽬⼆(超详细)---奔跑吧⼩恐龙
奔跑吧⼩恐龙是⼀款简单的跑酷游戏(代码简单,适合初学者学习)。玩家控制⼩恐龙向前狂奔,躲避沿途出现的⽯头和仙⼈掌,跑的越远,分数越⾼。游戏内还增加了背景⾳乐、跳跃⾳乐和碰撞⾳乐。
本⽂的代码虽然长,但不难理解,希望⼤家能够耐⼼看完。
⽂中代码均可直接运⾏,完整代码请见github
(如果觉得有帮助,记得给个star,谢谢!)
⽂章⽬录
系统结构设计
游戏功能架构图
项⽬⽬录结构预览
游戏模型设计
恐龙类
1.定义
Dinosaur类的成员属性绝⼤多数都是私有属性,只有少数公有属性⽤于游戏⾯板绘图使⽤。Dinosaur类的私有属性包含3张来回切换的跑步照⽚:
Dinosaur类的定义如下:
public class Dinosaur {
public BufferedImage image;// 主图⽚
private 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 =100;// 跳起最⼤⾼度
private final int LOWEST_Y =120;// 落地最低坐标
private final int FREASH = FreshThread.FREASH;// 刷新时间--刷新帧线程
}
在Dinosaur类的构造⽅法中将恐龙的横坐标固定在50像素的位置,纵坐标采⽤落地时的坐标,具体代码如下:
public Dinosaur(){
x =50;// 恐龙的横坐标
y = LOWEST_Y;// 恐龙的纵坐标
try{
image1 = ad(new File("image/恐龙1.png"));// 读取恐龙的图⽚
image2 = ad(new File("image/恐龙2.png"));
image3 = ad(new File("image/恐龙3.png"));
}catch(IOException e){
e.printStackTrace();
}
}
2.踏步
游戏中恐龙的横坐标虽然⼀直没变,但背景的运动会造成恐龙向前移动的假象。Step()⽅法就是踏步动作的⽅法,具体代码如下:/**
* 踏步
*/
private void step(){
// 每过250毫秒,更换⼀张图⽚。因为共有3图⽚,所以除以3取余,轮流展⽰这三张
int tmp = stepTimer /250%3;// 0、1、2
switch(tmp){
case1:
image = image1;
break;
case2:
image = image2;
break;
default:
image = image3;
}
stepTimer += FREASH;// 计时器递增
}
3.跳跃
跳跃是⼩恐龙躲避障碍的动作,也是玩家可以控制恐龙做出的唯⼀动作。
具体代码如下:
/**
* 跳跃
*/
public void jump(){
if(!jumpState){// 如果没处于跳跃状态
Sound.jump();// 播放跳跃⾳效
}
jumpState =true;// 处于跳跃状态
}
4.移动
move()是恐龙移动⽅法,move()⽅法不断地调⽤step()踏步⽅法
stepTimer踏步计时器会有效控制图⽚地切换频率
move()⽅法地具体代码如下:
/**
* 移动
*/
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;// 停⽌跳跃
}
}
}
5.边界对象
java.awt.Rectangle类是举⾏边界类。为恐龙的头部和⾜部创建矩形边界对象,⽤于做碰撞测试
getFootBounds()⽅法⽤于获取恐龙的⾜部边界对象,具体代码如下:
/**
* ⾜部边界区域
*
* @return
*/
public Rectangle getFootBounds(){// 获取恐龙的脚部边界对象
return new Rectangle(x +30, y +59,29,18);// ⽤于后续做碰撞检测
}
getHeadBounds()⽅法⽤于获取恐龙的头部边界对象,具体代码如下:
/**
* 头部边界区域
*
* @return
*/
public Rectangle getHeadBounds(){// 获取恐龙的头部边界对象
return new Rectangle(x +66, y +25,32,22);// new Rectangle(x, y, width, height)
}
障碍类
游戏中的障碍有两种,⼀种是很矮的⽯头,另⼀种是很⾼的仙⼈掌,如下图所⽰。恐龙碰到任何⼀种障碍,都会导致游戏的结束:
1.定义
项⽬中的dle.Obstacle类是障碍类,
因为所有的障碍都会随着背景⼀起移动,所以障碍的移动速度采⽤背景图⽚的速度。Obstacle类的定义如下:
public class Obstacle {
public int x, y;// 横纵坐标
public BufferedImage image;
private BufferedImage stone;// ⽯头图⽚---(32,26)
private BufferedImage cacti;// 仙⼈掌图⽚---(32,59)
private int speed;// 移动速度--图⽚跟着背景⾛
}
在Obstacle类的构造⽅法中,Obstacle对象会随机成为⽯头或者仙⼈掌。具体代码如下:
public Obstacle(){
try{
stone = ad(new File("image/⽯头.png"));// ⽯头图⽚
cacti = ad(new File("image/仙⼈掌.png"));// 仙⼈掌图⽚
}catch(IOException e){
e.printStackTrace();
}
Random r =new Random();// 创建随机对象
Int(2)==0){// 从0和1中取⼀值,若为0
image = cacti;// 采⽤仙⼈掌图⽚
简单的java游戏代码}else{
image = stone;// 采⽤⽯头图⽚
}
x =800;// 初始横坐标
y =Height();// 纵坐标--使图⽚处在地平线上
//  System.out.Width());
speed = BackgroundImage.SPEED;// 移动速度与背景同步--BackgroundImage=背景
}
2.移动
Obstacle类中的move()⽅法可以让障碍在游戏画⾯中移动,且移动速度与背景图⽚的移动速度相同。move()⽅法的具体代码如下:/**
* 移动
*/
public void move(){
x -= speed;// 横坐标递减--障碍物的速度与背景的速度⼀致
}
3.消除
当障碍移动出游戏画⾯之后,就不会再对游戏产⽣任何影响。
要及时将移出画⾯之外的障碍删除掉,isLive()⽅法⽤于获取障碍的有效状态。isLive()的具体代码如下:
/**
* 是否存活
*
* @return
*/
public boolean isLive(){
// 如果移出了游戏界⾯
if(x <=-Width()){
return false;// 消亡
}
return true;// 存活
}
4.边界对象
障碍的边界对象⽤于做碰撞检测计算。
⽤getBounds()⽅法返回边界对象,该⽅法的具体代码如下:
/**
* 获取边界
*
* @return
*/
// 通过getBounds()⽅法返回边界对象
public Rectangle getBounds(){
if(image == cacti){// 如果使⽤仙⼈掌图⽚
// 返回仙⼈掌的边界
return new Rectangle(x +7, y,15, Height());
}
// 返回⽯头的边界
return new Rectangle(x +5, y +4,23,21);
}
⾳效模块设计
本节介绍如何利⽤java代码播放⾳乐⽂件。
JDK⽀持播放的⾳乐格式⾮常少,本章使⽤的所有⾳乐⽂件均为WAVE格式。JDK⽀持的具体⾳乐格式可以参考
javax.sound.sampled.AudioFileFormat.Type类
⾳频播放器
项⽬中的service.MusicPlayer类是⾳频播放器类,该类使⽤javax.sound.sampled包提供的混⾳器⼯具实现⾳频播放功能。MusicPlayer类实现了Runnerable接⼝,并在成员属性中定义了⼀个线程对象,该线程对象⽤于启动混⾳器数据⾏的读写业务。MusicPlayer类的定义如下:
```java
/**
* ⾳乐播放器
*/
public class MusicPlayer implements Runnable {
File soundFile;// ⾳乐⽂件
Thread thread;// ⽗线程 -- 执⾏run⽅法
boolean circulate;// 是否循环播放
MusicPlayer类的构造⽅法有两个参数,filepath表⽰⾳乐⽂件的完整⽂件名,circulate表⽰是否重复播放。MusicPlayer类构造⽅法的具体代码如下:
/**
* 构造⽅法
*
* @param filepath  ⾳乐⽂件完整名称
* @param circulate 是否循环播放
* @throws FileNotFoundException
*/
// 构造⽅法--2
public MusicPlayer(String filepath,boolean circulate)throws FileNotFoundException {
this.circulate = circulate;
soundFile =new File(filepath);// File soundFile
if(!ists()){// 如果⽂件不存在
throw new FileNotFoundException(filepath +"未到");// 抛出错误,⽂件未到
}
}
MusicPlayer类要实现Runnable接⼝,必须先实现run()⽅法。
在run()⽅法中声明了⼀个128K的缓冲区字节数组,程序以不断循环的⽅式将⾳乐⽂件以⾳频输⼊流格式读⼊缓冲区,再把缓冲区的数据写⼊混⾳器源数据⾏中,实现播放⾳乐的效果。run()⽅法的具体代码如下:
```java
/**
* ⾳乐播放器
*/
public class MusicPlayer implements Runnable {
File soundFile;// ⾳乐⽂件
Thread thread;// ⽗线程 -- 执⾏run⽅法
boolean circulate;// 是否循环播放
MusicPlayer类的构造⽅法有两个参数,filepath表⽰⾳乐⽂件的完整⽂件名,circulate表⽰是否重复播放。MusicPlayer类构造⽅法的具体代码如下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。