Step by Step Guide on How to build your first Slider Puzzle game in Cocos2d for Android – Part 1

Screenshot_2013-09-14-13-14-58

In the previous post about setting up cocos2d for android game development, I showed you how to import the cocos2d project into Eclipse and run the sample code included to give an idea of the capabilities/affordances of the Cocos2d game engine.

Before you proceed , would help if you understood The Anatomy of a Cocos2D for Android Game , and got some inkling on how to go about becoming a better programmer .

In this post we will be going through a step by step guide on how to develop a simple game from scratch – a Number slider puzzle game. The game logic is simple. We will offer players a scattered 3X3 matrix slider puzzle and their task is to correctly rearrange the numbers  in order of increasing magnitude. We also keep track of the amount of time used to complete task. Lets get started!

Note : I know a few people have less time to go through the entire tutorial or preferentially learn by doing … so  here a link to the github repository that contains the complete code from this tutorial series . Feel free to download, use, modify and even contribute updates . Good luck and Godspeed in your Cocos2D for android journey!

Create a New Project and Import the Cocos2D

  1. You must have downloaded the Cocos2D library already to your machine … if not please checkout the previous post on how to dowload Cocos2D and run the sample applications that come with it!
  2. Create a new Android Application Project – PuzzleGameUntitled-5You may click Next, Next Button. On the create Activity Prompt, select Blank Activity and finish.Untitled-5
  3. There are two ways to import the Cocos2d libraries into your PuzzleGame project.
    1. First, you may simply copy the cocos2d-android.jar file to the libs folder within your project. If this folder does not exist, you may create it.
      You can find the cocos2d-android.jar file in the downloaded cocos2d source (cocos2d-master.zip\cocos2d-master\cocos2d-android\libs) from github  .Next, you must notify the compiler about the existence of this library by adding it to the build path. To do thatRight Click on your project > Properties > Resource > Java Build Path > Libraries > Add JARS ..Navigate to the libs folder in your project and select cocos2d-android.jarUntitled-5
    2. You can copy the entire src folder in the cocos2d-master zip file (cocos2d-master.zip\cocos2d-master\cocos2d-android\src) into your own PuzzleGame project src folder.
      We will be using Method A above  for this tutorial because there are less files to manage. However, as you develop more complex projects, you might want to work directly with the main cocos2d source files.
  4. Next, copy the fps_images.png file to your PuzzleGame project assets folder. You can find the file in the cocos2d-master zip file you downloaded.
    cocos2d-master\cocos2d-android\assets

See Also : How to Create a Sliding Menu in Cocos2d for Android

Lets Start Writing the Main Code

We begin by modifying the default activity (MainActivity.java) . At the top of your class, add the following field:

protected CCGLSurfaceView _glSurfaceView;

Eclipse might flag this as an error – could not resolve type. This is because the type “CCGLSurfaceView” has not been imported. You can fix this by pressing Ctrl + Shift + O . Or hovering over the error and clicking “import CCGLSurfaceView”. You may use this to solve other similar errors. Next, replace the OnCreate Method with the following

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
_glSurfaceView = new CCGLSurfaceView(this);
setContentView(_glSurfaceView);
}

Above snippet sets up the OpenGL surface for Cocos2D , sets some flags to ensure fullscreen and attaches the OpenGL surface to the current application screen. Next, we further extend the onCreate as follows :


@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
_glSurfaceView = new CCGLSurfaceView(this);
setContentView(_glSurfaceView);

//
CCDirector director = CCDirector.sharedDirector();
 director.attachInView(_glSurfaceView);
 director.setDeviceOrientation(CCDirector.kCCDeviceOrientationLandscapeLeft); // set orientation
 CCDirector.sharedDirector().setDisplayFPS(true);  //display fps
CCDirector.sharedDirector().setAnimationInterval(1.0f / 60.0f);  //set frame rate

}

The added snippet tells Cocos2D which surface to render, set the screen orientation to landscape left, to display the current FPS rate and set animation interval to 60fps. The actual framerate achieved depends on the capabilities of the device. Next, add the following snippets to instruct Cocos2D on what to do when the device changes state – e.g when the application is terminated or paused or switched.

 @Override
public void onPause()
{
super.onPause();
CCDirector.sharedDirector().pause();
}

@Override
public void onResume()
{
super.onResume();
CCDirector.sharedDirector().resume();
}

@Override
public void onStop()
{
super.onStop();
CCDirector.sharedDirector().end();
}

