这一页有 72 张卡片,一个类一张。别的页面上的类名小标签(比如 C Battle ),点一下就跳到这里它的卡片。想找某个类,用下面的筛选:输入框里打类名、方法名或中文词;“全部 / 类 / 抽象类 / 接口 / 枚举”按种类筛,“所有包 / mokepon / battle …”按包筛,可以一起用。
小标签左边的字母,和老师打印的 UML 图上类名旁边的圆圈一样(C / A / I / E ):C Coffee 是 C,普通类(class);A Item 是 A,抽象类(abstract class);I EnemyStrategy 是 I,接口(interface);E Stat 是 E,枚举(enum)。
四种类型,各一个你代码里的例子。实线空心三角 = extends,虚线空心三角 = implements。最右边 Battle 的两条线,就是卡片上的“谁存着它”和“谁创建它”
每张卡片里有两行要特别看:
为什么重要:打印的 UML 图只画继承和实现的线,不画谁 new 谁、谁存着谁,可设计题常问的正是这两件事。答题时照卡片说清楚:哪个类、第几行、哪个字段。
全部 类 抽象类 接口 枚举
所有包 mokepon battle data effect item model skill ui world
C Main Main au.edu.unimelb.swen.oop.mokepon 类
程序入口:读数据文件、解析成对象,然后打开游戏窗口。
在游戏里 看不见:只在启动时工作。它最后 new GameWindow 并调用 show(),你才看到选择界面;数据读不了就在控制台打印 “Error loading ...” 并退出。
它的职责 继承 JavaFX 的 Application;依次调用各个解析器,再把结果交给 GameWindow,是把整个程序组装起来的地方。
家族关系 继承 Application
谁创建它 JavaFX 启动时自动创建
谁存着它 没有别的类把它存成字段
方法 2 个 + start(Stage stage): void · 第 22 行 + main(String[] args): void · 第 42 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;09 遇敌:地形、类型和挑敌人 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 Main.java(46 行)
看老师打印稿里的这个类(UMLDoclet)
C Battle Battle au.edu.unimelb.swen.oop.mokepon.battle 类
一场战斗的规则:双方轮流出招、用道具、记日志、判输赢。
在游戏里 战斗界面右下日志框里的每一行(如 “Player's Impike used Stun!”、“You win”)都是它 log 里的字符串;BattleScreen 只负责显示。
它的职责 纯规则(model),完全不碰界面;只依赖 EnemyStrategy 接口来选敌人技能,是 Strategy 模式的使用方(context)。
谁创建它 C Encounter (第 56 行 new Battle(…))
谁存着它 C BattleScreen 的字段 battle: Battle
字段 8 个 - final player: Fighter - final enemy: Fighter - final inventory: Inventory - final enemyStrategy: EnemyStrategy - final random: Random - final log: List<String> - finished: boolean - playerWon: boolean
方法 12 个 + Battle(Fighter player, Fighter enemy, Inventory inventory) · 第 25 行 + Battle(Fighter player, Fighter enemy, Inventory inventory, EnemyStrategy enemyStrategy, Random random) · 第 30 行 + getPlayer(): Fighter · 第 41 行 + getEnemy(): Fighter · 第 45 行 + getInventory(): Inventory · 第 49 行 + isFinished(): boolean · 第 53 行 + hasPlayerWon(): boolean · 第 57 行 + getLog(): List<String> · 第 62 行 + playTurn(Skill playerSkill): void · 第 69 行 + useItem(Item item): void · 第 101 行 - endTurn(): void · 第 116 行 - finish(boolean playerWon): void · 第 134 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 battle/Battle.java(148 行)
看老师打印稿里的这个类(UMLDoclet)
接口:决定敌人这一回合用哪个技能。
在游戏里 看不见:在 Battle.playTurn 里被调用,结果出现在日志 “Enemy Galecrest used Tackle!” 这一行。
它的职责 Strategy 模式的接口。Battle 只认识它,以后加更聪明的敌人只要写新的实现类,不用改 Battle。
子类 / 实现者 C RandomEnemyStrategy
谁创建它 接口不能被 new,只能 new 它的实现类
谁存着它 C Battle 的字段 enemyStrategy: EnemyStrategy
方法 1 个 + chooseSkill(Fighter enemy, Random random): Skill · 第 11 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 battle/EnemyStrategy.java(13 行)
看老师打印稿里的这个类(UMLDoclet)
C Fighter Fighter au.edu.unimelb.swen.oop.mokepon.battle 类
正在战斗的 Mokepon:带着会变的 HP、能量、属性和状态效果。
在游戏里 战斗界面两块卷轴上的 HP 条、能量条和 “225 / 225” 这类数字,显示的都是 Fighter 当前的值(已经乘过地形倍率)。
它的职责 把战斗中会变的数据和不变的 Mokepon 分开;战斗结束就丢掉,属性自然复原。伤害公式 calculateDamage 也在这里。
谁创建它 C Encounter (第 54、55 行 new Fighter(…))
谁存着它 C Battle 的字段 player: Fighter、enemy: Fighter;C Bleeding 的字段 attacker: Fighter;C FighterPanel 的字段 fighter: Fighter
字段 5 个 - static final DAMAGE_SCALE: int - final mokepon: Mokepon - final startingStats: Map<Stat, Integer> - final stats: Map<Stat, Integer> - final effects: List<StatusEffect>
方法 23 个 + Fighter(Mokepon mokepon, TerrainEffect terrainEffect) · 第 31 行 + getName(): String · 第 40 行 + getImagePath(): String · 第 44 行 + getSkills(): List<Skill> · 第 48 行 + getStat(Stat stat): int · 第 52 行 + getHp(): int · 第 56 行 + getMaxHp(): int · 第 60 行 + getEnergy(): int · 第 64 行 + getMaxEnergy(): int · 第 68 行 + isAlive(): boolean · 第 72 行 + canUse(Skill skill): boolean · 第 77 行 + takeDamage(int amount): void · 第 82 行 + spendEnergy(int amount): void · 第 89 行 + raiseStat(Stat stat, int amount): int · 第 95 行 + restoreHp(): void · 第 102 行 + restoreEnergy(): void · 第 106 行 + reduceHpToOne(): void · 第 110 行 + calculateDamage(Fighter target, double power): int · 第 118 行 + addEffect(StatusEffect effect): void · 第 124 行 + getMissChance(): double · 第 131 行 + applyLingeringDamage(): List<String> · 第 142 行 + countDownEffects(): void · 第 154 行 - getDamageMultiplier(): double · 第 168 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 battle/Fighter.java(176 行)
看老师打印稿里的这个类(UMLDoclet)
EnemyStrategy 的实现:从能量够用的技能里随机挑一个。
在游戏里 看不见:每个敌人回合在 Battle 里运行,它挑出的技能名出现在日志 “Enemy ... used ...!”。
它的职责 Strategy 模式的具体策略(concrete strategy);Battle 的三参数构造器默认就用它。
家族关系 实现 I EnemyStrategy
谁创建它 C Battle (第 26 行 new RandomEnemyStrategy(…))
谁存着它 没有别的类把它存成字段
方法 1 个 + chooseSkill(Fighter enemy, Random random): Skill · 第 12 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 battle/RandomEnemyStrategy.java(22 行)
看老师打印稿里的这个类(UMLDoclet)
C GameData GameData au.edu.unimelb.swen.oop.mokepon.data 类
数据文件里的全部键值对,外加转成数字和坐标的小工具。
在游戏里 看不见:启动时在 Main 里使用。所有解析器都通过它读 mokepon.game,比如 getPosition 把 “10,18” 变成一个 Position。
它的职责 包装 Java 的 Properties,把“怎样读文本”集中在一处;countEntries 数出编号条目有几个。
谁创建它 C GameDataReader (第 34 行 new GameData(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - final properties: Properties
方法 6 个 + GameData(Properties properties) · 第 12 行 + has(String key): boolean · 第 16 行 + getText(String key): String · 第 20 行 + getNumber(String key): int · 第 24 行 + getPosition(String key): Position · 第 29 行 + countEntries(String prefix, String suffix): int · 第 37 行
在哪章讲 02 Java 最小知识包 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;09 遇敌:地形、类型和挑敌人 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 data/GameData.java(45 行)
看老师打印稿里的这个类(UMLDoclet)
读取命令行参数 data=... 指定的数据文件,生成 GameData。
在游戏里 看不见:启动时第一个运行。参数缺失或文件不存在时,Main 在控制台打印 “Error loading ...”,游戏窗口不会打开。
它的职责 只负责找到并加载文件,并去掉每个值两边的空格;出错就抛异常,交给 Main 处理。
谁创建它 C Main (第 25 行 new GameDataReader(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final ARGUMENT_PREFIX: String
方法 1 个 + read(List<String> arguments): GameData · 第 17 行
在哪章讲 04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 data/GameDataReader.java(37 行)
看老师打印稿里的这个类(UMLDoclet)
C GameImages GameImages au.edu.unimelb.swen.oop.mokepon.data 类
界面要用的图片路径:类型图标、地块、方向按钮、道具、玩家。
在游戏里 看不见它本身,但它存的路径就是你看到的图:地图格子、四个箭头按钮、道具图标、地图上的玩家、名字旁的火焰图标。
它的职责 只存路径、不加载图片,所以 data 包不依赖 JavaFX;构造时用 Map.copyOf 拷贝,外面改不了。
谁创建它 C ImageParser (第 20 行 new GameImages(…))
谁存着它 C GameWindow 的字段 images: GameImages;C SelectScreen 的字段 images: GameImages
字段 5 个 - final typeImages: Map<MokeponType, String> - final tileImages: Map<Terrain, String> - final buttonImages: Map<Direction, String> - final itemImages: Map<Item, String> - final playerImage: String
方法 7 个 + GameImages(Map<MokeponType, String> typeImages, Map<Terrain, String> tileImages, Map<Direction, String> buttonImages, Map<Item, String> itemImages, String playerImage) · 第 20 行 + hasTypeImage(MokeponType type): boolean · 第 31 行 + getTypeImage(MokeponType type): String · 第 35 行 + getTileImage(Terrain terrain): String · 第 39 行 + getButtonImage(Direction direction): String · 第 43 行 + getItemImage(Item item): String · 第 47 行 + getPlayerImage(): String · 第 51 行
在哪章讲 04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 data/GameImages.java(55 行)
看老师打印稿里的这个类(UMLDoclet)
C ImageParser ImageParser au.edu.unimelb.swen.oop.mokepon.data 类
从数据文件读出所有图片路径,组装成一个 GameImages。
在游戏里 看不见:启动时在 Main 里运行一次,结果交给 GameWindow 和各个界面。
它的职责 一个泛型方法 readImages 按枚举值的名字找键(如 map.tiles.images.grass);NORMAL 没有键,所以没有图标。
谁创建它 C Main (第 37 行 new ImageParser(…))
谁存着它 没有别的类把它存成字段
方法 3 个 + parse(GameData data): GameImages · 第 14 行 - readImages(GameData data, String prefix, T[] values): <T extends Enum<T>> Map<T, String> · 第 28 行 - readItemImages(GameData data): Map<Item, String> · 第 41 行
在哪章讲 02 Java 最小知识包 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;07 选择界面 SelectScreen ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 data/ImageParser.java(49 行)
看老师打印稿里的这个类(UMLDoclet)
C MapParser MapParser au.edu.unimelb.swen.oop.mokepon.data 类
把数据文件的地图部分变成 GameMap:地块、起点和地图上的物体。
在游戏里 看不见:启动时运行。地图的样子,以及感叹号、问号箱子和出口门的位置,都是它读出来的。
它的职责 给三组标记配不同的 EnemyPicker(随机、强、弱),在这里把策略对象注入 Marker,Marker 本身不用知道区别。
谁创建它 C Main (第 36 行 new MapParser(…))
谁存着它 没有别的类把它存成字段
字段 2 个 - static final TILES_PREFIX: String - static final ITEMS_PREFIX: String
方法 5 个 + parse(GameData data): GameMap · 第 25 行 - parseTiles(GameData data): Terrain[][] · 第 43 行 - parseMarkers(GameData data, String group, EnemyPicker picker): List<MapObject> · 第 57 行 - parseMysteryBoxes(GameData data): List<MapObject> · 第 69 行 - parseExit(GameData data): Exit · 第 81 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 data/MapParser.java(86 行)
看老师打印稿里的这个类(UMLDoclet)
把数据文件里的 Mokepon 条目变成 Mokepon 对象列表。
在游戏里 看不见:启动时运行。选择界面左边那 36 个名字按钮,就来自它读出的列表。
它的职责 按编号 mokepon.0、mokepon.1… 逐个读;技能名通过 SkillCatalogue.find 换成共享的技能对象。
谁创建它 C Main (第 35 行 new MokeponParser(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final PREFIX: String
方法 3 个 + parse(GameData data): List<Mokepon> · 第 18 行 - parseMokepon(GameData data, String prefix): Mokepon · 第 27 行 - parseSkills(String skillNames): List<Skill> · 第 43 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 data/MokeponParser.java(51 行)
看老师打印稿里的这个类(UMLDoclet)
C Bleeding Bleeding au.edu.unimelb.swen.oop.mokepon.effect 类
流血效果:每回合结束按攻击者一半力量扣血,持续 2 回合。
在游戏里 流血伤害不写日志,只看到 HP 条在回合末变短;第二次扣血后,日志出现 “The bleeding stopped.”。
它的职责 StatusEffect 的子类,只覆盖 applyLingeringDamage;记住攻击者,用他一半的力量算伤害。
家族关系 继承 A StatusEffect
谁创建它 C Lance (第 20 行 new Bleeding(…))
谁存着它 没有别的类把它存成字段
字段 3 个 - static final TURNS: int - static final HALF_STRENGTH: double - final attacker: Fighter
方法 2 个 + Bleeding(Fighter attacker) · 第 15 行 + applyLingeringDamage(Fighter owner): List<String> · 第 24 行
在哪章讲 04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 effect/Bleeding.java(32 行)
看老师打印稿里的这个类(UMLDoclet)
C Blinded Blinded au.edu.unimelb.swen.oop.mokepon.effect 类
致盲效果:目标性技能额外有 50% 机会打空,持续 3 回合。
在游戏里 效果本身看不见:中招时日志写 “Pocket sand blinded ...!”(这句来自 PocketSand);之后被致盲的一方更常出现 “But they missed.”。
它的职责 StatusEffect 的子类,只覆盖 getMissChance() 返回 0.5;TargetedSkill 通过普通命中检查后再用它判一次。
家族关系 继承 A StatusEffect
谁创建它 C PocketSand (第 17 行 new Blinded(…))
谁存着它 没有别的类把它存成字段
字段 2 个 + static final TURNS: int - static final MISS_CHANCE: double
方法 2 个 + Blinded() · 第 10 行 + getMissChance(): double · 第 15 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 effect/Blinded.java(19 行)
看老师打印稿里的这个类(UMLDoclet)
A StatusEffect StatusEffect au.edu.unimelb.swen.oop.mokepon.effect 抽象类
抽象类:所有状态效果的共同部分,主要是还剩几回合。
在游戏里 看不见:挂在 Fighter 的 effects 列表里,在战斗中改变伤害、命中,或在回合末扣血。
它的职责 三个方法先写好“不改变任何东西”的默认值,子类只覆盖自己要改的那个;Fighter 用多态统一处理所有效果。
子类 / 实现者 C Bleeding C Blinded C Stunned
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 C Fighter 的字段 effects: List<StatusEffect>
字段 1 个 - turnsLeft: int
方法 7 个 # StatusEffect(int turns) · 第 12 行 + getDamageMultiplier(): double · 第 17 行 + getMissChance(): double · 第 22 行 + applyLingeringDamage(Fighter owner): List<String> · 第 29 行 + countDown(): void · 第 34 行 + isOver(): boolean · 第 38 行 # isLastTurn(): boolean · 第 43 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 effect/StatusEffect.java(47 行)
看老师打印稿里的这个类(UMLDoclet)
C Stunned Stunned au.edu.unimelb.swen.oop.mokepon.effect 类
眩晕效果:被眩晕的一方造成的伤害减半,持续 3 回合。
在游戏里 中招时日志写 “... was stunned! Their damage is halved for 3 turns.”(这句来自 Stun);之后它打出的伤害数字变小。
它的职责 StatusEffect 的子类,只覆盖 getDamageMultiplier() 返回 0.5;算伤害时最后乘上它。
家族关系 继承 A StatusEffect
谁创建它 C Stun (第 17 行 new Stunned(…))
谁存着它 没有别的类把它存成字段
字段 2 个 + static final TURNS: int - static final DAMAGE_MULTIPLIER: double
方法 2 个 + Stunned() · 第 8 行 + getDamageMultiplier(): double · 第 13 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 effect/Stunned.java(17 行)
看老师打印稿里的这个类(UMLDoclet)
C Coffee Coffee au.edu.unimelb.swen.oop.mokepon.item 类
道具 Coffee:把玩家 Mokepon 的能量补满。
在游戏里 战斗界面第 3 个道具按钮(杯子图标);地图卷轴里的 “Coffee:” 一行;用后日志写 “... It restored all your energy!”。
它的职责 Item 的子类,只覆盖 use():调用 player.restoreEnergy();数据文件里叫 COFFEE。
家族关系 继承 A Item
谁创建它 C ItemCatalogue (第 11 行 new Coffee(…))
谁存着它 没有别的类把它存成字段
方法 2 个 + Coffee() · 第 7 行 + use(Fighter player, Fighter enemy): String · 第 12 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 item/Coffee.java(17 行)
看老师打印稿里的这个类(UMLDoclet)
C HealthTonic HealthTonic au.edu.unimelb.swen.oop.mokepon.item 类
道具 Health Tonic:把玩家 Mokepon 的 HP 回满。
在游戏里 战斗界面第 1 个道具按钮(绿色十字);地图卷轴里的 “Health Tonic:” 一行;用后日志写 “... It healed you to max hp!”。
它的职责 Item 的子类,只覆盖 use():调用 player.restoreHp();数据文件里叫 HEALTH。
家族关系 继承 A Item
谁创建它 C ItemCatalogue (第 10 行 new HealthTonic(…))
谁存着它 没有别的类把它存成字段
方法 2 个 + HealthTonic() · 第 7 行 + use(Fighter player, Fighter enemy): String · 第 12 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;10 战斗的数据:Mokepon、Fighter、Battle ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 item/HealthTonic.java(17 行)
看老师打印稿里的这个类(UMLDoclet)
C Inventory Inventory au.edu.unimelb.swen.oop.mokepon.item 类
背包:记录每种道具各有几个。
在游戏里 地图右上卷轴 Inventory 下面的三个数字,和战斗界面道具按钮上的数字,读的都是同一个 Inventory。
它的职责 用 LinkedHashMap 计数;每种道具只有一个对象,所以直接拿对象当键。Player 和 Battle 共用它。
谁创建它 C Overworld (第 38 行 new Inventory(…))
谁存着它 C Battle 的字段 inventory: Inventory;C Player 的字段 inventory: Inventory
字段 1 个 - final counts: Map<Item, Integer>
方法 6 个 + Inventory(List<Item> items) · 第 15 行 + getItems(): List<Item> · 第 21 行 + getCount(Item item): int · 第 25 行 + has(Item item): boolean · 第 29 行 + add(Item item): void · 第 33 行 + remove(Item item): void · 第 38 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;08 地图世界:走一步发生了什么 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;13 状态效果和道具 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 item/Inventory.java(44 行)
看老师打印稿里的这个类(UMLDoclet)
A Item Item au.edu.unimelb.swen.oop.mokepon.item 抽象类
抽象类:一次性道具,有类型名、显示名、图片键和 use()。
在游戏里 它本身看不见;三个子类就是三个道具按钮和卷轴里的三行。日志 “You used your ... on ...” 的开头由它的 describeUse 拼出。
它的职责 抽象方法 use() 让每种道具各写各的效果(多态);加新道具只要写新子类,不改旧代码(开闭原则)。
子类 / 实现者 C Coffee C HealthTonic C Poison
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 C GameImages 的字段 itemImages: Map<Item, String>;C Inventory 的字段 counts: Map<Item, Integer>;C BattleScreen 的字段 itemButtons: Map<Item, GameButton>;C PlayerStatsScroll 的字段 itemValues: Map<Item, Label>;C MysteryBox 的字段 item: Item
字段 3 个 - final typeName: String - final name: String - final imageName: String
方法 6 个 # Item(String typeName, String name, String imageName) · 第 14 行 + getTypeName(): String · 第 20 行 + getName(): String · 第 24 行 + getImageName(): String · 第 28 行 + use(Fighter player, Fighter enemy): String · 第 35 行 # describeUse(Fighter target, String result): String · 第 40 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 item/Item.java(44 行)
看老师打印稿里的这个类(UMLDoclet)
全部道具的目录:每种道具只造一个对象,全游戏共用。
在游戏里 看不见,但它决定顺序:卷轴里是 Health Tonic、Coffee、Poison;战斗按钮是 Health Tonic、Poison、Coffee。
它的职责 只有静态方法 getAll、getBattleOrder、find;find 把数据文件里的 “POISON” 换成道具对象。
谁创建它 只有 static 成员,直接用类名调用,不需要 new
谁存着它 没有别的类把它存成字段
字段 5 个 - static final HEALTH_TONIC: Item - static final COFFEE: Item - static final POISON: Item - static final ITEMS: List<Item> - static final BATTLE_ORDER: List<Item>
方法 3 个 + getAll(): List<Item> · 第 19 行 + getBattleOrder(): List<Item> · 第 23 行 + find(String typeName): Item · 第 28 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;10 战斗的数据:Mokepon、Fighter、Battle ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 item/ItemCatalogue.java(37 行)
看老师打印稿里的这个类(UMLDoclet)
C Poison Poison au.edu.unimelb.swen.oop.mokepon.item 类
道具 Poison:把敌人的 HP 直接降到 1。
在游戏里 战斗界面第 2 个道具按钮(绿色圆球);地图卷轴里的 “Poison:” 一行;用后日志写 “You used your Poison on ... It devastated them!”。
它的职责 Item 的子类,只覆盖 use():调用 enemy.reduceHpToOne();是唯一作用在敌人身上的道具。
家族关系 继承 A Item
谁创建它 C ItemCatalogue (第 12 行 new Poison(…))
谁存着它 没有别的类把它存成字段
方法 2 个 + Poison() · 第 7 行 + use(Fighter player, Fighter enemy): String · 第 12 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 item/Poison.java(17 行)
看老师打印稿里的这个类(UMLDoclet)
C Mokepon Mokepon au.edu.unimelb.swen.oop.mokepon.model 类
数据文件里的一只 Mokepon:名字、图片、类型、六项属性和技能。
在游戏里 选择界面的头像、名字和属性卷轴,以及地图右上卷轴里的属性,都来自 Mokepon(没有乘地形倍率的原始值)。
它的职责 不可变(immutable):字段全是 final,构造时拷贝 Map 和 List;战斗中会变的数据交给 Fighter。
谁创建它 C MokeponParser (第 39 行 new Mokepon(…))
谁存着它 C Fighter 的字段 mokepon: Mokepon;C GameWindow 的字段 mokepons: List<Mokepon>;C SelectScreen 的字段 selectedMokepon: Mokepon;C Encounter 的字段 playerMokepon: Mokepon、enemy: Mokepon;C Overworld 的字段 mokepons: List<Mokepon>;C Player 的字段 mokepon: Mokepon
字段 5 个 - final name: String - final imagePath: String - final type: MokeponType - final stats: Map<Stat, Integer> - final skills: List<Skill>
方法 6 个 + Mokepon(String name, String imagePath, MokeponType type, Map<Stat, Integer> stats, List<Skill> skills) · 第 19 行 + getName(): String · 第 28 行 + getImagePath(): String · 第 32 行 + getType(): MokeponType · 第 36 行 + getStat(Stat stat): int · 第 40 行 + getSkills(): List<Skill> · 第 44 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 model/Mokepon.java(48 行)
看老师打印稿里的这个类(UMLDoclet)
E MokeponType MokeponType au.edu.unimelb.swen.oop.mokepon.model 枚举
枚举:五种类型;除 NORMAL 外,每种有一个强势地形和一个弱势地形。
在游戏里 选择界面名字旁边的类型图标(如 FIRE 的火焰)和 “Type: FIRE” 这一行;NORMAL 没有图标。
它的职责 每个常量带构造参数(强、弱地形);getEffectOn(terrain) 返回 ADVANTAGE、DISADVANTAGE 或 NEUTRAL。
谁创建它 枚举的几个值在类加载时就自动建好了,不用 new
谁存着它 C GameImages 的字段 typeImages: Map<MokeponType, String>;C Mokepon 的字段 type: MokeponType
枚举值 NORMAL、FIRE、ICE、WATER、LIGHTNING
字段 2 个 - final strongTerrain: Terrain - final weakTerrain: Terrain
方法 2 个 ~ MokeponType(Terrain strongTerrain, Terrain weakTerrain) · 第 17 行 + getEffectOn(Terrain terrain): TerrainEffect · 第 23 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;17 考试准备:用这份代码答题
源文件 model/MokeponType.java(33 行)
看老师打印稿里的这个类(UMLDoclet)
E Stat Stat au.edu.unimelb.swen.oop.mokepon.model 枚举
枚举:六项属性(HP、Energy、Strength 等)和各自的合法范围。
在游戏里 选择界面和地图卷轴上的 “HP:”、“Energy:”… 用的是它的 label;日志 “They raised their strength ...” 里的属性名也是。
它的职责 limit() 把数值压回范围(HP 1–1000,其余 1–100),所以 Impike 力量 76×1.5=114,进战斗后只有 100。
谁创建它 枚举的几个值在类加载时就自动建好了,不用 new
谁存着它 C Fighter 的字段 startingStats: Map<Stat, Integer>、stats: Map<Stat, Integer>;C Mokepon 的字段 stats: Map<Stat, Integer>;A BoostSkill 的字段 stat: Stat;C SelectScreen 的字段 statValues: Map<Stat, Label>
枚举值 HP、ENERGY、STRENGTH、ACCURACY、DEFENCE、DODGE
字段 3 个 - final label: String - final minimum: int - final maximum: int
方法 3 个 ~ Stat(String label, int minimum, int maximum) · 第 16 行 + getLabel(): String · 第 22 行 + limit(int value): int · 第 27 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;15 逃跑、回主菜单、走到出口 ;17 考试准备:用这份代码答题
源文件 model/Stat.java(31 行)
看老师打印稿里的这个类(UMLDoclet)
E Terrain Terrain au.edu.unimelb.swen.oop.mokepon.model 枚举
枚举:地图上的七种地块,每种对应数据文件里的一个字母。
在游戏里 地图上的每一格:草地、森林、水、岩石、小路,以及走不上去的 OCEAN(深蓝色)和 BARRIER(灰色方砖)。
它的职责 每种地块带一个字母和 walkable;fromSymbol(‘G’) 把字母变成枚举值,MapParser 用它读每一行地图。
谁创建它 枚举的几个值在类加载时就自动建好了,不用 new
谁存着它 C GameImages 的字段 tileImages: Map<Terrain, String>;E MokeponType 的字段 strongTerrain: Terrain、weakTerrain: Terrain;C Encounter 的字段 terrain: Terrain;C GameMap 的字段 tiles: Terrain[][]
枚举值 BARRIER、FOREST、GRASS、OCEAN、PATH、ROCKS、WATER
字段 2 个 - final symbol: char - final walkable: boolean
方法 3 个 ~ Terrain(char symbol, boolean walkable) · 第 16 行 + isWalkable(): boolean · 第 21 行 + fromSymbol(char symbol): Terrain · 第 26 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;17 考试准备:用这份代码答题
源文件 model/Terrain.java(35 行)
看老师打印稿里的这个类(UMLDoclet)
枚举:地形对属性的影响:优势 ×1.5、中性 ×1、劣势 ×0.5。
在游戏里 遇敌对话框里 “Your mokepon will be at an advantage here!” 的后半句;进入战斗后属性改变,如 Impike 的 HP 150 → 225。
它的职责 adjust() 乘上倍率再四舍五入(Math.round);Fighter 构造时对每项属性调用它,再用 Stat.limit 限制范围。
谁创建它 枚举的几个值在类加载时就自动建好了,不用 new
谁存着它 C TerrainEnemyPicker 的字段 wantedEffect: TerrainEffect
枚举值 ADVANTAGE、NEUTRAL、DISADVANTAGE
字段 2 个 - final multiplier: double - final description: String
方法 3 个 ~ TerrainEffect(double multiplier, String description) · 第 12 行 + getDescription(): String · 第 18 行 + adjust(int value): int · 第 23 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;17 考试准备:用这份代码答题
源文件 model/TerrainEffect.java(27 行)
看老师打印稿里的这个类(UMLDoclet)
C Aim Aim au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Aim:花 3 点能量,提高自己的命中(Accuracy)。
在游戏里 战斗按钮 “Aim [3]”;日志 “They raised their accuracy by N points!”。
它的职责 BoostSkill 的子类,只在构造器里传入名字、费用 3 和 Stat.ACCURACY,没有别的代码。
家族关系 继承 A BoostSkill
谁创建它 C SkillCatalogue (第 13 行 new Aim(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final ENERGY_COST: int
方法 1 个 + Aim() · 第 9 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;17 考试准备:用这份代码答题
源文件 skill/Aim.java(13 行)
看老师打印稿里的这个类(UMLDoclet)
A AttackSkill AttackSkill au.edu.unimelb.swen.oop.mokepon.skill 抽象类
抽象类:命中后造成伤害的攻击技能,彼此只差威力 power。
在游戏里 日志 “Hit Galecrest for 83 damage!” 这句由它的 applyHit 拼出;目标的 HP 条随之变短。
它的职责 TargetedSkill 的子类,实现 applyHit:按威力算伤害再扣血;是 Template Method 里的一步。
家族关系 继承 A TargetedSkill
子类 / 实现者 C Bite C Lance C Tackle
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 没有别的类把它存成字段
字段 1 个 - final power: double
方法 2 个 # AttackSkill(String name, int energyCost, double power) · 第 12 行 # applyHit(Fighter user, Fighter target, Random random): String · 第 18 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/AttackSkill.java(24 行)
看老师打印稿里的这个类(UMLDoclet)
C Bite Bite au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Bite:花 1 点能量的普通攻击,威力 1。
在游戏里 战斗按钮 “Bite [1]”;打中时日志写 “Hit ... for N damage!”。
它的职责 AttackSkill 的子类,只传入名字、费用 1 和威力 1。
家族关系 继承 A AttackSkill
谁创建它 C SkillCatalogue (第 12 行 new Bite(…))
谁存着它 没有别的类把它存成字段
字段 2 个 - static final ENERGY_COST: int - static final POWER: double
方法 1 个 + Bite() · 第 8 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;12 技能家族:继承和模板方法 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/Bite.java(12 行)
看老师打印稿里的这个类(UMLDoclet)
A BoostSkill BoostSkill au.edu.unimelb.swen.oop.mokepon.skill 抽象类
抽象类:一定成功、给自己某项属性加 1 到 10 点的强化技能。
在游戏里 日志 “They raised their strength by 5 points!” 这类句子;写的是实际加了多少(到上限就加得少)。
它的职责 Skill 的子类,实现 applyEffect:随机 1–10 再 raiseStat,不做命中检查;四个子类只差加哪项属性。
家族关系 继承 A Skill
子类 / 实现者 C Aim C Bunker C Nimble C Swole
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 没有别的类把它存成字段
字段 2 个 - static final MAX_BOOST: int - final stat: Stat
方法 2 个 # BoostSkill(String name, int energyCost, Stat stat) · 第 15 行 # applyEffect(Fighter user, Fighter target, Random random): String · 第 22 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/BoostSkill.java(29 行)
看老师打印稿里的这个类(UMLDoclet)
C Bunker Bunker au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Bunker:花 3 点能量,提高自己的防御(Defence)。
在游戏里 战斗按钮 “Bunker [3]”;日志 “They raised their defence by N points!”。
它的职责 BoostSkill 的子类,只传入名字、费用 3 和 Stat.DEFENCE。
家族关系 继承 A BoostSkill
谁创建它 C SkillCatalogue (第 13 行 new Bunker(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final ENERGY_COST: int
方法 1 个 + Bunker() · 第 9 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;12 技能家族:继承和模板方法 ;17 考试准备:用这份代码答题
源文件 skill/Bunker.java(13 行)
看老师打印稿里的这个类(UMLDoclet)
C Lance Lance au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Lance:花 4 点能量,用一半力量攻击,并让目标流血。
在游戏里 战斗按钮 “Lance [4]”;日志 “Hit Galecrest for 83 damage! They started bleeding!”。
它的职责 AttackSkill 的子类,覆盖 applyHit:先 super.applyHit 造成伤害,再给目标加 new Bleeding(user)。
家族关系 继承 A AttackSkill
谁创建它 C SkillCatalogue (第 12 行 new Lance(…))
谁存着它 没有别的类把它存成字段
字段 2 个 - static final ENERGY_COST: int - static final HALF_STRENGTH: double
方法 2 个 + Lance() · 第 12 行 # applyHit(Fighter user, Fighter target, Random random): String · 第 18 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/Lance.java(24 行)
看老师打印稿里的这个类(UMLDoclet)
C Nimble Nimble au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Nimble:花 3 点能量,提高自己的闪避(Dodge)。
在游戏里 战斗按钮 “Nimble [3]”;日志 “They raised their dodge by N points!”。
它的职责 BoostSkill 的子类,只传入名字、费用 3 和 Stat.DODGE。
家族关系 继承 A BoostSkill
谁创建它 C SkillCatalogue (第 13 行 new Nimble(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final ENERGY_COST: int
方法 1 个 + Nimble() · 第 9 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;12 技能家族:继承和模板方法 ;17 考试准备:用这份代码答题
源文件 skill/Nimble.java(13 行)
看老师打印稿里的这个类(UMLDoclet)
C PocketSand PocketSand au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Pocket Sand:花 4 点能量,没有伤害,但让目标致盲 3 回合。
在游戏里 战斗按钮 “Pocket Sand [4]”;日志 “Pocket sand blinded Bubbore!” 和 “Their targeted skills may miss for 3 turns.”。
它的职责 TargetedSkill 的子类,实现 applyHit:给目标加上 new Blinded();必须先通过命中检查才生效。
家族关系 继承 A TargetedSkill
谁创建它 C SkillCatalogue (第 12 行 new PocketSand(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final ENERGY_COST: int
方法 2 个 + PocketSand() · 第 11 行 # applyHit(Fighter user, Fighter target, Random random): String · 第 16 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/PocketSand.java(22 行)
看老师打印稿里的这个类(UMLDoclet)
A Skill Skill au.edu.unimelb.swen.oop.mokepon.skill 抽象类
抽象类:所有技能的共同部分:名字、能量费用和 use()。
在游戏里 技能按钮上的 “Lance [4]” 就是 getName() 加 getEnergyCost();每回合日志里技能的结果由 use() 返回。
它的职责 Template Method:final 的 use() 先扣能量,再调用抽象的 applyEffect(),由子类决定效果。
子类 / 实现者 A BoostSkill A TargetedSkill C Wait
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 C Mokepon 的字段 skills: List<Skill>
字段 2 个 - final name: String - final energyCost: int
方法 5 个 # Skill(String name, int energyCost) · 第 14 行 + getName(): String · 第 19 行 + getEnergyCost(): int · 第 23 行 + use(Fighter user, Fighter target, Random random): String · 第 30 行 # applyEffect(Fighter user, Fighter target, Random random): String · 第 36 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/Skill.java(38 行)
看老师打印稿里的这个类(UMLDoclet)
全部 10 个技能的目录:按名字找到对应的技能对象。
在游戏里 看不见:启动时 MokeponParser 用它把 “Bite|Wait” 这样的技能名换成技能对象。
它的职责 技能对象不会变,所以全游戏共用一份;find() 区分大小写,找不到就抛异常。加新技能要在这里登记。
谁创建它 只有 static 成员,直接用类名调用,不需要 new
谁存着它 没有别的类把它存成字段
字段 1 个 - static final SKILLS: List<Skill>
方法 1 个 + find(String name): Skill · 第 16 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/SkillCatalogue.java(25 行)
看老师打印稿里的这个类(UMLDoclet)
C Stun Stun au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Stun:花 4 点能量,没有伤害,但让目标伤害减半 3 回合。
在游戏里 战斗按钮 “Stun [4]”;日志 “Galecrest was stunned! Their damage is halved for 3 turns.”。
它的职责 TargetedSkill 的子类,实现 applyHit:给目标加上 new Stunned();必须先通过命中检查才生效。
家族关系 继承 A TargetedSkill
谁创建它 C SkillCatalogue (第 12 行 new Stun(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final ENERGY_COST: int
方法 2 个 + Stun() · 第 11 行 # applyHit(Fighter user, Fighter target, Random random): String · 第 16 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/Stun.java(22 行)
看老师打印稿里的这个类(UMLDoclet)
C Swole Swole au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Swole:花 3 点能量,提高自己的力量(Strength)。
在游戏里 战斗按钮 “Swole [3]”;日志 “They raised their strength by N points!”。
它的职责 BoostSkill 的子类,只传入名字、费用 3 和 Stat.STRENGTH。
家族关系 继承 A BoostSkill
谁创建它 C SkillCatalogue (第 13 行 new Swole(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - static final ENERGY_COST: int
方法 1 个 + Swole() · 第 9 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;12 技能家族:继承和模板方法 ;17 考试准备:用这份代码答题
源文件 skill/Swole.java(13 行)
看老师打印稿里的这个类(UMLDoclet)
C Tackle Tackle au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Tackle:花 5 点能量的重击,威力 2(双倍伤害)。
在游戏里 战斗按钮 “Tackle [5]”;能量不到 5 时按钮变灰(如 Shellurk 只剩 3 点能量时)。
它的职责 AttackSkill 的子类,只传入名字、费用 5 和威力 2。
家族关系 继承 A AttackSkill
谁创建它 C SkillCatalogue (第 12 行 new Tackle(…))
谁存着它 没有别的类把它存成字段
字段 2 个 - static final ENERGY_COST: int - static final POWER: double
方法 1 个 + Tackle() · 第 8 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;12 技能家族:继承和模板方法 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/Tackle.java(12 行)
看老师打印稿里的这个类(UMLDoclet)
抽象类:对准对手的技能,必须先通过命中检查才生效。
在游戏里 没打中时日志写 “But they missed.”,这句就是它的 MISS_MESSAGE。
它的职责 Template Method 的第二层:final 的 applyEffect 先做命中检查(再看致盲),通过了才调用子类的 applyHit。
家族关系 继承 A Skill
子类 / 实现者 A AttackSkill C PocketSand C Stun
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 没有别的类把它存成字段
字段 1 个 - static final MISS_MESSAGE: String
方法 5 个 # TargetedSkill(String name, int energyCost) · 第 13 行 # applyEffect(Fighter user, Fighter target, Random random): String · 第 18 行 # applyHit(Fighter user, Fighter target, Random random): String · 第 26 行 - hits(Fighter user, Fighter target, Random random): boolean · 第 31 行 - calculateHitChance(Fighter user, Fighter target): double · 第 38 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/TargetedSkill.java(46 行)
看老师打印稿里的这个类(UMLDoclet)
C Wait Wait au.edu.unimelb.swen.oop.mokepon.skill 类
技能 Wait:什么都不做;费用是 -2,所以反而回 2 点能量。
在游戏里 战斗按钮 “Wait [-2]”;日志随机一句,如 “They wonder if this is a good strategy.”。
它的职责 直接继承 Skill,applyEffect 只返回一句随机消息;负的费用让 spendEnergy 变成加能量,也不会打空。
家族关系 继承 A Skill
谁创建它 C SkillCatalogue (第 13 行 new Wait(…))
谁存着它 没有别的类把它存成字段
字段 2 个 - static final ENERGY_COST: int - static final MESSAGES: List<String>
方法 2 个 + Wait() · 第 15 行 # applyEffect(Fighter user, Fighter target, Random random): String · 第 20 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 skill/Wait.java(24 行)
看老师打印稿里的这个类(UMLDoclet)
战斗界面:显示双方 Mokepon、技能按钮、道具按钮和日志。
在游戏里 整个战斗界面:左下玩家卷轴、右上敌人卷轴、Actions 下的技能按钮、上方道具按钮、右下日志框,以及 You Win / Game Over 对话框。
它的职责 GameScreen 的子类,只把点击和按键 1–4 交给 Battle 再刷新显示,规则全在 Battle;覆盖 canRunAway。
家族关系 继承 A GameScreen
谁创建它 C GameWindow (第 67 行 new BattleScreen(…))
谁存着它 没有别的类把它存成字段
字段 35 个 - static final SKILL_KEYS: List<KeyCode> - static final BUTTON_RADIUS: int - static final PLAYER_X: int - static final PLAYER_Y: int - static final PLAYER_WIDTH: int - static final PLAYER_HEIGHT: int - static final PLAYER_CONTENT_X: int - static final ENEMY_X: int - static final ENEMY_Y: int - static final ENEMY_WIDTH: int - static final ENEMY_HEIGHT: int - static final ENEMY_CONTENT_X: int - static final ACTIONS_X: int - static final ACTIONS_LABEL_Y: int - static final ACTIONS_FONT_SIZE: int - static final SKILLS_Y: int - static final SKILL_WIDTH: int - static final SKILL_HEIGHT: int - static final SKILL_GAP: int - static final SKILL_FONT_SIZE: int - static final ITEM_WIDTH: int - static final ITEM_HEIGHT: int - static final ITEM_ICON_SIZE: int - static final ITEM_GAP: int - static final ITEM_FONT_SIZE: int - static final LOG_X: int - static final LOG_Y: int - static final LOG_HEIGHT: int - static final LOG_FONT_SIZE: int - final battle: Battle - final playerPanel: FighterPanel - final enemyPanel: FighterPanel - final logArea: TextArea - final skillButtons: List<GameButton> - final itemButtons: Map<Item, GameButton>
方法 13 个 + BattleScreen(Battle battle, GameImages images, GameNavigator navigator) · 第 73 行 + canRunAway(): boolean · 第 103 行 # handleKey(KeyEvent event): void · 第 109 行 - useSkill(Skill skill): void · 第 117 行 - useItem(Item item): void · 第 122 行 - update(): void · 第 128 行 - showLog(): void · 第 141 行 - updateSkillButtons(): void · 第 148 行 - updateItemButtons(): void · 第 157 行 - showResult(): void · 第 170 行 - createSkillButtons(List<Skill> skills): VBox · 第 182 行 - createItemButtons(GameImages images): HBox · 第 203 行 - createLogArea(): TextArea · 第 225 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/BattleScreen.java(236 行)
看老师打印稿里的这个类(UMLDoclet)
战斗中一方的显示块:卷轴、头像、名字、HP 条和能量条。
在游戏里 战斗界面左下(玩家)和右上(敌人)两块卷轴各是一个 FighterPanel;只有玩家的条上写数字。
它的职责 组合(composition)一个 FighterScroll 和两个 StatBar;update() 让条和红色遮罩跟上 Fighter 的数据。
谁创建它 C BattleScreen (第 78、81 行 new FighterPanel(…))
谁存着它 C BattleScreen 的字段 playerPanel: FighterPanel、enemyPanel: FighterPanel
字段 14 个 - static final HP_COLOUR: String - static final ENERGY_COLOUR: String - static final PORTRAIT_SIZE: int - static final NAME_FONT_SIZE: int - static final NAME_OFFSET: int - static final PORTRAIT_OFFSET: int - static final HP_BAR_OFFSET: int - static final ENERGY_BAR_OFFSET: int - final fighter: Fighter - final scroll: FighterScroll - final portrait: ImageView - final name: Label - final hpBar: StatBar - final energyBar: StatBar
方法 4 个 + FighterPanel(Fighter fighter, Rectangle2D area, double contentX, boolean showNumbers) · 第 37 行 + getNodes(): List<Node> · 第 63 行 + getFaintMask(): Rectangle · 第 71 行 + update(): void · 第 76 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;14 战斗界面是怎么画出来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/FighterPanel.java(82 行)
看老师打印稿里的这个类(UMLDoclet)
战斗者身后的卷轴图片,和倒下时盖上去的红色遮罩。
在游戏里 卷轴背景本身;Mokepon 倒下时整张卷轴变红(如 You Win 时敌人 Galecrest 的卷轴)。
它的职责 半透明红色矩形用卷轴图片做 clip,所以只有卷轴形状变红;遮罩单独返回,好画在最上层。
谁创建它 C FighterPanel (第 41 行 new FighterScroll(…))
谁存着它 C FighterPanel 的字段 scroll: FighterScroll
字段 3 个 - static final FAINT_TINT: Color - final scroll: ImageView - final faintMask: Rectangle
方法 5 个 + FighterScroll(double x, double y, double width, double height) · 第 15 行 + getScroll(): ImageView · 第 21 行 + getFaintMask(): Rectangle · 第 26 行 + setFainted(boolean fainted): void · 第 30 行 - createFaintMask(Image scrollImage, double x, double y, double width, double height): Rectangle · 第 35 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;14 战斗界面是怎么画出来的 ;17 考试准备:用这份代码答题
源文件 ui/FighterScroll.java(49 行)
看老师打印稿里的这个类(UMLDoclet)
C GameButton GameButton au.edu.unimelb.swen.oop.mokepon.ui 类
游戏统一样式的按钮:圆角、半透明的灰色背景。
在游戏里 选择界面的名字按钮和 Choose Mokepon、战斗的技能和道具按钮、地图的四个箭头按钮;变淡(40% 不透明)表示不能点。
它的职责 继承 JavaFX 的 Button,加上按下变深、选中高亮、setUsable 整体变淡;对话框里的按钮不是它。
家族关系 继承 Button
谁创建它 C BattleScreen (第 189、212 行 new GameButton(…));C OverworldScreen (第 169 行 new GameButton(…));C SelectScreen (第 216、238 行 new GameButton(…))
谁存着它 C BattleScreen 的字段 skillButtons: List<GameButton>、itemButtons: Map<Item, GameButton>;C OverworldScreen 的字段 moveButtons: Map<Direction, GameButton>;C SelectScreen 的字段 chooseButton: GameButton、selectedButton: GameButton
字段 4 个 - static final NORMAL: double - static final HIGHLIGHTED: double - static final DISABLED_OPACITY: double - final cornerRadius: int
方法 6 个 + GameButton(String text, Font font, int cornerRadius) · 第 18 行 + GameButton(ImageView icon, int cornerRadius) · 第 26 行 + addPressEffect(): void · 第 32 行 + setHighlighted(boolean highlighted): void · 第 46 行 + setUsable(boolean usable): void · 第 51 行 - setBackgroundOpacity(double opacity): void · 第 57 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;08 地图世界:走一步发生了什么 ;11 一个回合的完整流程 ;12 技能家族:继承和模板方法 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/GameButton.java(63 行)
看老师打印稿里的这个类(UMLDoclet)
接口:界面和菜单可以请窗口做的事,主要是切换界面。
在游戏里 看不见:点 Choose Mokepon、Fight!、Back to it! 或菜单项时,代码调用的就是它的方法(startGame、startBattle 等)。
它的职责 Dependency Inversion:界面和菜单只依赖这个接口,不依赖 GameWindow;GameWindow 实现它。
子类 / 实现者 C GameWindow
谁创建它 接口不能被 new,只能 new 它的实现类
谁存着它 A GameScreen 的字段 navigator: GameNavigator
方法 7 个 + startGame(Mokepon playerChoice): void · 第 12 行 + startBattle(): void · 第 15 行 + winBattle(): void · 第 18 行 + runAway(): void · 第 21 行 + returnToMainMenu(): void · 第 24 行 + quit(): void · 第 27 行 + updateMenu(): void · 第 32 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/GameNavigator.java(34 行)
看老师打印稿里的这个类(UMLDoclet)
A GameScreen GameScreen au.edu.unimelb.swen.oop.mokepon.ui 抽象类
抽象类:三个界面的共同部分:背景、对话框、按键、菜单开关。
在游戏里 每个界面底下的棕色背景图;对话框由它放到最上层,对话框打开时它不再处理按键。
它的职责 Template Method:final 的 handleKeyPress 先挡掉对话框和组合键,再调子类的 handleKey。
子类 / 实现者 C BattleScreen C OverworldScreen C SelectScreen
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 C GameWindow 的字段 currentScreen: GameScreen
字段 3 个 - final navigator: GameNavigator - final view: Pane - dialog: ModalDialog
方法 13 个 # GameScreen(GameNavigator navigator) · 第 18 行 + getView(): Pane · 第 24 行 + handleKeyPress(KeyEvent event): void · 第 32 行 + canRunAway(): boolean · 第 42 行 + canReturnToMainMenu(): boolean · 第 47 行 # handleKey(KeyEvent event): void · 第 52 行 # getNavigator(): GameNavigator · 第 55 行 # addToView(Node... nodes): void · 第 60 行 # addToView(List<Node> nodes): void · 第 64 行 # showDialog(ModalDialog newDialog): void · 第 69 行 # closeDialog(): void · 第 76 行 # isDialogOpen(): boolean · 第 83 行 # createGameEndDialog(String heading): ModalDialog · 第 88 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/GameScreen.java(95 行)
看老师打印稿里的这个类(UMLDoclet)
C GameWindow GameWindow au.edu.unimelb.swen.oop.mokepon.ui 类
游戏窗口:拥有 Stage,决定现在显示哪个界面。
在游戏里 标题为 Mokepon 的整个窗口:顶部菜单栏一直不变,下面换成选择、地图或战斗界面。
它的职责 实现 GameNavigator;用 BorderPane(菜单在 top、界面在 center)切换界面;用事件过滤器把按键交给当前界面。
家族关系 实现 I GameNavigator
谁创建它 C Main (第 38 行 new GameWindow(…))
谁存着它 没有别的类把它存成字段
字段 10 个 - final stage: Stage - final mokepons: List<Mokepon> - final map: GameMap - final images: GameImages - final menu: GameMenu - final root: BorderPane - final selectScreen: SelectScreen - currentScreen: GameScreen - world: Overworld - overworldScreen: OverworldScreen
方法 10 个 + GameWindow(Stage stage, List<Mokepon> mokepons, GameMap map, GameImages images) · 第 31 行 + show(): void · 第 52 行 + startGame(Mokepon playerChoice): void · 第 58 行 + startBattle(): void · 第 66 行 + winBattle(): void · 第 71 行 + runAway(): void · 第 77 行 + returnToMainMenu(): void · 第 84 行 + quit(): void · 第 92 行 + updateMenu(): void · 第 97 行 - showScreen(GameScreen screen): void · 第 101 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/GameWindow.java(107 行)
看老师打印稿里的这个类(UMLDoclet)
带数字的属性条:在条上写出 “225 / 225” 这样的数字。
在游戏里 战斗界面玩家卷轴上的 HP 条和能量条(如 “225 / 225”、“25 / 33”);敌人的条没有数字。
它的职责 继承 StatBar,覆盖 update() 和 getNodes()(先调 super),在父类的条上面多叠一个 Label。
家族关系 继承 C StatBar
谁创建它 C FighterPanel (第 51、53 行 new LabelledStatBar(…))
谁存着它 没有别的类把它存成字段
字段 3 个 - static final SEPARATOR: String - static final FONT_SIZE: int - final numbers: Label
方法 3 个 + LabelledStatBar(double x, double y, String colour, int current, int max) · 第 17 行 + update(int current, int max): void · 第 28 行 + getNodes(): List<Node> · 第 35 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;11 一个回合的完整流程 ;14 战斗界面是怎么画出来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/LabelledStatBar.java(41 行)
看老师打印稿里的这个类(UMLDoclet)
C MapView MapView au.edu.unimelb.swen.oop.mokepon.ui 类
画地图:地块、还留在地图上的物体,以及玩家。
在游戏里 地图界面中间 20×20 格的大地图:每格 32 像素,上面有感叹号、问号、门和玩家图标。
它的职责 JavaFX 绘图集中在这里,world 包就不用碰 JavaFX;update() 按 Overworld 重新摆放物体;每张图片只加载一次。
谁创建它 C OverworldScreen (第 63 行 new MapView(…))
谁存着它 C OverworldScreen 的字段 mapView: MapView
字段 7 个 + static final TILE_SIZE: int - final world: Overworld - final pane: Pane - final objectLayer: Pane - final playerView: ImageView - final loadedImages: Map<String, Image> - final objectViews: Map<MapObject, ImageView>
方法 8 个 + MapView(Overworld world, GameImages images, double x, double y) · 第 30 行 + getNode(): Pane · 第 46 行 + update(): void · 第 53 行 - createTileLayer(GameMap map, GameImages images): Pane · 第 61 行 - createObjectView(MapObject object): ImageView · 第 74 行 - createTileView(Image image, Position position): ImageView · 第 84 行 - placeOnTile(ImageView imageView, Position position): void · 第 91 行 - getImage(String path): Image · 第 96 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;08 地图世界:走一步发生了什么 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/MapView.java(103 行)
看老师打印稿里的这个类(UMLDoclet)
模态对话框:屏幕中间的白框,带标题、消息和按钮。
在游戏里 “Encountered a Hexwing”、“You Win”、“Game Over”、“You finished the game! ...” 这些白框,以及后面的暗色遮罩。
它的职责 暗层盖住整个屏幕,挡住后面的点击;用 addMessage / addButton 按需加内容;按钮是普通的 Button。
谁创建它 C BattleScreen (第 173 行 new ModalDialog(…));A GameScreen (第 89 行 new ModalDialog(…));C OverworldScreen (第 81 行 new ModalDialog(…))
谁存着它 A GameScreen 的字段 dialog: ModalDialog
字段 10 个 - static final SHADE_STYLE: String - static final BOX_STYLE: String - static final BUTTON_STYLE: String - static final HEADING_SIZE: int - static final SPACING: int - static final BUTTON_GAP: int - static final PADDING: Insets - final layer: StackPane - final messages: VBox - final buttons: HBox
方法 5 个 + ModalDialog(String heading) · 第 37 行 + getLayer(): StackPane · 第 56 行 + addMessage(String text): void · 第 61 行 + addButton(String text, EventHandler<ActionEvent> action): void · 第 68 行 + focusFirstButton(): void · 第 78 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;09 遇敌:地形、类型和挑敌人 ;11 一个回合的完整流程 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/ModalDialog.java(84 行)
看老师打印稿里的这个类(UMLDoclet)
地图界面:地图、右上属性卷轴、方向按钮和下方状态栏。
在游戏里 整个地图界面;状态栏的 “You picked up a Poison!”、遇敌对话框的 Fight! / Run Away! 都由它显示。
它的职责 GameScreen 的子类,实现 OverworldListener(Observer 的观察者);只显示,移动规则在 Overworld。
家族关系 继承 A GameScreen ;实现 I OverworldListener
谁创建它 C GameWindow (第 60 行 new OverworldScreen(…))
谁存着它 C GameWindow 的字段 overworldScreen: OverworldScreen
字段 20 个 - static final ARROW_KEYS: Map<KeyCode, Direction> - static final MAP_Y: int - static final STATS_X: int - static final STATS_Y: int - static final STATS_WIDTH: int - static final STATS_HEIGHT: int - static final STATUS_WIDTH: int - static final STATUS_HEIGHT: int - static final STATUS_GAP: int - static final STATUS_STYLE: String - static final PAD_X: int - static final PAD_Y: int - static final BUTTON_SIZE: int - static final BUTTON_GAP: int - static final ICON_SIZE: int - final world: Overworld - final mapView: MapView - final statsScroll: PlayerStatsScroll - final statusBar: Label - final moveButtons: Map<Direction, GameButton>
方法 12 个 + OverworldScreen(Overworld world, GameImages images, GameNavigator navigator) · 第 55 行 + onPlayerMoved(): void · 第 73 行 + onEncounter(Encounter encounter): void · 第 80 行 + onItemCollected(Item item): void · 第 97 行 + onEncounterWon(Mokepon enemy): void · 第 103 行 + onExitReached(int fightsWon): void · 第 109 行 # handleKey(KeyEvent event): void · 第 116 行 - movePlayer(Direction direction): void · 第 127 行 - update(): void · 第 134 行 - createStatusBar(double y): Label · 第 142 行 - createMovePad(GameImages images): GridPane · 第 153 行 - createMoveButton(Direction direction, GameImages images): GameButton · 第 166 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;13 状态效果和道具 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/OverworldScreen.java(178 行)
看老师打印稿里的这个类(UMLDoclet)
地图界面右上的卷轴:玩家的 Mokepon、属性、胜场和道具数量。
在游戏里 右上卷轴里的 “Mokepon: Impike”、HP 等六项属性、“Fights: 0”,以及 Inventory 下三种道具的数量。
它的职责 属性在地图上不会变,所以只写一次;update() 只刷新胜场和道具数。名字用无衬线字体,数字用等宽字体。
谁创建它 C OverworldScreen (第 64 行 new PlayerStatsScroll(…))
谁存着它 C OverworldScreen 的字段 statsScroll: PlayerStatsScroll
字段 12 个 - static final FONT_SIZE: int - static final ROW_HEIGHT: int - static final LABEL_WIDTH: int - static final SEPARATOR_WIDTH: int - static final TEXT_X: int - static final TEXT_Y: int - final player: Player - final nameFont: Font - final numberFont: Font - final pane: Pane - final fightsValue: Label - final itemValues: Map<Item, Label>
方法 5 个 + PlayerStatsScroll(Player player, double x, double y, double width, double height) · 第 37 行 + getNode(): Pane · 第 76 行 + update(): void · 第 81 行 - addRow(GridPane grid, int row, String name, Label value): void · 第 89 行 - createLabel(String text, Font font): Label · 第 94 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;08 地图世界:走一步发生了什么 ;10 战斗的数据:Mokepon、Fighter、Battle ;13 状态效果和道具 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/PlayerStatsScroll.java(100 行)
看老师打印稿里的这个类(UMLDoclet)
选择界面:从列表里挑一只 Mokepon,并查看它的属性。
在游戏里 游戏一打开的界面:左边可滚动的名字列表、灰色圆里的头像、名字和类型图标、属性卷轴、Choose Mokepon 按钮。
它的职责 GameScreen 的子类;覆盖 canReturnToMainMenu 返回 false;没选之前 Choose 按钮不能点。
家族关系 继承 A GameScreen
谁创建它 C GameWindow (第 41 行 new SelectScreen(…))
谁存着它 C GameWindow 的字段 selectScreen: SelectScreen
字段 47 个 - static final PROMPT: String - static final TITLE_X: int - static final TITLE_Y: int - static final TITLE_FONT_SIZE: int - static final LIST_X: int - static final LIST_Y: int - static final LIST_WIDTH: int - static final LIST_HEIGHT: int - static final LIST_BUTTON_WIDTH: int - static final LIST_FONT_SIZE: int - static final LIST_GAP: int - static final BUTTON_RADIUS: int - static final CIRCLE_CENTRE_X: int - static final CIRCLE_CENTRE_Y: int - static final CIRCLE_RADIUS: int - static final PORTRAIT_SIZE: int - static final CIRCLE_COLOUR: Color - static final NAME_Y: int - static final NAME_WIDTH: int - static final NAME_FONT_SIZE: int - static final TYPE_ICON_SIZE: int - static final TYPE_ICON_GAP: int - static final SCROLL_X: int - static final SCROLL_Y: int - static final SCROLL_WIDTH: int - static final SCROLL_HEIGHT: int - static final STATS_X: int - static final STATS_Y: int - static final LABEL_WIDTH: int - static final VALUE_WIDTH: int - static final ROW_HEIGHT: int - static final STAT_FONT_SIZE: int - static final CHOOSE_X: int - static final CHOOSE_Y: int - static final CHOOSE_SIZE: int - static final CHOOSE_FONT_SIZE: int - static final CHOOSE_RADIUS: int - final images: GameImages - final portraitView: ImageView - final nameLabel: Label - final typeIcon: ImageView - final statValues: Map<Stat, Label> - final skillsValue: Label - final typeValue: Label - final chooseButton: GameButton - selectedButton: GameButton - selectedMokepon: Mokepon
方法 15 个 + SelectScreen(List<Mokepon> mokepons, GameImages images, GameNavigator navigator) · 第 88 行 + canReturnToMainMenu(): boolean · 第 120 行 + clearSelection(): void · 第 125 行 - select(Mokepon mokepon, GameButton button): void · 第 143 行 - showTypeIcon(boolean visible): void · 第 170 行 - formatSkills(Mokepon mokepon): String · 第 175 行 - createTitle(DropShadow outline): Label · 第 183 行 - createPortraitCircle(): Circle · 第 193 行 - createNameRow(): HBox · 第 202 行 - createMokeponList(List<Mokepon> mokepons): ScrollPane · 第 212 行 - createChooseButton(): GameButton · 第 237 行 - createStatsGrid(): GridPane · 第 253 行 - addStatRow(GridPane grid, int row, String name, Label value, int height): void · 第 271 行 - createValueLabel(): Label · 第 280 行 - createRowLabel(String text, Font font): Label · 第 285 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;10 战斗的数据:Mokepon、Fighter、Battle ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/SelectScreen.java(292 行)
看老师打印稿里的这个类(UMLDoclet)
C StatBar StatBar au.edu.unimelb.swen.oop.mokepon.ui 类
彩色进度条:显示 HP 或能量还剩多少。
在游戏里 战斗界面的绿色 HP 条和蓝色能量条;敌人卷轴上的两条就是普通 StatBar(没有数字)。
它的职责 包装 JavaFX 的 ProgressBar;只要值大于 0,至少显示 3%,免得看不见。是 LabelledStatBar 的父类。
子类 / 实现者 C LabelledStatBar
谁创建它 C FighterPanel (第 56、57 行 new StatBar(…))
谁存着它 C FighterPanel 的字段 hpBar: StatBar、energyBar: StatBar
字段 4 个 # static final WIDTH: int # static final HEIGHT: int - static final MIN_VISIBLE_RATIO: double - final bar: ProgressBar
方法 4 个 + StatBar(double x, double y, String colour, int current, int max) · 第 18 行 + update(int current, int max): void · 第 28 行 + getNodes(): List<Node> · 第 33 行 - calculateRatio(int current, int max): double · 第 37 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;11 一个回合的完整流程 ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/StatBar.java(44 行)
看老师打印稿里的这个类(UMLDoclet)
C UiStyle UiStyle au.edu.unimelb.swen.oop.mokepon.ui 类
公共样式工具:游戏尺寸、素材文件,以及造标签和图片的静态方法。
在游戏里 它本身看不见,但哥特字体、棕色背景、卷轴图片、标记的着色(白、红、绿感叹号和品红色的门)都经过它。
它的职责 只有 static 常量和方法的工具类(utility class),所有界面共用,样式只写一处。
谁创建它 只有 static 成员,直接用类名调用,不需要 new
谁存着它 没有别的类把它存成字段
字段 8 个 + static final GAME_WIDTH: int + static final GAME_HEIGHT: int + static final SCROLL_FILE: String - static final BACKGROUND_FILE: String - static final FONT_FILE: String - static final SANS_SERIF: String - static final MONOSPACE: String - static final STRAIGHT_DOWN: double
方法 11 个 + loadGameFont(int size): Font · 第 29 行 + createSansSerifFont(FontWeight weight, int size): Font · 第 33 行 + createMonospaceFont(FontWeight weight, int size): Font · 第 37 行 + loadImage(String path): Image · 第 42 行 + createImageView(Image image, double x, double y, double width, double height): ImageView · 第 47 行 + createIcon(Image image, double size): ImageView · 第 58 行 + createBackground(): ImageView · 第 66 行 + tint(ImageView imageView, String colour): void · 第 74 行 + createWhiteOutline(): DropShadow · 第 83 行 + createCenteredLabel(String text, Font font, double x, double y, double width): Label · 第 92 行 + createLabel(String text, Font font): Label · 第 105 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;14 战斗界面是怎么画出来的 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 ui/UiStyle.java(112 行)
看老师打印稿里的这个类(UMLDoclet)
E Direction Direction au.edu.unimelb.swen.oop.mokepon.world 枚举
枚举:上下左右四个移动方向,各带 x、y 的变化量。
在游戏里 地图界面右下的四个箭头按钮和键盘方向键,各对应一个 Direction。
它的职责 y 向下增大,所以 UP 是 (0, -1);Position.move(direction) 用它算出新的坐标。
谁创建它 枚举的几个值在类加载时就自动建好了,不用 new
谁存着它 C GameImages 的字段 buttonImages: Map<Direction, String>;C OverworldScreen 的字段 moveButtons: Map<Direction, GameButton>
枚举值 UP、DOWN、LEFT、RIGHT
字段 2 个 - final xChange: int - final yChange: int
方法 3 个 ~ Direction(int xChange, int yChange) · 第 13 行 + getXChange(): int · 第 18 行 + getYChange(): int · 第 22 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;17 考试准备:用这份代码答题
源文件 world/Direction.java(26 行)
看老师打印稿里的这个类(UMLDoclet)
C Encounter Encounter au.edu.unimelb.swen.oop.mokepon.world 类
一次遇敌:哪个标记、玩家的 Mokepon、敌人和脚下的地形。
在游戏里 遇敌对话框的标题 “Encountered a Hexwing” 里的敌人和下面两句地形提示,都来自 Encounter。
它的职责 getTerrainMessages 生成地形提示;createBattle 按地形效果造出两个 Fighter,再造出 Battle。
谁创建它 C Overworld (第 106 行 new Encounter(…))
谁存着它 C Overworld 的字段 encounter: Encounter
字段 4 个 - final marker: Marker - final playerMokepon: Mokepon - final enemy: Mokepon - final terrain: Terrain
方法 8 个 + Encounter(Marker marker, Mokepon playerMokepon, Mokepon enemy, Terrain terrain) · 第 21 行 + getMarker(): Marker · 第 28 行 + getEnemy(): Mokepon · 第 32 行 - getPlayerEffect(): TerrainEffect · 第 36 行 - getEnemyEffect(): TerrainEffect · 第 40 行 + getTerrainMessages(): List<String> · 第 45 行 + createBattle(Inventory inventory): Battle · 第 53 行 - addTerrainMessage(List<String> messages, String who, TerrainEffect effect): void · 第 59 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;11 一个回合的完整流程 ;13 状态效果和道具 ;14 战斗界面是怎么画出来的 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/Encounter.java(65 行)
看老师打印稿里的这个类(UMLDoclet)
I EnemyPicker EnemyPicker au.edu.unimelb.swen.oop.mokepon.world 接口
接口:决定在某个标记上遇到哪只 Mokepon。
在游戏里 看不见:踩上感叹号时在 Overworld.startEncounter 里运行,结果就是对话框 “Encountered a ...” 里的名字。
它的职责 Strategy 模式的接口;随机、强、弱三种标记只是用的 picker 不同,Marker 的代码完全一样。
子类 / 实现者 C RandomEnemyPicker C TerrainEnemyPicker
谁创建它 接口不能被 new,只能 new 它的实现类
谁存着它 C Marker 的字段 picker: EnemyPicker
方法 1 个 + pick(List<Mokepon> mokepons, Terrain terrain, Random random): Mokepon · 第 12 行
在哪章讲 03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;09 遇敌:地形、类型和挑敌人 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/EnemyPicker.java(14 行)
看老师打印稿里的这个类(UMLDoclet)
C Exit Exit au.edu.unimelb.swen.oop.mokepon.world 类
出口门:踩上去游戏就结束。
在游戏里 地图最上面 (6,0) 的品红色门;踩上去弹出 “You finished the game! You won 1 fights!”。
它的职责 MapObject 的子类,interact() 只调用 world.reachExit();结束对话框由 OverworldScreen 弹出。
家族关系 继承 A MapObject
谁创建它 C MapParser (第 83 行 new Exit(…))
谁存着它 没有别的类把它存成字段
方法 2 个 + Exit(Position position, Sprite sprite) · 第 6 行 ~ interact(Overworld world): void · 第 11 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/Exit.java(15 行)
看老师打印稿里的这个类(UMLDoclet)
C GameMap GameMap au.edu.unimelb.swen.oop.mokepon.world 类
数据文件里的地图:每格的地形、玩家起点和开局时的物体。
在游戏里 地图 20×20 的格子布局,和开局时的标记、箱子、门;玩家从 (10,18) 出发。
它的职责 游戏中不会变:构造时逐行拷贝数组、用 List.copyOf 拷贝物体,防止隐私泄露(privacy leak);isWalkable 判断能否走。
谁创建它 C MapParser (第 39 行 new GameMap(…))
谁存着它 C GameWindow 的字段 map: GameMap;C Overworld 的字段 map: GameMap
字段 3 个 - final tiles: Terrain[][] - final startPosition: Position - final objects: List<MapObject>
方法 8 个 + GameMap(Terrain[][] tiles, Position startPosition, List<MapObject> objects) · 第 15 行 + getWidth(): int · 第 26 行 + getHeight(): int · 第 30 行 + getStartPosition(): Position · 第 34 行 + getObjects(): List<MapObject> · 第 38 行 + getTerrain(Position position): Terrain · 第 42 行 + isWalkable(Position position): boolean · 第 47 行 - isInside(Position position): boolean · 第 51 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/GameMap.java(56 行)
看老师打印稿里的这个类(UMLDoclet)
A MapObject MapObject au.edu.unimelb.swen.oop.mokepon.world 抽象类
抽象类:放在地图某一格上、玩家踩上去会有反应的东西。
在游戏里 地图上的感叹号、问号箱子和门都是它的子类对象;样子由各自的 Sprite 决定。
它的职责 抽象方法 interact(Overworld) 让每种物体自己决定做什么;Overworld 一视同仁地调用,不用 instanceof(多态)。
子类 / 实现者 C Exit C Marker C MysteryBox
谁创建它 抽象类不能直接 new,只能 new 它的子类
谁存着它 C MapView 的字段 objectViews: Map<MapObject, ImageView>;C GameMap 的字段 objects: List<MapObject>;C Overworld 的字段 objects: List<MapObject>
字段 2 个 - final position: Position - final sprite: Sprite
方法 5 个 # MapObject(Position position, Sprite sprite) · 第 10 行 + getPosition(): Position · 第 15 行 + getSprite(): Sprite · 第 19 行 + isAt(Position other): boolean · 第 23 行 ~ interact(Overworld world): void · 第 30 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;13 状态效果和道具 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/MapObject.java(32 行)
看老师打印稿里的这个类(UMLDoclet)
C Marker Marker au.edu.unimelb.swen.oop.mokepon.world 类
Mokepon 标记(感叹号):踩上去遇到一只野生 Mokepon。
在游戏里 地图上的感叹号:白色是随机,红色是强(敌人占优势),绿色是弱(敌人占劣势)。
它的职责 MapObject 的子类,持有一个 EnemyPicker;interact() 调用 world.startEncounter(this)。
家族关系 继承 A MapObject
谁创建它 C MapParser (第 63 行 new Marker(…))
谁存着它 C Encounter 的字段 marker: Marker
字段 1 个 - final picker: EnemyPicker
方法 3 个 + Marker(Position position, Sprite sprite, EnemyPicker picker) · 第 14 行 ~ chooseEnemy(List<Mokepon> mokepons, Terrain terrain, Random random): Mokepon · 第 20 行 ~ interact(Overworld world): void · 第 25 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/Marker.java(29 行)
看老师打印稿里的这个类(UMLDoclet)
C MysteryBox MysteryBox au.edu.unimelb.swen.oop.mokepon.world 类
神秘箱子(问号):里面有一个道具,踩上去就捡到。
在游戏里 地图上的白色问号;捡到后问号消失,状态栏显示 “You picked up a Poison!”,卷轴里的数量加 1。
它的职责 MapObject 的子类,持有一个 Item;interact() 调用 world.collect(this),由 Overworld 移走它。
家族关系 继承 A MapObject
谁创建它 C MapParser (第 76 行 new MysteryBox(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - final item: Item
方法 3 个 + MysteryBox(Position position, Sprite sprite, Item item) · 第 9 行 + getItem(): Item · 第 14 行 ~ interact(Overworld world): void · 第 19 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;13 状态效果和道具 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/MysteryBox.java(23 行)
看老师打印稿里的这个类(UMLDoclet)
C Overworld Overworld au.edu.unimelb.swen.oop.mokepon.world 类
一局地图上的游戏:玩家、还剩下的物体和移动规则。
在游戏里 看不见:玩家每走一步、捡箱子、遇敌、到出口,都是它先改数据,再通知界面去画。
它的职责 Observer 模式的被观察者(subject):保存 listeners,用 notifyListeners 加 lambda 通知,不认识界面。
谁创建它 C GameWindow (第 59 行 new Overworld(…))
谁存着它 C GameWindow 的字段 world: Overworld;C MapView 的字段 world: Overworld;C OverworldScreen 的字段 world: Overworld
字段 7 个 - final map: GameMap - final mokepons: List<Mokepon> - final player: Player - final objects: List<MapObject> - final listeners: List<OverworldListener> - final random: Random - encounter: Encounter
方法 15 个 + Overworld(GameMap map, List<Mokepon> mokepons, Mokepon playerChoice) · 第 29 行 + Overworld(GameMap map, List<Mokepon> mokepons, Mokepon playerChoice, Random random) · 第 34 行 + addListener(OverworldListener listener): void · 第 44 行 + getMap(): GameMap · 第 48 行 + getPlayer(): Player · 第 52 行 + getObjects(): List<MapObject> · 第 57 行 + canMove(Direction direction): boolean · 第 61 行 + move(Direction direction): void · 第 66 行 + createBattle(): Battle · 第 82 行 + runAway(): void · 第 87 行 + winEncounter(): void · 第 94 行 ~ startEncounter(Marker marker): void · 第 103 行 ~ collect(MysteryBox box): void · 第 111 行 ~ reachExit(): void · 第 118 行 - notifyListeners(Consumer<OverworldListener> message): void · 第 125 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;06 窗口、界面切换和菜单 ;07 选择界面 SelectScreen ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;13 状态效果和道具 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/Overworld.java(131 行)
看老师打印稿里的这个类(UMLDoclet)
接口:地图上会发生的五件事(移动、遇敌、捡道具、打赢、到出口)。
在游戏里 看不见:OverworldScreen 实现它;比如 onItemCollected 被调用时,状态栏才写出 “You picked up a ...!”。
它的职责 Observer 模式的观察者接口;Overworld 只调用这些方法,不知道它们具体做什么。
子类 / 实现者 C OverworldScreen
谁创建它 接口不能被 new,只能 new 它的实现类
谁存着它 C Overworld 的字段 listeners: List<OverworldListener>
方法 5 个 + onPlayerMoved(): void · 第 12 行 + onEncounter(Encounter encounter): void · 第 15 行 + onItemCollected(Item item): void · 第 18 行 + onEncounterWon(Mokepon enemy): void · 第 21 行 + onExitReached(int fightsWon): void · 第 24 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/OverworldListener.java(26 行)
看老师打印稿里的这个类(UMLDoclet)
C Player Player au.edu.unimelb.swen.oop.mokepon.world 类
玩家:他的 Mokepon、位置、上一个位置、背包和胜场。
在游戏里 地图上玩家图标(白色光芒)所在的格子,和卷轴里 “Fights:” 的数字,读的都是 Player。
它的职责 moveTo、moveBack、addWin 是包内可见(package-private),只有 world 包里的 Overworld 能改它。
谁创建它 C Overworld (第 39 行 new Player(…))
谁存着它 C PlayerStatsScroll 的字段 player: Player;C Overworld 的字段 player: Player
字段 5 个 - final mokepon: Mokepon - final inventory: Inventory - position: Position - previousPosition: Position - fightsWon: int
方法 8 个 + Player(Mokepon mokepon, Position startPosition, Inventory inventory) · 第 17 行 + getMokepon(): Mokepon · 第 24 行 + getInventory(): Inventory · 第 28 行 + getPosition(): Position · 第 32 行 + getFightsWon(): int · 第 36 行 ~ moveTo(Position newPosition): void · 第 40 行 ~ moveBack(): void · 第 46 行 ~ addWin(): void · 第 50 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;06 窗口、界面切换和菜单 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;13 状态效果和道具 ;15 逃跑、回主菜单、走到出口 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/Player.java(54 行)
看老师打印稿里的这个类(UMLDoclet)
C Position Position au.edu.unimelb.swen.oop.mokepon.world 类
地图上的一格:x 是列,y 是行,(0,0) 在左上角。
在游戏里 看不见:玩家和每个物体的位置,如起点 (10,18);MapView 把 x、y 乘以 32 换成像素位置。
它的职责 不可变(immutable):move() 返回新对象;覆盖 equals 和 hashCode,坐标相同就算相等,isAt 靠它判断。
谁创建它 C GameData (第 31 行 new Position(…));C MapView (第 65 行 new Position(…))
谁存着它 C GameMap 的字段 startPosition: Position;A MapObject 的字段 position: Position;C Player 的字段 position: Position、previousPosition: Position
字段 2 个 - final x: int - final y: int
方法 6 个 + Position(int x, int y) · 第 12 行 + getX(): int · 第 17 行 + getY(): int · 第 21 行 + move(Direction direction): Position · 第 26 行 + equals(Object other): boolean · 第 32 行 + hashCode(): int · 第 45 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;15 逃跑、回主菜单、走到出口 ;17 考试准备:用这份代码答题
源文件 world/Position.java(49 行)
看老师打印稿里的这个类(UMLDoclet)
EnemyPicker 的实现:从全部 Mokepon 里随便挑一只,不管地形。
在游戏里 白色感叹号用它:踩上去遇到的敌人完全随机。
它的职责 Strategy 模式的具体策略;MapParser 把它交给 map.mokeponRandom 这一组标记。
家族关系 实现 I EnemyPicker
谁创建它 C MapParser (第 31 行 new RandomEnemyPicker(…))
谁存着它 没有别的类把它存成字段
方法 1 个 + pick(List<Mokepon> mokepons, Terrain terrain, Random random): Mokepon · 第 12 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;09 遇敌:地形、类型和挑敌人 ;10 战斗的数据:Mokepon、Fighter、Battle ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/RandomEnemyPicker.java(16 行)
看老师打印稿里的这个类(UMLDoclet)
C Sprite Sprite au.edu.unimelb.swen.oop.mokepon.world 类
地图物体的外观:图片路径和着色用的颜色字符串。
在游戏里 感叹号的白、红、绿和门的品红色就是 Sprite 的 colour;问号箱子没有颜色,按原图显示。
它的职责 只存字符串,没有 JavaFX 代码,让 world 包保持独立;真正的着色由 MapView 调用 UiStyle.tint 完成。
谁创建它 C MapParser (第 58、70、82 行 new Sprite(…))
谁存着它 A MapObject 的字段 sprite: Sprite
字段 3 个 - static final NO_TINT: String - final imagePath: String - final colour: String
方法 5 个 + Sprite(String imagePath) · 第 15 行 + Sprite(String imagePath, String colour) · 第 19 行 + getImagePath(): String · 第 24 行 + getColour(): String · 第 28 行 + hasTint(): boolean · 第 32 行
在哪章讲 02 Java 最小知识包 ;03 读懂老师打印的 UML ;04 项目地图:9 个包、72 个类 ;05 程序是怎么跑起来的 ;08 地图世界:走一步发生了什么 ;09 遇敌:地形、类型和挑敌人 ;13 状态效果和道具 ;17 考试准备:用这份代码答题
源文件 world/Sprite.java(36 行)
看老师打印稿里的这个类(UMLDoclet)
EnemyPicker 的实现:挑一只类型在这块地形上有指定效果的 Mokepon。
在游戏里 红色感叹号(要 ADVANTAGE)和绿色感叹号(要 DISADVANTAGE)用它;如在森林里遇到占劣势的 Hexwing。
它的职责 Strategy 模式的具体策略,构造时传入想要的 TerrainEffect;一只都不符合时,就从全部 Mokepon 里挑。
家族关系 实现 I EnemyPicker
谁创建它 C MapParser (第 33、35 行 new TerrainEnemyPicker(…))
谁存着它 没有别的类把它存成字段
字段 1 个 - final wantedEffect: TerrainEffect
方法 2 个 + TerrainEnemyPicker(TerrainEffect wantedEffect) · 第 16 行 + pick(List<Mokepon> mokepons, Terrain terrain, Random random): Mokepon · 第 21 行
在哪章讲 01 先玩一局:用真实截图认识游戏 ;02 Java 最小知识包 ;04 项目地图:9 个包、72 个类 ;09 遇敌:地形、类型和挑敌人 ;16 设计模式和 OOP 原则 ;17 考试准备:用这份代码答题
源文件 world/TerrainEnemyPicker.java(36 行)
看老师打印稿里的这个类(UMLDoclet)