【问题标题】:How to animate through an a container for windows.draw()?如何通过 windows.draw() 的容器制作动画?
【发布时间】:2015-12-20 08:54:01
【问题描述】:

我有一个对象容器:

std::vector<sf::Drawable> gameObjects;

我的目标是遍历这些对象并绘制它们:

for (auto it : gameObjects)
{
     window.draw(*it);
}

您可以假设这些方法已经实现。我所说的“动画”是什么意思:我希望这些对象一次绘制一个,而不是立即全部绘制。

void Run::render()
{
    window.clear(colorWindow);

    for (auto it : gameObjects)
    {
         window.draw(*it);
    }

    window.display();    
}

也就是说,让每个 render() 在容器中绘制一个附加对象。你知道我该怎么做吗?提前谢谢你。


编辑:我尝试了一些非常规的方法 - 我认为这不是好的做法,但它确实有效:

int count = 0;
int countReset = 1;

...

while (countReset > count)
{
    objects.at(count++).draw(window);

}
countReset++;
count = 0;

【问题讨论】:

    标签: c++ sfml auto


    【解决方案1】:

    您永远不应该在渲染中对您的游戏做出决定。你应该在某个地方有一个更新方法,它可以决定输入和时间如何影响你的游戏世界。渲染应该只做一件事:渲染。没有决策,没有数据操作。

    例如,您可以使用复合类来指示应该绘制哪个对象,或者您可以从 sf::Drawable 派生自己的基类并实现 bool IsVisible() const; 方法。无论哪种方式,是否绘制的决定都是在其他地方做出的,渲染只是执行命令要具体渲染什么:

    struct MaybeDrawn
    {
       bool IsVisible;
       sf::Drawable Object;      
    };
    

    ...

    std::vector<MaybeDrawn> gameObjects;
    

    ...

    void Run::render()
    {
        window.clear(colorWindow);
    
        for (auto it : gameObjects)
        {
             if(it->IsVisible)
             {
                 window.draw(it->Object);
             }
        }
    
        window.display();    
    }
    

    您的决定、如何以及何时将 bool 设置为 true 应该在您的 Update/ChangeWorld 方法中进行。也许您想看看here,了解有关如何构建游戏以及如何构建计时器的一般说明。

    或者,您可以让程序保持原样,并在您的决策方法中插入和/或删除向量。

    【讨论】:

      【解决方案2】:

      使用静态计数器作为对象列表中的索引。如果时间段已过,测量时间并增加计数器。所以下次绘制列表中的下一个对象。

      #include <chrono>
      
      void Run::render()
      {
          // actual time
          std::chrono::high_resolution_clock::time_point actTime = std::chrono::high_resolution_clock::now();
      
          // remember time
          static bool init = false;
          std::chrono::high_resolution_clock::time_point lastTime;
          if ( !init )
          {
              lastTime = actTime;
              init = true;
          }
      
          // delta time
          long microseconds = std::chrono::duration_cast<std::chrono::duration<long, std::micro> >( actTime - lastTime ).count();
          double deltaTms = ((double)microseconds) / 1000.0;
      
          window.clear(colorWindow);
      
          static size_t actObjInx = 0;
          window.draw(gameObjects[actObjInx]);
      
          // increment object index if time period has elapsed
          if ( deltaTms > 100.0 ) // 0.1 seconds
          {
              lastTime = actTime;
      
              actObjInx ++;
              if ( actObjInx == gameObjects.size() )
                  actObjInx = 0;
          }
      
          window.display();
      }
      

      【讨论】:

      • 这会动画得更快,我的 CPU/GPU 可以渲染得更快......在现代 CPU 上,它只会是一个疯狂的闪烁。
      • @nvoigt 你必须测量自上次调用 Run::render 以来经过的时间。如果达到时间阈值,则仅增加 actObjInx。一会儿我给你举个例子。
      猜你喜欢
      • 2022-01-11
      • 2017-05-29
      • 2013-05-16
      • 2013-02-11
      • 2018-05-16
      • 2013-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多