cocos2d实现SlotMachine(老*虎*机)
实现一个四个转子,每个转子有五个花色的老*虎机。转子的转动实现原理很简单,和背景图无限滚动的原理是一样的:排成列的精灵在屏幕上向上滚动,再通过裁剪结点的裁剪就造成了转子滚动的效果。
1 void LayerSlotMachine::on_btn_roll(CCObject* pSender, CCControlEvent event) 2 { 3 if (!flag_act_) 4 { 5 schedule(schedule_selector(XLayerSlotMachine::roll_update)); 6 stop_flag_ = 0; 7 int target_index; 8 float mov_dis; 9 10 target_index = rand() % 5; 11 CCLOG("slot1:%d", target_index); 12 mov_dis = get_mov_dis(target_index, cur_index1_); 13 cur_index1_ = target_index; 14 roll_act_start(array_1_, mov_dis); 15 16 target_index = rand() % 5; 17 CCLOG("slot2:%d", target_index); 18 mov_dis = get_mov_dis(target_index, cur_index2_); 19 cur_index2_ = target_index; 20 roll_act_start(array_2_, mov_dis); 21 22 target_index = rand() % 5; 23 CCLOG("slot3:%d", target_index); 24 mov_dis = get_mov_dis(target_index, cur_index3_); 25 cur_index3_ = target_index; 26 roll_act_start(array_3_, mov_dis); 27 28 target_index = rand() % 5; 29 CCLOG("slot4:%d", target_index); 30 mov_dis = get_mov_dis(target_index, cur_index4_); 31 cur_index4_ = target_index; 32 roll_act_start(array_4_, mov_dis); 33 34 flag_act_ = true; 35 } 36 } 37 38 void LayerSlotMachine::roll_act_start(CCArray* aray,float mov_dis) 39 { 40 CCObject* obj; 41 CCARRAY_FOREACH(aray, obj) 42 { 43 CCCallFunc* act_end = CCCallFunc::create(this, callfunc_selector(XLayerSlotMachine::roll_act_end)); 44 CCSequence* seq1 = CCSequence::create(CCMoveBy::create(mov_dis/rotate_v_, ccp(0, mov_dis)) 45 , act_end 46 , NULL); 47 CCSprite* spr = (CCSprite*)obj; 48 spr->runAction(seq1); 49 } 50 } 51 52 void LayerSlotMachine::roll_update(float dt) 53 { 54 roll_bound_test(array_1_,node_slot_1_, 1); 55 roll_bound_test(array_2_,node_slot_2_, 2); 56 roll_bound_test(array_3_,node_slot_3_, 3); 57 roll_bound_test(array_4_,node_slot_4_, 4); 58 } 59 60 void LayerSlotMachine::roll_act_end() 61 { 62 ++stop_flag_; 63 if (stop_flag_==slot_length_*4) 64 { 65 flag_act_ = false; 66 unschedule(schedule_selector(XLayerSlotMachine::roll_update)); 67 } 68 }
需要注意的问题有两个:
(1)移动距离的计算
1 float LayerSlotMachine::get_mov_dis(int target_index, int cur_index) 2 { 3 float mov_dis; 4 float slot_height = spr_model_->getContentSize().height; 5 int T = 7; 6 if (target_index > cur_index) 7 { 8 mov_dis = slot_height*(slot_length_*T + (target_index - cur_index)); 9 } 10 else 11 { 12 mov_dis = slot_height*(slot_length_*T + (slot_length_ - (cur_index - target_index))); 13 } 14 return mov_dis; 15 }
T:周期数
slot_height:转子的高度
slot_length:单个转子上花色的数量,本例是5
target_index:目标位置
cur_index:当前位置
这里对移动距离分两种情况计算:当target_index>cur_index时,在当前周期就能移动到指定的位置,需要移动的格数为(target_index - cur_index);
当target_index<cur_index时,由于转子只能向上滚动,所以要在下个周期才能达到指定的位置,需要移动的格数为
((slot_length_ - (cur_index - target_index)))。
(2)转子滚动的处理
1 void LayerSlotMachine::roll_bound_test(CCArray* arry,CCNode* node_slot, int slot_num) 2 { 3 CCObject* obj; 4 float bound_y = spr_model_->getContentSize().height*(slot_length_ - 2); 5 6 CCARRAY_FOREACH(arry, obj) 7 { 8 CCSprite* spr = (CCSprite*)obj; 9 10 if (spr->getPositionY() > bound_y) 11 { 12 if (spr->getTag() - 1000*slot_num == 0) 13 { 14 CCSprite* spr0 = (CCSprite*)node_slot->getChildByTag(1000*slot_num + slot_length_ - 1); 15 spr->setPositionY(spr0->getPositionY() - spr_model_->getContentSize().height); 16 } 17 else 18 { 19 CCSprite* spr0 = (CCSprite*)node_slot->getChildByTag(spr->getTag() - 1); 20 spr->setPositionY(spr0->getPositionY() - spr_model_->getContentSize().height); 21 } 22 } 23 } 24 }
当精灵位置高于边界高度boundY时,将精灵移到上一个精灵的下方,实现循环滚动。这里需要特别注意应该以上一个精灵的位置作为基准,否则会产生偏移。