首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XNA模仿游戏对象或解耦你的游戏

XNA模仿游戏对象或解耦你的游戏
EN

Stack Overflow用户
提问于 2009-04-30 00:27:21
回答 6查看 2.6K关注 0票数 10

我在想,是否可以模拟一个游戏对象来测试我的DrawableGameComponent组件?

我知道模拟框架需要一个接口才能运行,但我需要模拟实际的Game对象。

编辑:这是XNA社区论坛上各自讨论的link。有什么帮助吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-05-06 06:02:10

在那个论坛上有一些关于单元测试的很好的帖子。以下是我在XNA中进行单元测试的个人方法:

  • 忽略Draw()方法
  • 隔离您自己的类方法中的复杂行为
  • 测试棘手的东西,不用担心rest

下面是一个测试示例,用于确认我的Update方法在Update()调用之间将实体移动到正确的距离。(我使用的是NUnit。)我用不同的移动矢量修剪了几行代码,但是你明白了:你不应该需要一个游戏来驱动你的测试。

代码语言:javascript
复制
[TestFixture]
public class EntityTest {
    [Test]
    public void testMovement() {
        float speed = 1.0f; // units per second
        float updateDuration = 1.0f; // seconds
        Vector2 moveVector = new Vector2(0f, 1f);
        Vector2 originalPosition = new Vector2(8f, 12f);

        Entity entity = new Entity("testGuy");
        entity.NextStep = moveVector;
        entity.Position = originalPosition;
        entity.Speed = speed;

        /*** Look ma, no Game! ***/
        entity.Update(updateDuration);

        Vector2 moveVectorDirection = moveVector;
        moveVectorDirection.Normalize();
        Vector2 expected = originalPosition +
            (speed * updateDuration * moveVectorDirection);

        float epsilon = 0.0001f; // using == on floats: bad idea
        Assert.Less(Math.Abs(expected.X - entity.Position.X), epsilon);
        Assert.Less(Math.Abs(expected.Y - entity.Position.Y), epsilon);
    }
}

编辑:评论中的其他一些注释:

My Entity Class:我选择将所有游戏对象包装在一个集中的实体类中,如下所示:

代码语言:javascript
复制
public class Entity {
    public Vector2 Position { get; set; }
    public Drawable Drawable { get; set; }

    public void Update(double seconds) {
        // Entity Update logic...
        if (Drawable != null) {
            Drawable.Update(seconds);
        }
    }

    public void LoadContent(/* I forget the args */) {
        // Entity LoadContent logic...
        if (Drawable != null) {
            Drawable.LoadContent(seconds);
        }
    }
}

这给了我很大的灵活性来创建Entity (AIEntity,NonInteractiveEntity...)的子类。这可能会覆盖Update()。它还可以让我自由地创建Drawable子类,而不需要像AnimatedSpriteAIEntityParticleEffectNonInteractiveEntityAnimatedSpriteNoninteractiveEntity这样的n^2个子类的地狱。相反,我可以这样做:

代码语言:javascript
复制
Entity torch = new NonInteractiveEntity();
torch.Drawable = new AnimatedSpriteDrawable("Animations\litTorch");
SomeGameScreen.AddEntity(torch);

// let's say you can load an enemy AI script like this
Entity enemy = new AIEntity("AIScritps\hostile");
enemy.Drawable = new AnimatedSpriteDrawable("Animations\ogre");
SomeGameScreen.AddEntity(enemy);

我的可绘制类:我有一个抽象类,所有绘制的对象都是从这个抽象类派生出来的。我选择了一个抽象类,因为一些行为将被共享。将其定义为interface是完全可以接受的,如果您的代码不是这样的话。

代码语言:javascript
复制
public abstract class Drawable {
    // my game is 2d, so I use a Point to draw...
    public Point Coordinates { get; set; }
    // But I usually store my game state in a Vector2,
    // so I need a convenient way to convert. If this
    // were an interface, I'd have to write this code everywhere
    public void SetPosition(Vector2 value) {
        Coordinates = new Point((int)value.X, (int)value.Y);
    }

    // This is overridden by subclasses like AnimatedSprite and ParticleEffect
    public abstract void Draw(SpriteBatch spriteBatch, Rectangle visibleArea);
}

子类定义自己的绘制逻辑。在你的坦克例子中,你可以做一些事情:

  • 为每个项目符号添加一个新实体
  • 创建一个定义列表的TankEntity类,并覆盖

()以迭代项目符号(这些项目符号定义了它们自己的绘制方法)

  • 生成一个列表

下面是ListDrawable的一个示例实现,忽略了如何管理列表本身的问题。

代码语言:javascript
复制
public class ListDrawable : Drawable {
    private List<Drawable> Children;
    // ...
    public override void Draw(SpriteBatch spriteBatch, Rectangle visibleArea) {
        if (Children == null) {
            return;
        }

        foreach (Drawable child in children) {
            child.Draw(spriteBatch, visibleArea);
        }
    }
}
票数 14
EN

Stack Overflow用户

发布于 2009-05-05 16:06:17

MOQRhino Mocks这样的框架并不特别需要接口。它们还可以模拟任何非密封和/或抽象类。游戏是一个抽象的类,所以你可以毫不费力地模仿它:-)

至少在这两个框架中需要注意的一件事是,要对方法或属性设置任何期望,它们必须是虚拟或抽象的。这样做的原因是它生成的模拟实例需要能够覆盖。我相信IAmCodeMonkey提到的typemock有办法解决这个问题,但我不认为typemock是免费的,而我提到的两个是免费的。

顺便说一句,您还可以查看我的一个项目,该项目可以帮助为XNA游戏创建单元测试,而不需要进行模拟:http://scurvytest.codeplex.com/

票数 3
EN

Stack Overflow用户

发布于 2009-05-05 17:31:58

你不需要嘲笑它。为什么不做一个假的游戏对象呢?

从Game继承并覆盖您打算在测试中使用的方法,以便为您需要的任何方法/属性返回预设值或快捷计算。然后把假的传给你的测试。

在模仿框架之前,人们推出了他们自己的模仿/存根/伪造-也许这不是那么快和容易,但你仍然可以。

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

https://stackoverflow.com/questions/804904

复制
相关文章

相似问题

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