我发现在编写动画时,我有时会遇到一次for循环,然后再重复该值。这通常用于跳跃动画,或者消失然后再次出现动画。
这是我做过的一个例子 -
// Make the sprite slowly disappear
for (int i = 256; i > 0; --i)
{
sprite.opacity(i);
draw();
}
// Make the sprite slowly appear again
for (int i = 0; i < 256; ++i)
{
sprite.opacity(i);
draw();
}
每次我这样做,我都深深感到它太过分了。什么是更好的方式来解决这个问题?我不完全确定什么是最佳做法。我想我可以使用reverse_iterator
,但我也不确定如何实现它。
答案 0 :(得分:12)
考虑使用<cmath>
abs()函数:
for( int i = -255; i <= 255; i++)
use( abs( i ) );
答案 1 :(得分:2)
您可以使用abs()
中定义的绝对值函数<cmath>
。它会将您的代码中的代码减半。
for(int i=0; i<512; ++i)
{
sprite.opacity( abs(256-i) );
draw();
}
答案 2 :(得分:1)
这是迭代循环和“反向”循环的好方法 - 这是C ++程序员常用的循环。
对于你的精灵,似乎只需要256范围(你可以考虑设置const int RGB_RANGE
等于256 - 或更合适的标识符);但是,如果您的对象的大小是动态的,您还可以考虑使用.size()
函数(类似于ArrayList
或vector
- 这里就像迭代器一样有用) :
for (i = 9; i < RGB_RANGE; i++)
{
// CODE
}
以上代码是第一个const
建议的示例。请记住,简单的代码从来都不是坏事 - 这意味着你正在做正确的事情。
答案 3 :(得分:1)
我相信你所描述的情况,你必须遍历精灵来设置每个精灵的不透明度。无论您使用for循环还是reverse_iterator,花费的时间都是相同的。 reverse_iterator的任何实现仍然必须遍历每个sprite。可能有一些方法可以让它更容易阅读,但最终算法将归结为相同。例如,您可以利用堆栈并递归调用精灵来增加不透明度,然后在退出的路上减少;但是,我认为这样做没有任何好处,算法时间仍然会变得相同。
在某些情况下,你只需要咬紧牙关,花点时间做一些看似(甚至是)暴力的事情。
答案 4 :(得分:1)
如果您不想使用abs
,我会选择以下内容:
template<typename Func>
void animate (size_t step_count, Func && f)
{
size_t step;
for (step = step_count ; step > 0 ; --step)
f(step - 1);
for (step = 1 ; step < step_count ; ++step)
f(step);
}
用例:
animate(256, [](size_t step)
{
sprite.opacity(step);
draw();
});
答案 5 :(得分:1)
如果你想再次上下调整一个范围,你可以走非常疯狂的路线,只需定义一个提供迭代器的“容器”(或范围,在boost语言中)(从技术上讲,它们更接近于 - 迭代器),它允许您准确表达您打算做什么:
for(auto i : down_and_up(3)) ::std::cout << i << "\n";
例如应该打印
3
2
1
0
1
2
可悲的是,标准库中对此类型的支持不多,虽然此处提供了boost::iterator_range
,boost::counting_iterator
和boost::join
,与std::reverse_iterator
一致,可以提供down_and_up
。只要你没有完全滥用它,就自己写一个(虽然很冗长):
struct down_and_up
{
size_t from;
down_and_up(size_t const from) : from(from) { }
struct iterator : public ::std::iterator<::std::forward_iterator_tag, size_t> {
size_t cur;
bool down;
iterator(size_t cur, bool down) : cur(cur), down(down) { }
size_t operator*() const { return cur; }
iterator& operator++()
{
if(down)
{
--cur;
if(0 == cur) down = false;
}
else ++cur;
return *this;
}
friend bool operator==(iterator const& lhs, iterator const& rhs) { return lhs.down == rhs.down && lhs.cur == rhs.cur; }
friend bool operator!=(iterator const& lhs, iterator const& rhs) { return lhs.down != rhs.down || lhs.cur != rhs.cur; }
};
iterator begin() const { return iterator{ from, true }; }
iterator end() const { return iterator{ from, false }; }
};
注意:如果您愿意,可以使用更多容器功能轻松扩展它,例如value_type
成员typedef,但此定义足以满足上述示例。
P.S。:为您的娱乐提升方式:
boost::iterator_range<boost::counting_iterator<size_t>> up(boost::counting_iterator<size_t>(0), boost::counting_iterator<size_t>(3));
boost::iterator_range<std::reverse_iterator<boost::counting_iterator<size_t>>> down(
std::reverse_iterator<boost::counting_iterator<size_t>>(boost::counting_iterator<size_t>(4)),
std::reverse_iterator<boost::counting_iterator<size_t>>(boost::counting_iterator<size_t>(1)));
for(auto i : boost::join(down, up)) ::std::cout << i << "\n";