为游戏创建基于行为/组件的系统


11

背景

我将游戏开发作为一种业余爱好,并且正在寻找一种更好的设计方式。目前,我正在使用一种标准的OOP方法(我从事企业开发已经8年了,所以很自然)。以“坏蛋”为例

public class Baddie:AnimatedSprite //(or StaticSprite if needed, which inherit Sprite)
{
    //sprite base will have things like what texture to use, 
    //what the current position is, the base Update/Draw/GetInput methods, etc..
    //an AnimatedSprite contains helpers to animated the player while 
    //a StaticSprite is just one that will draw whatever texture is there
}

问题

可以说我正在制作2D平台游戏,并且需要坏家伙能够跳转。通常我要做的是在Update / GetInput方法中添加适当的代码。然后,如果我需要让玩家爬行,俯卧,攀爬等,代码就会去那里。

如果我不小心,这些方法会变得混乱,因此我最终会像这样创建方法对

CheckForJumpAction(Input input)DoJump()

CheckforDuckAction(Input input)DoDuck()

所以GetInput看起来像

public void DoInput(Input input)
{
    CheckForJumpAction(input);
    CheckForDuckAction(input);
}

和更新看起来像

public void Update()
{
    DoJump();
    DoDuck();
}

如果我去创建另一个需要玩家跳跃和躲避的游戏,我通常会进入具有该功能并将其复制的游戏。凌乱,我知道。那就是我为什么要寻找更好的东西。

解?

我真的很喜欢Blend的行为可以附加到元素上。我一直在考虑在游戏中使用相同的概念。因此,让我们看一下相同的示例。

我将创建一个基本的Behavior对象

public class Behavior
{
    public void Update()
    Public void GetInput()
}

我可以使用它来创建行为。JumpBehavior:BehaviorDuckBehavior:Behavior

然后,我可以将行为集合添加到Sprite库中,并将我需要的内容添加到每个实体中。

public class Baddie:AnimatedSprite
{
    public Baddie()
    {
        this.behaviors = new Behavior[2];
        this.behaviors[0] = new JumpBehavior();
        //etc...
    }

    public void Update()
    {
        //behaviors.update
    }

    public GetInput()
    {
        //behaviors.getinput
    }
}

因此,现在如果我想在许多游戏中使用Jump and Duck,我就可以将这些行为改过来。我什至可以为普通图书馆建立图书馆。

它行得通吗?

我不知道的是如何在它们之间共享状态。查看Jump和Duck,不仅会影响要绘制的纹理的当前部分,还会影响播放器的状态。(随着时间的推移,跳跃将施加递减的向上力,而鸭子则将停止移动,改变坏蛋的质地和碰撞大小。

我如何将它们绑在一起才能起作用?是否应该在行为之间创建依赖项属性?我应该让每个行为了解父级并直接对其进行修改吗?我认为的一件事是能够将委托传递给每个行为,以便在触发时执行。

我确定我正在寻找更多问题,但是整个目的是让我能够轻松地在游戏和同一游戏中的实体之间重用这些行为。

所以我把它交给你。仔细说明如何/是否可以这样做?你有更好的主意吗?我全是耳朵。


最好在gamedev.stackexchange.com上问一下?
rcapote

我喜欢您要去的地方,但不确定如何解决您提出的问题。非常有趣,其含义超出游戏开发范围。
爱德华·斯特朗奇

@rcapote不是此网站的白板/讨论吗?

2
@乔-不,不。在这里甚至不要提及“讨论”,否则您将被淘汰。该站点仅适用于问题->答案->完成的交互。
爱德华·斯特兰奇

好吧,基于组件的实体系统最近在游戏开发者社区中已经开始流行,因此我认为您在那里可能会得到更好的关注,但是无论如何您可能会在这里得到好的答案。下面是关于这个问题,你可能会感兴趣的gamedev.net一个有趣的讨论:gamedev.net/topic/...
rcapote

Answers:


1

看一下这个演示。听起来非常接近您要寻找的模式。此模式支持行为和可附加属性。我认为演示文稿中没有提到它,但是您也可以创建可附加事件。这个想法类似于WPF中使用的依赖项属性。


9

对我来说,这听起来像是使用策略模式的教科书案例。在这种模式下,可以在接口中定义您的常规行为,这将使您可以在运行时交换不同的行为实现(考虑加电如何影响角色的跳跃或奔跑能力)。

对于(人为)示例:

// The basic definition of the jump behavior
public interface IJumpBehavior {
    void Jump();
}

现在,您可以实现角色可以使用的各种类型的跳转,而不必知道每个特定跳转的详细信息:

// This is the jump the character may have when first starting
public class NormalJump : IJumpBehavior {

     public void Jump() {
         Console.WriteLine("I am jumping, and being pretty boring about it!");
     }

}

// This is the jump of a character who has consumed a power-up
public class SuperJump : IJumpBehavior {
    public void Jump() { 
         Console.WriteLine("I am all hopped up on star power, now my jumps can do damage!");
     }
}

您希望具有跳转功能的任何字符现在都可以包含对IJumpable的引用,并且可以开始使用各种实现

public class HeroCharacter {

    // By default this hero can perform normal jump.
    private IJumpBehavior _jumpBehavior = new NormalJump();

    public void Jump() {
        _jumpBehvaior.Jump();
    }

    // If you want to change the hero's IJumpable at runtime
    public void SetJump(IJumpBehavior jumpBehavior) {
      _jumpBehavior = jumpBehavior;
    }

}

然后您的代码可以类似于:

HeroCharacter myHero = new HeroCharacer();

// Outputs: "I am jumping, and being pretty boring about it!"
myHero.Jump()

// After consuming a power-up
myHero.SetJump(new SuperJump());

// Outputs: "I am all hopped up on star power, now my jumps can do damage!"
myHero.Jump();

现在,您可以轻松地重新使用这些行为,或者甚至在以后您想添加更多类型的跳跃或在单个侧滚动平台上创建更多游戏的情况下扩展它们。


虽然不完全是我要找的东西,但它非常接近并且喜欢它。我将使用它来确保。谢谢!

1

看一下DCI体系结构,这可能对OO编程很有趣。

在C#中实现DCI样式体系结构需要使用简单的域类,并使用带有扩展方法和接口的Context对象(行为)以允许域类在不同角色下进行协作。接口用于标记方案所需的角色。域类实现适用于其预期行为的接口(角色)。角色之间的协作在上下文(行为)对象中进行。

您可以创建常见行为和角色的库,这些库可以在单独项目的域对象之间共享。

有关C#中的代码示例,请参见C#中的DCI


0

将上下文对象传递给行为,该行为提供了更改受行为影响的子画面/对象状态的方法,该怎么办?现在,如果一个对象具有多种行为,则将它们分别循环调用,使它们有机会更改上下文。如果某个属性的某个修改排除/限制了其他属性的修改,则上下文对象可以提供方法来设置某种标志来指示这一事实,或者可以简单地拒绝不需要的修改。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.