|
本帖最后由 ancientcc 于 2017-6-3 15:39 编辑
代码中处理逐进变量
让深入程序,分析代码是如何处理逐进变量。处理逐进变量主要是两个操作,赋值和取值。程序用template <class T> class progressive_类封装逐进变量。简单的说,赋值就是根据一条mod中的逐进变量语句生成一个progressive_对象,取值就是借助当前时刻参数,从progressive_对象读出变量值。
(<class T> class progressive_类,当中模板参数T可取int,double,int的就typedef为progressive_int,double的就typedef为progressive_double。以上halo_y就以progressive_int类型被处理,offset则是progressive_double。)
赋值
根据一条mod中的逐进变量语句生成一个progressive_对象。让以duration=350; halo_y=-54:120,-54~-45,-45~-27,-27~0为例来说明。
- // @data: mod中的逐进变量字符串。实例值:-54:120,-54~-45,-45~-27,-27~0
- // @duration: 持续时间,单位毫秒。实例值:350
- template <class T>
- progressive_<T>::progressive_(const std::string &data, int duration) :
- data_(),
- input_(data)
- {
- // utils::split将以逗号为分隔符把字符串data变成字组串数组
- const std::vector<std::string> first_split = utils::split(data);
- // 生成的first_split:[4]("-54:120", "-54~-45","-45~-27","-27~0")
- const int time_chunk = std::max<int>(duration / (first_split.size()?first_split.size():1),1);
- // time_chunk就是默认的时间片持续时间:350 / 4 = 87(毫秒)
- std::vector<std::string>::const_iterator tmp;
- std::vector<std::pair<std::string,int> > first_pass;
- // 逐个处理值项
- for (tmp = first_split.begin(); tmp != first_split.end() ; tmp++) {
- std::vector<std::string> second_pass = utils::split(*tmp,':');
- if (second_pass.size() > 1) {
- // 值项中指定了时间,则把时间取出来作为该时间片时间然后生成pair
- first_pass.push_back(std::pair<std::string,int>(second_pass[0],atoi(second_pass[1].c_str())));
- } else {
- // 值项中没指定时间,以默认时间片生成pair
- first_pass.push_back(std::pair<std::string,int>(second_pass[0],time_chunk));
- }
- }
- // 生成的first_pass值:
- // [0] ("-54",120)
- // [1] ("-54~-45",87)
- // [2] ("-45~-27",87)
- // [3] ("-27~0",87)
- // 因为#0值项由87改为了120,这个总的过程时间已由350变成381
- std::vector<std::pair<std::string,int> >::const_iterator tmp2;
- // 逐个处理修正过时间片时间的值项
- for (tmp2=first_pass.begin();tmp2 != first_pass.end() ; tmp2++) {
- std::vector<std::string> range = utils::split(tmp2->first,'~');
- // 检查值项字符串是否有波浪号。
- // 1. 如果有波浪号,波浪号前的做为pair的first,后面的做为pair的second
- // 2. 如果没有波浪号,pair的second=first
- data_.push_back(std::pair<std::pair<T, T>,int> (
- std::pair<T, T>(
- lexical_cast<T>(range[0].c_str()),
- lexical_cast<T>(range.size() > 1 ? range[1].c_str() : range[0].c_str())),
- tmp2->second));
- }
- // 最终生成的data_:
- // [0] ((-54,-54),120)
- // [1] ((-54,-45),87)
- // [2] ((-45,-27),87)
- // [3] ((-27,0),87)
- }
复制代码
取值
取值就是根据访问时刻返回“正确”值项中的值。
以在130毫秒来取值为例来说明。
- // @current_time:当前访问时刻。值可以不在[0, duration],函数会执行修正。实例值:130
- // @default_val:当mod中其实未指定要访问的逐进变量时,要被返回的值。默认0
- template <class T>
- const T progressive_<T>::get_current_element(int current_time, T default_val) const
- {
- int time = 0;
- unsigned int sub_halo = 0;
- int searched_time = current_time;
- // 检查current_time有效性,不在[0, duration()]的务必使它落在这范围
- // duration()返回data_中时间片时间的累加值,也就是说返回的将是381而不是mod中写的350
- if (searched_time < 0) searched_time = 0;
- if (searched_time > duration()) searched_time = duration();
- // 这或许是mod中就没有该逐进变量,返回默认值。
- if (data_.empty()) return default_val;
- // 找出current_time是落在哪个时间片上
- while (time < searched_time&& sub_halo < data_.size()) {
- time += data_[sub_halo].second;
- sub_halo++;
- }
- // (sub_halo!=0)时,sub_halo是一个计数值而不是索引值,作为下标时应该被修正
- if (sub_halo != 0) {
- sub_halo--;
- time -= data_[sub_halo].second;
- }
- if (sub_halo >= data_.size()) {
- sub_halo = data_.size();
- time = searched_time; // Never more than max allowed
- }
- // 已确定出current_time是在#1区间,现在要确定出具体值
- const T first = data_[sub_halo].first.first;
- const T second = data_[sub_halo].first.second;
- // time = data_[0].second: 120
- // data_[1].second: 87
- // first = data_[1].first.first: -54
- // second = data_[1].first.second: -45
- // ====>
- // (130 - 120) / 87 * 9 + (-54) = -53
- return T((static_cast<double>(searched_time - time) /
- static_cast<double>(data_[sub_halo].second)) *
- (second - first) + first);
- }
复制代码
代码中封装逐进变量还有一个类:progressive_string,和progressive_差不多赋值/取值逻辑。它们不同点:
- progressive_是模板类,progressive_string不是;
- progressive_值项中的first要表示一个范围,定义了std::pair,progressive_string表示一个字符串,类型std::string;
由于progressive_string的data_[#].first不是范围,它处理上要比progressive_简单。
|
|