java

Cocos2D Sound in Android Tutorial

Update: This code is using an outdated version of the Cocos2D port. It’ll still work if you use the sample download linked at the end – but it’s using outdated API calls. Unfortunately I don’t have time to update the tutorial to the new release of Cocos2D. Sorry guys 🙁

Cocos2D for Android provides a very rudimentary sound system for playing background music, and simple sound effects. For the vast majority of games, this is plenty. However, if you have more advanced requirements you may need to look into either rolling out your own sound engine or sourcing something more complete elsewhere.

Overview

The Cocos2D ‘SoundEngine’ class provides all of the functionality you’ll need. It groups audio into two main groups: ‘Sound’ and ‘Effect’. Effects are the explosions, jump sounds, and other general effects you have within games. Sound is the background music and is the only audio type that can be paused and resumed. Sound effects should be kept under 5 seconds long, and ideally they should be under 3 seconds.

Android supports a wide range of different audio formats, you can view a complete list here. However, I’ve found that the SoundEngine doesn’t necessarily support all of these formats – so please do test your audio on a real device, preferably a few.

Let’s start coding!

Create a new Android project in your IDE of choice, IntelliJ Idea is my favourite, but Eclipse is very good also. You also need to download the latest source code for cocos2d-android-1, the downloadable jar doesn’t include the SoundEngine code. Include the source into your project – this also has the added advantage that you can poke around the code to see how everything works.

Also you need to add the two audio files in this zip, and put them in the ‘raw’ folder within the ‘resources’ folder. If you don’t have a raw folder, create it.

Before we get into any real coding, we’ll need to create a very rudimentary GUI to allow us to interact with the sound system. We’ll add two buttons to the main layout, one to play some background music and another to play a single sound effect:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <Button
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:text="BG Music Toggle"
        android:onClick="bgMusicClicked" />

    <Button
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:text="Play Sound Effect"
        android:onClick="sfxClicked" />
</LinearLayout>

Using SoundEngine

The SoundEngine offers functionality to pre-load audio, this is critical to ensure sound effects are played instantly. It also means we can use compressed audio formats such as mp3, without slowing down our game. Add the following field to the top of the main activity:

private Context _cocos2dContext;

Next add the following code to the onCreate() method:

_cocos2dContext = this;

// Preload background music
SoundEngine.sharedEngine().preloadSound(_cocos2dContext, R.raw.background_music_aac);

// Preload sound effect
SoundEngine.sharedEngine().preloadEffect(_cocos2dContext, R.raw.pew_pew_lei);

This code sets the context we’ll use for playing audio, and preloads the background audio, and the sound effect. We set the context to the current activity; this is because we’re not actually using Cocos2D in this demo. In your actual games you would use CCDirector.sharedDirector().getActivity() instead of this.
Now, create the event handlers for the two buttons we created:

public void bgMusicClicked(View button)
{
    // Play the background music
    SoundEngine.sharedEngine().playSound(_cocos2dContext, R.raw.background_music_aac, true);
}

public void sfxClicked(View button)
{
    // Play the sound effect
    SoundEngine.sharedEngine().playEffect(_cocos2dContext, R.raw.pew_pew_lei);
}

Give it a test!

It won’t stop playing!

OK I may have let you walk into this one – the background music plays even when the activity is ‘closed’ or otherwise not being used by the user. This is very handy if you’re making an mp3 player, but not so useful when making a game. Fortunately we can fix this problem by hooking into a few events Android offers. As a refresher, here is the Activity Lifecycle in Android:

We need to cater for the activity being obscured by another activity, being hidden, and being closed down. The onResume, onPause, and onDestroy methods should be plenty for our needs. In onResume we’ll need to resume playback of the background sound if it was playing. onPause will pause the sound (if any) ready for resuming. When onDestroy is called we’ll close everything down and free up any applicable resources.

First, add the following fields to the activity class:

private boolean _soundPlaying = false;
private boolean _soundPaused = false;
private boolean _resumeSound = false;

We need to populate these fields as necessary when the user wants to play / pause the background music. Replace the bgMusicClicked method with:

public void bgMusicClicked(View button)
{
    // If we haven't started playing the sound - play it!
    if (!_soundPlaying)
    {
        SoundEngine.sharedEngine().playSound(_cocos2dContext, R.raw.background_music_aac, true);
        _soundPlaying = true;
    }
    else
    {
        // We've loaded the sound, now it's just a case of pausing / resuming
        if (!_soundPaused)
        {
            SoundEngine.sharedEngine().pauseSound();
            _soundPaused = true;
        }
        else
        {
            SoundEngine.sharedEngine().resumeSound();
            _soundPaused = false;
        }
    }
}

Now we only play the sound once, rather than starting fresh each time. We pause / resume the sound depending on whether it’s currently playing or not – your typical toggle pattern.
Now we’ll create the onPause handler:

