我正在使用SDL编写程序。我在主函数之外实例化了以下变量:
std::vector<SDL_Rect[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES]> gPersonSpriteClips;
(所有大写字母均为常数)。它是数组的向量,因为我打算稍后进行大量的精灵开发。现在,我只有几个占位符精灵。因此,3D数组捕获了单个人体类型的Spritesheet的所有方面,当我拉动这张Spritesheet时,我会将代码拆分成多种人体类型...
我有一个“字符”类,在准备渲染时会使用该数组。这是在main中渲染myCharacter的调用:
myCharacter.render(bodySpritesheetTexture, &*gPersonSpriteClips[myCharacter.getBody()]);
Character.getBody()返回此字符实例使用的主体类型的向量索引。这是Character.h中的函数声明:
void render(LTexture& characterSpriteSheetTexture, SDL_Rect spriteClips[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES]);
这是Character.cpp中的函数本身:
void Character::render(LTexture& characterSpriteSheetTexture, SDL_Rect spriteClips[TOTAL_PERSON_ACTIVITIES][TOTAL_CARDINAL_DIRECTIONS][PERSON_ANIMATION_FRAMES])
{
characterSpriteSheetTexture.render( mPosition.x, mPosition.y, &spriteClips[mActivity][mDirection][mAnimations[mActivity][mCurrentFrame]] );
}
mActivity是角色“当前正在执行哪个活动”的枚举。 mDirection是他面对的方向。 mAnimations列出了帧顺序(因为其中某些动画以相同的顺序多次使用相同的精灵)。
最后,LTexture的渲染功能直接从LazyFoo的SDL教程中获取。
characterSpriteSheetTexture.render()正在使用以下声明(在LTexture.h中)调用一个函数:
void render( int x, int y, SDL_Rect* clip = NULL, int targetHeight = NULL, int targetWidth = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );
因此,需要一个SDL_Rect * clip类型的参数。该函数将调用:
SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );
编译代码时出现错误,将我指向SDL库中的某个位置。通过将SDL_Rect的一维数组的索引传递到LTexture的render函数中,我已经成功地使用了LTexture的render函数。
忽略关于命名约定的分歧……我在这里做错了什么,实现我想做的事情的正确方法是什么?
当然,我可能会简化我的计划,以便将来对动画进行大量动画处理;这是我制作球员角色的第一枪。无论如何,我想知道这种情况下发生问题的机理。
最后,请不要建议我使用boost。我真的很想避免对该程序进行增强。
ETA:
这是Character.h中mAnimations的声明:
std::vector<int> mAnimations[TOTAL_ACTIVITIES];
这是默认构造函数中的初始化:
for (int i = 0; i < TOTAL_ACTIVITIES; i++)
{
mAnimations[i].resize(ANIMATION_FRAMES);
for (int j = 0; j < ANIMATION_FRAMES; j++)
{
mAnimations[i][j] = j;
}
}
答案 0 :(得分:2)
像这样更改全局数组定义:
using SdlRectArray = std::array<std::array<std::array<SDL_Rect, ANIMATION_FRAMES>, TOTAL_DIRECTIONS>, TOTAL_ACTIVITIES>;
std::vector<SdlRectArray> gPersonSpriteClips;
See here,为什么不将数组存储在std::vector
或任何其他容器中。
相应地,如下定义您的Character::render()
方法:
void render(LTexture& characterSpriteSheetTexture, SdlRectArray& spriteClips)
{
characterSpriteSheetTexture.render( mPosition.x, mPosition.y, &spriteClips[mActivity][mDirection][mAnimations[mActivity][mCurrentFrame]] );
}
然后您可以这样称呼它:
myCharacter.render(bodySpritesheetTexture, gPersonSpriteClips[myCharacter.getBody()]);
因为不需要做&*
。
答案 1 :(得分:1)
很难从您的问题中分辨出确切的错误是什么,但似乎根本原因可能是“数组衰减”。
在C ++(和C语言)中,几乎总是将数组参数视为指向数组开头的指针。对于多维数组,这意味着您期望的多重索引无法工作,因为该语言已经剥夺了必要的大小和形状信息。
唯一的例外是reference parameters不会以这种方式衰减。但是,如果您依赖于此,那么您(以及其他在您的代码上工作的人)每次将多维数组传递给另一个函数时都将需要记住使用该确切的引用参数。
在现代C ++中,此问题通常使用std::array<>
来解决,该目的是为此而设计的。在您的情况下,这将非常冗长,因此我建议使用类型别名:
typedef std::array< std::array< std::array<SDL_Rect,
ANIMATION_FRAMES>, TOTAL_DIRECTIONS>, TOTAL_ACTIVITIES> SpriteClip;
std::vector<SpriteClip> gSpriteClips;
或者,您可以编写一个简短的类:
class SpriteClip {
SDL_Rect m_data[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES];
public:
SDL_Rect& get(activity, direction, frame) {
return m_data[activity][direction][frame];
}
};
这可以让您轻松更改表示形式-例如,如果您决定要让不同的精灵具有不同数量的活动和框架。