Cocos2d has now been setup! You should be able to run the application now, although it will be empty. Next, we will work on adding a game layer, game logic and adding the graphics/tiles ! Excited ? Lets go!

Create a New Game Layer

Create a new Class . File > New >  Class
Name your class GameLayer and Uncheck the public static void main(String[] args) option and Click OK. Eclipse will generate a some class code for you with a default constructor. Now, your class should extend the Cocos2D Layer class, so you add the extends CCLayer keyword to your class.

Next add the following static method

public static CCScene scene()
{
CCScene scene = CCScene.node();
CCLayer layer = new GameLayer();
scene.addChild(layer);
return scene;
}

The method above creates a   scene on which we can add our items. Your GameLayer class should now look like this . (Remember to use Ctrl + Shift + O) to solve type resolution errors.

package com.example.puzzlegame;

import org.cocos2d.layers.CCLayer;
import org.cocos2d.layers.CCScene;

public class GameLayer extends CCLayer {

	public GameLayer () {
		// TODO Auto-generated constructor stub
	}

	public static CCScene scene()
	{
		CCScene scene = CCScene.node();
		CCLayer layer = new GameLayer();
		scene.addChild(layer);
		return scene;
	}
}

Positioning in Cocos2D

Game development does require some simple but very interesting mathematics especially when figuring out the best way to position and scale you images to look good on device screens. Cocos2D uses an inverted cordinate positioning system where each point on the screen is described by its X and Y plane (x,y) distance from the bottom left of the screen . The bottom left is described as cordinate (0,0) and the x value increases as you move right and y value increases as you move up the screen.

Untitled-1

For this game tutorial we will be using the following image assets which I have designed .
background.jpg , tile.png , tile2.png, cancel.png (cancel.png originally sourced from iconfinder.com) . You may download them now, and add them to the assets folder of your puzzleGame project. We will be using a few other image assets which will be introduced later!

Adding a Sprite and Text Labels .

Sprites are pieces of 2D  graphics (images) that can be animated on screen. Typically the images we will be working with on this slider puzzle game will be implemented using Cocos2D sprite class.  First, lets add our game background and a sample tile.

Add the following field to your GameLayer class to store the device screenSize

private static CGSize screenSize;

Add the following code to your default constructor.

screenSize = CCDirector.sharedDirector().winSize();
generalscalefactor  = CCDirector.sharedDirector().winSize().height / 500 ;
CCSprite background = CCSprite.sprite("background.jpg");
background.setScale(screenSize.width / background.getContentSize().width);
background.setAnchorPoint(CGPoint.ccp(0f,1f)) ;
background.setPosition(CGPoint.ccp(0, screenSize.height));
addChild(background,-5);

Scaling in Cocos2D

While adding images and positioning objects you must also pay  attention to scaling issues that arise when your game is run on devices of different resolutions. For example, our background image from the previous tutorial has a dimension of 1024 by 600. On an android device with a resolution different (smaller or larger than 1024 by 600), the image would look quite different – either too large or too small. To avoid this, we usually calculate some appropriate scale factor – a floating point value which we use to scale (expand or shrink) our image to fit the screen . In our code above we have calculated a general scale factor

generalscalefactor  = CCDirector.sharedDirector().winSize().height / 500 ; 

We will use this scale factor when scaling all our sprites added to the canvas to ensure it scales properly on devices of different screensize. We also set the scale factor value of the background sprite to a mathematical calculation that ensures it is scaled such that its width becomes the width of the device. Next we set our anchorpoint to the topleft (0,1) and also use similar positioning to set the sprites position to the topleft (0, screenSize.height) . We then add the background sprite to the scene using a z-index  of -5. This means every other sprite added with a value larger than -5 will be on “top” of the background!

Soo .. just before we run this and admire the pretty work thus far, you should inform Cocos2D to run the new GameLayer class. Go back to MainActivity.java  and add the following to the end of the onCreate Method

 CCScene scene = GameLayer.scene(); //
CCDirector.sharedDirector().runWithScene(scene); 

Now run! You should see your background, and your fps dynamic rates showing on screen. Congratulations on coming this far! Lets add a label to the top that shows game status to the user using the Cocos2d CCBitmapFontAtlas class. The CCBitmapFontAtlas class takes two arguments – the string you want to display and the font you want to use. You can create some exciting fonts for your game using the BMFont Generator tool by AngelCode . For this tutorial you may download the following two files and add to your assets folder bionic.fnt and  bionic_0.png .  Add the following to GameLayer.java at the bottom of the GameLayer default constructor.

