Sunday, March 30, 2008
After spending some time with the iPhone SDK, I've discovered that it is designed in a very Apple sort of way.  Duh.  The SDK is geared around using specific interface tools they give you.  In my case I was trying to find a video buffer I could just write to.  This sort of coding behavior has become frowned upon lately and for good reason.  Writing to video buffers outside of a sandbox is what brought us exploitable code, viruses, and crashing software.  This has given rise to the likes of managed code, .NET, Cocoa, take your pick of sandboxed safe coding environments.  The iPhone SDK is no different.  You can programatically create image objects (UIView) at instantiation time, after which they are read only.  There are all sorts of ways, actually one very striaght forward way of animating them, moving them, and intercepting clicks on them.  However if you have  a graphics engine that generates a game state essentially by bit-blt-ing to a video buffer, it looks like the only possibility for doing this is going to be through OpenGL/ES which doesn't work on the simulator.  So if I want to take this project any further I'm going to need to buy an iPhone.... drat.

Code | iPhone
Sunday, March 30, 2008 12:41:33 PM (Central Standard Time, UTC-06:00)
 Friday, March 28, 2008

Eureka!  Well it's not that much of a victory, but on a new platform, and one with a super shiny screen it's fun to see your code work.  So far developing for the iPhone is remarkably easy.  There are lots of framework objects and samples to get you started with simple applications.  The first thing I wanted to do was use the screen to interpret finger swipes.  You would think this would be built in, and according to the documentation, it is.  However I couldn't get it to work in the emulator.  Here is the sample code Apple provided to intercept swipes.

// Handles the continuation of a touch.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{  
    // Enumerates through all touch objects
    for (UITouch *touch in touches){
        if (touch.info & UITouchInfoSwipedDown) {
            touchInfoText.text = @"Swipe down";
        } else if (touch.info & UITouchInfoSwipedUp) {
            touchInfoText.text = @"Swipe up";
        } else if (touch.info & UITouchInfoSwipedRight) {
            touchInfoText.text = @"Swipe right";
        } else if (touch.info & UITouchInfoSwipedLeft) {
            touchInfoText.text = @"Swipe left";
        } 
        // Send to the dispatch method, which will make sure the appropriate subview is acted upon
        [self dispatchTouchEvent:[touch view] toPosition:[touch locationInView:self]];
    }
}

touchesMoved is a call back that gets executed while your finger is still moving across the screen.  Checking the .info member variable against an enumerated bit mask should do the trick.  In my simulator I could never get these events to fire while dragging across the screen, so I rolled my own.  It's pretty straight forward, but it works and I get all of the expected outputs on my cool little app.

#pragma mark -
#pragma mark === Touch handling  ===
#pragma mark
 
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    _labelDirection.text = @"";
 
    // Save the position
    for (UITouch *touch in touches) {
        // Send to the dispatch method, which will make sure the appropriate subview is acted upon
        [self dispatchFirstTouchAtPoint:[touch locationInView:self] forEvent:nil];
    }
}
 
// Saves the first position for reference when the user lets go.
-(void) dispatchFirstTouchAtPoint:(CGPoint)touchPoint forEvent:(UIEvent *)event
{
    _myTouchPoint = touchPoint;
}
 
// Handles the continuation of a touch.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{  
    for (UITouch *touch in touches) {
        // Send to the dispatch method, which will make sure the appropriate subview is acted upon
        [self dispatchTouchEndEvent:[touch view] toPosition:[touch locationInView:self]];
    }
}
 
#define MIN_SWIPE_DISTANCE 10
 
// Diffs the start and end points of the swipe to determine direction
-(void) dispatchTouchEndEvent:(UIView *)theView toPosition:(CGPoint)position
{   
    CGFloat xDelta = position.x - _myTouchPoint.x;
    CGFloat yDelta = position.y - _myTouchPoint.y;
 
    // We only want to see large strokes
    if(abs(xDelta) > MIN_SWIPE_DISTANCE || abs(yDelta) > MIN_SWIPE_DISTANCE)
    {
        // See which way the stroke went
        if(abs(xDelta) > abs(yDelta)) {
            if(xDelta > 0) {
                _labelDirection.text = @"Right";
            }
            else {
                _labelDirection.text = @"Left";        
            }
        }
        else
        {
            if(yDelta > 0) {
                _labelDirection.text = @"Down";
            }
            else {
                _labelDirection.text = @"Up";
            }
        }
    }
    // Short distances are considered clicks
    else
    {
        _labelDirection.text = @"Click";    
    }
}

touchesBegan and touchesEnded are also call backs that get executed when you think they would, when your finger touches and then leaves the screen.  I use a little subtraction and the magic of absolute value to determine the drag direction.  Small drags are considered clicks.  Now I'm ready to plug any code into my directions.  This doesn't use the delta or the accelerometer that are available, but for my purposes I just need a direction at this point.

Code | iPhone
Friday, March 28, 2008 6:15:18 PM (Central Standard Time, UTC-06:00)