In Cocos2d-x 3.0, the onContactBegin callback function does not respond to the problem, cocos2d Collision Detection

Source: Internet
Author: User
Tags bitmask

In Cocos2d-x 3.0, the onContactBegin callback function does not respond to the problem, cocos2d Collision Detection

Well, in fact, this is a temporary release. Recently, a friend wants to make a physical game. In the past, he used box2d for physics. Well, it really takes some time to understand the essence of it, however, it is much easier to hear that this engine has been re-encapsulated once, so I tried it for a while and it seems a lot simpler, but I still encountered some problems here, first, let's talk about the onContactBegin callback function response.


Let's talk about the situation first. We made a simple brick-hitting game, and everything went well before. We only found that the callback function was not called during collision detection. At first, I thought the function was wrong. Later I checked the api, and testCpp was correct. In api 3.0, there was no description of PhysicsBody and PhysicsWorld classes, so you want to check the steps to the 3.2 api.


The onContactBegin function has one parameter,

Bool onContactBegin (PhysicsContact & contact), which is somewhat different from the 3.0beta version. It used to be two. Therefore, do not write an error when adding event listening. like this,

auto contactListener = EventListenerPhysicsContact::create();contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

The callback function responds once when two objects are in Contact state. The parameters in the callback function can also be seen in the Contact state, which naturally involves two objects.


Okay, now we should focus on it. Why is this onContactBegin function not responding? The problem lies in the three mask values. Here we recommend you read this blog post.

Or open the source code of the engine. You can view this code in the header file CCPhysicsShape,

/**     * A mask that defines which categories this physics body belongs to.     * Every physics body in a scene can be assigned to up to 32 different categories, each corresponding to a bit in the bit mask. You define the mask values used in your game. In conjunction with the collisionBitMask and contactTestBitMask properties, you define which physics bodies interact with each other and when your game is notified of these interactions.     * The default value is 0xFFFFFFFF (all bits set).     */    inline void setCategoryBitmask(int bitmask) { _categoryBitmask = bitmask; }    inline int getCategoryBitmask() const { return _categoryBitmask; }    
/**     * A mask that defines which categories of bodies cause intersection notifications with this physics body.     * When two bodies share the same space, each body’s category mask is tested against the other body’s contact mask by performing a logical AND operation. If either comparison results in a non-zero value, an PhysicsContact object is created and passed to the physics world’s delegate. For best performance, only set bits in the contacts mask for interactions you are interested in.     * The default value is 0x00000000 (all bits cleared).     */    inline void setContactTestBitmask(int bitmask) { _contactTestBitmask = bitmask; }    inline int getContactTestBitmask() const { return _contactTestBitmask; }   
 /**     * A mask that defines which categories of physics bodies can collide with this physics body.     * When two physics bodies contact each other, a collision may occur. This body’s collision mask is compared to the other body’s category mask by performing a logical AND operation. If the result is a non-zero value, then this body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body. For example, you might use this to avoid collision calculations that would make negligible changes to a body’s velocity.     * The default value is 0xFFFFFFFF (all bits set).     */    inline void setCollisionBitmask(int bitmask) { _collisionBitmask = bitmask; }    inline int getCollisionBitmask() const { return _collisionBitmask; }

To put it bluntly, whether two objects can collide or send contact event information depends on the three parameter values.

To sum up:

When the logic of the CategoryBitmask of one body and the ContactTestBitmask of another body are not equal to 0, the contact event is sent; otherwise, the contact event is not sent.
When the logic and result of the CategoryBitmask of one body and the CollisionBitmask of the other body are not equal to 0, the system will collide. Otherwise, the system will not collide.


All three parameters have their own default values, which are represented by 16 bits,

CategoryBitmask; default value: 0 xFFFFFFFF
ContactTestBitmask; default value: 0x00000000
CollisionBitmask; default value: 0 xFFFFFFFF


You can simply calculate it. If you do not know about this calculation, you can check it out, or pull out the calculator on your computer.

According to the previous summary, if all the bodies we created use the default value

CategoryBitmask & ContactTestBitmask = 0
CategoryBitmask & CollisionBitmask =-1


In this case, the situation is clear. If the default value is used, the collision can be detected, but the collision event will not be issued. so our onContactBegin will be blocked, of course, we will not do things.

So if we want to detect the collision between our two objects, it is very easy to avoid them from being OK if their & value is not equal to 0, therefore, you can set the three masks of two objects to be collided to 1,

m_ball->getPhysicsBody()->setCategoryBitmask(0x01);  m_ball->getPhysicsBody()->setContactTestBitmask(0x01); m_ball->getPhysicsBody()->setCollisionBitmask(0x01);
block->getPhysicsBody()->setCategoryBitmask(0x01);block->getPhysicsBody()->setContactTestBitmask(0x01);block->getPhysicsBody()->setCollisionBitmask(0x01);


In this way, when the bitwise AND result between them are both 1, the corresponding result can be obtained.

bool HelloWorld::onContactBegin(PhysicsContact& contact){auto sp1 = (Sprite*)contact.getShapeA()->getBody()->getNode();auto sp2 = (Sprite*)contact.getShapeB()->getBody()->getNode();if (sp1->getTag() == 1)sp1->removeFromParentAndCleanup(true);if (sp2->getTag() == 1)sp2->removeFromParentAndCleanup(true);return true;}

As mentioned above, there must be two objects in contact. Therefore, the logic of brick-making is to judge one of the tags. If it is a brick, it indicates that we have met, then we can remove it.

This is the result.





Cocos2d-x I want to add a button, click the genie to move it, ask the callback function how to write

CCActionInterval * monstersMove = CCMoveTo: create (1, ccp (x, y); monstersSprite-> runAction (monstersMove); annotation: ccp (x, y) is the moving destination 1 is the time second, you can also use ccpDistance (monstersMove-> getPosition (), ccp (x, y)/speed to calculate the time to reach the constant speed motion ~ Speed is a number that represents speed

How to trigger the CClayer touch message response when the cocos2d-x clicks on the button

There are two solutions: CCMenu is inherited from CCLayer, but CCMenu sets swallowsTouches to true when it is added to CCTouchDispatcher, indicating that the touch is swallowed, it will not continue to be passed down. You can see if you can change the swallowsTouches attributes from this aspect.
Also, you need to make a CCMenu and make a common CCSprite. First, the CCLayer detects the touch time and then checks that the touch point is within the range of CCSprite, if so, it indicates that CCSprite is verbose. You can process the events in the CCSprite point first, and then process the touch time of the CCLayer.

Related Article

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.