Monday, 3 October 2011

Using SharedPreferences to save Data

Using SharedPreferences is probably the easiest way you can persistently store primitive data types (ints, strings etc), and thus it is very useful in games for storing things like high scores, or where the player is in the game.

To use it, first create get a reference to the SharedPreferences with

SharedPreferences preferences = Context.getPreferences(int mode);

If you are calling from your main activity you can just leave out Context, otherwise you need to provide it. mode specifies whether other applications can access your SharedPreferences. 0 means they can't, 1 means they can read them and 2 means they can read and write to them.

If you would like to have more than one SharedPreferences file you can use

Context.getSharedPreferences(String name, int mode);

instead, however this isn't really necessary as you can store as many objects as you want in one SharedPreferences file.

Now that you have the reference, to store data in the file you will need to get a SharedPreferences Editor, and then use that to make the changes


SharedPreferences.Editor editor = preferences.edit();
editor.putInt("exampleName", exampleValue);


main.editor.commit();


As you can see, we first get a reference to the editor, and then use that to put in an int which we called "exampleName" and that has a value of exampleValue. Finally we called commit which actually saves the changes.

To later read values from SharedPreferences is even easier, just use:



exampleInt = preferences.getInt("exampleName", int defaultValue);
exampleString = preferences.getString("exampleStringName", String defaultValue);

In this case, if an object with the name you specified does not exist in the SharedPreferences, then the default value will be returned instead, useful for telling if someone is playing your game for the first time.

That's pretty much all there is to it. You can remove certain values if you want by using Editor.remove(String name) and then calling Editor.commit(). In future posts I'll be looking at other ways of storing data, but for simple things I would always use SharedPreferences.








Questions regarding the post or ideas for an upcoming article? Go ahead and leave a comment

Friday, 30 September 2011

Playing Sounds with SoundPool

Android provides us with two main classes for playing sounds; SoundPool and MediaPlayer. SoundPool is used ideally for playing shorter tracks and MediaPlayer for longer ones, and in this post I'm going to be focusing on using SoundPool.

First of all, to create a new SoundPool object use the constructor

SoundPool soundpoolexample = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);

The first parameter states how many sounds can be played at the same time before some are stopped even if they aren't finished. The second is the stream type, which you can just leave as STREAM_MUSIC for games, and the final number is the sample-rate converter quality, although apparently this doesn't actually do anything yet so just leave it at 0. The most important one of these is obviously how many concurrent sounds you want to be able to play.

Next you have to load all of the different sounds that you are going to use. To do this use the line

int soundID = soundPool.load(context, R.raw.example, 1);

In this example I have a track in my res/raw/ directory called example. Note that the file extension is dropped. The context is simply the activity context, which if you're calling this line from your main activity you can probably just put this to get the context. The final 1 is the priority, although again apparently this does nothing yet but a 1 should be used for future compatibility.

You will have no doubt noticed that SoundPool.load will return something since I have made an int equal the return value. What is returned is an int that is later used as a reference to that specific sound and used to play it. (Also note that it might take a few seconds after the call to load() for the sound to be ready, so if you try and play it straight away and it doesn't work that might be the reason why.)

soundPool.play(soundID, float leftVolume, float rightVolume, int priority, int loop, float rate);

As you can see we need to use the int that was returned to play the sound, and NOT the resourceID of the sound (i.e. R.raw.example). The two volume 's are floats from 0-1 that represent the left and right speaker volumes respectively. priority tells the SoundPool which sound to stop playing first if there are too many being played at the same time. loop is obviously how many times to loop, with -1 meaning keep looping and 0 don't loop. Finally, rate is how fast it should be played, with 1 .0 being normal frequency and 2 being twice as fast etc..

That's basically all there is to it. Other things to note are that SoundPool.play returns a StreamID that can later be used as SoundPool.pause(StreamID) to pause that sound if you wish, and SoundPool.resume(StreamID) to resume it.

Below is a sample MusicPlayer class that I wrote which you're free to use to simplify playing short sound tracks. It uses a HashMap to store the resource IDs of the sounds and the sound ID returned from SoundPool.load() as key/value pairs so that you can later simply call the play method with the sound's resource ID to play it. It is a static class so you don't need to create an instance of it and can play 4 sounds concurrently but you can easily change that if you wish. An example of using it would be:

MusicPlayer.initSounds(context,R.raw.example1,R.raw.example2,R.raw.example3);


A few seconds later so it has time to load

MusicPlayer.play(R.raw.example2);




import java.util.HashMap;
import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;



/**
 * @author tixopi
 * @initSounds
 *             Call first with the context from your main activity
 *             and a comma separated list of the resource IDs of the tracks you want to be able to play
 * @play
 *       Call with the resource ID of the track as a parameter to play it
 * @playBackground
 *                 Use to set the background track
 * @mute-and-unMute
 *                  Self-explanatory
 */




public class MusicPlayer {


	static SoundPool					soundPool;
	static boolean						muted			= false;
	static HashMap<Integer, Integer>	soundPoolMap	= new HashMap<Integer, Integer>();

	static float						volume			= (float) 0.6;



	public static void initSounds(Context context, int... trackIDs) {


		int length = trackIDs.length;


		soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);

		for (int i = 0; i < length; i++) {


			//Uses the track resource id as the hashmap key, which allows the track to later be played
			//The value is the sound id returned by load which is what is used to play
			//This way the two are linked to together and the sound can be played knowing only its resource id

			soundPoolMap.put(trackIDs[i], soundPool.load(context, trackIDs[i], 1));


		}
	}



	public static void play(int resID) {

		if (!muted) {

			soundPool.play(soundPoolMap.get(resID), volume, volume, 1, 0, 1f);


		}
	}




	public static void mute() {

		muted = true;

	}



	public static void unMute() {

		muted = false;

	}



}