// Add Game Status Label
CCBitmapFontAtlas statusLabel = CCBitmapFontAtlas.bitmapFontAtlas ("Tap Tiles to Begin", "bionic.fnt");
statusLabel.setScale(1.3f* generalscalefactor); //scaled
statusLabel.setAnchorPoint(CGPoint.ccp(0,1));
statusLabel.setPosition( CGPoint.ccp( 25* generalscalefactor , screenSize.height - 10* generalscalefactor));
addChild(statusLabel,-2, STATUS_LABEL_TAG); 

Of course, Eclipse will complain (cannot be resolved to a variable.). You create this variable easily in eclipse by simply hovering over the error and clicking “Create constant STATUS_LABEL_TAG . Don’t forget to assign it a unique value.  This constant is used as a tag for the sprite. We can use this tag value to reference it in the future.

private static final int STATUS_LABEL_TAG = 20;

Similarly, we add two more labels to display time and also to display number of moves.

// Add Timer Label to track time
CCBitmapFontAtlas timerLabel = CCBitmapFontAtlas.bitmapFontAtlas ("00:00", "bionic.fnt");
timerLabel.setScale(1.5f* generalscalefactor);
timerLabel.setAnchorPoint(1f,1f);
timerLabel.setColor(ccColor3B.ccc3(50, 205, 50));
timerLabel.setPosition(CGPoint.ccp(screenSize.width - 25* generalscalefactor , screenSize.height - 10* generalscalefactor ));
addChild(timerLabel,-2,TIMER_LABEL_TAG);

// Add Moves Label to track number of moves
CCBitmapFontAtlas movesLabel = CCBitmapFontAtlas.bitmapFontAtlas ("Moves : 000", "bionic.fnt");
movesLabel.setScale(0.8f* generalscalefactor);
movesLabel.setAnchorPoint(1f,0f);
movesLabel.setColor(ccColor3B.ccc3(50, 205, 50));
movesLabel.setPosition(CGPoint.ccp(screenSize.width - 25* generalscalefactor, timerLabel.getPosition().y - timerLabel.getContentSize().height* generalscalefactor - 10* generalscalefactor - timerLabel.getContentSize().height* generalscalefactor));
addChild(movesLabel,-2,MOVES_LABEL_TAG);

We have used the ..setColor(ccColor3B.ccc3(50, 205, 50)); method to change the color of the label. The value (50, 205, 50) is RGB equivalent of any color and you can get that from Colorpicker.com .

Now .. we have the timer label .. lets write some code to make it start ticking! Cocos2D provides a schedule function to run repeated activities and takes an argument for the repeat interval.  Let create the method which the schedule function will run. Create it outside your default constructor but inside the GameLayer class . The schedule function will run this method every one second.

public void updateTimeLabel(float dt) {

thetime += 1;
String string = CCFormatter.format("%02d:%02d", (int)(thetime /60) , (int)thetime % 60 );
CCBitmapFontAtlas timerLabel = (CCBitmapFontAtlas) getChildByTag(TIMER_LABEL_TAG) ;
timerLabel.setString(string);

}

In the code above we first increment the time value by 1, then we format its value to be displayed in time format (90 seconds becomes 1:30).  Remember the tag we set on the timerLabel, we then use this tag to reference the label and set its string content.

Ofcourse, remember to create an integer field variable (thetime) in your class to save the time digits .

private static int thetime = 0 ;

Now we add the following code to the bottom of the default constructor to run the schedule function

schedule("updateTimeLabel", 1.0f);

At this point .. your game should be coming on nicely .. You should see your timer counting .. ticking away gently! Congratulations.

Screenshot_2013-09-14-13-14-58

Whats Next ?

Next .. Part 2 of this tutorial .. game logic and adding tiles .. coming soon!!! Let me know how the first part went in the comment section!
Update : View Part 2 of the Tutorial Here



style=”display:inline-block;width:728px;height:90px”
data-ad-client=”ca-pub-5103730469785618″
data-ad-slot=”7988038888″>

About Vykthur

