Cocos2d-x collision detection principle and hero to death monsters -- game development "Zhao cloud to fight" (7), cocos2d Collision Detection
This is the blog of Evankaka. You are welcome to discuss and exchange the above ~~~~~~
Reprinted please indicate the sourceHttp://blog.csdn.net/evankaka/article/details/42689689
This article will detail the collision detection principles of heroes and monsters in cocos2dx. It is actually a collision detection between Genie and genie. This article mainly starts with rectangular collision and writes a function for rectangular collision detection, which is used in the game. On the other hand, when a hero initiates an attack, if the hero and the monster collide, the monster will lose blood, and when the monster's blood volume is 0, the monster will die, before death, it will flash a few times on the ground. Next, let's start.
Cocos2d-x version: 2.2.5
Project Environment: Windows 7 + VS2010
Open Method: place the project in the project folder under the cocos2d-x installation directory open with
Source code download (the blogger decides that all resources in this series are free of charge ~)
Let's take a look at the effect:
Directory
I. Genie Collision Detection Principle
Ii. Custom Collision Detection Functions
3. A hero wants to kill a monster
Iv. Summary
I. Genie Collision Detection Principle
Many people are talking about Collision Detection on the Internet, but they generally only talk about how to use it, but they have not talked about the principle in detail. They have come down and figured out that this is actually very simple.
First, let's look at two rectangles. We define the following two rectangles,Rectangle 1: red; rectangle 2: Black
If we list all of their non-collision situations, then what else is not collision. When we think of this, I will start from this, then they do not conflict with each other. We can divide them into four types.
Rectangle 1: red; rectangle 2: Black
1. The rectangle 1 is at the left of the rectangle 2, and there is no collision between the two.
Condition: x1 + w1 * 0.5 <x2-w2*0.5
2. The rectangle 1 is on the right of the rectangle 2, and there is no collision between the two.
Conditions: x1-w1 * 0.5> x2 + w2 * 0.5
3. The rectangle 1 is under the rectangle 2, and there is no collision between the two
Condition: y1 + h1 * 0.5 <y2-h2*0.5
4. The rectangle 1 is above the rectangle 2, and there is no collision between the two
Condition: y1-h1 * 0.5> y2 + h2 * 0.5
The above four cases are all non-collision cases. Then, let's make a judgment and check the above four cases in sequence. Once one case is found to be true, no collision will be returned, if neither of the four cases is true, congratulations! The collision is successful!
Ii. Custom Collision Detection Functions
Collision detection can be used for Genie classes
sprite1->boundingBox().intersectsRect(sprite1->boundingBox())
However, the heroes and monsters in my game are all defined classes. Therefore, a problem occurs when I directly call the above functions. Therefore, I wrote a function for the principle of collision detection, it can be called directly, regardless of what you are.
First, where collision detection is used # include "HelloWorldScene. h"
Define functions
// Rectangular Collision Detection
Bool isRectCollision (CCRect rect1, CCRect rect2 );
Then in the implementation function HelloWorldScene. cpp:
/// Collision detection bool HelloWorld: isRectCollision (CCRect rect1, CCRect rect2) {float x1 = rect1.origin. x; // float y1 = rect1.origin of the Center of rectangle 1. y; // float w1 = rect1.size of the Center of rectangle 1. width; // float h1 = rect1.size of the rectangle 1. height; // float x2 = rect2.origin. x; float y2 = rect2.origin. y; float w2 = rect2.size. width; float h2 = rect2.size. height; if (x1 + w1 * 0.5 <x2-w2 * 0.5) return false; // rectangle 1 on the left side of rectangle 2, no collision between the two else if (x1-w1 * 0.5> x2 + w2 * 0.5) return false; // rectangle 1 in the right side of rectangle 2, no collision between the two else if (y1 + h1 * 0.5 <y2-h2 * 0.5) return false; // The rectangle 1 is below the rectangle 2, there is no collision between the two else if (y1-h1 * 0.5> y2 + h2 * 0.5) return false; // The rectangle 1 is above the rectangle 2, and the two do not collide return true ;}The principle of this Code is what we mentioned above. It's easy!
3. A hero wants to kill a monster
Now we need to call the second function. Let's take a look at the collision scope between heroes and monsters.
(I made the background transparent. Actually, this is the case)
(I made the background transparent. Actually, this is the case)
Therefore, pay attention to it. Please be careful not to include the width and height of the entire image;
A simple process of Collision Detection
Then it is implemented ~
Added to the void HelloWorld: update (float delta) Function
If (hero-> IsAttack) // the hero is attacking {if (! Monster1-> Isdead) // the monster is not dead yet {if (abs (hero-> getPositionY ()-monster1-> getPositionY () <30) // The monsters and heroes should be at the same level and the attack will be effective. {// check whether the attack hits the monsters, note that you need to subtract some border values if (this-> isRectCollision (CCRectMake (hero-> getPositionX (), hero-> getPositionY (), hero-> GetSprite () -> getContentSize (). width-70, hero-> GetSprite ()-> getContentSize (). height-30), CCRectMake (monster1-> getPositionX (), monster1-> getPositionY (), monster1-> GetSprite ()-> getContentSize (). width-30, monster1-> GetSprite ()-> getContentSize (). height-20) {monster1-> HurtAnimation ("monster_hurt", 2, monster1-> MonsterDirecton); // injury }}}}
Now, let's talk about the animation of the death of a monster.
The Monster. h mentioned in the previous article adds a function.
// The injured animation void HurtAnimation (const char * name_each, const unsigned int num, bool run_directon); // The injured animation ends void HurtEnd (); // determine whether the animation bool IsHurt is injured; // death animation void DeadAnimation (const char * name_each, const unsigned int num, bool run_directon ); // death animation ends void DeadEnd (); // determines whether bool Isdead is killed; // The Death of a monster flashes ends void BlinkEnd ();
Then in the implementation function Monster. cpp
// Void Monster: HurtAnimation (const char * name_each, const unsigned int num, bool run_directon) {if (IsHurt | Isdead) return; // if (IsRunning | IsAttack) {m_MonsterSprite-> stopAllActions (); // The current genie stops all animations. // restores the original initialization texture of the sprite. this-> removeChild (m_MonsterSprite, TRUE); // deletes the original sprite m_MonsterSprite = CCSprite :: create (Monster_name); // restore the sprite's original texture m_MonsterSprite-> setFlipX (MonsterDirecton); this-> addChild (m_MonsterSprit E); IsRunning = false; IsAttack = false;} CCAnimation * animation = CCAnimation: create (); for (int I = 1; I <= num; I ++) {char szName [100] = {0}; sprintf (szName, "s0000d.png", name_each, I); animation-> addSpriteFrameWithFileName (szName ); // frame for loading the animation} animation-> setDelayPerUnit (2.8f/14.0f); animation-> setRestoreOriginalFrame (true); animation-> setLoops (1 ); // One animation loop // wrap the animation into an action CCAnimate * act = CCAnimate: create (animat Ion); // creates a callback action. When the injured animation ends, HurtEnd () CCCallFunc * callFunc = CCCallFunc: create (this, callfunc_selector (Monster: HurtEnd) is called )); // create a continuous action CCActionInterval * hurtackact = CCSequence: create (act, callFunc, NULL); m_MonsterSprite-> runAction (hurtackact); IsHurt = true ;} // void Monster: HurtEnd () {IsHurt = false; Monster_xue-> setCurrentProgress (Monster_xue-> getCurrentProgress ()-10); if (Monster_xue-> getCurrentProgress () = 0) {// play DeadAnimation ("monster_dead", 2, MonsterDirecton) ;}// death animation void Monster: DeadAnimation (const char * name_each, const unsigned int num, bool run_directon) {Isdead = true; CCAnimation * animation = CCAnimation: create (); for (int I = 1; I <= num; I ++) {char szName [100] = {0}; sprintf (szName, "s0000d.png", name_each, I); animation-> addSpriteFrameWithFileName (szName ); // frame for loading the animation} animation-> setDelayPerUnit (2.8f/14.0 F); animation-> setRestoreOriginalFrame (true); animation-> setLoops (1); // One animation loop // wrap the animation into an action CCAnimate * act = CCAnimate :: create (animation); // creates a callback action. After the call ends, call deadact () CCCallFunc * callFunc = CCCallFunc: create (this, callfunc_selector (Monster: DeadEnd )); // create a continuous action CCActionInterval * deadact = CCSequence: create (act, callFunc, NULL); m_MonsterSprite-> runAction (deadact);} // The death animation ends void Monster :: deadEnd () {// restore death this-> r EmoveChild (m_MonsterSprite, TRUE); // Delete the original genie m_MonsterSprite = CCSprite: create ("monster_dead2.png "); // restore the death state m_MonsterSprite-> setFlipX (MonsterDirecton); this-> addChild (m_MonsterSprite); // if (Monster_xue! = NULL) {if (MonsterDirecton) // because the monster center is not in the image center, it can only be oriented Based on the monster's face, set the horizontal Monster_xue-> setPosition (ccp (m_MonsterSprite-> getPositionX () + 60, m_MonsterSprite-> getPositionY ())); // set elseMonster_xue-> setPosition (ccp (m_MonsterSprite-> getPositionX ()-60, m_MonsterSprite-> getPositionY () on the monster header ()));} // The monster will flash twice and then die again. CCBlink * blinkact = CCBlink: create (); // 3 indicates the duration, and 6 indicates the number of flashes. // create a callback, call BlinkEnd () CCCallFunc * callFunc = CCCallFunc: create (this, callfunc_selector (Monster: BlinkEnd) after flashing ends; // create a continuous action CCActionInterval * deadact = CCSequence :: create (blinkact, callFunc, NULL); m_MonsterSprite-> runAction (deadact);} // flashes to end void Monster: BlinkEnd () {this-> removeAllChildren (); // Delete the monsters and blood records ;}
A process of death of a monster, after each injury to the blood, immediately detect the current blood volume, if the blood volume is 0, immediately play the animation of death, and then play the flashing animation, then you can delete the monster ~~ That's simple.
Effect:
1. The monster is patrolling, and no collision is detected during the attack.
2. The hero is under attack, and a collision is detected. The monster is injured and blood is lost.
3. The monster's blood volume is 0, the monster dies, and a flashing animation is played.
Iv. Summary
Here, the collision detection is against other paths, listing all the possible non-collision events. Isn't the other items collision? Then you can program it on your own. On the other hand, monsters are animations of injury and death, and flashes. These are all very basic and basically the same functions. You only need to use them once. Remember that this is an action in order. Remember this.