Sneaky Joystick

Learn how to create virtual joysticks in cocos2d. Here is a sample project which you can download. Before watching this tutorial you might want to watch: How to show an image.

On my youtube channel ZenmasterRashmi asked for an expanded version. Here is an expanded version which you can download. Here is a short video showing the new version. On simulator I can only use one button at the time, but on the device you can use both the joystick and the shoot button simultaneously.

Thanks

This entry was posted in Cocos2d. Bookmark the permalink.

19 Responses to Sneaky Joystick

  1. IronBlade says:

    Hello Bob,

    Thanks for the great tutorials.

    I would like to ask, why the missile is fired twice when you press the button in your example code? I put it a counter and always shoots twice.

    HelloWorldLayer.m

    //new
    if (shootButton.active == YES) {
    CCSprite *missile=[CCSprite spriteWithFile:@"missile.png"];
    missile.position=ccp(airfighter.position.x+10,airfighter.position.y-25);
    [self addChild:missile];
    id move=[CCMoveBy actionWithDuration:1.0 position:ccp(500,0)];
    [missile runAction:move];
    [[SimpleAudioEngine sharedEngine] playEffect:@”shoot.mp3″];
    cont++;
    NSLog(@”Disparo: %d”, cont); // Here is always 2 shoots

    Thanks!

    • IronBlade says:

      Problem solved! I set the time between shots using deltaTime.

      -(void) update:(ccTime)deltaTime {

      //Used to calculate shoot time
      totaltime+=deltaTime; //NEW

      if (shootButton.active == YES && totaltime > nextshot)//NEW
      {
      nextshot = totaltime + 1.0f; //NEW
      CCSprite *missile=[CCSprite spriteWithFile:@"missile.png"];
      missile.position=ccp(move.sprite.position.x+80,move.sprite.position.y);
      [self addChild:missile];
      id move=[CCMoveBy actionWithDuration:1.0 position:ccp(500,0)];
      [missile runAction:move];
      [[SimpleAudioEngine sharedEngine] playEffect:@”sound.mp3″];
      cont++; //NEW
      NSLog(@”Disparo: %d”, cont);
      }
      // NEW – Use this option if you want to make repetitive shoots
      if (shootButton.active == NO){
      nextshot = 0;
      }
      }

      }

  2. Carlos says:

    It doesn’t work in cocos2d v2.0 :’(

    • Erik Andersen says:

      Bob below got it right. I’m running Cocos2D myself and got it to work thanks to him. Here’s a repost of what he said

      “You can get this type of error if your class’ .m file is not listed under the “Compile Sources” step of the “Build Phases” tab of your target. Normally Xcode does this for you, but sometimes it loses the plot and you need to add the .m file manually.

      So in Xcode click on the root (the icon in the topleft corner of groups and files) and then click on your target in right window. Then click on Build phases tab, and open the compile sources. Scroll down until you see + and – and click on the +. Add the needed SneakyJoystickSkinnedBase.m.”

      It worked for me. Hopefully it will for you.

      Best of luck.

  3. Hi there very nice website!! Man .. Beautiful .. Amazing .. I will bookmark your website and take the feeds also…I’m happy to search out a lot of helpful information right here in the submit, we need work out extra strategies in this regard, thanks for sharing. . . . . .

  4. Chris says:

    Hey Bob
    Is there a way to make the plane fly 2 directions: left and right?
    Thanks for your tutorial!
    Regards

  5. Vanja says:

    Hello, Bob!
    I have two errors when trying to run this app:
    Undefined symbols for architecture i386:
    “_OBJC_CLASS_$_SneakyJoystickSkinnedBase”, referenced from:
    objc-class-ref in HelloWorldLayer.o
    “_OBJC_CLASS_$_SneakyJoystick”, referenced from:
    objc-class-ref in HelloWorldLayer.o
    ld: symbol(s) not found for architecture i386
    collect2: ld returned 1 exit status

    Can U give some advice regarding this issue?

    • Bob says:

      Hi Vanja,
      This has nothing to do with my tutorial but the normal Xcode hassle, that you need to handle by Googling and reading cryptic messages. When I Googled I got this advice.

      You can get this type of error if your class’ .m file is not listed under the “Compile Sources” step of the “Build Phases” tab of your target. Normally Xcode does this for you, but sometimes it loses the plot and you need to add the .m file manually.

      So in Xcode click on the root (the icon in the topleft corner of groups and files) and then click on your target in right window. Then click on Build phases tab, and open the compile sources. Scroll down until you see + and – and click on the +. Add the needed SneakyJoystickSkinnedBase.m. Hopefully it will stop complaining.

      Regards
      Bob

  6. How could i find out which wordpress design this specific web page is making use of? Its wonderful! Being a former artist I genuinely recognize the value of it

  7. I was more than happy to seek out this web-site.I wanted to thanks for your time for this glorious learn!! I positively enjoying every little little bit of it and I have you bookmarked to take a look at new stuff you blog post.

  8. Jim says:

    Hi Bob,

    Great tutorials!

    I’m trying to incorporate sneaky joystick/button into a HUD layer so that it controls the action layer, but having problems. Can you suggest how to achieve this?

    Jim

    • Bob says:

      Hi Jim.

      You must have a pointer from the hud layer to the action layer..

      There are sveral ways to do that.. one way is to introduce a property called actionLayer in the hud class and then let the actionlayer set that property to self..

      Bob

      • Jim Rota says:

        Hi Bob,

        Thanks. I understand in principle, but am not clear on the details…

        1. I first create a *actionlayer variable pointer in the Hud layer and it should have @property (which means I need to synthesize and then dealloc it). It should probably be a CCScene type, or CCLayer type (depending upon what ActionLayer.h is)…
        2. Once created, I assign it to self in the ActionLayer implementation file…something like [self = *actionlayer] or simply self = *actionlayer?
        3. Once assigned, how to I call it from the Hud layer? E.g. say I wanted the joystick to move the hero sprite..

        • Bob says:

          Your ActionLayer must set the actionLayer variable of the Hud layer. So from a the ActionLayer write

          hud.actionLayer=self;

          Then you can access the hero (if it is declared as a property) from the hud by

          actionLayer.hero.position=ccp(100,200)

          • Jim Rota says:

            Hi Bob,

            Thanks for all your help. After trying to follow your instructions I ended up more confused, so thought I would send you my code and see if it’s a simple fix:

            >>>
            Hud.h
            #import
            #import “cocos2d.h”
            #import “HelloWorldLayer.h”
            @interface Hud : CCScene {
            CCLabelTTF *scoreLabel;
            int score;
            CCLayer *actionlayer;
            CCSprite *spider;
            }
            @property(nonatomic,retain) CCLayer *actionlayer;
            @property(nonatomic,retain) CCSprite *spider;
            >>>

            >>>
            Hud.m
            @implementation Hud
            @synthesize actionlayer, spider;

            //inside one of the Hud methods
            actionlayer.spider.position=ccp(100,200);
            id move=[CCMoveTo actionWithDuration:4.2 position:ccp(400,160)];
            [actionlayer.spider runAction:move];
            //it complains about the above saying spider is not a property of CCLayer
            >>>

            >>>
            @interface HelloWorldLayer : CCLayer
            {
            cpSpace *space;
            Hud *hud;
            }
            @property (nonatomic, retain) Hud *hud;
            >>>

            >>>
            @implementation HelloWorldLayer
            @synthesize hud;
            +(CCScene *) scene
            {
            CCScene *scene = [CCScene node];
            HelloWorldLayer *layer = [HelloWorldLayer node];
            [scene addChild: layer];
            //add another layer to the scene
            Hud *hudlayer = [Hud node];
            [scene addChild: hudlayer];
            //the following connects the Hud layer to this layer so that you can send messages to it.
            layer.hud=hudlayer;
            return scene;
            }

            //in init
            CCSprite *spider=[CCSprite spriteWithFile:@"spider_game.png"];
            spider.position=ccp(60,160);
            [self addChild:spider];

  9. Carter says:

    Is there any way to provide the object with some inertia, so after the directional thumbstick is released it slides for a little while before stopping?

  10. Jho Philippines says:

    Good Tutorial it help a lot :-)

  11. Bob says:

    Thanks to Rohan for suggesting this tutorial.

Leave a Reply