数据结构采用双向循环链表。由候选角色组成链表的节点,将链表中的节点在屏幕上按照椭圆分布。
.h:
1 //链表节点——候选角色 2 class CandidateRole :public CCNode{ 3 public: 4 CandidateRole(); 5 ~CandidateRole(); 6 virtual bool init(const char* name); 7 static CandidateRole* create(const char* name); 8 CandidateRole* mpNextRole; //节点右面角色的指针 9 CandidateRole* mpForeRole; //..左.......... 10 11 void setPositionIndex(int ); 12 int getPositionIndex(); 13 14 int mDistance; //到椭圆最低点的距离 15 int mPositionIndex; //节点在链表中的序号 16 int mNextPositionX; 17 int mNextPositionY; 18 int mColorR; 19 int mColorG; 20 int mColorB; 21 CCArmature* mpArmature; 22 bool mbIsSelected; // 是否被选中 23 24 }; 25 26 27 //由候选角色组成的链表,在屏幕上成椭圆分布 28 class CircleStage :public CCNode{ 29 30 public: 31 CircleStage(); 32 ~CircleStage(); 33 virtual bool init(); 34 35 CREATE_FUNC(CircleStage); 36 void addRole(CandidateRole *); //添加一个角色到链表 37 void changeToNext(); //顺时针旋转 38 void changeToFore(); //逆时针旋转 39 40 bool isOnAction(); 41 void actionEnd(); 42 43 private: 44 bool mbOnAction; 45 int mRoleNum; 46 CandidateRole* mpCurrentRole; //操作链表用的指针 47 CandidateRole* mpHead; 48 CandidateRole* mpLast; 49 CandidateRole* mpSelectRole; //被选中的角色,在椭圆最低点 50 int mCircleA; //椭圆的a 51 int mCircleB; //椭圆的b 52 void updateColor(); //更新每个节点的明暗,越远越暗 53 void updateZorders(); //更新遮盖关系 54 void updateZordersCallBack(); 55 void updateDistances(); //更新每个节点到中央节点的距离 56 void initAppearance(); //初始化颜色和缩放 57 58 };
.cpp:
1 CandidateRole::CandidateRole() 2 { 3 4 } 5 CandidateRole::~CandidateRole() 6 { 7 8 } 9 bool CandidateRole::init(const char* name) 10 { 11 12 mPositionIndex=0; 13 mbIsSelected=false; 14 mDistance=0; 15 mColorB=255; 16 mColorG=255; 17 mColorR=255; 18 19 mpArmature = CCArmature::create(name); 20 this->addChild(mpArmature); 21 22 return true; 23 } 24 25 CandidateRole* CandidateRole::create(const char* name) 26 { 27 CandidateRole* pRet = new CandidateRole(); 28 if (pRet && pRet->init(name)) 29 { 30 pRet->autorelease(); 31 } 32 else 33 { 34 CC_SAFE_DELETE(pRet); 35 } 36 return pRet; 37 } 38 39 void CandidateRole::setPositionIndex(int index) 40 { 41 mPositionIndex=index; 42 } 43 44 int CandidateRole::getPositionIndex() 45 { 46 return mPositionIndex; 47 48 } 49 50 CircleStage::CircleStage() 51 { 52 53 } 54 55 CircleStage::~CircleStage() 56 { 57 58 } 59 60 bool CircleStage::init() 61 { 62 63 mCircleA=ScreenWidth*0.4; 64 mCircleB=80; 65 mRoleNum=0; 66 mpHead=NULL; 67 mbOnAction=false; 68 for(int i=0;i<8;i++) 69 { 70 CandidateRole* role=CandidateRole::create("role"); 71 this->addRole(role); 72 73 } 74 updateDistances(); 75 updateZorders(); 76 initAppearance(); 77 return true; 78 79 } 80 void CircleStage::updateColor() 81 { 82 mpCurrentRole=mpSelectRole; 83 for (int i=0;i<mRoleNum;i++) 84 { 85 mpCurrentRole->mColorR=255; 86 mpCurrentRole->mColorG=255; 87 mpCurrentRole->mColorB=255; 88 for (int j=0;j<mpCurrentRole->mDistance;j++) 89 { 90 91 mpCurrentRole->mColorR*=0.6; 92 mpCurrentRole->mColorG*=0.6; 93 mpCurrentRole->mColorB*=0.6; 94 } 95 mpCurrentRole->mpArmature->setColor(ccc3(mpCurrentRole->mColorR,mpCurrentRole->mColorG,mpCurrentRole->mColorB)); 96 mpCurrentRole=mpCurrentRole->mpNextRole; 97 } 98 } 99 100 void CircleStage::updateDistances() 101 { 102 mpCurrentRole=mpSelectRole; 103 int distance=0; 104 for (int i=0;i<=mRoleNum/2;i++) 105 { 106 mpCurrentRole->mDistance=distance; 107 ++distance; 108 mpCurrentRole=mpCurrentRole->mpNextRole; 109 110 } 111 mpCurrentRole=mpSelectRole; 112 distance=0; 113 for (int i=0;i<=mRoleNum/2;i++) 114 { 115 mpCurrentRole->mDistance=distance; 116 ++distance; 117 mpCurrentRole=mpCurrentRole->mpForeRole; 118 } 119 120 mpSelectRole->mDistance=0; 121 } 122 void CircleStage::initAppearance() 123 { 124 mpCurrentRole=mpSelectRole; 125 126 for (int i=0;i<mRoleNum;i++) 127 { 128 double scale=1; 129 130 for (int j=0;j<mpCurrentRole->mDistance;j++) 131 { 132 scale*=0.8; 133 mpCurrentRole->mColorR*=0.6; 134 mpCurrentRole->mColorG*=0.6; 135 mpCurrentRole->mColorB*=0.6; 136 } 137 mpCurrentRole->setScale(scale); 138 139 mpCurrentRole->mpArmature->setColor(ccc3(mpCurrentRole->mColorR,mpCurrentRole->mColorG,mpCurrentRole->mColorB)); 140 mpCurrentRole=mpCurrentRole->mpNextRole; 141 } 142 mpSelectRole->setScale(1.0f); 143 144 } 145 146 void CircleStage::updateZorders() 147 { 148 mpSelectRole->setZOrder(mRoleNum); 149 mpSelectRole->mDistance=0; 150 mpCurrentRole=mpSelectRole; 151 152 for (int i=0;i<=mRoleNum/2;i++) 153 { 154 155 mpCurrentRole->setZOrder(mRoleNum-mpCurrentRole->mDistance); 156 mpCurrentRole=mpCurrentRole->mpNextRole; 157 } 158 for (int i=mRoleNum/2+1;i<mRoleNum;i++) 159 { 160 161 mpCurrentRole->setZOrder(abs(mRoleNum/2-mpCurrentRole->mDistance)); 162 mpCurrentRole=mpCurrentRole->mpNextRole; 163 } 164 165 } 166 167 168 169 170 void CircleStage::addRole(CandidateRole *newRole) 171 { 172 if (!mpHead) 173 { 174 mpHead=newRole; 175 this->addChild(newRole); 176 mpLast=mpHead; 177 mpLast->mpNextRole=mpHead; 178 mpHead->mpForeRole=mpHead; 179 mpCurrentRole=mpHead; 180 mRoleNum++; 181 mpCurrentRole->setPositionIndex(mRoleNum); 182 mpSelectRole=newRole; 183 } 184 else 185 { 186 mpLast->mpNextRole=newRole; 187 newRole->mpNextRole=mpHead; 188 newRole->mpForeRole=mpLast; 189 mpHead->mpForeRole=newRole; 190 this->addChild(newRole); 191 mpLast=newRole; 192 mRoleNum++; 193 newRole->setPositionIndex(mRoleNum); 194 } 195 int x,y; 196 double t; 197 while(1) 198 { 199 t=360/mRoleNum*(mpCurrentRole->getPositionIndex()-1)-90; 200 t=t*3.14/180;//convert t to radian 201 x=mCircleA*cos(t); 202 y=mCircleB*sin(t); 203 mpCurrentRole->setPositionX(x); 204 mpCurrentRole->setPositionY(y); 205 mpCurrentRole=mpCurrentRole->mpNextRole; 206 207 if (mpCurrentRole==mpHead) 208 { 209 break; 210 } 211 212 } 213 } 214 215 void CircleStage::changeToNext() //从右向左 216 { 217 mpSelectRole=mpSelectRole->mpNextRole; 218 CCCallFunc* callFuncActionEnd = CCCallFunc::create(this,callfunc_selector(CircleStage::actionEnd)); 219 CCCallFunc* callUpdateZorder = CCCallFunc::create(this,callfunc_selector(CircleStage::updateZordersCallBack)); 220 if (mpCurrentRole->mpNextRole) 221 { 222 223 mpSelectRole->setZOrder(mRoleNum); 224 for (int i=0;i<mRoleNum;i++) 225 { 226 227 mpCurrentRole->mNextPositionX=mpCurrentRole->mpForeRole->getPositionX(); 228 mpCurrentRole->mNextPositionY=mpCurrentRole->mpForeRole->getPositionY(); 229 mbOnAction=true; 230 CCMoveTo *moveToNext=CCMoveTo::create(0.4f,ccp(mpCurrentRole->mNextPositionX,mpCurrentRole->mNextPositionY)); 231 CCScaleTo *scaleToFore=CCScaleTo::create(0.4f,mpCurrentRole->mpForeRole->getScale()); 232 CCFiniteTimeAction* spawnAction = CCSpawn::create(moveToNext,scaleToFore,NULL); 233 234 CCSequence* actions = CCSequence::create(spawnAction,callUpdateZorder,callFuncActionEnd,NULL); 235 mpCurrentRole->runAction(actions); 236 237 mpCurrentRole=mpCurrentRole->mpNextRole; 238 239 } 240 updateDistances(); 241 updateColor(); 242 243 } 244 245 246 } 247 248 void CircleStage::updateZordersCallBack() 249 { 250 updateZorders(); 251 } 252 void CircleStage::actionEnd() 253 { 254 mbOnAction=false; 255 256 } 257 258 void CircleStage::changeToFore() //从左向右 259 { 260 mpSelectRole=mpSelectRole->mpForeRole; 261 CCCallFunc* callFuncActionEnd = CCCallFunc::create(this,callfunc_selector(CircleStage::actionEnd)); 262 263 if (mpCurrentRole->mpForeRole) 264 { 265 for (int i=0;i<mRoleNum;i++) 266 { 267 mpCurrentRole->mNextPositionX=mpCurrentRole->mpNextRole->getPositionX(); 268 mpCurrentRole->mNextPositionY=mpCurrentRole->mpNextRole->getPositionY(); 269 mbOnAction=true; 270 271 CCMoveTo *moveToFore=CCMoveTo::create(0.4f,ccp(mpCurrentRole->mNextPositionX,mpCurrentRole->mNextPositionY)); 272 CCScaleTo *scaleToFore=CCScaleTo::create(0.4f,mpCurrentRole->mpNextRole->getScale()); 273 CCFiniteTimeAction* spawnAction = CCSpawn::create(moveToFore,scaleToFore,NULL); 274 CCSequence* actions = CCSequence::create(spawnAction,callFuncActionEnd,NULL); 275 mpCurrentRole->runAction(actions); 276 mpCurrentRole=mpCurrentRole->mpNextRole; 277 278 } 279 updateDistances(); 280 updateZorders(); 281 updateColor(); 282 283 } 284 } 285 286 bool CircleStage::isOnAction() 287 { 288 return mbOnAction; 289 }
cocos2dx实现环形角色选择界面
时间: 2024-10-28 23:40:05