回答您的问题的难点在于您要同时问:“我现在应该做什么,对于 Pong”和“我以后应该做什么,在一些通用游戏中”。
要制作 Pong,您甚至不需要 Ball 和 Paddle 课程,因为它们基本上只是位置。只需在您的 Game 类中添加这样的内容即可:
Vector2 ballPosition, ballVelocity;
float leftPaddlePosition, rightPaddlePosition;
然后在游戏的Update 和Draw 函数中按照适合您的顺序更新和绘制它们。简单!
但是,假设您要创建多个球,并且球具有许多属性(位置、速度、旋转、颜色等):您可能想要创建一个可以实例化的 Ball 类或结构(同样适用于桨)。您甚至可以将一些函数移动到它们自包含的类中(Draw 函数就是一个很好的例子)。
但保持设计理念不变 - 所有对象到对象的交互处理(即:游戏玩法)都发生在您的 Game 类中。
如果你有两个或三个不同的游戏元素(或类),这一切都很好。
但是,让我们假设一个更复杂的游戏。让我们以基本的乒乓球游戏为例,添加一些弹球元素,如多人球和玩家控制的脚蹼。让我们添加一些来自 Snake 的元素,假设我们有一条 AI 控制的“蛇”以及一些球或蛇可以击中的拾取物体。为了更好地衡量,假设桨也可以像太空侵略者中一样发射激光,并且激光螺栓会根据它们击中的东西做不同的事情。
天哪 真是一团糟!我们将如何应对?我们不能把它全部放在游戏中!
简单!我们创建了一个接口(或抽象类或虚拟类),我们游戏世界中的每个“事物”(或“演员”)都将从中派生。这是一个例子:
interface IActor
{
void LoadContent(ContentManager content);
void UnloadContent();
void Think(float seconds);
void UpdatePhysics(float seconds);
void Draw(SpriteBatch spriteBatch);
void Touched(IActor by);
Vector2 Position { get; }
Rectangle BoundingBox { get; }
}
(这只是一个例子。没有“一个真正的演员界面”适用于每场比赛,你需要自己设计。这就是我不喜欢@的原因987654330@.)
拥有一个通用界面可以让 Game 只讨论 Actor,而不需要了解游戏中的每一种类型。只需要做每种类型的通用操作 - 碰撞检测、绘制、更新、加载、卸载等。
一旦你进入演员,你就可以开始担心具体类型的演员了。比如这可能是Paddle中的一个方法:
void Touched(IActor by)
{
if(by is Ball)
((Ball)by).BounceOff(this.BoundingBox);
if(by is Snake)
((Snake)by).Kill();
}
现在,我喜欢让球被 Paddle 弹起,但这真的是一个品味问题。你可以反过来做。
最后,您应该能够将所有演员放入一个大列表中,您可以在游戏中简单地迭代。
实际上,出于性能或代码简单性的原因,您最终可能会拥有多个不同类型的参与者列表。这没关系 - 但总的来说,请尽量坚持 Game 只知道通用演员的原则。
Actor 也可能出于各种原因想要查询存在哪些其他 Actor。所以给每个actor一个Game的引用,并在Game上公开actor列表(当你编写游戏代码时,不需要对public/private非常严格,这是你自己的内部代码。)
现在,您甚至可以更进一步,拥有多个界面。例如:一种用于渲染,一种用于脚本和AI,一种用于物理等。然后有多种实现可以组合成对象。
这在this article中有详细描述。我在this answer 中有一个简单的例子。如果您开始发现您的单个参与者接口开始变成更多的抽象类“树”,那么这是一个合适的下一步。