@Override
public void onPause()
{
    super.onPause();

    // If the sound is loaded and not paused, pause it - but flag that we want it resumed
    if (_soundPlaying && !_soundPaused)
    {
        SoundEngine.sharedEngine().pauseSound();
        _soundPaused = true;
        _resumeSound = true;
    }
    else
        _resumeSound = false; // No sound playing, don't resume
}

In this method we check if the sound is playing, and if it is – whether it’s paused or not. If the sound is playing but it’s not paused, we pause it and request that it’s resumed at the earliest opportunity. If the sound isn’t playing or it’s paused, then we request that the sound isn’t resumed when the activity is.

Now it’s time for the onResume method:

@Override
public void onResume()
{
    super.onResume();

    // Resume playing sound only if it's loaded, paused and we want to resume it
    if (_soundPlaying && _soundPaused && _resumeSound)
    {
        SoundEngine.sharedEngine().resumeSound();
        _soundPaused = false;
    }
}

We check if the sound is playing, it’s paused, and a request is pending to resume the sound. If all of this is true (phew, that’s a lot of checking!) we resume the sound.

At this point we can run the app, and the audio will be handled properly. The user won’t be irritated by music playing when it shouldn’t, and our game can resume seamlessly when the user comes back. However, we haven’t yet implemented the onDestroy method – we never clean everything up.

Cleaning up our mess

Strictly speaking, cleaning up isn’t necessary in this app. Android will automatically reclaim the consumed resources when the app is destroyed. However, it’s always good to clean everything up anyway, if only so you know how to do it when it really is important. Add the following destroy method:

@Override
public void onDestroy()
{
    super.onDestroy();

    // Clean everything up
    SoundEngine.sharedEngine().realesAllSounds();
    SoundEngine.sharedEngine().realesAllEffects();

    // Completely shut down the sound system
    SoundEngine.purgeSharedEngine();
}

First we release all of the preloaded sounds and effects. You can selectively release individual sounds and effects if you need to. If your game is made up of multiple scenes with different audio in each, it’s a very good idea to release the audio you’re not using to save on memory.

Finally we shut down the sound engine itself. This isn’t really necessary, but it’s here for you to see how it can be done. If you have completely different areas in your game, you could feasibly want to have no trace of the SoundEngine between those scenes since the SoundEngine is a singleton by design.

And we’re done!

And that’s it; you now know everything you need to add basic audio to your Android Cocos2D games.

You can download the sample project here.

If you want more Cocos2D, don’t forget to check out the basic tutorial series starting here.

Posted by Dan in Android, Java, Tutorials, 3 comments

Enum in Java with int conversion

If you’ve found this post, chances are you want to convert from an enum to an int, or alternatively from an int to an enum in Java. Well… you can’t. Java has the most robust implementation of the ‘enum pattern’ of any language, in essence enums are a class that can only be instantiated once. This makes them ideal as singletons by the way…

Anyway, since enums are a class, you need to provide the int functionality yourself. For my example, I’m going to be making a ‘difficulty’ enum which should be very familiar with anyone making games for Android. First declare your enum:

public enum Difficulty
{
    EASY(0),
    MEDIUM(1),
    HARD(2);

    /**
     * Value for this difficulty
     */
    public final int Value;

    private Difficulty(int value)
    {
        Value = value;
    }
}

This should be fairly familiar to you if you’ve worked with Java enums for any length of time. Each enum is effectively an instance of itself, so we can pass values to the constructor. We store the value in a final field (enums are by definition immutable – don’t go breaking this without good reason!) for future retrieval. Ideally the value should be accessed by a getter rather than directly, but I think in this case it makes more sense to making it a public field. The user can’t change it, and we don’t need any code to run on access; so I think a getter would just reduce performance and make consumption that little bit more tedious.

Now we need to add the important part, the conversion from int to the enum itself:

// Mapping difficulty to difficulty id
private static final Map<Integer, Difficulty> _map = new HashMap<Integer, Difficulty>();
static
{
    for (Difficulty difficulty : Difficulty.values())
        _map.put(difficulty.Value, difficulty);
}

/**
 * Get difficulty from value
 * @param value Value
 * @return Difficulty
 */
public static Difficulty from(int value)
{
    return _map.get(value);
}

So what are we doing here, exactly? Well we create a map that will be our lookup table, we do this rather than a switch statement to minimise long-term maintenance. If someone added an extra enumeration in the future, they may forget to update the switch statement – and this error won’t be picked up until runtime, and even then it may appear as incorrect behaviour rather than throwing an exception. After we’ve created the map, we populate it automatically by looping through all of the enums and adding them and their value to the map.

So there you have it, the proper pattern for adding int values to an enumeration. The code in full is below:

