Cocos 2d-xFinal Project Trample Record
We have to Tucao first, the overall framework of Cocos is very strong, but many details are not humanized, and the official documents are not keeping up with them. This leads to wasting a lot of time in some unnecessary pits. It is really not cost-effective. Record the end of the project and use cocos2d-x3.10 to develop the pits.
1. Acquisition of csb file components exported by Cocos Studio
auto rootNode = CSLoader::createNode("LoginScene/LoginScene.csb");//Getting csb Layout* background = (Layout*)rootNode->getChildByName("background");//Getting Layers on csb Button* btnMenu = (Button*)Helper::seekWidgetByName(background, "menubutton");//Get the button on the layer
Note that the child control name can only be capitalized, if not capitalized, there will be no error (Orz, I really do not know what the siege lion thought at that time, a long step to look at the address found)
Pit daddy index:
2. Touch Detection of Cocos Studio Button Control
The range is based on your Button image, so if it's a circular button, you have to cut out the circle to make it accurate.
Number of Prime Number of Pit Dad:
3. Role Moving and Animation Playing
This plan is to write a detailed topic in the summer vacation. The role's position movement is the default dispatcher + keyboard monitor. Each frame will detect keys and make corresponding movement. The role's animation is written in init with another function + keyboard monitor. At first, I didn't think so much about it. Both of them are combined, but I found that using the dispatcher to play animation or function. Controlling movement will lead to discontinuity of action or distortion of coordination, so we have to write two things separately, and then separate the speed, and finally achieved.
Role Location Mobility:
//Scheduler void MapOfGame::update(float delta) { Node::update(delta); role1.loadPositon(); auto upArrow = EventKeyboard::KeyCode::KEY_UP_ARROW, downArrow = EventKeyboard::KeyCode::KEY_DOWN_ARROW, leftArrow = EventKeyboard::KeyCode::KEY_LEFT_ARROW, rightArrow = EventKeyboard::KeyCode::KEY_RIGHT_ARROW; if (isKeyPressed(upArrow)) { keyPressedMovement(upArrow); } else if (isKeyPressed(downArrow)) { keyPressedMovement(downArrow); } else if (isKeyPressed(leftArrow)) { keyPressedMovement(leftArrow); } else if (isKeyPressed(rightArrow)) { keyPressedMovement(rightArrow); } } ........ //Corresponding Moving Function void MapOfGame::keyPressedMovement(EventKeyboard::KeyCode keyCode) { CCPoint moveByPosition; RoleDirection tag; //you can set move speed here switch (keyCode) { case EventKeyboard::KeyCode::KEY_UP_ARROW: moveByPosition = ccp(0, role1.getSpeed()); break; case EventKeyboard::KeyCode::KEY_DOWN_ARROW: moveByPosition = ccp(0, -role1.getSpeed()); break; case EventKeyboard::KeyCode::KEY_LEFT_ARROW: moveByPosition = ccp(-role1.getSpeed(), 0); break; case EventKeyboard::KeyCode::KEY_RIGHT_ARROW: moveByPosition = ccp(role1.getSpeed(), 0); break; default: moveByPosition = ccp(0, 0); break; } //Create MoveBy objects and perform mobile actions auto move = CCMoveBy::create(0.01f, moveByPosition); role1.role->runAction(move); }
Animation in Character Moving
//These are written in init. //add keyboard listener auto listener = EventListenerKeyboard::create(); //call responding animation when realted key is pressed listener->onKeyPressed = [=](EventKeyboard::KeyCode keyCode, Event *event) { keys[keyCode] = true; switch (keyCode){ case EventKeyboard::KeyCode::KEY_UP_ARROW: keyPressedAnimation(keyCode); break; case EventKeyboard::KeyCode::KEY_DOWN_ARROW: keyPressedAnimation(keyCode); break; case EventKeyboard::KeyCode::KEY_LEFT_ARROW: keyPressedAnimation(keyCode); break; case EventKeyboard::KeyCode::KEY_RIGHT_ARROW: keyPressedAnimation(keyCode); break; default: break; } }; ....... //Corresponding to the animation function, walkAnimation is the animation array of four directional sequence frames previously made. void MapOfGame::keyPressedAnimation(EventKeyboard::KeyCode keyCode) { RoleDirection tag; //you can set move speed here switch (keyCode) { case EventKeyboard::KeyCode::KEY_UP_ARROW: tag = kUp; break; case EventKeyboard::KeyCode::KEY_DOWN_ARROW: tag = kDown; break; case EventKeyboard::KeyCode::KEY_LEFT_ARROW: tag = kLeft; break; case EventKeyboard::KeyCode::KEY_RIGHT_ARROW: tag = kRight; break; default: break; } animations[tag] = RepeatForever::create(CCAnimate::create(walkAnimations[tag])); //animations[tag] = CCAnimate::create(walkAnimations[tag]); role1.role->runAction(animations[tag]); }
Pit daddy index:
4. Attention to Collision Detection Using Scheduler
My idea of collision detection is to call the correlation function once per frame in the dispatcher (in fact, it will not move illegally when it is written with the position moving function) to ensure the timeliness of detection, but it is unexpectedly found that there is no problem when one-step debugging, once it runs, it will appear that the "inertia is too big" to rush out of the collision area and get stuck (coordinates at this time). It's illegal, so I can't move. It took me several hours to detect no logic error. After sleeping the next day, I suddenly found that the duration set by my MoveBy is 0.28f. That is to say, it takes 0.28 seconds to move every frame. However, I have 60 frames per second. That is to say, if I hold the mobile key, it takes 60*0.28s to complete the second movement. This is impossible, so the system may interrupt the last duration process directly when it executes the next time, resulting in collision detection failure. To verify this conjecture, I replace scheduleUpdate, the default scheduler invoked by each frame, with a scheduler that can set the time interval.
//Now the scheduler can set the interval this->schedule(schedule_selector(MapOfGame::update), 0.05f); //The code for the collision detection section is a function of the previously posted moving position code. //collision check CCPoint targetPosition = ccpAdd(role1.role->getPosition(), moveByPosition); if (checkCollision(targetPosition, tag) == kWall) { setFaceDirection(tag); return; } auto move = CCMoveBy::create(0.01f, moveByPosition); role1.role->runAction(move);
I set the time interval of the scheduler to > MoveBy time interval, that is to say, every keyboard monitor and collision detection can ensure that the last movement process has been completed. Sure enough, my role did not appear "inertia too big" into the illegal area of the jam.
Pit daddy index:
5. Switching Background Music in Different Scenes
In the morning after completing the collision detection, I was very happy to think that I had finished the plan ahead of time and wanted to add the sound effects. In my imagination, it would be very easy to put some background music in the next game engine. However, the design of cocos egg pain made it difficult to realize this simple idea.
I used cocos2d-x's audio component # include "Simple Audio Engine. h", and then in each scene called the corresponding function to play background music, Daddy's place came, for example, my Scene1 and Scene2 intend to use different background music, from the former to the latter, the background music will stop playing, the latter music can only play a few seconds, stuck in the consulting network. After a lot of information, it is found that this is due to the characteristics of Cocos 2d-x scene switching. See Guan Dongsheng's blog specifically:
Scene Switching and Background Music
In particular, in this case, you need to rewrite the scenario lifecycle function yourself.
void MapOfGame::onEnter() { Layer::onEnter(); } void MapOfGame::onEnterTransitionDidFinish() { Layer::onEnterTransitionDidFinish(); //play music SimpleAudioEngine::getInstance()->playBackgroundMusic("MusicSource/bg/Village.mp3", true); SimpleAudioEngine::getInstance()->playEffect("MusicSource/appear.wav"); } void MapOfGame::onExit() { Layer::onExit(); } void MapOfGame::onExitTransitionDidStart() { Layer::onExitTransitionDidStart(); } void MapOfGame::cleanup() { Layer::cleanup(); }
The corresponding switching mode should also be set to push Scene. If repeat Scene is used, the system will automatically transfer the music stopping function. No matter how to make the subsequent Scene silent.
void Login::StartGameTouch(Ref* pSender, Widget::TouchEventType type) { switch (type) { case Widget::TouchEventType::ENDED: auto director = Director::getInstance(); //transfer to MapScene auto scene = MapOfGame::createScene(); auto transition = TransitionCrossFade::create(1.0f, scene); SimpleAudioEngine::getInstance()->stopBackgroundMusic(); director->pushScene(transition); break; } }
The pit daddy index: It's my Tai cuisine.