首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >游戏架构

游戏架构
EN

Stack Overflow用户
提问于 2011-03-28 20:08:05
回答 4查看 7.4K关注 0票数 17

我有一个关于我正在制作的XNA游戏的问题,但这也是未来游戏的一个通用问题。我正在制作一个乒乓球游戏,我不知道在哪里更新什么,所以我会更好地解释我的意思。我有一个类游戏,Paddle和Ball,例如,我想验证球与屏幕限制或球拍之间的碰撞,但我遇到了两种方法:

更高层次的方法-使球拍属性公开,并在Game.Update上检查冲突?

低级方法-我将我需要的所有信息(屏幕限制和球拍信息)提供给ball类(通过参数,或者在通用公共静态类中),并在Ball.Update上检查冲突?

我想我的问题用更一般的方式是:

一个对象需要知道如何更新和绘制自己吗,即使有来自更高级别的依赖项也是如此?

是在Game.Update或Game.Draw的更高级别上处理它,还是使用管理器来简化代码?

我认为这是一个适用于每个游戏的游戏逻辑模型问题。我不知道我的问题是否讲得很清楚,如果不是,请随时提问。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-03-28 21:51:36

回答你的问题的困难之处在于,你同时问了两个问题:“我现在应该为Pong做什么”和“我以后应该在一些通用游戏上做什么”。

要制作Pong,您甚至不需要Ball和Paddle类,因为它们基本上只是位置。只需在您的Game类中粘贴如下内容:

代码语言:javascript
复制
Vector2 ballPosition, ballVelocity;
float leftPaddlePosition, rightPaddlePosition;

然后只需在游戏的UpdateDraw函数中按适合您的顺序更新和绘制它们即可。简单!

但是,假设您想要创建多个球,并且球具有许多属性(位置、速度、旋转、颜色等):您可能想要创建一个可以实例化的Ball类或结构(paddles也是如此)。您甚至可以将一些函数移到该类中,在该类中它们是自包含的( Draw函数就是一个很好的例子)。

但是保持设计概念相同-所有的对象到对象的交互处理(例如:游戏)都发生在你的Game类中。

如果您有两个或三个不同的游戏元素(或类),这一切都很好。

然而,让我们假设一个更复杂的游戏。让我们以基本的乒乓球游戏为例,添加一些弹球元素,如多弹球和玩家控制的脚手架。让我们从Snake中添加一些元素,比如我们有一条AI控制的“蛇”,以及一些球或蛇都可以击中的拾取对象。为了更好的衡量,让我们假设这些桨也可以发射激光,就像在太空入侵者中一样,激光闪电根据它们击中的物体做不同的事情。

天哪,这是一个巨大的交互混乱!我们该如何应对呢?我们不能把这一切都放在游戏中!

很简单!我们创建一个接口(或抽象类或虚拟类),游戏世界中的每个“事物”(或“角色”)都将从中派生。下面是一个示例:

代码语言:javascript
复制
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的原因。)

有了一个通用的界面,游戏就可以只谈论演员-而不是需要了解游戏中的每一种类型。它只需要做每种类型通用的事情--冲突检测、绘制、更新、加载、卸载等。

一旦你进入角色,你就可以开始担心特定类型的角色了。例如,这可能是Paddle中的一个方法

代码语言:javascript
复制
void Touched(IActor by)
{
    if(by is Ball)
         ((Ball)by).BounceOff(this.BoundingBox);
    if(by is Snake)
         ((Snake)by).Kill();
}

现在,我喜欢让球拍弹起,但这真的是一个品味问题。你可以反过来做这件事。

最后,你应该能够把你所有的角色放在一个很大的列表中,你可以在中简单地遍历这个列表。

在实践中,出于性能或代码简单性的原因,您可能最终拥有多个不同类型的参与者列表。这是可以的-但总的来说,试着坚持游戏的原则,只知道通用的演员。

出于各种原因,参与者可能还想查询其他参与者存在的情况。因此,给每个参与者一个对Game的引用,并在Game上公开参与者列表(当您编写游戏代码时,没有必要对public/private非常严格,因为这是您自己的内部代码)。

现在,您甚至可以更进一步,拥有多个接口。例如:一个用于渲染,一个用于脚本和AI,一个用于物理,等等。然后有多个可以组合到对象中的实现。

这在this article中有详细的描述。我在this answer中有一个简单的例子。如果您开始发现您的单个参与者接口开始变成更多抽象类的“树”,那么这是一个合适的下一步。

票数 47
EN

Stack Overflow用户

发布于 2011-03-28 22:19:52

您也可以选择开始思考游戏的不同组件需要如何相互交谈。

球和桨都是游戏中的对象,在本例中是可渲染的、可移动的对象。Paddle具有以下条件

它只能上下移动

  1. 桨固定在屏幕的一侧,或固定在屏幕的底部
  2. 可能由用户控制(1 vs计算机或1 vs 1)
  3. 桨可呈现
  4. 只能将桨移动到屏幕的底部或顶部,它不能越过其边界

<代码>G29

该球具有以下条件

它不能离开屏幕的边界

如果它在球拍后面,你可以间接地控制它(一些简单的物理原理)如果它在球拍后面finished

  • When is
  1. 比赛就开始了,球通常是附着在输家的球拍上的。

确定可以提取接口的通用标准

代码语言:javascript
复制
public interface IRenderableGameObject
{
   Vector3 Position { get; set; }
   Color Color { get; set; }
   float Speed { get; set; }
   float Angle { get; set; }
}

你也有一些GamePhysics

代码语言:javascript
复制
public interface IPhysics
{
    bool HasHitBoundaries(Window window, Ball ball);
    bool HasHit(Paddle paddle, Ball ball);
    float CalculateNewAngle(Paddle paddleThatWasHit, Ball ball);
}

然后还有一些博弈逻辑

代码语言:javascript
复制
public interface IGameLogic
{
   bool HasLostRound(...);
   bool HasLostGame(...);
}

这并不是所有的逻辑,但它应该让您知道要寻找什么,因为您正在构建一组库和函数,您可以使用这些库和函数来确定将要发生的事情以及可能发生的事情,以及当这些事情发生时需要如何操作。

此外,看看这一点,你可以改进和重构它,使其成为更好的设计。

了解你的领域,写下你的想法。不做计划就是计划失败

票数 2
EN

Stack Overflow用户

发布于 2011-03-28 20:21:35

您可以将您的球和球拍视为游戏的一个组件,XNA提供了一个基类GameComponent,它具有一个Update(GameTime gameTime)方法,您可以重写它来执行逻辑。此外,还有DrawableGameComponent类,它有自己的要覆盖的Draw方法。每个GameComponent类还有一个Game属性,该属性保存创建它们的游戏对象。在那里,您可以添加一些服务,您的组件可以使用这些服务来自己获取信息。

您想要采用哪种方法,要么拥有一个处理每个交互的“主”对象,要么将信息提供给组件并让它们自己做出反应,这完全取决于您。后一种方法在较大的项目中是首选的。此外,这将是面向对象的方式来处理事情,为每个实体提供自己的Update和Draw方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5458760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档