Welcome to my Programming Blog...

I am currently working on a couple of projects: An original game called "Implosion" which I am porting from Flash to the iPad, and a remake of Q*bert in Python (pygame), as part of the class I am teaching. Please feel free to use the "Labels" (at right) to follow a specific project or theme. If you are one of my Python students, I recommend that you check out the Python thread.

Thursday, January 20, 2011

Gesticulate this!

"What did you do in school today, Johnny?"

"Oh, Mom! Mr. Howe taught us how to make some gestures!"

(Before I forget, here is the example project for this.)

In the iOs world, a gesture is a motion that can be recognized by the iPhone, iPad, or iPod - such as a tap, a two finger pinch, a two finger swipe (aka a pan), or a two finger rotate. It turns out that there is a built-in way of handling this!

In this post, I'm going to show you how to use a PanGesture - this is when you drag two fingers across the screen together, and the object on the screen moves around with your fingers. In this case, we'll move an entire layer around, one that has a TMXMap in it.

The basic idea is to create an instance of UIPanGestureRecognizer and link it to a function you will write that handles the motion of the object. The second part is getting information about what the pan gesture involved - how far to move the layer, and doing so.

Part 1 is pretty straightforward. I started with a layer class that has another layer, called "gameLayer" in it, and I added a TMXMap to it. (You could add just about anything, but this made for a good example.) I then added a new function, which I called from the "init:" function:
-(void) setupPanGestureRecognition
{
    UIPanGestureRecognizer* panGesture = [[UIPanGestureRecognizer alloc] initWithTarget: self action:@selector:(handlePanGesture:)[;
    [[[CCDirector sharedDirector] openGLView] addGestureRecognizer: panGesture];
    [panGesture release];
}

This creates a new PanGestureRecognizer, which is going to tell the target (self) to execute the function (handlePanGesture:) if it happens to notice a pan gesture. We then add it to the main view of the program - the director's openGLView. (And we release it, because the initWithTarget: method had retained it, but our class doesn't need to do so - the openGL view has it now.)

Then we have to make the actual handlePanGesture: function. It gets information about how much the pan gesture has moved from the beginning of the gesture. Before we can write this function, pop over to the header (.h) file and create a new CGPoint variable, panSoFar. Also, write the header for the function in the (.h) file:
-(IBAction)handlePanGesture:(UIPanGestureRecognizer*)sender;

Then we can write the function in the main (.m) file:

-(IBAction)handlePanGesture:(UIPanGestureRecognizer*)sender
{
    if (sender.state == UIGestureRecognizerStateBegan)
        panSoFar = ccp(0,0); // reset to a new pan...

    CGPoint panFromSender = [sender translationInView:[[CCDirector sharedDirector] openGLView]]; 
                  // how far does the system say the image should pan... from the start of the motion 
    CGPoint panChange=ccpSub(panFromSender, panSoFar); // how far did the pan change since the last time we updated the pan?
    panChange.y = panChange.y*-1; // flip the y-axis
    gameLayer.position = ccpAdd(gameLayer.position, panChange); // move the gameLayer to match the pan.
    panSoFar = panFromSender; //update the "panSoFar" so that next time it will just be a small increment to the pan.
}

Most of this calculation happens because despite the fact that you are moving the gameLayer a little bit every time this function is called, the information from the gesture recognizer is actually giving you how far the gameLayer needs to be moved from when the pan started. So we have to subtract how far we already moved it to find out how much more we need to move the layer.

Give it a try!

3 comments:

  1. Thanks to Zach and Summant for field-testing this. We found some things that are worth mentioning.
    First of all, make sure that you activate the multitouch feature. (http://howeprogramming.blogspot.com/2011/01/sneakyinput-addendum.html)
    Second, by default, even a single finger dragged across the screen will count as a pan. When setting up the pan gesture recognizer, you can set the number of fingers that "count":
    panGesture.minimumNumberOfTouches = 2;
    (There's also a maximumNumberOfTouches, if you need it.)

    ReplyDelete
  2. If you’re looking for a destination to outsource your software development, then one of the Eastern European countries may be a a good match for you. Check out this article to find how to find blockchain developers.

    ReplyDelete
  3. If you’re looking for a destination to outsource your software development, then one of the Eastern European countries may be a a good match for you. Check out this article to find how to find blockchain developers.

    ReplyDelete