C# 抽象类是正确的选择。虽然接口在某些情况下确实有用且正确,但它并不总是正确的工具:-)@Joel Martinez-当涉及到模仿/伪造时,接口什么时候不是正确的工具?@Peter Lillevold-关于此主题的最佳指导来自.net framework设计指
C# 抽象类是正确的选择。虽然接口在某些情况下确实有用且正确,但它并不总是正确的工具:-)@Joel Martinez-当涉及到模仿/伪造时,接口什么时候不是正确的工具?@Peter Lillevold-关于此主题的最佳指导来自.net framework设计指,c#,unit-testing,mocking,xna,C#,Unit Testing,Mocking,Xna,抽象类是正确的选择。虽然接口在某些情况下确实有用且正确,但它并不总是正确的工具:-)@Joel Martinez-当涉及到模仿/伪造时,接口什么时候不是正确的工具?@Peter Lillevold-关于此主题的最佳指导来自.net framework设计指南。你可以在这里在线阅读有趣的部分:有没有什么方法可以让我继承一件东西而不是两件?还有,从IGame继承给我什么?似乎没有从中继承什么都不会改变。也许我只是不太清楚,抱歉。这不起作用,因为drawablegamecomponent的构造函数需要
抽象类是正确的选择。虽然接口在某些情况下确实有用且正确,但它并不总是正确的工具:-)@Joel Martinez-当涉及到模仿/伪造时,接口什么时候不是正确的工具?@Peter Lillevold-关于此主题的最佳指导来自.net framework设计指南。你可以在这里在线阅读有趣的部分:有没有什么方法可以让我继承一件东西而不是两件?还有,从IGame继承给我什么?似乎没有从中继承什么都不会改变。也许我只是不太清楚,抱歉。这不起作用,因为drawablegamecomponent的构造函数需要一个游戏实例,而不是IGame;-)我喜欢。不知何故,这些框架的旋风模糊了我的道路。我会尝试一下,然后在这里给你回复结果!听起来很棒。祝你好运我很高兴知道结果如何,因为我自己有一个1/4完成的游戏项目被搁置了。在进一步研究之后,很遗憾我想不出一个简单的方法来完成。除非我伪造了一大堆方法。我不确定它也会产生什么副作用。谢谢,谢谢你的回答。很抱歉,我没有太多时间调试另一个框架。不过看起来很有趣。我很想试一试。只需在过程中加入另一个不确定因素(XNA新增,TDD新增)。有人有经验吗?@boris callens:我经常使用Rhino Mock。它工作得很好。你能给我看看你的“实体”界面吗?这是怎么一回事?组件?自定义类?它是一个自定义类--我渲染的每个游戏对象都使用它。除了我的输入处理器和屏幕管理器之外,我特别避免使用游戏组件。它定义了像Update(double time)这样的方法,将其速度*时间移动到下一步的方向。为了支持多种类型的可绘制对象(精灵、动画精灵、粒子),my Entity包含一个可绘制对象——一个处理Draw()调用的抽象类。您能否详细介绍一下“Entity包含一个可绘制对象”它如何处理draw调用?它不只是创建了另一种依赖关系吗(我还不知道怎么做)。我设置了我的类结构以允许有趣的继承——例如,扩展实体的AIEntity。如果我想要一个被渲染为粒子效果的实体(例如,像寻找目标的魔法效果),该怎么办?我必须创建一个AIEntity子类ParticleEffectAIEntity。如果我想制作一个非互动性(一个没有人能捡起的不动的火炬),它也有粒子效应(对于火焰)。我必须让另一个particleeffect非交互。对不起,没有阅读这个示例,你的答案没有多大意义。我稍后会在家里查看。这个想法的要点是,将渲染逻辑保存在一个单独的类中,然后编写两个类,它们基本上是各自环境中渲染逻辑的外壳——GameComponent和WinForms控件。因此,你不是在编写一个伪造游戏实例的组件,而是在编写一个从不使用游戏实例的控件,并在两个表示类之间共享实现。例如,我面临的一个挑战是,是从构造函数传递一个sprite批处理,还是从类中创建一个sprite批处理。通过构造函数传递它会使代码更加解耦,但接下来我必须对调用sprite_batch.begin()和end()calls.Jeps的位置进行假设。我现在将它传递给构造函数,因为我不想让我的类知道它是什么样子。我认为这使它们可以移植到其他游戏中。而且,在我能想象的每一堂课上开始()和结束(),可能会导致明显的减速。我不确定减速的原因,我在一本书或一篇文章中读到,它不会改变整个想法。我应该在那上面搜索一下。但是如果没有性能命中的暗示,我不明白为什么这些方法会出现在第一位。。
public class MyGameObject : Game, IGame
{
//you can leave this empty since you are inheriting from Game.
}
public IGame
{
public GameComponentCollection Components { get; set; }
public ContentManager Content { get; set; }
//etc...
}
[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);
}
}
}
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);
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);
}
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);
}
}
}