Sunday, April 27, 2014

Add sound to my Cocos2dx game

At some point you will want to add some awesome sounds to your game. The way to do it is very simple but before explaining it let's check a couple concepts:

Background Music: The background music (or BGM for short) are the sounds that are played in the background. Normally this music is played at low volume to keep it out of the focus of the player and avoid obscuring sounds that are more important. BGM is normally long and there is only one at a time (Except maybe at some points where you are going to a new level and there is a fade in and fade out).

Effects: This kind of sound is short and normally represents a game event (Walking, running, jumping, shooting, etc). There are tons of effects in a game and they are played constantly.

Depending on the platform you are going to run your game the format of the sounds should be different according to documentation.

The module of Cocos2dx that handles music is called CocosDenshion. To use it you must include a .h file in your game:

#include "SimpleAudioEngine.h"

You can use CocosDenshion namespace too:

using namespace CocosDenshion;

To use different formats depending on what platform you are in, you can use this comparison:

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    #define EFFECT_FILE        "effect2.ogg"
#elif( CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
    #define EFFECT_FILE        "effect1.raw"
#else
    #define EFFECT_FILE        "effect1.wav"
#endif // CC_PLATFOR_ANDROID

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
    #define MUSIC_FILE        "music.mid"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
    #define MUSIC_FILE        "background.wav"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX )
    #define MUSIC_FILE        "background.ogg"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    #define MUSIC_FILE        "background.caf"
#else
    #define MUSIC_FILE        "background.mp3"
#endif // CC_PLATFOR_WIN32

I took this fragment of code from the test project on Cocos2dx download. As you can see depending on the platform the #define directive is different, pointing to a file with another format. The files in this case should be located at the Resources folder in your project. If you want to have a folder for sounds you can create it and then reference the files with the relative path from the Resources folder (Something like "sounds/myFile.mp3").

In your init() methods you should preload the sounds you are going to use later. You can do that like this:

SimpleAudioEngine::getInstance()->preloadBackgroundMusic( MUSIC_FILE );
SimpleAudioEngine::getInstance()->preloadEffect( EFFECT_FILE );

Now you can play the sounds wherever you want with:

SimpleAudioEngine::getInstance()->playBackgroundMusic(MUSIC_FILE, true);
SimpleAudioEngine::getInstance()->playEffect(EFFECT_FILE, false, pitch, pan, gain);

There are also functions to stop the playback, pause, resume, etc. To control volume use:

SimpleAudioEngine::getInstance()->setEffectsVolume(volume);
SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(volume);

The volume value must be between 0 and 1.

As a last hint remember to use bitrates that are enough for what you want. Use values around 128kbps - 256kbps, not something like 2822kbps (Yeah, happened to me once and took me a while to notice). You can find more information on supported formats for specific platforms in their respective documentations. In the case of android you can check this.

This should be enough to get you started with the music and effects on Cocos2dx. Good luck and rock on!



Thursday, April 17, 2014

Shooting bullets using Box2D

I got to the point where i wanted to shoot a bullet from some position toward my main character (its centroid).

To do this you have to make a little set up in the body definition:

b2BodyDef bulletBodyDef;
bulletBodyDef.type=b2_dynamicBody;
bulletBodyDef.bullet = true;

Additionally to the regular settings you have to set "isBullet" to true. This will tell Box2D to calculate collision continuosly for that body to avoid tunneling (passing through other bodies when moving too fast).

To actually shoot the bullet just apply a linear impulse to it. To calculate the direction in my case just get the vector from bullet to target, normalize it and multiply it by the magnitude of the impulse you are applying.

auto force = 10.0f;
auto hyp = target - bullet->GetPosition();
hyp.Normalize();
bullet->ApplyLinearImpulse(b2Vec2(force*hyp.x, force*hyp.y), bullet->GetWorldCenter(), true);

Once you have this you can shoot as many bodies as you want and if you are lucky enough your main character will have tons of holes :)

Tuesday, April 8, 2014

Using Box2D on Cocos2dx

Box2D is an open source C++ engine for simulating rigid bodies in 2D.

This does not pretend to be an exhaustive tutorial about using Box2D, there is a lot of information about that already. I will try to show you the biggest mistake i made when using it and that took me a while to figure out: using the PTM_RATIO.

There will be 2 worlds: a graphic world and a physics simulation world.
When you are working on the graphic world you will have everything on terms of pixels, so you need to define a "pixel to meter ratio". This ratio will allow the worlds to communicate.

You can define a couple macros on C++ like this:

#define PTM_RATIO 50
#define WORLD_TO_SCREEN(n) ((n) * PTM_RATIO) //macro to convert meters to pixels.
#define SCREEN_TO_WORLD(n) ((n) / PTM_RATIO) //macro to convert pixels to meters.

You have to remember to use those macros when sending info from a world to another.

You can send info to the physics world:

myBodyDef.position = b2Vec2(SCREEN_TO_WORLD(mySprite->getPositionX()), SCREEN_TO_WORLD(mySprite->getPositionY()));

You will need a method to update your graphics world, and inside it you will move your graphics depending on the output of the physics world. Remember to scale them back:


mySprite->setPosition(WORLD_TO_SCREEN(myBody->GetPosition().x), WORLD_TO_SCREEN(myBody->GetPosition().y));

