项目简介:

我们团队利用面向对象开发方法和Java swing框架,对经典游戏《SuperMario》进行编写。

此项目共设施三个关卡,玩家可通过键盘来控制马里奥的移动,跳跃可以顶掉砖块,下落时还可以踩死蘑菇敌人,如果马里奥最终安全到达堡垒,则通关成功。

功能需求:

本游戏需要实现监听键盘(上下左右键控制马里奥运动),双缓冲技术(避免GUI界面图像闪烁问题),障碍物(蘑菇敌人、食人花)的动态体现,统计和展示游戏积分,马里奥死亡或通关结束游戏并弹出窗口显示,BGM播放功能需求。

非功能需求:

本游戏需要友好的图形用户界面,该实验用了java swing和awt编写图形用户界面。此外,游戏界面需要良好的音频和图像效果,包括界面三个关卡的背景、障碍物安放位置,和马里奥、食人花、蘑菇敌人等动态设计。

个人项目负责任务:

  1. 创建背景类(BackGround)和常量类(StaticValue)。调用ImageIO流的read方法拼接图片路径,利用for循环绘制各关卡的地面、砖块和水管等(关卡的场景设计)。
  2. 将项目上传到远程git仓库。
  3. 使用issue推动项目进程:将项目开发过程中需要解决的重点和问题写上去,分门别类打上标签,清晰说明,方便组内成员解决。

项目git地址:

这里这里,我就是啦!!! 

团队博客:

请点击这里<( ̄︶ ̄)↗[GO!]

Gitee issues面板:


 

 


 功能需求图:

 

 

 功能构架图:

 黄底为我负责部分

 

项目文件结构:

 

项目类图:

 

静态扫描:

使用阿里巴巴静态代码扫描工具,对项目进行扫描

 

 

依据扫描出的问题并改正

 

本人负责模块的具体分析:

1.常量类(StaticValue.java):将要用到的图片素材打包进一个src下的软件包里(images),定义各变量存储单张素材物体,如Mario向左站立/向右站立、城堡、旗杆;对于多素材创建list集合来储存。然后将这些变量初始化操作【将图片与变量匹配以达到后续调用目的【图片路径用到的绝对路径(建议更改为相对路径)。

部分核心代码:

