本文介绍了游戏架构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a question about a XNA game I'm making, but it is also a generic question for future games. I'm making a Pong game and I don't know exactly what to update where, so I'll explain better what I mean. I have a class Game, Paddle and Ball and, for example, I want to verify the collisions between the ball with the screen limits or the paddles, but I come across 2 approaches to do this:

高级方法 - 在游戏中公开桨和球属性.更新是否检查碰撞?

Higher Level Approach - Make paddle and ball properties public and on the Game.Update check for collisions?

低级方法- 我将我需要的所有信息(屏幕限制和桨信息)提供给球类(按参数,或在公共静态类中)和 Ball.Update我检查碰撞?

Lower Level Approach- I supply every info I need (the screen limits and paddles info) to the ball class (by parameter, or in a Common public static class) and on the Ball.Update I check for collisions?

我想我的问题更笼统:

一个对象是否需要知道如何更新和绘制自身,即使以某种方式提供给它们的更高级别的依赖项?

Does an object need to know how to update and draw itself, even having dependencies from higher levels that somehow are supplied to them?

是在 Game.Update 或 Game.Draw 中在更高级别处理它还是使用 Managers 来简化代码更好?

Is better to process it at higher levels in Game.Update or Game.Draw or using Managers to simplify code?

我认为这是一个适用于所有游戏的游戏逻辑模型问题.不知道我的问题有没有说清楚,如果没有,请随时提问.

I think this is a game logic model question that applies to every game. I don't know if I made my question clear, if not, feel free to ask.

推荐答案

回答你的问题的难点在于你同时问:我现在应该做什么,对于 Pong"和我以后应该做什么,在一些通用游戏中".

The difficult part of answering your question is that you're asking both: "what should I do now, for Pong" and "what should I do later, on some generic game".

要制作 Pong,您甚至不需要 Ball 和 Paddle 类,因为它们基本上只是位置.只需在您的游戏课程中添加类似内容即可:

To make Pong you don't even need Ball and Paddle classes, because they're basically just positions. Just stick something like this in your Game class:

Vector2 ballPosition, ballVelocity;
float leftPaddlePosition, rightPaddlePosition;

然后只需在游戏的 UpdateDraw 函数中以适合您的任何顺序更新和绘制它们.简单!

Then just update and draw them in whatever order suits you in your Game's Update and Draw functions. Easy!

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

But, say you want to create multiple balls, and balls have many properties (position, velocity, rotation, colour, etc): You might want to make a Ball class or struct that you can instance (same goes for the paddles). You could even move some functions into that class where they are self-contained (a Draw function is a good example).

但保持设计理念不变 - 所有对象到对象的交互处理(即:游戏玩法)都发生在您的 Game 类中.

But keep the design concept the same - all of the object-to-object interaction handling (ie: the gameplay) happens in your Game class.

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

This is all just fine if you have two or three different gameplay elements (or classes).

然而,让我们假设一个更复杂的游戏.让我们以基本的乒乓球游戏为例,添加一些弹球元素,例如多球和玩家控制的脚蹼.让我们添加一些来自 Snake 的元素,假设我们有一个 AI 控制的蛇"以及一些球或蛇可以击中的拾取对象.为了更好的衡量,我们假设桨也可以像太空入侵者一样发射激光,激光螺栓根据它们击中的物体做不同的事情.

However let's postulate a more complicated game. Let's take the basic pong game, add some pinball elements like mutli-ball and player-controlled flippers. Let's add some elements from Snake, say we have an AI-controlled "snake" as well as some pickup objects that either the balls or the snake can hit. And for good measure let's say the paddles can also shoot lasers like in Space Invaders and the laser bolts do different things depending on what they hit.

天啊,真是一团糟的互动!我们将如何应对?我们不能把一切都放在游戏中!

Golly that is a huge mess of interaction! How are we going to cope with it? We can't put it all in Game!

简单!我们制作了一个接口(或抽象类或虚拟类),游戏世界中的每个事物"(或演员")都将派生自该接口.下面是一个例子:

Simple! We make an interface (or an abstract class or a virtual class) that each "thing" (or "actor") in our game world will derive from. Here is an example:

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.)

(This is only an example. There is not "one true actor interface" that will work for every game, you will need to design your own. This is why I don't like DrawableGameComponent.)

拥有一个通用界面允许 Game 只讨论 Actors - 而不需要了解游戏中的每一种类型.剩下的就是做每种类型通用的事情——碰撞检测、绘制、更新、加载、卸载等.

Having a common interface allows Game to just talk about Actors - instead of needing to know about every single type in your game. It is just left to do the things common to every type - collision detection, drawing, updating, loading, unloading, etc.

一旦您演员,您就可以开始担心特定类型的演员.例如,这可能是 Paddle 中的一个方法:

Once you're in the actor, you can start worrying about specific types of actor. For example, this might be a method in Paddle:

void Touched(IActor by)
{
    if(by is Ball)
         ((Ball)by).BounceOff(this.BoundingBox);
    if(by is Snake)
         ((Snake)by).Kill();
}

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

Now, I like to make the Ball bounced by the Paddle, but it is really a matter of taste. You could do it the other way around.

最后,您应该能够将所有演员放在一个大列表中,您可以在游戏中简单地遍历该列表.

在实践中,出于性能或代码简单的原因,您最终可能会拥有多个不同类型的 actor 列表.这没关系 - 但一般来说,尽量坚持游戏的原则,只知道通用演员.

In practice you might end up having multiple lists of actors of different types for performance or code simplicity reasons. This is ok - but in general try to stick to the principle of Game only knowing about generic actors.

由于各种原因,Actors 也可能想查询还有哪些其他 Actor 存在.所以给每个actor 一个Game 的引用,并在Game 上公开actor 的列表(当你编写游戏代码时,没有必要对public/private 非常严格,这是你自己的内部代码.)

Actors also may want to query what other actors exist for various reasons. So give each actor a reference to Game, and make the list of actors public on Game (there's no need to be super-strict about public/private when you're writing gameplay code and it's your own internal code.)

现在,您甚至可以更进一步,拥有多个接口.例如:一个用于渲染,一个用于脚本和人工智能,一个用于物理等.然后有多个可以组合成对象的实现.

Now, you could even go a step further and have multiple interfaces. For example: one for rendering, one for scripting and AI, one for physics, etc. Then have multiple implementations that can be composed into objects.

这在这篇文章中有详细描述.我在这个答案中有一个简单的例子.如果您开始发现您的单一 actor 接口开始变成更多抽象类的树",那么这是一个合适的下一步.

This is described in detail in this article. And I've got a simple example in this answer. This is an appropriate next step if you start finding that your single actor interface is starting to turn into more of a "tree" of abstract classes.

这篇关于游戏架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-17 12:15