The third option you will have is to set some variables to the physics world. If you have them in pixels you can use a macro, but if you have them directly on MKS system (the system Box2D uses by default) you can send them directly:

world = new b2World(b2Vec2(0.0f, -9.8f)); //Sets a gravity of 9.8m/s^2

Box2D is designed to work efficiently with objects ranging from 0.1m to 10m. You can scale them back in your graphics world as much as you want, but remember to use the values in that range in the physics world.

Have fun using Box2D...it is amazing!!! :)

Sunday, April 6, 2014

Installing cocos2dx 3.0 on Windows



Cocos2d-x is a multi-platform framework for building 2d games, interactive books, demos and other graphical applications. It is based on cocos2d-iphone, but instead of using Objective-C, it uses C++. It works on iOS, Android, Windows Phone, OS X, Windows and Linux.
This guide is based on Cocos2dx-3.0. I am using Windows 7 and plan to release it for android devices first, however i had several issues trying to make it work so i will post the whole process to make it easy for you.

To get started you will need to download a lot of things:
Cocos2d-x: Get the 3.0 version in this case.
Android SDK: There is a full packed release that includes eclipse and the ADT already, making your life easier. You can find it on android developer’s page.
Android NDK: Cocos2d-x uses native C++ code to get into the mobile application, so you need the android native development kit as well. There are some enhanced versions by Crystax. You can use the latest.
Python: You will need this to run a path setting script that comes along with Cocos2d-x. You can find all the stable releases for Windows on the download page.
Apache Ant: Apache Ant is a Java library and command-line tool whose mission is to drive processes described in build files as targets and extension points dependent upon each other. You should get the binary release.
Visual Studio Express 2012: The IDE and the tools for compiling for Windows. Developing it on a desktop OS makes the process faster than compiling and running on the device every time. Express version is free and can be downloaded directly from microsoft’s page.
And thats it!!!

Ok, now that you are done with the downloads lets get to the installing. You can install Python as you would install any other program however the rest of the downloads are compressed packages. Uncompress every package on a folder you can find easily.

Look on the root folder of Cocos2d-x for a python script named setup.py. This script will open a console and will ask you for the paths to the other pieces. It will look like:
-> Adding COCOS2D_CONSOLE_ROOT environment variable… ALREADY ADDED
-> Looking for NDK_ROOT envrironment variable… FOUND
-> Looking for ANDROID_SDK_ROOT envrironment variable… FOUND
-> Looking for ANT_ROOT envrironment variable… FOUND
For NDK_ROOT and ANDROID_SDK_ROOT just add the path where you uncompressed them. For ANT_ROOT add the path to the bin folder inside the root directory of ant.

Once this is done you can already compile the tests of the cocos2d-x framework to your android smartphone. Let’s create a blank project and compile it.
Inside the cocos2d-x directory look for tools/cocos2d-console/bin and then run install.py. This console makes creating projects and compiling for android quite easy. 
To create a game type on the comman prompt: > cocos new “My Game” -l cpp -p org.cocos2d.mygame and press enter. Once this is done go inside the project that was just created and type:

 >cocos compile -p android -m debug

If your command prompt says it cant figure what cocos is, add it to your path (cocos-console/bin) and restart it.
This process will take a while but once it is done you should have a .apk file inside the android folder of the project. Move it to your phone and install it so you can see how the hello world for cocos2d-x looks like!!!
 
Now we get to the part that took me a while: setting up the windows development enviroment.
First install microsoft visual studio express 2012. This may take a while.
Inside the game we created are several folders. Go to the one named proj.win32 and run Game1.sln. This will open visual studio:




You can run the solution and it will start compiling (may take long the first time). To do that click on the arrow “Local Windows Debugger”.
There are some issues with the current setting of the visual studio project so we will fix em now. Go to the project’s properties:



Find the Linker’s section and add the following at Ignore Specific Default Libraries: libcmt.lib; libcmtd.lib; msvcrt.lib.
Next step is important. Cocos2dx has several libs that you can add depending on what you are planning to do. In this example we are going to add Box2D but it is the same for anything else inside the cocos package.

Add libBox2D.lib to additional dependencies



To compile Box2D go to your game's directory and find cocos2d/external/Box2D/proj.win32 and run Box2D.vcxproj. This will open the visual studio project containing Box2D code. Compile it (make sure you are using debug settings).
Back at our game’s properties go to the Linker’s general configuration page and add to Additional Library Directories:
cocos2d-x/build/Debug.win32

With this you should have everything you need to make your project work including physics. 

You can run your apps directly on a device using the cocos-console. Make sure your device is in developer mode. You can find more info about setting it up here.

To run something directly on the device type on the command prompt:
> cocos run -p android

With the basic example it wont have any errors, but if you added extra libs you may need to set it up a little to make it work. Go to your game/proj.android/jni and open Android.mk. That file helps find the dependencies and libraries required. Whenever you add new source files or libraries you need to update this file too.

To add more source files just follow the pattern:

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/HelloWorldScene.cpp \
                   ../../Classes/MyNewSource.cpp

To add new include directories:

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../cocos2d

Notice the second one has a "+="

To add new libraries and load them use:

LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocostudio_static

$(call import-module,Box2D)
$(call import-module,editor-support/cocostudio)

This one is a little tricky but you can solve all the compiling/linking issues using it.

If you find any mistakes, parts you don't understand or something you would like to be explained better feel free to leave a comment :).