我目前正在构建一个小型的实时策略2D引擎。并且我想知道如何处理最终会破坏我的屏幕的许多不断变化的精灵。
仅供参考,我不是针对任何AAA级别的,我只是想尝试实现一些机器学习方法。因此,我选择了魔兽争霸II放弃软件ISOs,无耻地拍摄了一些图形,并且在第一期出现了问题。
http://img263.imageshack.us/img263/1480/footman.png
正如你上面所看到的,即使是魔兽争霸II的简单仆人也有大约50个精灵用于动画。这是很多。它会经常改变精灵。 (黑线只是检查我的alpha通道是否正确)
因此,最后一个问题:如何有效地实现不断变化的QGraphicsObject?如何有效地实现反复更改其外观的QGraphicsItem?
我是否只是重载QGraphicsPixmapItem的paint()
方法并继续更改屏幕上使用的Pixmap?它会导致一些“口吃”吗?
我听说有时候,创建一个所有像素图,隐藏所有像素图并在需要时复制它们是明智/可能的。 (复制比其他操作便宜)
还有其他明智的想法吗?
感谢任何输入! (RTS引擎教程,复杂性等等......)
答案 0 :(得分:15)
(我先从一般的想法开始,然后会有一个可能的Qt实现)
我不知道如何存储WCII精灵,但你应该使用精灵表(如果需要的话自己构建)。与此工作表相关联,您将获得一些精灵的描述,该精灵至少包含动画列表,并且对于每个动画,它的标识符/名称以及帧列表。
您描述这些动画帧的细节水平取决于您,但必须至少包含要显示的精灵表的矩形。
举个例子,看看this sprite sheet(显然没有优化,但举个例子,没关系:))。这是关联的animations descriptions(第12到39行)。所有动画都不包括在内,但你会明白这一点。
你可以看到“空闲”动画是由3帧构成的,这些子节点与精灵表中的前3帧相匹配。与子矩阵相关联,此示例中还有两个信息:
现在,你将如何在Qt中实现它?
动画的描述文件格式完全取决于您,但我推荐一些层次结构文件格式。由于Qt提供了XML解析器,因此它可以是完美的。如果您习惯于提升并喜欢像JSon这样的轻量级格式,那么可以使用boost.ptree来解析无关紧要的XML / JSon文件,并使用通用接口从中提取数据。
对于图形表示,您必须使用一些类:
我将从描述 TimerProxy 角色开始。它的作用是发送时间更新消息。它在这里是因为Qt Graphics对象不提供任何类型的“定时”更新(即 update(float dt),其中给出的dt是您最喜欢的时间单位)。您可能想知道为什么我们使用代理类来处理时间。这是为了限制活动 QTimer 的数量;如果您有 AnimatedSprite 中的一个,那么最终可能会有大量的计时器处于活动状态,这显然是一个很大的禁忌。
所以它履行了两个角色:
现在,对于解决方案的核心: AnimatedSprite 。该类具有以下角色:
在初始化时,您应该给它以下信息:
在运行时,更新方法如下所示:
在 timeUpdated(int)插槽中,您希望更新已用时间,并检查是否应使动画继续下一帧。如果是这样,只需将当前帧指针更新为新帧。
最后,要渲染,你只需重新实现 QGraphicsItem :: paint(...)方法来绘制当前的子句,这可能看起来像:
void AnimatedSprite::paint(QPainter *painter,
const QStyleOptionGraphicsItem * /*option*/,
QWidget * /*widget*/)
{
painter->drawImage(mCurrentAnim.mCurrentFrame->mOrigin,
mSpriteSheet,
mCurrentAnim.mCurrentFrame->mSubRect);
}
希望有所帮助(并且不会太大,哇哇哇哇)