Design of color edit input box for cocos2dx
During Game Development, we may have special needs. For example, we want to explain today to create a simple edit input box with game characteristics. Let's take a look at the old rules. There are three here, because there are three pop-up methods for the Input Keyboard. Here we will briefly describe its functional requirements based on each situation:
The first is the general form:
(The picture is so beautiful that you can't bear to look straight ...)
Functional requirements:
1. the keyboard is displayed only when you click the input box;
2. simple animation on the keyboard and simple animation on clicking the keyboard button;
3. The input box displays the keyboard input in real time and deletes the input content;
4. Click the OK button, or click a simple animation that disappears except the input box and keyboard.
Sometimes, when the keyboard pops up, it will block the input box and look a little uncomfortable. So we can use the following solution:
Functional requirements:
1. Compared with the previous one, it actually changed the keyboard pop-up mode, but it didn't actually change, that is, let the original background image also move together.
However, this display scheme is insufficient. If the input box is located at a relatively high position, the input box may not be visible when the background image is moved up. So the question is, which of the following is the best keyboard pop-up solution? (I typed it ~.~), Most people will know about it. Let's take a look at the last display:
Functional requirements:
1. Compared with the previous one, the system changes to full screen input, adding a shadow layer and an input box.
PS: 1. Add the keyboard to fit the screen size.
2. We can replace the button image on the keyboard with an image with an element in our game.
Next, let's take a look at the general implementation of the Code:
First browse the header file:
#ifndef _COLOR_EDIT_H_#define _COLOR_EDIT_H_#include cocos2d.h#include cocos-ext.hUSING_NS_CC;USING_NS_CC_EXT;enum EditType{EditType_No = 0,Edit_Number,Edit_Alphabet,Edit_PinYin};enum EditLocation{EditLocation_No = 0,Location_Down,Location_Nature,Location_Screen};enum KeyBtn{Key_Num_0 = 0,Key_Num_1,Key_Num_2,Key_Num_3,Key_Num_4,Key_Num_5,Key_Num_6,Key_Num_7,Key_Num_8,Key_Num_9,Key_Delete,Key_Sure};class ColorEdit : public cocos2d::Layer{public:~ColorEdit();ColorEdit();static ColorEdit * create(const Size & size, const char * BgFile,Node * parent,EditLocation editLocation,EditType editType = Edit_Number);static ColorEdit * create(const Size & size,Scale9Sprite * pBgSprite,Node * parent,EditLocation editLocation,EditType editType = Edit_Number);bool myInit(Scale9Sprite * pBgSprite,Node * parent,EditLocation editLocation,EditType editType);protected:virtual bool onTouchBegan(Touch* touch, Event* pEvent);void onNumBtnCallback(Ref * obj);void onFunBtnCallback(Ref * obj);int getMaxZOrder(Node * node);void moveAction(bool isShow);void updateText();private:Scale9Sprite * m_pEditBg;Sprite * m_pKeyBoard;EditType m_editType;EditLocation m_editLocation;Sprite * m_keyBg;Node * m_pTarget;bool m_isKeyShow;std::string m_text;};#endif
Let's take a look at the implementation section:
First initialize:
Bool ColorEdit: myInit (Scale9Sprite * pBgSprite, Node * parent, EditLocation editLocation, EditType editType) {if (! Layer: init () {return false;} m_pEditBg = pBgSprite; m_pTarget = parent; m_editLocation = editLocation; m_editType = editType; this-> addChild (m_pEditBg ); auto centerSize = m_pEditBg-> getContentSize (); // set the size of the rectangle in the middle of the jiugong image, because we need to display the input content on it, otherwise it will look messy m_pEditBg-> setCapInsets (Rect (, centerSize. width * 0.9, centerSize. height * 0.9); auto pLabel = Label: createWithTTF (, fonts/Marker Felt. ttf, centerSize. height * 0.75); pLabel-> setColor (Color3B: WHITE); pLabel-> setAnchorPoint (Vec2 (0, 0.5); pLabel-> setTag (103 ); pLabel-> setPosition (Vec2 (centerSize. width * 0.08, centerSize. height * 0.5); m_pEditBg-> addChild (pLabel, 2); // if it is a full screen display type if (m_editLocation = Location_Screen) {// Add a shadow layer, first hide auto keyLayer = LayerColor: create (Color4B (0,100, 100); keyLayer-> setPosition (Point: ZERO); keyLayer-> setTag ); m_pTarget-> addChild (keyLaye R, this-> getMaxZOrder (parent) + 2); keyLayer-> setVisible (false); // Add the input box auto key_bigbg = Scale9Sprite: create (coloredit/key_bigbg.png ); key_bigbg-> setContentSize (Size (Director: getInstance ()-> getWinSize (). width, key_bigbg-> getContentSize (). height); key_bigbg-> setTag (101); key_bigbg-> setAnchorPoint (Vec2 (0.5, 0); auto upSize = key_bigbg-> getContentSize (); key_bigbg-> setPosition (Vec2 (m_pTarget-> getContent Size (). width/2, m_pTarget-> getContentSize (). height); m_pTarget-> addChild (key_bigbg, this-> getMaxZOrder (parent) + 2); // set the rectangle key_bigbg-> setCapInsets (Rect, upSize. width * 0.9, upSize. height * 0.9); auto label_up = Label: createWithTTF (, fonts/Marker Felt. ttf, upSize. height * 0.75); label_up-> setColor (Color3B: WHITE); label_up-> setAnchorPoint (Vec2 (0, 0.5); label_up-> setTag (102 ); label_up-> setPositi On (Vec2 (upSize. width * 0.08, upSize. height/2); key_bigbg-> addChild (label_up);} m_keyBg = Sprite: create (coloredit/key_bg.png); m_keyBg-> setAnchorPoint (Vec2 (0.5, 1 )); m_keyBg-> setPosition (Vec2 (m_pTarget-> getContentSize (). width/2, 0); m_pTarget-> addChild (m_keyBg, this-> getMaxZOrder (parent) + 2); auto bgSize = m_keyBg-> getContentSize (); auto pMenu = Menu :: create (); pMenu-> setPosition (Vec2: ZERO); m_keyBg-> DdChild (pMenu); if (m_editType = Edit_Number) // Add a numeric keypad {for (int I = 0; I <2; I ++) {for (int j = 0; j <5; j ++) {auto numSprNor = Sprite: create (_ String: createWithFormat (coloredit/num_1_d.png, I * 5 + j)-> getCString (); auto numSprSel = Sprite: create (_ String: createWithFormat (coloredit/num_0000d.png, I * 5 + j) -> getCString (); auto numBtn = MenuItemSprite: create (numSprNor, numSprSel, CC_CALLBACK_1 (ColorEd It: onNumBtnCallback, this); numBtn-> setTag (Key_Num_0 + I * 5 + j); numBtn-> setPosition (Vec2 (bgSize. width/10 * (j * 2 + 1), bgSize. height/6 * (3-I) * 2-1); pMenu-> addChild (numBtn);} auto delSprNor = Sprite :: create (coloredit/resize); auto delSprSel = Sprite: create (coloredit/btn_del.png); auto delBtn = MenuItemSprite: create (delSprNor, delSprSel, CC_CALLBACK_1 (ColorEdit: onFunBtnCallback Is); delBtn-> setTag (Key_Delete); delBtn-> setPosition (Vec2 (bgSize. width/4-15, bgSize. height/6); pMenu-> addChild (delBtn); auto sureSprNor = Sprite: create (coloredit/btn_sure.png); auto sureSprSel = Sprite: create (coloredit/btn_sure.png ); auto sureBtn = MenuItemSprite: create (sureSprNor, sureSprSel, CC_CALLBACK_1 (ColorEdit: Unknown, this); sureBtn-> setTag (Key_Sure); sureBtn-> setPosition (Vec2 (bg Size. width/4*3 + 15, bgSize. height/6); pMenu-> addChild (sureBtn);} else if (m_editType = Edit_Alphabet) // similar to number, some more buttons {} else if (m_editType = Edit_PinYin) // if this is implemented, it will be the input method. Let's call the system. {}// Auto rate_x = Director: getInstance ()-> getWinSize (). width/bgSize. width; m_keyBg-> setScaleX (rate_x); auto listenerT = EventListenerTouchOneByOne: create (); listenerT-> onTouchBegan = CC_CALLBACK_2 (ColorEdit: onTouchBegan, this ); listenerT-> setSwallowTouches (false); ctor: getInstance ()-> getEventDispatcher ()-> addEventListenerWithSceneGraphPriority (listenerT, this); return true ;}
Then, implement the touch function:
Bool ColorEdit: onTouchBegan (Touch * touch, Event * pEvent) {auto touchPoint = touch-> getLocation (); // for full screen display, if (m_editLocation = Location_Screen & m_isKeyShow) {auto key_upEdit = (Scale9Sprite *) m_pTarget-> getChildByTag (101) is displayed on the keyboard ); // if you click a field other than the top-level input box and the keyboard, the keyboard disappears if (! M_keyBg-> getBoundingBox (). containsPoint (touchPoint )&&! Key_upEdit-> getBoundingBox (). containsPoint (touchPoint) {this-> moveAction (false); return true;} return false ;} // convert the touch point to the coordinates touchPoint = this-> convertToNodeSpace (touchPoint); if (! M_pEditBg-> getBoundingBox (). containsPoint (touchPoint) {if (m_isKeyShow) {if (! M_keyBg-> getBoundingBox (). containsPoint (Vec2 (touch-> getLocation (). x, touch-> getLocation (). y-(m_editLocation = Location_Down? 1: 0) * m_keyBg-> getContentSize (). height) {this-> moveAction (false) ;}} return false ;}// if the input box is clicked, And if (! M_isKeyShow) {this-> updateText (); this-> moveAction (true);} return true ;}
Note the following:
if (!m_keyBg->getBoundingBox().containsPoint(Vec2(touch->getLocation().x,touch->getLocation().y - (m_editLocation == Location_Down ? 1 : 0) * m_keyBg->getContentSize().height))){this->moveAction(false);}
When the keyboard is displayed as the second one, the y coordinate of touch-> getLocation () must be modified because the background image moves up for a certain distance. Otherwise, the getBoundingBox judgment is incorrect.
Let's take a look at the response function for keyboard clicks:
Void ColorEdit: onNumBtnCallback (Ref * obj) {int tag = (Node *) obj)-> getTag (); // simple animation (MenuItemSprite *) obj)-> runAction (Sequence: create (ScaleTo: create (0.1, 10/8 .0), ScaleTo: create (0.1, 1), NULL )); char temp [3]; sprintf (temp, % d, tag); m_text + = temp; // update content this-> updateText (); log (keyboard -------> % d, tag);} void ColorEdit: onFunBtnCallback (Ref * obj) {(MenuItemSprite *) obj)-> runAction (Sequence: create (ScaleTo: create (0.1, 10/8 .0), ScaleTo: create (0.1, 1), NULL); if (Node *) obj)-> getTag () = Key_Sure) {this-> moveAction (false);} else {auto n = m_text.size (); if (n> 0) {m_text = m_text.substr (0, n-1 );} this-> updateText ();}}
Next, the appearance and disappearance of the keyboard:
void ColorEdit::moveAction(bool isShow){if (m_editLocation == Location_Screen){auto keyLayer = (LayerColor *)m_pTarget->getChildByTag(100);auto key_upEdit = (Scale9Sprite *)m_pTarget->getChildByTag(101);keyLayer->setVisible(isShow);key_upEdit->runAction(MoveBy::create(0.35,Vec2(0,(isShow ? -1 : 1) * key_upEdit->getContentSize().height)));m_keyBg->runAction(MoveBy::create(0.35,Vec2(0,(isShow ? 1 : -1) * m_keyBg->getContentSize().height)));}else if (m_editLocation == Location_Down){Director::getInstance()->getRunningScene()->runAction(MoveBy::create(0.35,Vec2(0,(isShow ? 1 : -1) * m_keyBg->getContentSize().height)));}else if (m_editLocation == Location_Nature){m_keyBg->runAction(MoveBy::create(0.35,Vec2(0,(isShow ? 1 : -1) * m_keyBg->getContentSize().height)));}m_isKeyShow = isShow;if (!isShow){m_text = ;}}
Other functions:
// Obtain the largest Zorderint ColorEdit: getMaxZOrder (Node * node) {int zorder =-1; Vector
NodeVec = node-> getChildren (); for (auto node: nodeVec) {int temp = node-> getLocalZOrder (); if (temp> zorder) {zorder = temp ;}} log (children's max zorder is % d, zorder); return zorder;} void ColorEdit: updateText () {if (m_editLocation = Location_Screen) {(Label *) (Scale9Sprite *) (m_pTarget-> getChildByTag (101)-> getChildByTag (102)-> setString (m_text);} else {(Label *) (m_pEditBg-> getChildByTag (103)-> setString (m_text );}}
At last, we only need a few lines of code.
Auto colorEdit = ColorEdit: create (Size (), coloredit/input_box.png, this, Location_Nature );
ColorEdit-> setPosition (Vec2 (bgSize. width/2, bgSize. height/2 ));
Bg-> addChild (colorEdit );
This is basically the end of the article. Please forgive me for poor writing.