1.游戏初始化与资源加载模块:
图片资源加载:在ShootGame类的静态代码块中,运用ImageIO.read方法从指定资源路径加载游戏所需的各类图片资源,包括精美的游戏背景图、不同样式的飞机图片(英雄飞机、敌机等)、子弹图片等。若在加载过程中出现IOException异常,表明资源加载失败,此时通过JOptionPane弹出详细的错误提示对话框,告知用户 “游戏资源加载失败,请检查资源文件是否存在或损坏!”,并直接调用System.exit(1)终止程序,因为资源是游戏运行的基础,缺少资源游戏将无法正常运行。
游戏参数初始化:精心初始化游戏的一系列基本参数,如设定游戏窗口的固定宽高(WIDTH = 400,HEIGHT = 654),明确游戏初始状态为START(state = 0),设置初始关卡为 1(level = 1),确定定时器的时间间隔为 10 毫秒(intervel = 1000 / 100),并将玩家初始得分清零(score = 0)等,这些参数为游戏的正常运行和逻辑控制奠定基础。
2.绘制模块:
绘制背景:在ShootGame类的paint方法中,首要任务是使用g.drawImage方法绘制游戏背景图片,为整个游戏场景搭建基础框架,营造出逼真的游戏环境。
绘制英雄飞机:依据英雄飞机的当前状态(如是否处于双倍火力状态)和位置信息,通过paintHero方法调用g.drawImage绘制对应的英雄飞机图片,使其在游戏界面中准确呈现。
绘制子弹:在paintBullets方法中,遍历子弹列表,针对每一颗子弹,使用g.drawImage根据其坐标位置绘制在游戏界面中,展示子弹的飞行轨迹。
绘制飞行物:借助paintFlyingObjects方法,遍历飞行物列表,将各种敌机(如普通敌机AirPlane、携带奖励的蜜蜂敌机Bee)和其他飞行物按照其各自的图像和位置信息绘制出来,丰富游戏画面。
绘制得分与生命值:在paintScore方法中,创建特定字体(如Font font = new Font("Arial", Font.BOLD, 16))并设置颜色(g.setColor(Color.Yellow)),然后在游戏界面的指定位置(如g.drawString("SCORE: " + score, 10, 25)和g.drawString("LIFE: " + heroPlane.getLife(), 10, 45))绘制玩家的当前得分和英雄飞机的生命值信息,让玩家随时了解游戏进展。
绘制游戏状态界面:paintState方法根据游戏的当前状态(START、PAUSE、GAME_OVER),使用g.drawImage绘制相应的界面图片,如在游戏开始界面展示精美的开始界面图片,在暂停时显示暂停界面,在游戏结束时根据玩家得分判断。若得分大于等于 600 分,则显示通关完成界面,并绘制 “通关完成!” 字样;否则显示普通游戏结束界面,并绘制 “游戏结束!” 字样,给玩家明确的游戏结果反馈。
3.飞行物生成模块:
随机生成敌机或奖励飞行物:由ShootGame类的nextOne方法实现复杂的随机生成逻辑。首先创建Random对象,然后生成一个 0 到 19 的随机数type。若type为 0,则生成一只蜜蜂敌机Bee;若type小于 5 且当前关卡大于等于 2,则有一定概率生成更强的敌机AirPlane(level),并传递当前关卡参数以便敌机根据关卡调整属性;否则生成普通敌机AirPlane(level)。enterAction方法则按照设定的入场间隔(FLYING_ENTER_INTERVAL),通过flyEnterIndex计数,当flyEnterIndex满足特定间隔条件(根据关卡调整)时,调用nextOne方法生成飞行物并添加到管理飞行物的flyingObjects列表中,并且在后续关卡(如第二关开始缩短间隔,第三关进一步缩短)会动态调整入场间隔,显著增加游戏难度。
4.飞行物移动模块:
飞行物移动逻辑:ShootGame类的stepAction方法承担此关键功能,它遍历管理飞行物的flyingObjects列表和子弹列表。对于每个飞行物,调用其step方法,根据各自预设的移动方式移动,例如敌机按照设定速度向下移动,子弹则以特定速度向上移动等。同时,也会调用英雄飞机的step方法,虽然英雄飞机在该方法中的移动逻辑可能较为简单(如仅在某些特定情况下更新位置),但确保了所有飞行物和英雄飞机的移动统一在一个逻辑处理流程中,维持游戏的动态性和连贯性。
英雄飞机移动逻辑:在ShootGame类中定义的MouseAdapter监听器的mouseMoved方法里,当游戏处于运行状态(state == RUNNING)时,获取鼠标的当前位置坐标(int x = e.getX(); int y = e.getY();),然后通过英雄飞机的moveTo方法,根据鼠标位置精确更新英雄飞机的坐标位置(this.x = x - WIDTH / 2; this.y = y - HEIGHT / 2;),使其能够平滑地跟随鼠标移动,实现玩家对英雄飞机的精准操控,极大地增强了游戏的交互性和趣味性。
5.射击模块:
英雄飞机按间隔发射子弹:依赖ShootGame类的shootAction方法,该方法依据设定的射击间隔(SHOOT_INTERVAL),通过shootIndex计数。当shootIndex满足特定间隔条件时,触发英雄飞机的shoot方法。在英雄飞机的shoot方法中,根据当前双倍火力状态(doubleFire)生成不同数量和位置的子弹列表。若处于双倍火力状态,则在飞机的不同位置(如x + WIDTH / 4和x + WIDTH * 3 / 4)生成两颗子弹,并减少双倍火力计数;否则在飞机中间位置(x + WIDTH / 2)生成一颗子弹。并且从第二关开始(level >= 2),每次射击还会额外多生成一颗子弹在特定位置(y - 10),生成的子弹列表最终添加进子弹列表bullets中,这种随着关卡提升而增强玩家火力的设计,增加了游戏的策略性和挑战性。
6.碰撞检测模块:
子弹与飞行物碰撞检测:在ShootGame类的bangAction方法内实现精细的碰撞检测逻辑。首先创建一个临时的飞行物列表tempFlyingObjects,用于在碰撞检测过程中避免直接修改原始飞行物列表导致的并发问题。然后遍历子弹列表,对于每一颗子弹,调用bang方法检测其与飞行物是否碰撞。在bang方法中,遍历飞行物列表,通过比较子弹与飞行物的坐标范围(利用shootBy方法中的坐标判断逻辑),确定是否发生碰撞。若碰撞,针对敌机类型飞行物(通过instanceof Enemy判断),获取敌机的得分并累加到玩家总得分中;若是奖励类型飞行物(通过instanceof Award判断),则根据奖励类型(如Award.DOUBLE_FIRE或Award.LIFE),调用英雄飞机的相应方法(addDoubleFire或addLife)赋予玩家对应的奖励,如双倍火力或者增加生命值,最后将被击中的飞行物从临时飞行物列表中移除,碰撞检测完成后,将处理后的临时飞行物列表赋值回原始飞行物列表,确保飞行物列表的正确性和一致性。
英雄飞机与飞行物碰撞检测:在isGameOver方法中,遍历飞行物列表,通过英雄飞机的hit方法检测英雄飞机与飞行物是否碰撞。hit方法根据英雄飞机和飞行物的坐标及尺寸信息(如this.x < obj.getX() + obj.getImage().getWidth() && this.x + this.getWidth() > obj.getX() && this.y < obj.getY() + obj.getImage().getHeight() && this.y + this.getHeight() > obj.getY()),判断是否发生重叠碰撞。若碰撞,则减少英雄飞机的生命值(heroPlane.subtractLife()),并将英雄飞机的双倍火力重置为 0(heroPlane.setDoubleFire(0)),