Cocos2d-x 3.0 game instance learning notes "card tower guard" Step 7 --- hero to upgrade & amp; properties -- parsing csv configuration file
/* Description:
** 1. This game instance is the last game on the cocos2d-x game development journey, which is rewritten and noted down here with 3.0
** 2. I have also asked me about wood. He said: Write it as you like. First, do not copy the code completely. Second, You can note that it is a learning note-Good Guy.
** 3. Here With cocos2d-x 3.0 version rewriting, many places are different, but from the rewriting process also good learning cocos2d-x
*/
* ** All the code corresponding to each step and the resources used are packaged at the end.
* ** To avoid code overhead, the code in each step is marked. At first glance, the code is implemented in the first step to avoid errors and cannot be changed back (if not, Git should be used again ?)
* ** You can follow the design idea (well, the name is too tall. The reality is this step to do) first self-implementation-cocos2d-x is so, the same function has many different implementation methods; first self-toss is quite good.
* ** For the convenience of porting to the mobile phone, android testing is compiled for each step. Because the code can be compiled in win32 many times, compilation will fail, the code is tested.
Note content:
1. Design Ideas
2. Train of Thought code &
3. Next Content preview
4. Download The resource & complete code
I. Design Ideas
1. First, the Hero upgrade function is placed in Hero, which has different effects.
2. The upgrade operation is extracted from an operator inherited from the Node, and then bound to the turret. Then, click the turret. Three buttons are displayed: upgrade, close, and delete the hero.
3. A hero's upgrade is not only reflected in the appearance, but also has attributes. Attributes must be read from the csv file.
5. Because the subsequent ideas are basically based on the book, we will not be able to make an axe to the class-end directly in the code
Ii. Train of Thought code &
First, update the function for the hero. Here, the function is completely written and only supports four levels of improvement. After each promotion, an action is overwritten.
Void Hero: upgrade () {Sprite * sprite = getSprite (); if (sprite = NULL | _ level> = 4) {return ;} // Add level _ level ++; // if (_ level = 2) {Sprite * heroTop = Sprite: create ("sprite/hero/hero_top_1.png "); point pos = ccp (sprite-> getContentSize (). width/2, sprite-> getContentSize (). height/2); heroTop-> setPosition (pos); sprite-> addChild (heroTop);} if (_ level = 3) {Sprite * heroTop = Sprite :: create ("sprite/hero/hero_top_2.png"); heroTop-> setOpacity (255); Point pos = ccp (sprite-> getContentSize (). width/2, sprite-> getContentSize (). height/2); heroTop-> setPosition (pos); sprite-> addChild (heroTop); ActionInterval * rotateBy = RotateBy: create (25.0f, 360,360 ); actionInterval * repeat = RepeatForever: create (rotateBy); heroTop-> runAction (repeat);} if (_ level = 4) {Point pos = ccp (sprite-> getContentSize (). width/2, sprite-> getContentSize (). height/2); Sprite * heroTop = Sprite: create ("sprite/hero/hero_top_3.png"); heroTop-> setPosition (pos); sprite-> addChild (heroTop ); actionInterval * rotateBy = RotateBy: create (10.0f, 360,360); ActionInterval * repeat = RepeatForever: create (rotateBy); heroTop-> runAction (repeat );}}
The four basic effects are as follows:
Lv1 ---- lv2 ---- lv3 ------ lv4
The effect is a dynamic action.
--------------------------------------------------------------
Let's take a look at the operator TowerOperator; it needs to contact Hero and the bastion host, and needs the two members.
Class TowerOperator: public Node {public: TowerOperator ();~ TowerOperator (); static TowerOperator * create (TowerBorder * towerBorder, Hero * hero); bool init (TowerBorder * towerBorder, Hero * hero); private: Hero * _ hero; towerBorder * _ towerBorder; void createOprBtns (); // ** 7 ** button event void closeEvent (Ref * pSender, Control: EventType event); void upgradeEvent (Ref * pSender, control: EventType event); void deleteEvent (Ref * pSender, Control: EventType event );};
Implementation
TowerOperator::TowerOperator(){_hero = NULL;_towerBorder = NULL;}TowerOperator::~TowerOperator(){CC_SAFE_RELEASE(_hero);CC_SAFE_RELEASE(_towerBorder);}TowerOperator* TowerOperator::create(TowerBorder* towerBorder,Hero* hero){TowerOperator* towerOperator = new TowerOperator();if(towerOperator && towerOperator->init(towerBorder,hero)){towerOperator->autorelease();}else{CC_SAFE_DELETE(towerOperator);}return towerOperator;}bool TowerOperator::init(TowerBorder* towerBorder, Hero* hero){CC_SAFE_RETAIN(towerBorder);_towerBorder = towerBorder;CC_SAFE_RETAIN(hero);_hero = hero;createOprBtns();return true;}void TowerOperator::createOprBtns(){ LabelTTF* title = LabelTTF::create("Close", "Arial", 25);auto m_pos = this->getPosition(); ControlButton* closeBtn = ControlButton::create(title, Scale9Sprite::create("Button/opr_btn_nor.png"));closeBtn->setBackgroundSpriteForState(Scale9Sprite::create("Button/opr_btn_light.png"), Control::State::HIGH_LIGHTED);closeBtn->addTargetWithActionForControlEvents(this,cccontrol_selector(TowerOperator::closeEvent), Control::EventType::TOUCH_UP_INSIDE);closeBtn->setPosition(ccp(m_pos.x+100,m_pos.y));this->addChild(closeBtn); title = CCLabelTTF::create("Delete", "Arial", 25); ControlButton* deleteBtn = ControlButton::create(title, Scale9Sprite::create("Button/opr_btn_nor.png")); deleteBtn->setBackgroundSpriteForState(Scale9Sprite::create("Button/opr_btn_light.png"), Control::State::HIGH_LIGHTED);deleteBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(TowerOperator::deleteEvent), Control::EventType::TOUCH_UP_INSIDE);deleteBtn->setPosition(ccp(m_pos.x-100,m_pos.y));this->addChild(deleteBtn); title = CCLabelTTF::create("Upgrade", "Arial", 25); ControlButton* upgradeBtn = ControlButton::create(title, Scale9Sprite::create("Button/opr_btn_nor.png")); upgradeBtn->setBackgroundSpriteForState(Scale9Sprite::create("Button/opr_btn_light.png"), Control::State::HIGH_LIGHTED);upgradeBtn->addTargetWithActionForControlEvents(this, cccontrol_selector(TowerOperator::upgradeEvent), Control::EventType::TOUCH_UP_INSIDE);upgradeBtn->setPosition(ccp(m_pos.x,m_pos.y+100));this->addChild(upgradeBtn);}void TowerOperator::closeEvent(Ref* pSender,Control::EventType event){CCLOG("close!");this->removeFromParentAndCleanup(true);}void TowerOperator::upgradeEvent(Ref* pSender,Control::EventType event){CCLOG("upgrade!");_hero->upgrade();}void TowerOperator::deleteEvent(Ref* pSender,Control::EventType event){CCLOG("delete!");_towerBorder->deleteHero();this->removeFromParentAndCleanup(true);}
Three buttons. Here, we also need to pay attention to the placement of relative positions, that is, the location of son & parent.
The functions of the three buttons are relatively simple, so the corresponding delete operation is completed by -- _ towerBorder. The function is:
void TowerBorder::deleteHero(){_hero->removeFromParentAndCleanup(true);CC_SAFE_RELEASE_NULL(_hero);}
In addition, do not use _ hero to directly Delete the instance from the parent. Otherwise, the instance cannot be added next time.
Then our operator must be displayed. When we add a hero to the gun station, we will add it in the touch event when there is no hero on the gun station. If so, the following figure shows the operator:
Void TowerBorder: showOperator () {auto towerOperator = TowerOperator: create (this, _ hero); CC_SAFE_RETAIN (towerOperator); towerOperator-> setPosition (ccp (0, 0 )); this-> addChild (towerOperator);} // The setPostion here and the setPos in the operator are also related to the relative position mentioned above. bool HeroManager: initWithLevel (int curLevel) ***************** /listener-> onTouchEnded = [=] (Touch * touch, event * event) ***************** /if (clickBorder-> getHero () = NULL) {Hero * hero = Hero: createFromCsvFileByID (1); hero-> setPosition (clickBorder-> getPosition (); this-> addChild (hero ); clickBorder-> bindHero (hero);} else {clickBorder-> showOperator () ;};_ eventDispatcher-> addEventListenerWithSceneGraphPriority (listener, this); // returns true ;}
The effect is as follows:
Then, our hero's upgrades have an external representation.
However, our hero has never configured the attribute ----------------- this should be done through csv;
The first thing to note is:
Csv is a simple file. You can use Excel to make it look like a table. The last saved format is csv. But when you use NotePad to open it, you will find that it is actually separated by commas (,).
----------------------
So here the csv needs to be parsed, and then put in our cocos2d-x, use these attributes;
I am not talking about it here, but I have modified many things in version 3.0. At the same time, some modifications have been made to port the file to the mobile phone. There are three classes for parsing csv files:
FileLoadUtil --- file loading, StringUtil --- string parsing, CsvUtil --- the first two work together to complete the final parsing. If you know the specific work, the best way is step-by-step debugging, which is easy to understand.
Bytes ---------------------------------------------------------------------------------------------------------------
Let's take a look at Hero. h, the Hero's attribute:
Enum EnumHeroType {en_HeroType_Normal}; enum category {enHeroPropConf_ID, // hero category, // hero name enHeroPropConf_Type, // hero type category, // Hero Model category, // basic attack strength, // attack interval (unit: seconds) enHeroPropConf_AtkRange, // attack range (RADIUS) enHeroPropConf_UpgradeAtkBase, // upgrade the attack addition coefficient enHeroPropConf_UpgradeCostBase, // upgrade the consumption Base Value }; // -------------- the following are some class members-// ** 7 ** CC_SYNTHESIZE (EnumHeroType, _ heroType, HeroType); // the hero type CC_SYNTHESIZE (int, _ baseAtk, baseAtk); // basic attack CC_SYNTHESIZE (int, _ curAtk, CurAtk); // current attack -- eg: After Upgrade CC_SYNTHESIZE (int, _ atkSpeed, AtkSpeed ); // attack speed (interval) CC_SYNTHESIZE (int, _ atkRange, AtkRange); // attack range (RADIUS) CC_SYNTHESIZE (int, _ upgradeCostBase, UpgradeConstBase ); // upgrade consumption CC_SYNTHESIZE (float, _ upgradeAtkBase, UpgradeAtkBase); // upgrade attack bonus
In the Init function
// ** 7 ** CsvUtil * csvUtil = CsvUtil: getInstance (); Size csvSize = csvUtil-> getFileRowColNum ("cvs/Hero. cvs "); const char * chHeroID = _ String: createWithFormat (" % d ", heroID)-> getCString (); int line = csvUtil-> findValueInWithLine (chHeroID, enHeroPropConf_ID, "cvs/Hero. cvs "); if (line <0) {return false;} setID (heroID); setModeID (csvUtil-> getInt (line, enHeroPropConf_ModelID," cvs/Hero. cvs "); setBaseAtk (csvUtil-> getInt (line, enHeroPropConf_BaseAtk," cvs/Hero. cvs "); setCurAtk (getBaseAtk (); setAtkSpeed (csvUtil-> getInt (line, enHeroPropConf_AtkSpeed," cvs/Hero. cvs "); setAtkRange (csvUtil-> getInt (line, enHeroPropConf_AtkRange," cvs/Hero. cvs "); setUpgradeAtkBase (csvUtil-> getFloat (line, enHeroPropConf_UpgradeAtkBase," cvs/Hero. cvs "); setUpgradeConstBase (csvUtil-> getInt (line, enHeroPropConf_UpgradeCostBase," cvs/Hero. cvs "); // ---------------- upgrade -------------------- // increase the hero's attack power. setBaseAtk (getBaseAtk () * _ upgradeAtkBase); setCurAtk (getBaseAtk ());
Finally, in the constructor of AppDelegate,
AppDelegate::AppDelegate() {CC_SAFE_RETAIN(CsvUtil::getInstance());}AppDelegate::~AppDelegate(){CC_SAFE_RELEASE(CsvUtil::getInstance());}
OK. This time is over.
Iii. Next Content preview
The hero's attributes cannot be seen because there is no monster to make it bully, so we need to add a monster later and let it walk according to the route we previously edited.
IV:
-----------------------------------
Source code & Resources
--------------------------------------
Personal ignorance. Thank you for your correction and discussion.