回答您的问题的困难部分是您同时问:“我现在应该做什么,对于 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; }
}
(这只是一个例子。没有适用于所有游戏的“一个真正的演员界面”,你需要自己设计。这就是我不喜欢的原因DrawableGameComponent
。)
拥有一个通用界面允许 Game 只讨论 Actors - 而不是需要了解游戏中的每一种类型。只剩下要做每种类型通用的事情了——碰撞检测、绘图、更新、加载、卸载等。
一旦你在演员中,你可以开始担心特定类型的演员。例如,这可能是一个方法Paddle
:
void Touched(IActor by)
{
if(by is Ball)
((Ball)by).BounceOff(this.BoundingBox);
if(by is Snake)
((Snake)by).Kill();
}
现在,我喜欢让球被 Paddle 弹起,但这真的是一个品味问题。你可以反过来做。
最后,您应该能够将所有演员粘贴在一个大列表中,您可以在 Game 中简单地遍历该列表。
实际上,出于性能或代码简单性的原因,您最终可能会拥有多个不同类型的参与者列表。这没关系 - 但总的来说,尽量坚持 Game 只知道通用演员的原则。
演员也可能出于各种原因想要查询其他演员的存在。所以给每个actor一个Game的引用,并在Game上公开actor列表(当你编写游戏代码时,不需要对public/private非常严格,它是你自己的内部代码。)
现在,您甚至可以更进一步,拥有多个接口。例如:一种用于渲染,一种用于脚本和AI,一种用于物理等。然后有多种实现可以组合成对象。
这在本文中有详细描述。我在这个答案中有一个简单的例子。如果您开始发现您的单个参与者接口开始变成更多抽象类的“树”,那么这是一个合适的下一步。