设计模式入门
本课属于 Coddy GDScript 学习旅程的“面向对象编程”单元。第 45 课,共 65 课。
设计模式是针对反复出现在不同程序中的问题,用一种已知且有名称的方式来组织类。它不是库,也不是可以直接复制的代码,而是描述了有哪些对象、每个对象负责什么,以及它们如何协作。你需要根据自己的游戏编写代码。
模式还能让开发者拥有共同的表达方式。“敌人由工厂生成”或“生命值条观察玩家”,能在队友打开文件之前告诉他们代码是如何组织的。
这里有一个模式可以解决的问题。启动一个关卡意味着要与三个对象交互,而每个启动关卡的脚本都会重复这些语句:
var music := MusicPlayer.new()
var level_map := LevelMap.new()
var hud := Hud.new()
music.play("forest.ogg")
level_map.load_map(1)
hud.show_hearts(3)Facade 模式会在这些对象前面放置一个类,并为它提供一个简单的方法:
# game_facade.gd
class_name GameFacade
extends RefCounted
var music := MusicPlayer.new()
var level_map := LevelMap.new()
var hud := Hud.new()
func start_level(number: int) -> void:
music.play("forest.ogg")
level_map.load_map(number)
hud.show_hearts(3)# main.gd
var game := GameFacade.new()
game.start_level(1)Music: playing forest.ogg
Map: level 1 loaded
HUD: hearts 3程序的其余部分会调用 start_level(),而启动关卡的方式发生变化时,你只需编辑一个文件。
模式按其解决的问题进行分组:
- 创建型模式控制对象的创建方式:Singleton、Factory。
- 结构型模式将对象组合成更大的结构:Facade、Adapter、Decorator、Composite。
- 行为型模式组织对象之间的协作方式:Observer、Strategy、Command、Template Method、State。
本章和下一章会介绍这些模式。每种模式都基于你已经学过的内容构建:写在各自文件中的类、继承、多态、组合和信号。
挑战
简单游戏通过三个已编写好的对象来开始和退出关卡:MusicPlayer(music_player.gd)、LevelMap(level_map.gd)和 Hud(hud.gd)。在它们前面编写外观类 GameFacade:
- 在成员变量中分别创建一个
MusicPlayer、一个LevelMap和一个Hud。 start_level(number, hearts)播放曲目level_N.ogg(N 是关卡编号);如果编号是5的倍数,则播放boss.ogg。然后加载该关卡的地图,最后显示爱心。quit_level()隐藏 HUD,然后停止音乐。
给定的代码会读取后续命令的数量,然后逐行读取命令:start NUMBER HEARTS 或 quit。对于 start 5 2 和 quit,输出为:
Music: playing boss.ogg
Map: level 5 loaded
HUD: hearts 2
HUD: hidden
Music: stopped你的代码写在 game_facade.gd 中。main.gd 中包含给定的输入/输出代码,不能编辑。
亲手试试
extends Node
func _ready():
# 提供的输入输出代码:保持原样
var game := GameFacade.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "start":
game.start_level(int(parts[1]), int(parts[2]))
elif parts[0] == "quit":
game.quit_level()
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: GDScript 在线编译器