[Cocos3.0 Tutorial] Accurate hit testing with Cocos2d-x 3.0 integrated physics feature

#Accurate hit testing with Cocos2d-x 3.0 integrated physics feature.

Cocos2d-x 3.0 version has an integrated physics feature based on chipmunk. It’s very easy to make accurate hit testing in our cocos2d-x game.

###Source code at github/xhcnb/accurate_hit_testing_cocos2d_x_3_0

create bodies.json

####How to run?
Clone source code, android copy cocos2d-x 3.0 version files under cocos2d, the project looks like:

open proj.ios_mac/PhysicsDemo.xcodeproj to build for ios or mac

run proj.android/build_native.py to build for android.
I have put prbuilt files under prebuilt编译好的, please checkout and test.

####Basic principle

There is an open source body editor Google Code Archive - Long-term storage for Google Code Project Hosting. , with this free&powerful tool we can get physicsbody polygons of an sprite. Then we import the polygons data into game and let the physics engine handle the rest thing.
All we need is to write an parse function which can load file exported by [box2d-editor] to cocos2d-x physics system.

Here we go.

####1.create new project:

cocos new  -p com.example.phy -l cpp -d ~/Documents PhysicsDemo

####2.open the new project in xcode(I use xcode, chose your favorite IDE)
open ~/Documents/PhysicsDemo/proj.ios_mac/PhysicsDemo.xcodeproj

####3.make an image for test, I have downloaded the cocos2d-x logo from
http://www.cocos2d-x.org/wiki/Logo_Resources_of_Cocos2d-x
name it as 2dx.png, add the image to project.

####4.download box2d-editor
Google Code Archive - Long-term storage for Google Code Project Hosting.

get a jar file, open it.

Node: please use JRE6 to run it.
####5.get the body data

open the editor, create one new project, name bodies.json and save under the project’s Resource.


Don’t forget addbodies.json to project.

Create new body definition, name it 2dx.



Use Auto-trace to get the image edge.


Save bodies.json

Next, we should write some code to import bodies.json.

####6.modify our scene

Edit method HelloWorld::createScene to enable physics feature.

auto scene = Scene::createWithPhysics();
//enable debug draw
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);

Add our sprite to the layer:

	// add "2dx.png"
    sp_2dx = Sprite::create("2dx.png");
    // position the sprite on the center of the screen
    sp_2dx->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    //load
    MyBodyParser::getInstance()->parseJsonFile("bodies.json");
    //bind physicsbody to sprite
    auto _body = MyBodyParser::getInstance()->bodyFormJson(sp_2dx, "2dx");
    if (_body != nullptr) {
        _body->setDynamic(false); //set it static body.
        _body->setCollisionBitmask(0x000000); //don't collision with anybody.
        sp_2dx->setPhysicsBody(_body);
    }
    // add the sprite as a child to this layer
    this->addChild(sp_2dx, 0);

MyBodyParser is the helper class to load bodies.json, use rapidjson.
You can check the detailes in source code, key function is MyBodyParser::bodyFormJson.

Then, add touchListener, this’s simple and nothing interesting to waste words.

####7.check whether our sprite is clicked

In function HelloWorld::nodeUnderTouch:

Node* HelloWorld::nodeUnderTouch(cocos2d::Touch *touch)
{
    Node* node = nullptr;
    //translate the touch to layer coordinate.
    auto location = this->convertTouchToNodeSpace(touch);
	
    //retrive all physics shapes under the touch location though cocos2d-x.
    auto scene = Director::getInstance()->getRunningScene();
    auto arr = scene->getPhysicsWorld()->getShapes(location);
	
    //iterate the shapes, find our sprite!
    for (auto& obj : arr)
    {
        //find it!!!!
        if ( obj->getBody()->getNode() == sp_2dx)
        {
            node = obj->getBody()->getNode();
            break;
        }
    }
    return node;
}

If this function return nullptr, means you havn’t touch inside the Sprite’s physics body.

This’s all the magic, Checkout the source code and read more.

2 Likes

It’s great.

Your tutorial seems very suitable for me to do some practice.

But as a novice, I still confused about something, like I don’t have a mac system only window 7, so I should open the “proj.win32/XXX.sln” instead of "PhysicsDemo/proj.ios_mac/PhysicsDemo.xcodeproj "?

And what do you mean “Don’t forget add bodies.json to project.” ? After I create “bodies.json” in the resource file. I just don’t get the idea. Let me feel like I forget something.

Never mind. I got it and make it work. Thanks again for your nice tutorial.

Thank you for a great tutorial! I got it working perfectly fine on Xcode but for android (using eclipse) I am having some trouble. Could you please take a look at the attachment and let me know whats wrong?

Try to include/Link (Project > Properties > C++ General > Paths and Symbols ) file “document.h” or “json” folder in your project.
Its present in “cocos/external/json/document.h”

Rammehta thank you for replying. I did all you suggested but still nothing. I believe the file document.h is in fact included but I do not know why I am getting the error. I have attached two new images so you can see that the “missing” file is actually there.

Have you tried Linking … ? (Source Loaction > Link )

@xhcnb it doesnt work with Box2D…
its only for Cocos2d-x-V-3.x-PhysicsBody…

Can you make one for Box2D ?

@rammehta I think I did when I followed your steps on your first reply. Here are some images. Also, I noticed that I get the error in “terminal” too when I ./build_native.py the project for android. Please check it out

@jezer can you show me your “Source Location” tab ?
You are getting same error because its the same process…eclipse does it behind the scene while we do it using the terminal…

Also hav you cleaned your project ?

@rammehta Here it is. Also, please note that it works perfectly fine in Xcode.

Thank you so much for your help. I really appreciate it.

okay i just made a project for this issue…
i didnt got any error on “MyBodyParser” class…
I do got an error for “to_string” function(which is a live issue/bug in cocos2dx)…but not for json…even though i havnt included/linked any files yet…
Sorry cant find a solution for you…

@rammehta sorry that I have no knowledge with box2d
I used chipmunk for a long time.

@xhcnb can you have a look at this : http://www.cocos2d-x.org/forums/6/topics/56236

Or if you know someone who uses Box2D and can correct me …

These program and tutorial are absolutely awsome! They helped me alot. Thank you.

I just Completed a Physics Based Bike game using this technique.
The app is on IOS. Chipmunk is hard to port for android…
Game Link:

The Complete Source for above game is on sale on CodeCanyon http://codecanyon.net/item/hill-climb-bike-chipmunk-physics-game-cocos2d-x/9997328/analytics/page-views Cheers!!

@xhcnb After the zoom-in or zoom-out to the Sprite, we can’t touch/click the spite, it always return nullptr .how to solve that problem?