一、个人负责模块
将障碍物和敌人绘制到场景中,并且设置隐形通关要点。实现初始化类用于存放所需要的所有静态文件,并将所有需要用到的图片进行分类。
二、个人任务简述
2.1 BackGround类的实现
该类表示马里奥及障碍物和敌人所处的场景,并且将障碍物和敌人绘制到场景中。在该类中包括用于存放敌人和障碍物的list集合,以及当敌人或者障碍物被消灭后用于存放已经消失的敌人和障碍物的集合,这样做是为了在马里奥死亡时重置场景所用的。其次在该类中还使用了控制敌人移动的方法,是为了在程序之初控制敌人静止,然后在玩家点击空格以后在使得敌人开始移动。并且在第六个关卡处设置了一个隐形通关要点,只有当马里奥顶到这个隐形砖块时才会出现马里奥就可以借助这个砖块通过关卡。
2.1.1定以并私有化所需成员变量
//当前场景图片
private BufferedImage bgImage = null;
//场景顺序
private int sort;
//是否为最后的场景
private boolean flag;
//游戏结束标记
private boolean isOver = false;
//定义降旗结束
private boolean isDown = false;
//用集合保存敌人
private List<Enemy> allEnemy = new ArrayList<Enemy>();
//用集合保存障碍物
private List<Obstruction> allObstruction = new ArrayList<Obstruction>();
//被消灭的敌人
private List<Enemy> removeEnemy = new ArrayList<Enemy>();
//被消灭的障碍物
//这是我们小组新增加的功能,当玩家用头顶到砖块障碍物时,障碍物会消失
private List<Obstruction> removeObstruction = new ArrayList<Obstruction>();
2.1.2 实现敌人开始移动方法
该方法中使用了控制敌人移动的方法,是为了在程序之初控制敌人静止,然后玩家点击空格之后使得敌人开始移动。
//敌人开始移动
public void enemyStartMove(){
for(int i=0;i<this.allEnemy.size();i++){
//循环遍历怪兽集合
this.allEnemy.get(i).startMove();
//调用怪兽startMove()方法,让对应怪兽作出反应
}
}
2.1.3 实现构造方法并绘制场景
该方法是一个构造方法,传递当前所处关卡以及是否是最后一个关卡信息,并且绘制相应关卡场景。
2.1.3.1构造方法
//构造方法
//这是一个关卡对应的构造方法,该构造方法用于传递当前所处关卡以及是否是最后一个关卡信息,并且绘制场景
public BackGround(int sort,boolean flag){
//当前所处关卡
this.sort = sort;
//是否是最后一个关卡
this.flag = flag;
//此处暂时省略场景绘制代码
}
2.1.3.2绘制对应关卡场景
对sort进行判断,并且绘制对应关卡场景。
类型0为可消失的方块,当玩家头顶到这里时会消失;类型为1的是蘑菇怪;类型为2的是食人花;类型为3的是隐形砖块,只有当玩家头到这个砖块时才显现;类型4为问号砖块,当玩家头顶到这里时会加十分;类型为5、6、7和8的是水管碎片;类型9为地面土块。
关卡一
if(flag){
//如果是最后一个关卡的话,背景图片换成endImage
bgImage = StaticValue.endImage;
}else{
//如果不是最后一张一个关卡,则使用bgImage图片
bgImage = StaticValue.bgImage;
}
//不同之处:背景图片是否有旗杆
//关卡一
//绘制土块,完整无坑
if(sort==1){
for(int i=0;i<15;i++){
this.allObstruction.add(new Obstruction(i*60, 540, 9,this));
}
//绘制砖块和问号
//type为0表示可消失的粗糙砖块
//type为4表示平滑砖块
//Y为360高度的六块砖块
//砖块大小60*60
this.allObstruction.add(new Obstruction(120, 360, 4,this));
this.allObstruction.add(new Obstruction(300, 360, 0,this));
this.allObstruction.add(new Obstruction(360, 360, 4,this));
this.allObstruction.add(new Obstruction(420, 360, 0,this));
this.allObstruction.add(new Obstruction(480, 360, 4,this));
this.allObstruction.add(new Obstruction(540, 360, 0,this));
//y为180高度的砖块
this.allObstruction.add(new Obstruction(420, 180, 4,this));
//砖块绘制完成
//绘制水管
//将四张图片拼接,构成水管
//水管碎片大小:60*60
this.allObstruction.add(new Obstruction(660, 540, 6,this));
this.allObstruction.add(new Obstruction(720, 540, 5,this));
this.allObstruction.add(new Obstruction(660, 480, 8,this));
this.allObstruction.add(new Obstruction(720, 480, 7,this));
//隐藏砖块
//新增创意,只有当玩家触碰到这里时,这个隐藏的砖块才会显示
this.allObstruction.add(new Obstruction(660, 300, 3,this));
//绘制怪物
//蘑菇怪:可以被玩家踩死
this.allEnemy.add(new Enemy(600, 480, true, 1,this));
//食人花:放置水管上面的中央
this.allEnemy.add(new Enemy(690, 540, true, 2, 420, 540,this));
}
效果图:
关卡二
//关卡二:
//绘制土块
if(sort==2){
for(int i=0;i<15;i++){
if(i != 9 && i != 10 && i != 11 ){
//if判断用于留下一个坑
this.allObstruction.add(new Obstruction(i*60, 540, 9,this));
}
}
//绘制水管一
//最下一层
this.allObstruction.add(new Obstruction(60, 540, 6,this));
this.allObstruction.add(new Obstruction(120, 540, 5,this));
//第二层
this.allObstruction.add(new Obstruction(60, 480, 6,this));
this.allObstruction.add(new Obstruction(120, 480, 5,this));
//水管顶部
this.allObstruction.add(new Obstruction(60, 420, 8,this));
this.allObstruction.add(new Obstruction(120, 420, 7,this));
//绘制水管二,比水管一多一层
//最下边一层
this.allObstruction.add(new Obstruction(300, 540, 6,this));
this.allObstruction.add(new Obstruction(360, 540, 5,this));
//第二层
this.allObstruction.add(new Obstruction(300, 480, 6,this));
this.allObstruction.add(new Obstruction(360, 480, 5,this));
//第三层
this.allObstruction.add(new Obstruction(300, 420, 6,this));
this.allObstruction.add(new Obstruction(360, 420, 5,this));
//水管顶部
this.allObstruction.add(new Obstruction(300, 360, 8,this));
this.allObstruction.add(new Obstruction(360, 360, 7,this));
//绘制怪物
this.allEnemy.add(new Enemy(330, 360, true, 2, 300, 420,this));
}
效果图:
关卡三
//第三个场景
if(sort==3){
//循环添加土块
for(int i=0;i<15;i++){
this.allObstruction.add(new Obstruction(i*60, 540, 9,this));
}
//绘制砖块,绘制四个平滑砖块在场景中
this.allObstruction.add(new Obstruction(180, 360, 4,this));
this.allObstruction.add(new Obstruction(420, 360, 4,this));
this.allObstruction.add(new Obstruction(660, 360, 4,this));
this.allObstruction.add(new Obstruction(420, 180, 4,this));
}
效果图:
关卡四
//第四个场景
if(sort==4){
for(int i=0;i<15;i++){
//在两侧绘制土块
if(i<2||i>12){
this.allObstruction.add(new Obstruction(i*60, 540, 9,this));
}
}
//该场景添加砖块全部为可消失的粗糙砖块
//也是给玩家设计的陷阱,一不小心碰掉关键方块,通关将会是一个难题
//左侧下方两个
this.allObstruction.add(new Obstruction(120, 360, 0,this));
this.allObstruction.add(new Obstruction(180, 360, 0,this));
//中间上方五个
this.allObstruction.add(new Obstruction(300, 180, 0,this));
this.allObstruction.add(new Obstruction(360, 180, 0,this));
this.allObstruction.add(new Obstruction(420, 180, 0,this));
this.allObstruction.add(new Obstruction(480, 180, 0,this));
this.allObstruction.add(new Obstruction(540, 180, 0,this));
//右侧下方两个
this.allObstruction.add(new Obstruction(660, 360, 0,this));
this.allObstruction.add(new Obstruction(720, 360, 0,this));
}
我们发现,中间上方四个五个砖块,代码重复较多,这里可以简化代码:
for(int i=300;i<=540;i+=60){
this.allObstruction.add(new Obstruction(i,180,0,this))
}
运行效果:
关卡五
//第五个场景
if(sort==5){
//z用来协助后一半土块的放置
int z = 2;
for(int i=0;i<15;i++){
//i小于七的时候,从底到高堆积
if(i%2==0 && i<7){
//i为双数堆积土块儿
//最上面堆积长草的土块
this.allObstruction.add(new Obstruction(i*60, 540-(i*60), 9,this));
//循环给长草土块下面堆积没有长草的土块
for(int x=i;x>0;x--){
this.allObstruction.add(new Obstruction(i*60, 540-(x*60)+60, 10,this));
}
}
//i>7的时候,反过来,与小于七的部分对称
if(i%2==0 && i>7){
//先给最上面放带有草坪的土块
this.allObstruction.add(new Obstruction(i*60, 540-((i-z)*60), 9,this));
for(int x=i-z;x>0;x--){
//循环给下面放置土块
this.allObstruction.add(new Obstruction(i*60, 540-(x*60)+60, 10,this));
}
z+=4;//为下一次循环做准备
}
}
}
运行结果:
关卡六
本关设置隐形通关要点,需要玩家不断尝试才能发现。
//第六个场景
if(sort==6){
for(int i=0;i<15;i++){
//循环遍历,完成草地的绘制
this.allObstruction.add(new Obstruction(i*60, 540, 9,this));
}
//绘制石块
//逐行递减,实现阶梯型画面
//六块
this.allObstruction.add(new Obstruction(480, 480, 1,this));
this.allObstruction.add(new Obstruction(480, 420, 1,this));
this.allObstruction.add(new Obstruction(480, 360, 1,this));
this.allObstruction.add(new Obstruction(480, 300, 1,this));
this.allObstruction.add(new Obstruction(480, 240, 1,this));
this.allObstruction.add(new Obstruction(480, 180, 1,this));
//五块
this.allObstruction.add(new Obstruction(540, 240, 1,this));
this.allObstruction.add(new Obstruction(540, 300, 1,this));
this.allObstruction.add(new Obstruction(540, 360, 1,this));
this.allObstruction.add(new Obstruction(540, 420, 1,this));
this.allObstruction.add(new Obstruction(540, 480, 1,this));
//四块
this.allObstruction.add(new Obstruction(600, 300, 1,this));
this.allObstruction.add(new Obstruction(600, 360, 1,this));
this.allObstruction.add(new Obstruction(600, 420, 1,this));
this.allObstruction.add(new Obstruction(600, 480, 1,this));
//三块
this.allObstruction.add(new Obstruction(660, 360, 1,this));
this.allObstruction.add(new Obstruction(660, 420, 1,this));
this.allObstruction.add(new Obstruction(660, 480, 1,this));
//两块
this.allObstruction.add(new Obstruction(720, 420, 1,this));
this.allObstruction.add(new Obstruction(720, 480, 1,this));
//一块
this.allObstruction.add(new Obstruction(780, 480, 1,this));
//通关要点,隐形砖块
this.allObstruction.add(new Obstruction(300, 360, 3,this));
}
我们发现,中间上方四个五个砖块,代码重复较多,这里可以简化代码:
//由于以上方法代码重复比较多,这里来实现代码优化:
for(int i=8;i<=13;i++){
for(int j=0;j<14-i;j++){
this.allObstruction.add(new Obstruction(i*60,480-60*j, 1, this));
}
}
运行效果:
关卡七
本关为最后一个场景,这里更换了背景图片,以实现旗杆的显示效果。
//第七个场景
if(sort==7){
for(int i=0;i<15;i++){
//平铺草快地面
this.allObstruction.add(new Obstruction(i*60, 540, 9,this));
}
//绘制旗子
this.allObstruction.add(new Obstruction(490, 180, 11,this));
//旗子下面的方块
this.allObstruction.add(new Obstruction(520, 480, 2,this));
//地上障碍物
this.allObstruction.add(new Obstruction(240, 360, 1,this));
this.allObstruction.add(new Obstruction(240, 420, 1,this));
this.allObstruction.add(new Obstruction(180, 420, 1,this));
this.allObstruction.add(new Obstruction(240, 480, 1,this));
this.allObstruction.add(new Obstruction(180, 480, 1,this));
this.allObstruction.add(new Obstruction(120, 480, 1,this));
}
运行效果:
2.1.4 重置障碍物和敌人方法
编写场景重置方法,这样做是为了在马里奥死亡时重置场景所用的。
//重置方法,重置障碍物和敌人
public void reset(){
//将移除的怪物还原
this.allEnemy.addAll(this.removeEnemy);
//将移除的障碍物还原
this.allObstruction.addAll(this.removeObstruction);
//循环遍历将怪物重置
for(int i=0;i<this.allEnemy.size();i++){
this.allEnemy.get(i).reset();
}
//循环遍历将障碍物重置
for(int i=0;i<this.allObstruction.size();i++){
this.allObstruction.get(i).reset();
}
}
2.1.5get和set方法
编写成员变量get和set方法。
//返回背景图片
public BufferedImage getBgImage() {
return bgImage;
}
//返回障碍物
public List<Obstruction> getAllObstruction() {
return allObstruction;
}
//返回消失的障碍物
public List<Obstruction> getRemoveObstruction() {
return removeObstruction;
}
//返回当前场景顺序
public int getSort() {
return sort;
}
//返回敌人集合
public List<Enemy> getAllEnemy() {
return allEnemy;
}
//返回被消除的敌人的集合
public List<Enemy> getRemoveEnemy() {
return removeEnemy;
}
//返回是否是最后一个场景
public boolean isFlag() {
return flag;
}
//返回是否应该结束
public boolean isOver() {
return isOver;
}
//外界调用该方法传递是否该结束的信息
public void setOver(boolean isOver) {
this.isOver = isOver;
}
//返回是否该降旗
public boolean isDown() {
return isDown;
}
//外界调用该方法传递旗子是否降落信息
public void setDown(boolean isDown) {
this.isDown = isDown;
}
至此,BackGround类就完成啦!
2.2StaticValue类的实现
该类用于存放游戏所需要的所有静态文件,在游戏开始的时候将所有文件导入,提高游戏的运行速度。并且在该类中将所有需要用到的图片进行分类,分为障碍物类马里奥类,敌人类以及背景图片。当游戏运行时可以直接调用这些集合中的图片进行遍历,在调用的时候更加方便,而且可以使马里奥或者敌人在移动的时候产生动态效果。
2.2.1定义类变量
//存放马里奥照片的集合
public static List<BufferedImage> allMarioImage = new ArrayList<BufferedImage>();
//游戏开始页面图片
public static BufferedImage startImage = null;
//最后一个关卡的背景图
public static BufferedImage endImage = null;
//每个关卡的背景图片
public static BufferedImage bgImage = null;
//存放食人花图片的集合
public static List<BufferedImage> allFlowerImage = new ArrayList<BufferedImage>();
//存放蘑菇怪图片集合
public static List<BufferedImage> allTriangleImage = new ArrayList<BufferedImage>();
//所有障碍物集合
public static List<BufferedImage> allObstructionImage = new ArrayList<BufferedImage>();
//马里奥死亡的图片
public static BufferedImage mariDeadImage = null;
//后面多次用到图片路径,所以我将图片路径存入字符串中
public static String ImagePath = System.getProperty("user.dir")+"/src/";
2.2.2初始化图片
将所有用到的图片全部初始化。
马里奥图片初始化
for(int i=1;i<=10;i++){
try {
//将照片1~10放进马里奥图片集合中
allMarioImage.add(ImageIO.read(new File(ImagePath+i+".png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
所有背景图片初始化
//导入背景图片
try {
//游戏开始页面图片
startImage = ImageIO.read(new File(ImagePath+"start.jpg"));
//每个关卡的背景图片
bgImage = ImageIO.read(new File(ImagePath+"firststage.jpg"));
//最后一个关卡的图片,不同:旗杆
endImage = ImageIO.read(new File(ImagePath+"firststageend.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
敌人图片初始化
//导入敌人图片
for(int i=1;i<=5;i++){
try {
if(i<=2){
//导入食人花的两张图片
allFlowerImage.add(ImageIO.read(new File(ImagePath+"flower"+i+".png")));
}
if(i<=3){
//导入蘑菇怪的三张图片
allTriangleImage.add(ImageIO.read(new File(ImagePath+"triangle"+i+".png")));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
障碍物图片初始化
//导入障碍物图片
for(int i=1;i<=12;i++){
try {
allObstructionImage.add(ImageIO.read(new File(ImagePath+"ob"+i+".png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
三、心得与体会
通过这次协作完成马里奥闯关小游戏,我学会了如何分工合作、共同解决问题,并深刻理解了软件开发中团队合作的重要性。每个人都在项目中贡献了自己的专长,从设计到编码再到测试,每个环节都体现了团队的智慧和力量。这个过程不仅提高了我们的编程技能,还锻炼了我们的沟通和协调能力,让我们更加珍惜团队合作带来的成就感和乐趣。