Cocos2d-x virtual Joystick Control genie up and down movement ---- game development "Zhao cloud to fight", cocos2d Delete genie

Source: Internet
Author: User

Cocos2d-x virtual Joystick Control genie up and down movement ---- game development "Zhao cloud to fight", cocos2d Delete genie

This is the first mini-game developed by myself. I have to leave a mailbox for source code and materials. Here, I can use a virtual joystick to control the movements of the genie and change the face orientation of the genie. I have read many people writing virtual joystick before, but I did not write the movements and face orientation of the control genie. So I want to write an article to explain its implementation ideas. Okay. Let's get started.

Directory:

1. Modify the background image and window size

2. Add a virtual joystick

3. Add the genie and use the joystick to control the movements of the genie.

Iv. Summary



1. Modify the background image and window size

Create a new project named HelloCpp. First, modify the window size in main. cpp to improve the effect.

EglView-> setFrameSize (480,320); For eglView-> setFrameSize (640,480 );


Then add the init () function of HelloWorldScene. cpp on the layer we want to display:

// Obtain the window size. CCSize visibleSize = CCDirector: shareddire()-> getVisibleSize (); CCPoint origin = CCDirector: sharedDirector ()-> getVisibleOrigin (); // modify the background image CCSprite * pSprite = CCSprite: create ("background_1.jpg"); pSprite-> setPosition (ccp (visibleSize. width/2 + origin. x, visibleSize. height/2 + origin. y); this-> addChild (pSprite, 0); // The value 0 indicates that it is placed at the bottom layer.

The effect is as follows:


2. Add a virtual joystick

First, put the joystick material in the Resources folder of the Project. Note that you 'd better put all the materials to be used here. The default material of the project is to be searched under this folder.

This is the background image of the joystick, which is hard to find. Without an artist, you can only find some information on the Internet,

This is the button image in the joystick and it can be moved.

Now, let's start adding the joystick to the background. My idea is to encapsulate the joystick into a class and then take care of the inherited CCLayer to respond to the touch event and look at the code, create an HRocker. h header file. Put. cpp and. h In the class folder of the project, and the file cannot be found. The Code is as follows:

# Ifndef _ HROCKER_H __# define _ HROCKER_H __# include "cocos2d. h "using namespace cocos2d; // used to identify the background typedef enum {tag_rocker, tag_rockerBG,} tagForHRocker; // used to identify typedef enum {rocker_stay, rocker_right, rocker_up, rocker_left, rocker_down,} tagDirecton; class HRocker: public CCLayer {public: HRocker (void );~ HRocker (void); // create a joystick (name of the joystick operation question image resource, name of the joystick background image resource, start coordinate) static HRocker * createHRocker (const char * rockerImageName, const char * rockerBGImageName, CCPoint position); // start the joystick (displaying the joystick and listening to the joystick touch screen events) void startRocker (bool _ isStopOther); // stop the joystick (hiding the joystick, cancel touch screen monitoring of the joystick) void stopRocker (); // determines the direction of the control lever, which is used to determine the movement of the int rocketDirection on the top, bottom, left, and right of the genie; // The walking direction of the current character, used to determine the direction of the Genie. The sprite face is either right or left bool rocketRun; CREATE_FUNC (HRocker); private: // custom initialization function void rockerInit (const char * rockerImageName, const char * rockerBGImageName, CCPoint position); // determine whether the joystick bool isCanMove can be operated; // obtain the float getRad (CCPoint pos1, CCPoint pos2) of the current joystick and the user's touch point ); // coordinate CCPoint rockerBGPosition of the joystick background; // float rockerBGR of the radius of the joystick background; // touch screen event virtual bool ccTouchBegan (CCTouch * pTouch, CCEvent * pEvent ); virtual void ccTouchMoved (CCTouch * pTouch, CCEvent * pEvent); virtual void ccTouchEnded (CCTouch * pTouch, CCEvent * pEvent);}; # endif

Create the corresponding implementation of HRocker. cpp. Put. cpp and. h In the class folder of the project, and the file cannot be found. The Code is as follows:

# Include "HRocker. h" const double PI = 3.1415; HRocker: HRocker (void) {rocketRun = false;} HRocker ::~ HRocker (void) {}// create a joystick (name of the joystick operation question image resource, name of the joystick background image resource, start coordinate) HRocker * HRocker: createHRocker (const char * rockerImageName, const char * rockerBGImageName, CCPoint position) {HRocker * layer = HRocker: create (); if (layer) {layer-> rockerInit (rockerImageName, rockerBGImageName, position ); return layer;} CC_SAFE_DELETE (layer); return NULL;} // custom initialization function void HRocker: rockerInit (const char * rockerImageName, const char * rockerBGImag EName, CCPoint position) {CCSprite * spRockerBG = CCSprite: create (rockerBGImageName); spRockerBG-> setPosition (position); spRockerBG-> setVisible (false); addChild (spRockerBG, 0, tag_rockerBG); CCSprite * spRocker = CCSprite: create (rockerImageName); spRocker-> setPosition (position); spRocker-> setVisible (false); addChild (spRocker, 1, tag_rocker ); rockerBGPosition = position; rockerBGR = spRockerBG-> getContentSize (). w Idth * 0.5; // rocketDirection =-1; // indicates that the joystick direction remains unchanged} // start the joystick (display the joystick and listen to the joystick touch screen event) void HRocker :: startRocker (bool _ isStopOther) {CCSprite * rocker = (CCSprite *) this-> getChildByTag (tag_rocker); rocker-> setVisible (true); CCSprite * rockerBG = (CCSprite *) this-> getChildByTag (tag_rockerBG); rockerBG-> setVisible (true); CCDirector: sharedDirector ()-> getTouchDispatcher ()-> addTargetedDelegate (this,-1, _ isStopOther);} // stop the joystick (hide the joystick and cancel Touch screen listener) void HRocker: stopRocker () {CCSprite * rocker = (CCSprite *) this-> getChildByTag (tag_rocker); rocker-> setVisible (false ); CCSprite * rockerBG = (CCSprite *) this-> getChildByTag (tag_rockerBG); rockerBG-> setVisible (false); CCDirector: shareddire()-> getTouchDispatcher () -> removeDelegate (this);} // obtain the float HRocker: getRad (CCPoint pos1, CCPoint pos2) {float px1 = pos1.x; float py1 = pos1.y; float Px2 = pos2.x; float py2 = pos2.y; // obtain the float x from two points = px2-px1; // obtain the float y from two points = py1-py2; // calculate the length of the Oblique Edge float xie = sqrt (pow (x, 2) + pow (y, 2); // obtain the cosine of this angle (through the store in the trigonometric function: angle cosine = oblique side/oblique side) float cosAngle = x/xie; // obtain the radian float rad = acos (cosAngle) of the expiration angle using the inverse cosine theorem; // note: when the position of the touch screen is Y coordinate <Y coordinate of the joystick, we need to reverse-0 ~ -180if (py2 <py1) {rad =-rad;} return rad;} CCPoint getAngelePosition (float r, float angle) {return ccp (r * cos (angle ), r * sin (angle);} // lift event bool HRocker: ccTouchBegan (CCTouch * pTouch, CCEvent * pEvent) {CCPoint point = pTouch-> getLocation (); CCSprite * rocker = (CCSprite *) this-> getChildByTag (tag_rocker); if (rocker-> boundingBox (). containsPoint (point) {isCanMove = true; CCLOG ("begin");} return true;} // move event void HRocker: ccTouchMoved (CCTouch * pTouch, CCEvent * pEvent) {if (! IsCanMove) {return;} CCPoint point = pTouch-> getLocation (); CCSprite * rocker = (CCSprite *) this-> getChildByTag (tag_rocker ); // obtain the float angle = getRad (rockerBGPosition, point) formed between the joystick and the touch screen ); // determine whether the center distance of the two circles is greater than the radius of the rocker background if (sqrt (pow (rockerBGPosition. x-point. x), 2) + pow (rockerBGPosition. y-point. y), 2)> = rockerBGR) {// guarantee the length of the inner circle movement restriction rocker-> setPosition (ccpAdd (getAngelePosition (rockerBGR, angle), ccp (rockerBGPositio N. x, rockerBGPosition. y); // CCLOG ("touch");} else {// if the value does not exceed, move the joystick following the user's touch point to rocker-> setPosition (point ); // CCLOG ("touch");} // determine the direction if (angle >=- PI/4 & angle <PI/4) {rocketDirection = rocker_right; rocketRun = false; CCLOG ("% d", rocketDirection);} else if (angle >=pi/4 & angle <3 * PI/4) {rocketDirection = rocker_up; CCLOG ("% d", rocketDirection);} else if (angle> = 3 * PI/4 & angle <= PI) | (angle> =-PI & angle <-3 * PI/4) {rocketDirection = rock Er_left; rocketRun = true; CCLOG ("% d", rocketDirection);} else if (angle >=- 3 * PI/4 & angle <-PI/4) {rocketDirection = rocker_down; CCLOG ("% d", rocketDirection) ;}// void HRocker: ccTouchEnded (CCTouch * pTouch, CCEvent * pEvent) {if (! IsCanMove) {return;} CCSprite * rockerBG = (CCSprite *) this-> getChildByTag (tag_rockerBG); CCSprite * rocker = (CCSprite *) this-> getChildByTag (tag_rocker ); rocker-> stopAllActions (); rocker-> runAction (CCMoveTo: create (0.08f, rockerBG-> getPosition (); isCanMove = false; rocketDirection = rocker_stay; CCLOG ("% d", rocketDirection); CCLOG ("end");} void HRocker: update (float dt) {if (isCanMove ){}}
Here's the idea. Let's talk about it later.

