gpt4 book ai didi

c# - XNA 模拟游戏对象或解耦你的游戏

转载 作者:可可西里 更新时间:2023-11-01 08:56:11 24 4
gpt4 key购买 nike

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

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

编辑:这是一个link在 XNA 社区论坛上进行相应的讨论。有帮助吗?

最佳答案

该论坛中有一些关于单元测试主题的好帖子。这是我在 XNA 中进行单元测试的个人方法:

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

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

[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);
}
}

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

我的实体类:我选择将我所有的游戏对象包装在一个集中的实体类中,看起来像这样:

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);
}
}
}

这给了我很大的灵 active 来创建实体的子类(AIEntity、NonInteractiveEntity...),这些子类可能会覆盖 Update()。它还让我可以自由地对 Drawable 进行子类化,而无需像 AnimatedSpriteAIEntityParticleEffectNonInteractiveEntityAnimatedSpriteNoninteractiveEntity 这样麻烦的 n^2 个子类。相反,我可以这样做:

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

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

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 类,并重写 Draw() 以迭代 Bullets(它们定义了自己的 Draw 方法)
  • 制作一个 ListDrawable

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

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);
}
}
}

关于c# - XNA 模拟游戏对象或解耦你的游戏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/804904/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com