复制代码
 //路径的前缀,方便后续调用
    public static String path = System.getProperty("user.dir") + "/src/images/";

    //初始化方法
    public static void init() {
        try {
            //加载背景图片
            bg = ImageIO.read(new File(path + "bg.png"));
            bg2 = ImageIO.read(new File(path + "bg2.png"));
            //加载马里奥向左站立
            stand_L = ImageIO.read(new File(path + "s_mario_stand_L.png"));
            //加载马里奥向右站立
            stand_R = ImageIO.read(new File(path + "s_mario_stand_R.png"));
            //加载城堡
            tower = ImageIO.read(new File(path + "tower.png"));
            //加载旗杆
            gan = ImageIO.read(new File(path + "gan.png"));
            //加载马里奥向左跳跃
            jump_L = ImageIO.read(new File(path + "s_mario_jump1_L.png"));
            //加载马里奥向右跳跃
            jump_R = ImageIO.read(new File(path + "s_mario_jump1_R.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        //加载马里奥向左跑
        for (int i = 1;i <= 2;i++) {
            try {
                run_L.add(ImageIO.read(new File(path + "s_mario_run"+ i +"_L.png")));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //加载马里奥向右跑
        for (int i = 1;i <= 2;i++) {
            try {
                run_R.add(ImageIO.read(new File(path + "s_mario_run"+ i +"_R.png")));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try {
            //加载障碍物
            obstacle.add(ImageIO.read(new File(path + "brick.png")));
            obstacle.add(ImageIO.read(new File(path + "soil_up.png")));
            obstacle.add(ImageIO.read(new File(path + "soil_base.png")));
        } catch (IOException e) {
            e.printStackTrace();
        }
复制代码

 

2.背景类(BackGround.java):先创建一个用于显示当前场景的图片(1、2关卡同一个背景图)的对象(bgImage);再定义一个int变量(sort),用于储存当前关卡;最后定义一个boolean变量(flag),判断当前是否最后一个场景。在构造方法里,分别对三个关卡的背景【地面绘制、两种砖块放置(可积分与不可积分)、固定建筑物】进行绘制。

部分核心代码:

复制代码
 //判断是否是第一关
        if (sort == 1) {
            //绘制第一关的地面,上地面type=1,下地面type=2
            for (int i = 0;i < 27;i++) {
                obstacleList.add(new Obstacle(i*30,420,1,this));
            }
            for (int j = 0;j <= 120;j += 30) {
                for (int i = 0;i < 27;i++) {
                    obstacleList.add(new Obstacle(i*30,570-j,2,this));
                }
            }
            //绘制砖块A
            for (int i = 120;i <= 150;i += 30) {
                obstacleList.add(new Obstacle(i,300,7,this));
            }
            //绘制砖块B-F
            for (int i = 300;i <= 570;i += 30) {
                if (i == 360 || i == 390 || i == 480 || i == 510 || i == 540) {
                    obstacleList.add(new Obstacle(i,300,7,this));
                } else {
                    obstacleList.add(new Obstacle(i,300,0,this));
                }
            }
            //绘制砖块G
            for (int i = 420;i <= 450;i += 30) {
                obstacleList.add(new Obstacle(i,240,7,this));
            }
            //绘制水管
            for (int i = 360;i <= 600;i += 25) {
                if (i == 360) {
                    obstacleList.add(new Obstacle(620,i,3,this));
                    obstacleList.add(new Obstacle(645,i,4,this));
                }else {
                    obstacleList.add(new Obstacle(620,i,5,this));
                    obstacleList.add(new Obstacle(645,i,6,this));
                }
            }
            //绘制第一关的蘑菇敌人
            enemyList.add(new Enemy(580,385,true,1,this));
            //绘制第一关的食人花敌人
            enemyList.add(new Enemy(635,420,true,2,328,428,this));
        }
复制代码

游戏运行展示:

第一关:

第二关:

第三关:

 死亡界面弹窗:

当马里奥碰到蘑菇敌人和食人花时,会被判断死亡。

 

本次课设感想:

 

在我和我的团队在设计这个游戏项目初时,面向对象的设计思想还很不成熟,我们在Java开发小游戏,30分钟教会你 - 知乎 (zhihu.com)这个文章中,基础了解用面向对象思想开发一个小游戏的大致流程。在共同商讨之后,一致决定基于经典小游戏《超级玛丽》进行开发——我们小组讨论并完成了《菜鸟版超级玛丽》小游戏大纲(参考了b站老师的设计思路,和csdn一位团队的课设纲要)。

之后,在组长负责找到《超级玛丽》的照片素材后,我们按照游戏设计大纲分好各自的负责区域,开始在学习的过程中写游戏程序。

在我负责的游戏设计模块中,关卡设计是一个困难点,但不难解决,我参考了别人的界面成果图,将每个关卡中画面物体全部用坐标表示出来(界面设计的是800*600,素材图片是30*30)整理记录在issues里。第二个困难点,是界面出现了图像闪烁残缺问题,我从csdn上查阅,采用了双缓冲技术来解决。

这个项目给我提供了一个极好的学习机会,让我将课堂上学到的面向对象的知识应用到实践中。通过实际设计和开发游戏,我更深入地理解和掌握面向对象的原则、概念和设计模式。同时,我积累了宝贵的实践经验和团队的合作经验。从项目的需求分析、系统设计、编码实现到测试和维护,我了解了整个软件开发生命周期的各个阶段,锻炼了我的团队合作能力、沟通能力和解决问题的能力。这对我的职业发展和未来的工作经验是非常有益的。