public enum Difficulty
{
    EASY(0),
    MEDIUM(1),
    HARD(2);

    /**
     * Value for this difficulty
     */
    public final int Value;

    private Difficulty(int value)
    {
        Value = value;
    }

    // Mapping difficulty to difficulty id
    private static final Map<Integer, Difficulty> _map = new HashMap<Integer, Difficulty>();
    static
    {
        for (Difficulty difficulty : Difficulty.values())
            _map.put(difficulty.Value, difficulty);
    }

    /**
     * Get difficulty from value
     * @param value Value
     * @return Difficulty
     */
    public static Difficulty from(int value)
    {
        return _map.get(value);
    }
}

Bonus

OK I can’t leave you with just this without providing a little ‘from here’ info. Switching on an enum in Java isn’t ideal since you can add all sorts of information to the enum to minimise the necessity for a glorified if..elseif statement. For this difficulty example, we could add a ‘multiplier’ field that allows code to automatically modify state values based on the selected difficulty. See below:

public enum Difficulty
{
    EASY(0, 0.5f),
    MEDIUM(1, 1.0f),
    HARD(2, 2.0f);

    /**
     * Value for this difficulty
     */
    public final int Value;

    /**
     * Multiplier for difficulty
     */
    public final float DifficultyMultiplier;

    private Difficulty(int value, float multiplier)
    {
        Value = value;
        DifficultyMultiplier = multiplier;
    }
}

So now we’ve added the multiplier to the difficulty, we could use it like so:

enemy.speed = baseSpeed * difficulty.DifficultyMultiplier;
player.speed = baseSpeed / difficulty.DifficultyMultiplier;

This has the added advantage that you can manipulate the global difficulty in a single central place.

Posted by Dan in Guides, Java, 7 comments

How To Make A Simple Android Game with Cocos2D Part 2 – Rotating Turrets

Update: This code is using an outdated version of the Cocos2D port. It’ll still work if you use the sample download linked at the end – but it’s using outdated API calls. Unfortunately I don’t have time to update the tutorial to the new release of Cocos2D. Sorry guys 🙁

This is the second tutorial in the Simple Android Cocos2D Game Tutorial series, originally written by Ray Wenderlich for the iPhone. This one builds on the first tutorial by replacing the ninja with a rotating turret, and the projectiles with cannon balls.

Getting Set Up

Ideally you’ll have followed the first tutorial, in which case you can continue from where you left of. Failing that you can download the code from the previous tutorial and use that as your base – however, I highly recommend starting from the beginning.

Now download a new player sprite and projectile sprite, put both in the ‘assets’ folder of your project. You’ll need to update your code to use these new sprites, so without further ado let’s get modifying. In the GameLayer constructor, update the player line with the following:

CCSprite player = CCSprite.sprite("Player2.png");

Next update the ccTouchesEnded method, find where you create the projectile sprite and replace with the following:

CCSprite projectile = CCSprite.sprite("Projectile2.png");

Compile and run your project, it should now look like the following screenshot:


You’ve probably noticed it doesn’t look quite right, the turret doesn’t rotate with the projectile direction. Let’s fix that now.

Rotating To Shoot

Before we can rotate the turret, we need to store a reference to the player sprite so we can rotate it elsewhere in the program. In the GameLayer class, add the following field:

protected CCSprite _player;

Next we need to use the new field, update the Constructor instantiation code to the following:

_player = CCSprite.sprite("Player2.png");
_player.setPosition(CGPoint.ccp(_player.getContentSize().width / 2.0f, winSize.height / 2.0f));

addChild(_player);

Rotating the turret with the projectile is easier said than done, we’re forced to use a little maths to work out the angle. For this we’ll use a little Trigonometry, which means remembering back to SOH CAH TOA. In this example we’ll be using the ‘TOA’, or Tangent of an angle is equal to the Opposite over the Adjacent. The following illustration should help:

As you can see from the graphic, the angle we want to rotate to is equal to the arctangent of the Y offset divided by the X offset. Seems easy enough right? Unfortunately there are two caveats you must be aware off before we can go implementing general geometry in our games:

  1. The maths functions in Java use and return radians, not degrees
  2. Cocos2D rotations are clockwise rather than anti-clockwise, which is the opposite to what is expected, as shown in the graphic below:

Fortunately the solutions are very simple. The Java Math class provides a method to convert to and from radians. The second solution is to invert the angle by multiplying by negative 1. So for example 20° x -1 = -20°. This will effectively convert the counter-clockwise rotation to the clockwise rotation Cocos2D expects:

Let’s put what we’ve learned into practice. Add the following code to the ccTouchesEnded code, just before we play the sound effect:

// Determine angle to face
double angleRadians = Math.atan((double)offRealY / (double)offRealX);
double angleDegrees = Math.toDegrees(angleRadians);
double cocosAngle = -1 * angleDegrees;
_player.setRotation((float)cocosAngle);