Add the header file # include "HRocker. h" in HelloWorldScene. h and add the member variables of the joystick class.

private:         HRocker*  rocker;

Add the following in the init () function of HelloWorldScene. h:

// Add the joystick rocker = HRocker: createHRocker ("Direction_bt.png", "Direction_bc.png", ccp (); // The button with the first picture as the joystick, the second is the background. this-> addChild (rocker, 2); rocker-> startRocker (true );

The effect is as follows: we can see that you can move the joystick.


The effect is good, very sensitive, and the ball won't jump out.

3. Add the genie and use the joystick to control the movements of the genie.

Here, in order to allow the genie to run, I created a class, Hero, which inherits CCNode and implements animation play and stop.

Zhao Yun's actions are actually a series of images merged together,



In addition, when Zhao Yun does not exercise, the image is



Zhoayun.png. This is the texture image of the sprite when it is not moving,

Here I directly use the tool TexturePacker to package them to generate the corresponding png and plist, the two together can form an animation in the cocos2d-x, relatively easy


The names are run_animation.png and run_animation.plist, and place them in the Resources folder of the project.



To make the code easier to understand, I created a class, Hero, which inherits CCNode and contains the member variable CCSprite * m_HeroSprite; we achieve motion by controlling its animation. It implements playing and stopping the animation. The Code is as follows:

Hero. h

# Ifndef _ HERO_H __# define _ HERO_H __# include "cocos2d. h "# include" cocos-ext.h "using namespace cocos2d; USING_NS_CC_EXT; class Hero: public cocos2d: CCNode {public: Hero (void );~ Hero (void); // create the Hero void InitHeroSprite (char * hero_name) based on the image name; // set the animation. num indicates the number of images, run_directon indicates the sprite face orientation, and false indicates the right direction, name_each is the public name of each small image in name_png <span style = "white-space: pre"> </span> void SetAnimation (const char * name_plist, const char * name_png, const char * name_each, const unsigned int num, bool run_directon); // stop the animation void StopAnimation (); // determine whether the animation bool IsRunning is running; // bool HeroDirecton; CREATE_FUNC (Hero); private: CCSprite * m_HeroSprite; // genie char * Hero_name; // The Name Of The genie image used to save the initial state }; # endif/_ HERO_H __

Then Hero. cpp

# Include "Hero. h "USING_NS_CC; USING_NS_CC_EXT; Hero: Hero (void) {IsRunning = false; // HeroDirecton = false; // Hero_name = NULL to the right;} Hero :: ~ Hero (void) {} void Hero: InitHeroSprite (char * hero_name) {Hero_name = hero_name; this-> m_HeroSprite = CCSprite: create (hero_name ); this-> addChild (m_HeroSprite);} // animation playback, which can be run, attack, death, injury, etc. void Hero: SetAnimation (const char * name_plist, const char * name_png, const char * name_each, unsigned int num, bool run_directon) {if (HeroDirecton! = Run_directon) {HeroDirecton = run_directon; m_HeroSprite-> setFlipX (run_directon);} if (IsRunning) return; // load the image to the cache pool of the sprite frame. Optional * m_frameCache = cached :: values (); m_frameCache-> values (name_plist, name_png); // save all CCSpriteFrameCache CCArray * frameArray = CCArray: createWithCapacity (num); unsigned int I; for (I = 2; I <= num; I ++) {CCSpriteFrame * fra Me = m_frameCache-> spriteFrameByName (CCString: createWithFormat ("%s0000d.png", name_each, I)-> getCString (); frameArray-> addObject (frame );} // use the list to create an animation object CCAnimation * animation = CCAnimation: createWithSpriteFrames (frameArray); if (HeroDirecton! = Run_directon) {HeroDirecton = run_directon;} animation-> setLoops (-1); // indicates the infinite loop playback of animation-> setDelayPerUnit (0.1f ); // The interval between two images. The smaller the number of images, the smaller the interval. // encapsulate the animation into an action CCAnimate * act = CCAnimate: create (animation ); m_HeroSprite-> runAction (act); IsRunning = true;} void Hero: StopAnimation () {if (! IsRunning) return; m_HeroSprite-> stopAllActions (); // The current genie stops all animations. // restores the original initialization texture of the Genie. this-> removeChild (m_HeroSprite, TRUE ); // Delete the original sprite m_HeroSprite = CCSprite: create (Hero_name); // restore the sprite's original texture m_HeroSprite-> setFlipX (HeroDirecton ); this-> addChild (m_HeroSprite); IsRunning = false ;}