Questions regarding the post or ideas for an upcoming article? Go ahead and leave a comment

Wednesday, 28 September 2011

Circle Collision Detection


One of the most common things you need to check in a game is if two objects are colliding. Normally, for irregular objects this can get quite complicated if you want a pixel perfect collision, and you often just simplify to seeing if the bounding rectangles overlap. However if you have two circles, there is a far simpler and more elegant way of checking if they overlap.

If you add together the radii of the circles, and then work out the distance between the circles, if the sum of the radii is greater than the distance between them, then the two circles must be overlapping each other, i.e. we have a collision.

So let’s look how to do this
We can work out the distance between the circles using a little bit of Pythagoras. Remember that

c^2 = a^2 + b^2

In this case we can take a as being the horizontal distance between the two circles (i.e. the distance on the x axis) and b as being the vertical distance between the two (i.e. the distance on the y axis).



To work out the x distance we simply work out the difference of the two x coordinates, and the same for the y distance. Then all we have to do is sum the two radii and check if that is greater than the distance.

In terms of efficiency, performing a square root takes longer than a multiplication, so it is faster to square both sides than having to perform a square root to get the actual distance. Below is a sample class that performs this collision check and returns true if there is a collision, false if there isn't. The parameters it takes are self explanatory.

 public static boolean collisionCheck(int circle1X, int circle1Y, int circle2X, int circle2Y, int circle1Radius, int circle2Radius) {


  final int a = circle1Radius + circle2Radius;
  final int dx = circle1X - circle2X;
  final int dy = circle1Y - circle2Y;


  if (a * a > (dx * dx + dy * dy)) {
   return true;
  }

  return false;


 }




Questions regarding the post or ideas for an upcoming article? Go ahead and leave a comment

Tuesday, 27 September 2011

Drawing with SurfaceView


Possibly the most important thing in a game is what’s on the screen, and in this post I’ll be explaining how you can put stuff there. We’re going to be using a SurfaceView, which is the method employed in the lunar lander example

So first of all create a new Android project in eclipse and this code should come up if you open the newly created activity


public class TestActivity extends Activity {


	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}
}

Because we're using our own custom SurfaceView, we're going to want to set that as the content view rather than the default layout we're given. So replace the line

setContentView(R.layout.main);


with


DrawClass draw = new DrawClass();
setContentView(draw);


Now obviously we haven't actually made our custom SurfaceView class yet so let's do that now. We’re going to create a new class that extends SurfaceView, which will be where we do all of our drawing. So go ahead and do that and call it DrawClass (or any other name you wish) 


Now to draw on the surfaceView we’re going to need a canvas, and to get that we need the SurfaceHolder of the SurfaceView. It would also be useful to know when the surface has been created, so add the line implements SurfaceHolder.Callback after extends SurfaceView, which will allow us to use some methods that are called when certain things happen

You should now have a new class that looks like this



public class DrawClass extends SurfaceView implements SurfaceHolder.Callback {

	public DrawClass(Context context) {

		super(context);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {

		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {

		// TODO Auto-generated method stub
		
	}

}

We can get a reference to the SurfaceHolder by using getHolder, and we can then use this to give us a canvas to draw on

Now, being that we’re trying to draw stuff for games, everything is obviously going to be happening in real time, so we’re going to need a thread to constantly keep redrawing everything. I find it helps to keep everything organised if we simply implement the runnable interface in our surfaceView class, which basically allows us to use it as its own thread

So after you've put implements surfaceHolder.callBack, add a comma and then put runnable as well, which means that we can then implement a run method and create a new thread to run it

And now we need to obviously implement the run method


	@Override
	public void run() {

		Canvas c;
		while (true) {
			c = null;
			try {
				c = surface.lockCanvas(null);
				synchronized (surface) {
					onDraw(c);

				}
			} finally {
				// do this in a finally so that if an exception is thrown
				// during the above, we don't leave the Surface in an
				// inconsistent state
				if (c != null) {
					surface.unlockCanvasAndPost(c);
				}
			}
		}

	}


In this, we have a while loop that will always be running so we are always updating the screen. We call lockCanvas which returns a canvas for us to draw on and locks it, we then call onDraw (where we'll be doing all the actual drawing) and pass the canvas as a parameter, and then finally we unlock the canvas which will show it on the screen after the drawing is finished.

To start the thread running, add these lines to the onSurfaceCreated method, which is called when the surface has been created and so the thread will only start running after the surface is ready to draw.

	@Override
	public void surfaceCreated(SurfaceHolder holder) {

		
		Thread drawThread = new Thread(this);
		drawThread.start();

	}


Now finally we’ve got everything set up, so all we need to do is decide what to draw. For this tutorial I’m simply going to draw a circle that moves across the screen so you can see that it is repeatedly being called. To do this, simply implement the onDraw() method and add whatever you want.

	int	x	= 10;



	@Override
	public void onDraw(Canvas canvas) {

		canvas.drawColor(Color.BLACK);

		Paint p = new Paint();
		p.setColor(Color.RED);
		canvas.drawCircle(x, 10, 10, p);
		x += 1;
	}


Every time we draw x is incremented by one, so the ball will slowly move across the screen. As you can see I also put canvas.drawColor which clears the screen every time it's redrawn, otherwise everything would keep being drawn on top of each other and we'd end up with a red streak across the screen. You can see what I mean by commenting this line out.

And now using this setup, you can draw whatever you want as long as you put it in the onDraw() method

Also note that declaring a new Paint object every time you draw is extremely inefficient, it would be better to simply declare it once when this new class is created. I just did it like this for simplicity's sake.


Questions regarding the post or ideas for an upcoming article? Go ahead and leave a comment