You may have noticed we’re using doubles rather than floats. According to Google doubles are just as fast as floats with the only trade-off being increased memory consumption. Since there is no float version of Math.atan or Math.toDegrees, it’s better to stick with doubles so we don’t waste CPU cycles converting between double and float repeatedly.

Now compile and run, and you should have a rotating turret!

Rotate Then Shoot

We’ve got a great game here, but it could be better. The turret rotates instantly, which is unlikely given we’re firing cannon balls. It would be much better for immersion and realism if we smoothly rotate the turret to its new direction. This will take a little refactoring.

Add the following field to the GameLayer class:

protected CCSprite _nextProjectile;

Replace the projectile instantiation code in ccTouchesEnded with the following:

_nextProjectile = CCSprite.sprite("Projectile2.png");

Next replace all occurrences of ‘projectile’ with ‘_nextProjectile’ within ccTouchesEnded. While you’re replacing these occurrences, make sure to delete the following lines:

addChild(projectile);
_projectiles.add(projectile);

Update the turret rotation code (also in ccTouchesEnded) with the following:

// Determine angle to face
double angleRadians = Math.atan((double)offRealY / (double)offRealX);
double angleDegrees = Math.toDegrees(angleRadians);
double cocosAngle = -1 * angleDegrees;
double rotationSpeed = 0.5 / Math.PI;
double rotationDuration = Math.abs(angleRadians * rotationSpeed);
_player.runAction(CCSequence.actions(
		CCRotateTo.action((float)rotationDuration, (float)cocosAngle),
		CCCallFunc.action(this, "finishShoot")));

This code will rotate the turret with a rotation speed of half a second (0.5) for half a circle’s worth of rotation (since full circle in radians is 2 PI, a half circle is 1 PI).
Once the rotation is complete, we then call a method called ‘finishShoot’. Since we haven’t created that method, we should create it now:

public void finishShoot()
{
	addChild(_nextProjectile);
	_projectiles.add(_nextProjectile);
}

This method adds the projectile to the game. Since it’s called once the turret has finished rotating we can guarantee that projectiles will only fire once the turret is in position.
That’s it, we’re all finished! Have a play, and enjoy your handiwork.

What’s Next?

You can download the full source code here.

In the future I should be porting Ray’s final part of the series, but in the meantime you could have a look at his tutorial and see if you can port it yourself!

Posted by Dan in Java, Programming, Tutorials, 31 comments

Access outer ‘parent’ class from inner class in Java

Sometimes in Java you’ll create an inner or anonymous class, and need to access the containing class. The code is fairly simple:

ParentClass.this

ParentClass is the class type, this will resolve to the instance that contains the instance of the inner class. You can access methods using this too:

ParentClass.this.myMethod();

Hope this helps!

Posted by Dan in Java, Programming, 0 comments

Customising Eclipse

Eclipse is a very good IDE, I hesitate to say ‘excellent’ because it does have its drawbacks. For example it constantly gets in a muddle with dependencies when you deal with plugins. It’s also developed in Java, so it’s not the fastest IDE in the world. Still, it does offer the most important functionality necessary for fast development of Android applications. Of course being a programmer means I’m notoriously fickle about my development environment – all IDEs should follow Visual Studio and that includes Eclipse. First on the agenda is code hinting, Visual Studio provides this instantly and so should Eclipse!

To bring up the handy dropdowns instantly, go to Window > Preferences. Then go to Java > Editor > Content Assist. Set the Auto activation delay to 0. Of course you’ll need a fast PC, but I’m sure you do.

Next up is the colour scheme, I have my own (which is the correct one) and many other programmers have their own (which are incorrect). Fortunately Eclipse Color Themes have your back. Install their plugin, then download the theme that most closely matches your ideal colour scheme. A minor tweak later and you should get a good match to what you’re used to:


Lastly you’ll probably want to change the code formatting. What do you mean it’s fine as it is? OK OK, I was taught a specific code formatting style and to be frank while it’s not necessarily ‘standard’ in Java, it is very clear. I prefer code to be as clear as possible, giving bugs fewer places to hide. Fortunately Eclipse has the most advanced code formatting customisation I’ve ever seen. First up is the code style:


This lets you set up some basic prefixes / suffixes along with a few other style tweaks. The best part though, is the formatter:

This really lets you customise the code formatting, ensuring all code is formatted in the correct manner – my manner. The customisation is extremely extensive, and it’ll probably take you a while to make it format in exactly the manner you desire. Once you’re happy you can open up any source file and press CTRL + Shift + F to reformat the code, it’s extremely effective.

So that’s it for this little guide. There’s a lot to explore in the Eclipse preferences, and it’s well worth taking the time out to see just what’s available.

Posted by Dan in Guides, 1 comment