简体   繁体   English

用c ++编写一堆类似的if语句的漂亮方法?

[英]Pretty way to code a bunch of similar if statements in c++?

i want to animate a sprite. 我想动画一个精灵。 To do that i have a ticker that gives me a time in milliseconds. 为此,我有一个自动收录器,可以给我一个以毫秒为单位的时间。 Depending on the time i want the sprite to show a different image. 根据时间,我希望子画面显示不同的图像。 Unfortunately i can't think of a simple and pretty way to do this except for a bunch of if statements. 不幸的是,除了一堆if语句外,我想不出一种简单而漂亮的方法。

    if (ticker_.getElapsedTime().asMilliseconds() >= ANIMATION_STEP * 0 &&
           ticker_.getElapsedTime().asMilliseconds() < ANIMATION_STEP * 1)
    {
        sprite_.setTexture(*game_->getResourceManager().getTexture("animation/explosion_00.png"));
    }

    if (ticker_.getElapsedTime().asMilliseconds() >= ANIMATION_STEP * 1 &&
           ticker_.getElapsedTime().asMilliseconds() < ANIMATION_STEP * 2)
    {
        sprite_.setTexture(*game_->getResourceManager().getTexture("animation/explosion_01.png"));
    }

    // 10 more of these ...

    if (ticker_.getElapsedTime().asMilliseconds() >= ANIMATION_STEP * 13 &&
           ticker_.getElapsedTime().asMilliseconds() < ANIMATION_STEP * 14)
    {
        sprite_.setTexture(*game_->getResourceManager().getTexture("animation/explosion_13.png"));
    }

How about something like 怎么样

int frame = ticker_.getElapsedTime().asMilliseconds() / ANIMATION_STEP;
if (frame < MAX_FRAMES) {
    std::string filename = "animation/explosion_"
                         + std::to_string(frame) + ".png";
}

Given that the steps are even, you could just compute which one to use: 假设步骤是偶数,则只需计算要使用的步骤:

int step = ticker_.getElapsedTime().asMilliseconds() / ANIMATION_STEP;

You could do an integer-to-string conversion to use that to create the file-name, but that's both somewhat awkward to use and overly rigid. 您可以进行整数到字符串的转换以使用它来创建文件名,但是使用起来有点笨拙,而且过于僵化。 Instead, you could populate an array of filenames: 相反,您可以填充文件名数组:

// populate array during program initialization 
vector<string> explosion_filenames;

// In your function,
sprite_.setTexture(*game_->getResourceManager().getTexture(explosion_filenames[step]));

or even better, an array of textures: 甚至更好的是一系列纹理:

// populate array during program initialization 
vector<whatever_the_texture_type_is> explosion_textures;

// In your function,
sprite_.setTexture(*explosion_textures[step]));

If the steps aren't even, you could instead use an ordered map 如果步骤甚至不行,您可以改用有序地图

// I use `int`, but use whatever type is most appropriate
// populate map during program initialization 
map<int, texture_type> explosion_textures;

// In your function,
int step = ticker_.getElapsedTime().asMilliseconds();
sprite_.setTexture(*explosion_textures.lower_bound(step)->second);
unsigned frame = ticker_.getElapsedTime().asMilliseconds() / ANIMATION_STEP;
auto digit0 = std::to_string(frame % 10);
auto digit1 = std::to_string(frame / 10);
sprite_.setTexture(*game_->getResourceManager().getTexture("animation/explosion_"+digit1+digit0+".png"));

How about: 怎么样:

bool check(std::size_t step)
{
    auto tm = ticker_.getElapsedTime().asMilliseconds();
    return (tm >= ANIMATION_STEP * step) && (tm < ANIMATION_STEP * (step + 1));
}

for(int i=0; i <n;++i)
{
    if (check(i))
    {
        std::stringstream fname;
        fname<<"animation/explosion_"<<
        fname<<std::setfill(0)<<std::setw(2)<<i<<".png";
        sprite_.setTexture(*game_->getResourceManager().getTexture(fname.str()));
    }
}

Here is some oop like approach, which makes it easy to extend to a arbitrary number of animation_files. 这是一些类似于oop的方法,它可以很容易地扩展到任意数量的animation_files。

It's just a quick'n'dirty prototype, but the scheme should be clear. 这只是一个快速的“肮脏”原型,但是该方案应该很清楚。

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

class AnimationManager
{
public:
    AnimationManager(float pStepsize) : mStepsize(pStepsize) {}
    void registerSprite(std::string pFilename) //assuming that animation files are registered in the right order, alternatively use std::map as backend or something else
    {
        mFilenames.push_back(pFilename);
    }
    std::string getFilenameForAnimationStep(float ellapsed_time)
    {
        if (ellapsed_time < 0) //we dont want go pack in the past
            ellapsed_time = 0;
        unsigned int step = static_cast<unsigned int>(ellapsed_time/mStepsize); //trunc to int
        step = std::min(step, mFilenames.size() - 1); //make shure we use the last registered animation, if we are to fahre in the future
        return mFilenames[step];
    }

private:
    std::vector<std::string> mFilenames;
    float mStepsize;
};




int main()
{
    AnimationManager my_manager(0.2);
    my_manager.registerSprite("step_0.jpq");
    my_manager.registerSprite("step_1.jpq");
    my_manager.registerSprite("step_2.jpq");
    my_manager.registerSprite("step_3.jpq");
    //....
    //testing
    std::cout << my_manager.getFilenameForAnimationStep(-0.5) << std::endl;
    std::cout << my_manager.getFilenameForAnimationStep(0.1) << std::endl;
    std::cout << my_manager.getFilenameForAnimationStep(0.2) <<std::endl;
    std::cout << my_manager.getFilenameForAnimationStep(0.5) << std::endl;
    std::cout << my_manager.getFilenameForAnimationStep(0.7) << std::endl;
    std::cout << my_manager.getFilenameForAnimationStep(1.7) << std::endl;

    system("Pause");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM