Wednesday, July 1, 2015

Cocos2d-x : A 3D game on iOS App Store

There are not many 3D games written in Cocos2d-x.  Here is one:

https://itunes.apple.com/us/app/surfer-girl-run/id1005052774?mt=8

Here is a screenshot from AppStore:




It is a 3D game with a 3D model of a girl in bikini running on the waves and jumping over sharks.  Also interesting to note is that the waves are scrolling endlessly as in an endless 3D runner.   Cocos2d-x can do 3D games such as this endless 3D runner.

Friday, May 29, 2015

Cocos2d-x: Blender to fbx

To export blender to fbx format set the following:


Important to use FBX6.1 ASCII and not any binary format. Otherwise cocos2d-x fbx-conv will produce horizontally compressed model when animating.

Thursday, May 28, 2015

Cocos2d-x: EXEC_BAD_ACCESS Frustum Dirty

If you get this error message:

     EXEC_BAD_ACCESS Frustum Dirty

it means that the 3D model was wrongly added to

GameScene::init()

To solve it, you need to delay the adding of the 3D model until all the other code has executed.
So, do this:

bool GameScene::init()
{
    
    if ( !Layer::init() )
    {
        return false;
    }

    //  Add all your 2D Sprites here

    this->scheduleOnce(schedule_selector(GameScene::Init3DScene), 0.1f);

    return true;
}

void GameScene::Init3DScene(float dt){
    //  Add all your 3D Sprite models here
    auto girl = Sprite3D::create("girl.c3b");

    this->addChild(girl);
}

Tuesday, May 26, 2015

Cocos2d-x: Extracting animation frames from 3D Model

If the 3D model already has animation frames attached to it. There are 2 ways to extract and use the embedded animation frames depending on what information you have.

If you know the individual frames and how it is spanned you can do this:

auto shootAnim = Animation3D::create("Army.c3b");//Read all animation clips
auto shoot = Animate3D::createWithFrames(shootAnim, 40, 79);//Extract frames 40-79
shoot->setSpeed(2);

army->runAction(RepeatForever::create(shoot));


If you know the name of the animation, or if the frames are layered instead of in sequence, you can do this instead:


auto shootAnim = Animation3D::create("Army.c3b","Shoot");//Read only 'Shoot' frames
auto shoot  = Animate3D::create(shootAnim);
shoot->setSpeed(2);
army->runAction(RepeatForever::create(shoot));



Cocos2d-x: Converting fbx to c3b

If you got a 3D model in  fbx format with the textures placed in a separate folder, eg.

soldier.fbx

but the textures are in another subfolder:

Tex/body.png

Then, when doing the conversion using fbx-conv tool, put the subfolder containing the textures in the same folder containing the soldier.fbx, eg.

soldier.fbx
Tex/body.png

Then, do the conversion:

./fbx-conv soldier.fbx

Then copy the soldier.c3b file that is generated to your target Resource folder of your iOS project, and copy the contents of Tex to the target Resource folder of your iOS project. Do not create a Tex subfolder in the Resource folder of your iOS project.  You should have something like this:

soldier.c3b
body.png


Then, after creating the 3D sprite in your game, if you get this error:

GL_CLAMP_TO_EDGE should be used in NPOT textures

it means you are not using power of 2 textures. NPOT means Not Power of Two. To solve, open your textures and resize to power of 2, e.g., 256 x 256, 512 x 512 etc.




Monday, May 25, 2015

Cocos2d-x: 2D Sprites covering 3D Sprites

For certain Android devices e.g., Galaxy Tab 2, the 2D sprites will always be rendered on top of all 3D sprites and will cover 3D sprites. This gives the impression that the 3D sprites are never rendered. To solve this problem,  set the Global Z Order  of the 2D sprites to a high negative number, e.g. -1000. Then add your 3D sprite the usual way. For example, if you have a 2D background sprite and a 3D model of a gun, this how you could do it:

Size visibleSize = Director::getInstance()->getWinSize();
auto background = Sprite::create("Gfx/background.jpg");

background->setGlobalZOrder(-1000);
this->addChild(background);

auto gun = Sprite3D::create("Gfx/m16.c3b");
gun->setPosition3D(Vec3(x,y,z));
this->addChild(gun);