Mobile and Web App Developer and Researcher. Passionate about learning, teaching, and recently - writing.
This entry was posted in Android Tutorials, Cocos2d, Cocos2D for android, Developer Tips, Programming, Tutorials and tagged , , , , , , . Bookmark the permalink.
  • Pingback: Setting up Cocos2D for Android, in Eclipse | Denvycom()

  • Matt

    Hi, looking forward to part 2! I’m just learning Java/Cocas2D and this seems like a good learning example. I’m struggling to work out how to make objects slide around relative to touch input. Using ccTouchesMoved I know how to use CGPoint touchLocation = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(e.getX(), e.getY())); then
    object.setPosition(touchLocation); but this is too basic as it just jumps the object to the touch position.

    • Vykthur

      Hi Matt!!

      Thanks for stopping by! I’v been busy and cooped up with school work …
      If I understand your point, you want your objects to gently slide to where your touch event occurs . You can achieve this by using the cocos2D CCMOveTo class . Instead of using object.setPosition(touchLocation), you can use .

      object.runAction(CCMoveTo.action(0.2f, touchLocation)) ;

      This does something similar but does it in o.2 seconds giving the sliding/animation feeling instead of “jumping” . This is what I use in the second part of this tutorial to slide the tiles (coming soon).

      One more thing though. In the touch event processing .. do you want your object to slide around when a single touch is made (more like a tap)? Or you would like it to slide around as the user touches and slides his finger across the screen (more like dragging) ?
      If you are responding to tap event .. the you should place the code above in the ccTouchesEnded method instead of the ccTouchesMoved. If you would like a drag, then leave it at ccTouchesMoved (you might need to write extra code here to achieve a more decent slide effect …. such as ) .

      Let me know if this helped!

      V.

      • Matt

        Hi Vykthur, thanks for the detailed reply which makes sense but not quite what I need to do (my fault for the poor post above).

        I would like to make a large object slide along a X or Y position based on touch movement – think scrolling a page or a volume slider. So when ccTouchesMoved is used, the object will move, for example, left if the user drags to the left but not move too the touch location, just move in relation to the movement.

        I guess I need to record the touch start location (in ccTouchesBegan), then the current touch position (in ccTouchesMove) and then tell the object to move to object.position.x – (touchStartLoction.x – touchPosition.x). Having tried this, the object moves erratically around the screen but I have just read that touch locations and screen positions are different, and that convertToGL might be required (?).

        Thanks for your help, especially as you’re so busy!
        M.

        • Vykthur

          Hi Matt,

          I think I understand you much better now. 🙂
          Yeap, you are right. SetPosition works for your particular use case.

          Here’s what your ccTouchesMoved function could look like …

          @Override

          public boolean ccTouchesMoved (MotionEvent event)

          {

          // Get the position our touch has just moved to.

          CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(event.getX(), event.getY()));

          //Use the tag to get a reference to the Background image or object you want to slide around

          CCSprite background = (CCSprite)getChildByTag(BACKGROUND_SPRITE_TAG ) ;

          //Set its position to the current position plus the distance moved. We get the distance moved by c

          //calculating the difference between the last known position and position it has moved to

          background.setPosition(CGPoint.ccp(background.getPosition().x + (location.x – positionholder), background.getPosition().y));

          //We set the current move position as the last known position of our image.

          positionholder = location.x ;

          return true;

          }

          I have created a small tutorial on the above and attached the sample code.
          http://denvycom.com/blog/how-to-slide-a-sprite-around-based-on-touchdrag-input-in-cocos2d-for-android/

          Hope it helps this time.

          V.

          • Matt

            Brilliant! This is perfect and you’ve also introduced a new concept to me – Tags. You clearly know your stuff.
            M.

    • Vykthur

      Hi Matt

      The next part of the tutorial is out .. there should be some more things to learn on positioning, handling touch response etc .

      http://denvycom.com/blog/step-by-step-guide-on-how-to-build-your-first-slider-puzzle-game-in-cocos2d-for-android-part-2/

      Feel free to also share the apps you have made!

      V.

      • Matt

        Hi Vykthur, brilliant, I’ll check it out. I’ve not had much time to work on my main app but I’ve been messing about with blending modes, audio, drawing basic shapes, and creating fire/smoke effects – there’s so much to learn!

        • Vykthur

          Audio …. I should write a tutorial about audio … Was a bit of a headache for me getting audio to work well in Cocos2D for Android.
          Fire and Smoke effects … you can find some sample code in the examples provided.

  • Pingback: How to Slide a Sprite around based on touch/drag input in Cocos2D for Android | Denvycom()

  • Abhinaw Kumar

    error in

    • Vykthur

      Hello Abhi,

      Thanks for pointing that out. Its an error that occurs sometimes when I paste code on the webpage while writing the post. its meant to be
      CCSprite background = CCSprite.sprite(“background.jpg”);

      " is the html representation of ” .

      I have now corrected it, that should fix the error.

      Victor.

  • Abhinaw Kumar

    Thank you sir,
    But I have another problem that
    When I run your project then it run successfully, but whenever I copy your files to a new project then it compiled, but there is run time error!!

    and another problem occurring when I follow your above steps and I get no background image. and whatever I am doing in GameLayer class is not affecting MainActivity

    • Vykthur

      Can you please paste the exact runtime error you encountered?
      Regarding the background image, are you sure you have downloaded and placed it in the appropriate folder ? It should be within the assets folder in your project.

      Regards,
      Victor.

  • Abhinaw Kumar

    Actually the error is

    • sanchit

      i am having this same error, what is the solution?

    • Vykthur

      Hi to fix this error, you can go tot he assets/fps_image.png directory in your project folder and delete the fps_images.png file there.
      The above error suggests this file exists both in the assets folder and also inside your cocos2d-android.jar library.

      I hope this helps you Abhinaw (and Sanchit below)

      Regards,

      V

  • Matt

    I’ve been experiencing strange rendering when switching applications but I’ve finally found out the following line is needed in the onStart() method: _glSurfaceView.setPreserveEGLContextOnPause(true);
    Apparently, by default, the glSurface gets trashed when switching apps (or locking the phone). With this in place, the GUI renders correctly. 🙂

    • Vykthur

      Interesting … I never noticed this issue.
      Now I’ll be able to recognise it (and solve it) whenever I see such.
      thanks for sharing Matt!

      V.

      • Matt

        Actually, this glSurfaceView code doesn’t completely solve the problem. It fixes glitches when switching apps but if I lock/unlock my phone with the app running, it still gets screwed up. Also it’s API11 code (I guess as pre-Andriod 4.0 didn’t have the same some of app switching). You’ll probably know more about this than me, but apparently by default glSurfaceView gets scraped when the app is pause and then needs rebuilding on resume and this is where things start to get screwed.

        • Vykthur

          Hi Matt,

          Great to see you are finding solutions and contributing! Im sure many others will find this very helpful!
          One more thing about lock screen and app switching (both trigger the onPause event), its probably a good idea to write code to save your game’s state within the onPause() method of your main activity. As your game grows to have multiple scenes, you will want to keep track of which scene (and its parameters) was in focus before the onPause event and also release any resources you might be holding on to …
          You can then use the saved data to recreate the scene your app is resumed within the onResume() method

          V.

  • Matt

    Hi Vykthur, I’m pulling my hair out trying to get CCBitmapFontAtlas fonts to render correctly and I’m not sure what I’m doing wrong. I’ve tried creating the bitmap fonts in a variety of tools (e.g. Shoebox, BMfonts, Littera, etc) and they look OK when viewed in Photoshop but, when rendered within the app, about 1px is cropped off around the edges. Large characters (e.g. ‘G’) appear with a straight line across the top and left side, which gives an odd look. I’ve tried changing typefaces but the same problem occurs. It’s as if font bitmap is slightly bigger than the boundary box. Any ideas? Thanks.

  • Mircea

    i get error: unfortunately app stopped… what about it?

    • Vykthur

      At what point did you get this error ?
      Can you look paste the error you get on logcat ? This way, you can get some idea on the exact cause of the problem.
      To view the error, open the LogCat view and inspect the output while running your code.
      To open logCat .. Window->Show View->Other…->Android->LogCat

      On the other hand, you can simple download the FULL working source code from Github here https://github.com/chuvidi2003/PuzzleGame

      Regards,
      V.

  • Turk

    I am trying to make this puzzle game from the start..Thanks i am able to run your versions..
    Well i believe i did something wrong but couldnt solve it… It doesnt recognize
    protected CCGLSurfaceView _glSurfaceView; even if i add all src folder or jar file..i showed the jar file inside lib as path but it gives syntax error because doesnt recognize
    CCGLSurfaceView i guess.Why do you think it happens :d ?

  • Turk

    I tried your 1st part puzzle and i guess there appear a problem about adding the images according to current screen…I mean i tried your codes that you tell above i couldnt see anything after i tried your upgraded version i saw the corner of the background..I believe some calculations are made to found according screen size but i use 480×800 emulator and couldn see it ..why do you think… :S i now that emulator not working so good but it seems didnt work for me somehow

    • Vykthur

      Hi Turk,

      Like you mentioned, its likely a positioning problem.
      Theres something called anchor points in Cocos2D .. you can learn a little more about them here
      http://www.koboldtouch.com/display/IDCAR/How+The+Anchor+Point+Works+And+What+To+Use+It+For
      (the article able is written for objective C language but the idea can be translated to java)
      I believe you might not be setting the proper anchor point or proper position. You can confirm that.
      Were there errors in the code downloaded from Github ?

      Regards,
      V

      • Turk

        No its perfectly working..I will look that positioning calculations and try to see how the one from github works.Thanks for the link :d

      • Turk

        Well your code of finding the center is working :d I guess i made some mistake in Main activity but still couldnt see it maybe i couldnt see some code and thought i wrote it.

  • Matt

    Hi again,
    I’d like to make use of ‘CCSkewTo’ but I notice CCSkewTo (and CCSkewBy) is not included in the pre-compiled cocos2d_android.jar file. It is however in the source code so I’ve recompiled cocos2d_android.jar and added it to my project (replacing the old jar file).
    I can now write ‘CCSkewTo’ actions but when I try to run the app I get the error: “java.lang.NoClassDefFoundError: org.cocos2d.opengl.CCGLSurfaceView”.
    Any ideas why? To me this looks like it’s saying CCGLSurfaveView is missing but it’s in the jar file.
    Cheers,
    Matt

    • Vykthur

      Hi Matt!

      Its interesting that you recompiled the Cocos2d_android.jar. You are right, your error suggests the CCGLSurfaceView was not properly included in your compiled cocos2d_android.jar.

      However, I usually go about this issue in a different manner. I just include the entire cocos2d java source files (excluding the tests and other files I dont need). This way I can make deep customizations (such as even modify the skew behaviour etc) of the code for better performance. From my tests, including the source files actually results in even lighter final apk sizes for my games and I havent thought up any other significant drawback of this method. So far, I have re-written a couple of the standard cocos2d behaviours when I wasnt satisfied with the original behaviour (particularly horizontal scrollview for menus) and it was an exciting learning experience . Cocos2D for android has really been maintained by a single guy (Zhou Weikuan .. the guy hosting the current version on github) and I think dealing with the source files directly would be a great opportunity for us to contribute great code in improving the java library.

      Kindly try this out and let me know how it goes.

      Great job by the way!

      Regards,

      V .

      • Matt

        Hi V, this started to get confusing as I think my project had too many different versions of Cocos2D. When I get time, I’ll probably create a fresh new project and run this entity off the Cocos2D source files (like you suggest) but for now I’ll just stick to the basics. Thanks for your help though, and Turk too.
        I wonder if you could advice me one other mystery: getting dialog boxes start correctly from the CCLayer. I’ve learnt they must be started via a thread (example code below) and it works but it creates a new thread every time the method is called. Surely this is bad coding?

        private void dialogBoxThread() {
        new Thread() {
        @Override
        public void run() {
        Looper.prepare();

        Context context = CCDirector.sharedDirector().getActivity();
        AlertDialog.Builder dialogBox = new AlertDialog.Builder(context);
        dialogBox.setTitle(“Choose a level…”)
        .setItems(R.array.level_list, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,
        int choice) {changeLevel(choice);}})
        .create();
        dialogBox.show();

        Looper.loop();
        }
        }.start();
        }

        • Vykthur

          Interesting ..
          Sounds like an unfair use of system resources if a new thread is created every time a new dialog box is created (and not explicitly terminated) .
          Unfortunately I cannot proffer a better solution right now as I tend to approach dialogs within my games in a different manner. Heres how I do it.

          To simulate the dialog effect, I usually create a CCLayer with a transparent background which I lay over the current layer. I can then populate this layer with the dialog box content (in your case .. chose a level) . I then add a back button which removes the layer (and destroys it if needed) . The same layer can be displayed and removed whenever a dialog box is needed.

          An example is below.

          In the part 3 of the cocos2d slider puzzle tutorial I have provided code that shows a dialog when the player wins and also a back button to continue. You should be able to easily add this to your game.

          A benefit of this approach is that you keep your theme consistent throughout the game . It might actually detract from your overall game aesthetics to still see the native android dialog boxes popping up in that beautifully themed game your making.

          Hopefully this helps.

          V.

        • Vykthur

          Interesting ..

          Sounds like an unfair use of system resources if a new thread is created every time a new dialog box is created (and not explicitly terminated) .

          Unfortunately I cannot proffer a better solution right now as I tend to approach dialogs within my games in a different manner. Heres how I do it.

          To simulate the dialog effect, I usually create a CCLayer with a transparent background which I lay over the current layer. I can then populate this layer with the dialog box content (in your case .. chose a level) . I then add a back button which removes the layer (and destroys it if needed) . The same layer can be displayed and removed whenever a dialog box is needed. An image of such a box is attached.

          In the part 3 of the cocos2d slider puzzle tutorial I have provided code that shows a dialog when the player wins and also a back button to continue. You should be able to easily add this to your game.

          A benefit of this approach is that you keep your theme consistent throughout the game . It might actually detract from your overall game aesthetics to still see the native android dialog boxes popping up in that beautifully themed game your making.

          Hopefully this helps.

          V.

          • Matt

            Thanks for the quick reply, I was thinking about about creating a new layer but a dialog seemed a quick solution. I agree, a themed layer would look much better and give better customisation (e.g. a checkbox for sound on/off, help guide, etc).

          • Vykthur

            And it wont take so much effort too. Once you build one you can repetitively use it .

            V.

          • Matt

            Brief update, whilst researching this a bit further, seems I was doing it all wrong. Rather than create a new thread just to run the dialog box, I needed use ‘runOnUiThread’. So the correct code is below. However, I’ll still look at creating a CCLayer menu too.

            private void dialogBoxThread() {
            CCDirector.sharedDirector().getActivity().runOnUiThread(new Runnable() {
            public void run() {
            AlertDialog.Builder builder = new AlertDialog.Builder(CCDirector.sharedDirector().getActivity());
            builder.setTitle(“Choose a level”)
            .setItems(R.array.level_list, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int choice) {
            changeLevel(choice);
            }
            });
            AlertDialog msgBox = builder.create();
            msgBox.show();
            }
            });
            }

    • Turk

      I once saw that problem.Dont know why it happened but in one of my project it gave that error.Then i followed that way;
      In Eclipse, right click your folder–>Properties–>Java Build
      Path–>Libraries remove cocos2d.jar and after that drag the
      cocos2d.jar into your libs folder in Eclipse Screen.
      Lastly, right click folder–>Android Tools–>Fix Project
      Properties and run it. It should be ok. Note: After fixing project
      properties jar files will have a little library images.

  • Pingback: Adding a Game Menu in Cocos2D for Android | Denvycom()

  • Matt

    Hi V, just a quick question. I wondered if you had any tips on memory management that might be useful for us noobs?
    I’ve been trying to ‘= null’ as much as possible and keep variables defined locally within each method but I’m not sure what else to do. The heap size for my app is 11MB once it’s finished loading but starts at almost 20MB.
    I’ve been looking at Memory Analyzer too and it gives possible leak warnings about GameLayer being loaded twice (?) and a there seems to be a lot of bitmaps (but a guess these are all my CCSprites).
    Cheers,
    M

    • Vykthur

      Hi Matt,

      Now, about memory management, I would need to carefully do some personal analysis on the memory usage … especially Gamelayer being called twice.. I unfortunately have not paid much attention to this (very bad programming practice I admit) .

      Off the top of my head, one way to improve bitmap use would be to use spritesheets . Spritesheets can improve memory consumption by up to 50%. Please read this article ..
      http://www.codeandweb.com/what-is-a-sprite-sheet

      Spritesheets achieve this by making it possible to store several images in a single bitmap and access portions of this bitmap selectively, saving memory in the process.

      Theres a nice tool called Texture Packer which can help you create these spritesheets and use them easily in your code..
      http://www.codeandweb.com/texturepacker

      I can confirm that Cocos2d for android supports spritesheets via the CCSpriteSheet class

      https://github.com/ZhouWeikuan/cocos2d/blob/master/cocos2d-android/src/org/cocos2d/nodes/CCSpriteSheet.java

      As usual, I’ll let you know once I’ve gotten a chance to write a tutorial on this.
      Thanks for asking great questions and creating opportunity for us all to learn!

      Regards!

      -V.

      • Matt

        Thanks for the useful links, I’ll study them. I’ve also notice you can also ‘getTexture’ from one CCSprite to another which I would assume reuses the same memory space (or maybe not). On closer inspection of the GameLayer loading twice warning message in Memory Analyser, it seems the first load is only a few KB in size so perhaps this is normal in Cocos2D. Certainly my code is very similar to yours and other Cocos2D tutorials I’ve come across so I can’t see how else to write it. Thanks again, M.

        • Vykthur

          Hi Matt,

          I suspect the code that instantiates the GameLayer is wrongly placed in the Onstart() method. Try moving it to the bottom of the OnCreate method … and let me know if that fixes the double call observation.

          By the way, several updates have been pushed to the sample code repository .. interesting is a sample on how to create a sliding menu … http://denvycom.com/blog/sliding-menu-in-cocos2d-for-android/

          Always, happy to get your feedback.

          Regards,
          V.

          • Matt

            Hi V, you are correct, the gamelayer was wrongly placed and moving it to OnCreate are you suggest fixes Memory Analyzer’s warning about it being called twice. Thanks! 🙂

          • Vykthur

            OnResume() in your mainActivity.java is where the resuming matter should get handled … make sure your onResume() has the right code in it …

  • Mahbubur Rahman Turzo

    Excellent Tutorial !!! 😀 Thanks a lot ! 🙂

    • Vykthur

      Thanks Mahbub!
      Glad you found it useful!

      V.

    • rellay excellent 😀

      • Vykthur

        Thanks Masuk …
        At some point, please feel free to share your games you have developed and Im happy to write a post about them!

        -V.

  • urmyfaith

    the “fnt” file is broken using the link given in your article. so

    use the fnt file in your github project or create a fnt file by using hiero.

    • Vykthur

      Thanks for pointing that out ..
      Links have been updated …
      -V.

  • nguyenvandinh90

    hi! i am new,i worked Step by Step Guide on How to build your first Slider Puzzle game in Cocos2d but i have problem : java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.demo/com.example.demo.MainActivity}: java.lang.NullPointerException

  • Jerry Hernandez

    Hi! I’m quite new to cocos2dx. I’m having problem with running the application(crash). Any help here?? I’m still quite at the beginning of the tutorial.

  • Jayson Pinzon

    Hi Vykthur.
    Can you help me to make this game in a portrait view?

  • Akshay Paliwal

    i developed number puzzle on PORTRAIT mode for ANDROID using cocos2d, working fine but now i installed it on KITKAT device now the interface not showing but when i touch the screen game starts but still black screen showing. now i changes my games orientation to LandscapeLeft now all game showing fine, but i want to develop game in portrait mode. please help.
    Thanks.

    • rence

      can you post your code ? 😀

  • Matt

    Hi V,
    Have you encountered any problems with foreign font characters (e.g. àèéêäöóç)? Although I’ve included them in the bitmap font file, they don’t render on screen. Any ideas why?
    Thanks,
    Matt

    • Matt

      Ignore me, user error. I had updated the wrong font.fnt and font.png files, d’oh! Works fine now.

  • Matt

    Hi Vykthur,
    Last week I obtained a secondhand Oppo Find 5. It’s got a 441 dpi screen and this causes problems within CCDirector resulting in a blank screen. I found out (from another forum) that the solution was to change the following line in setProjection from 1500.0f to 2000.0f
    GLU.gluPerspective(gl, 60, size.width/size.height, 0.5f, 1500.0f);
    Thought this info might help others.
    M.

    • Vykthur

      Thanks Matt ,

      thats really useful! I have a question though. Would it be better to simply increase the setProjection value, or to attempt to estimate the current devices resolution dpi and then set setProjection. E.g did you test if the 2000 value worked with lower resolution screens ?

      This is something important enough to contribute to the Github repository … I’d like us to cordinate on this hopefully
      Thanks thank thanks!
      V.

      • Matt

        I found the solution on StackOverflow.com so it’s not my solution. I don’t understand exactly what the setProjection value does but I too wondered if simply changing it too 2000 was too simplistic (e.g. perhaps it should be calculated on DPI). I tested the change on a number of other devices I have and they all seem to work fine.

  • Matt

    Hi V,
    I’ve come across another problem with these Cocos2D files and I’m starting to think it would be easier to switch to Cocos2DX (someone on another forum seemed shocked that people are still using these old Android Cocos2D files).
    I’ve created a basic app that acts as a system launcher with lock-screen properties. The app works perfectly but on some devices (newer tablets) when you reboot the device, the CCGLSurfaceView gets all screwed up as it boots into the app (e.g. sprites are stretched to abnormal sizes). On other devices, on boot, the CCGLSurfaceView is black. This only occurs when the app is set to be the system launcher and the device is rebooted (up until the reboot, the app works perfectly). I assume there’s a bug somewhere in the Cocos2D files but I’m not sure where to start looking. Any ideas?
    Thanks,
    M

  • julius maurin

    Hello im new in android app developing and im currently using your sample sliding puzzle game as a presentation i already run it . but the problem is how can i able to add an sound option a background sound and also a sound control what i mean is volume control and also how can i able to the right image for the puzzle like a pattern image for the one that is solving the puzzle

  • Khaled Murshed Adnan

    The method getChildByTag(int) is undefined for the type GameLayer ????