Add the header file # include "Hero. h" in HelloWorldScene. h and add the member variables.

private:           Hero*    hero;

 

Add the following in the init () function of HelloWorldScene. h:

// Add the hero = Hero: create (); hero-> InitHeroSprite ("zhoayun.png"); hero-> setPosition (ccp (200,200 )); this-> addChild (hero, 1 );

The effect is as follows:


At this time, the picture is still static. To verify the movement of an genie, let's play a moving animation on it.

hero=Hero::create();hero->InitHeroSprite("zhoayun.png");hero->setPosition(ccp(200,200));this->addChild(hero,1);
Add a sentence

Hero-> SetAnimation ("run_animation.plist", "run_animation.png", 8, false); // 8 indicates the number of images in plist; false indicates the number of faces facing to the right.
Let's take a look at the effect, and the genie will keep moving.



What if we want to change the face orientation of the genie? Simple: Change false to true.
Hero-> SetAnimation ("run_animation.plist", "run_animation.png", 8, true); // 8 indicates the number of images in plist, and false indicates face to right

Effect:


Well, after the verification is correct, we didn't comment out the above sentence, because the genie should have been moved by a joystick.

In fact, it is very easy to control the movement of characters. It is nothing more than moving the genie position while playing the room animation. Of course, here we also need to judge the face orientation of the genie, in the above joystick class HRocker

// Determines the direction of the control lever. It is used to determine the movement of the int rocketDirection on the top, bottom, left, and right of the Genie. // It is used to determine the direction of the sprite, whether the sprite face is right or left bool rocketRun;

We only need to pass these two parameters to Zhao's Hero

// Set the animation. num indicates the number of images, run_directon indicates the sprite face orientation, and false indicates the right direction.
Void SetAnimation (const char * name_plist, const char * name_png, const unsigned int num, bool run_directon );

No. One is the int type and the other is the bool type. So how can we control it. We didn't create two objects in HelloWorldScene.

Private: HRocker * rocker; // joystick Hero * hero; // genie

Is it possible to pass the rocker value to hero? To update each frame, add an event to HelloWorldScene. h.

virtual void update(float delta);

Be sure to add the following content under the init () function of HelloWorldScene. cpp.

// Start the updata event this-> scheduleUpdate ();
Then there is the event.

Void HelloWorld: update (float delta) {// determines whether to press the joystick and its type switch (rocker-> rocketDirection) {case 1: hero-> SetAnimation ("run_animation.plist ", "run_animation.png", "run _", 8, rocker-> rocketRun ); // "run _" indicates the public name of each image in the run_animation.png set. hero-> setPosition (ccp (hero-> getPosition (). x + 1, hero-> getPosition (). y); // break to the right; case 2: hero-> SetAnimation ("run_animation.plist", "run_animation.png", "run _", 8, rocker-> rocketRun ); // "run _" indicates the public name of each image in the run_animation.png set. hero-> setPosition (ccp (hero-> getPosition (). x, hero-> getPosition (). y + 1); // go up to break; case 3: hero-> SetAnimation ("run_animation.plist", "run_animation.png", "run _", 8, rocker-> rocketRun); // "run _" indicates the public name of each image in the run_animation.png set. hero-> setPosition (ccp (hero-> getPosition (). x-1, hero-> getPosition (). y); // take break to the left; case 4: hero-> SetAnimation ("run_animation.plist", "run_animation.png", "run _", 8, rocker-> rocketRun ); // "run _" indicates the public name of each image in the run_animation.png set. hero-> setPosition (ccp (hero-> getPosition (). x, hero-> getPosition (). y-1); // walk down break; default: hero-> StopAnimation (); // stop all animation and motion break ;}}

Okay. Let's see how it works.

The effect is not bad. It's done!
Iv. SummaryIn fact, the idea here is to split the genie classes of the joystick class into different ones. The joystick class can control the movement of buttons and return the current operation type of your joystick, whether it is up or down, yes, face-to-right and left, and then pass these parameters to the hero genie class. Here, the hero should also be animated, then, you can call them at the image layer of the instance that creates two classes, and in the updata () function, you can determine whether the joystick is pressed and in the direction, then set the playing of the mobile animation of the Zhao Yun genie class. This is the way of thinking. Because the project has to be changed all the time, if anyone wants my materials and projects now, leave me an email. I will send it to you.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.