Sunday, November 28, 2010

New Website

The new website is up and running. Any new posts will show up there.


edit: Okay, now that website is old and broken and unmaintained as well. I need a new place to put things.

Thursday, November 25, 2010

A Quick Update

I know things have been quiet here lately, but some new stuff will be coming along. I'm in the process of building a website that will host this blog as well as other information on Championship Ultimate. It will also be a source of information on my other games and projects.

There will also be a smallish update to CU coming soon. It won't have multiplayer, but there will be a number of nice little tweaks. Multiplayer is simply a huge project will take some more time.

Thursday, October 21, 2010


The multiplayer code is finally looking playable. The gameplay elements are just about done, but there's still a bit of work to sync up team / game selection, sounds, etc.

But, here's the thing: Bluetooth performance has seemed pretty terrible during my own testing. I think I do an okay job compensating for the lag, but once in a while it will spike up and the disc will jump around, or your player won't catch the disc when it seems like it should. So, should I release the Bluetooth multiplayer, or just work on the GameCenter internet play which should (most of the time) yield better results?

I'm leaning toward releasing it. I think it will be fun, even if the performance isn't great. Thoughts?

Tuesday, September 21, 2010

TimeSync was a time sink

An important part of my networking code for Championship Ultimate is getting all the devices clocks synced up, so that they can talk intelligently about what time events occurred in the game. It turns out that this is not a trivial problem, and I spent a couple days working on it.

This question I asked on goes into more detail, and I got some helpful answers:

This wikipedia page was also helpful:

So, with all that info, I made a class to do the job that I'm fairly proud of. Perhaps it will be useful to someone else someday. Do whatever you want with the code, but it would be fun if you left a comment to say it was useful. The actual network communication stuff obviously needs to be changed to fit in your code.


//Call [timeSync startSync] on the client. The offset variable will be continually updated
//throughout the life of the program, and it will be sent back to the server also.

#define TS_DELAY_MAX 10000

@interface TimeSync : NSObject 
    NSTimeInterval t1, t2; //t1 is client time - server time, and t2 is server time - client time
    NSTimeInterval offset; //this doesn't get calculated from t1 and t2 until it's stabilized
    uint synccount;

-(void)processPacketType:(uint8_t)type TimeStamp:(NSTimeInterval)timeStamp;


@implementation TimeSync

    if (self = [super init])
        t1 = TS_DELAY_MAX;
        t2 = TS_DELAY_MAX;
        offset = TS_DELAY_MAX;
        synccount = 0;
    return self;

    [[Basket shared].connection sendPacket:PT_SYNC_REQ Data:nil Mode:GKSendDataReliable];

    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
    [[Basket shared].connection sendPacket:PT_TIME_SYNC Data:[NSData dataWithBytes:&now  length:sizeof(NSTimeInterval)] Mode:GKSendDataUnreliable];

    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
    [[Basket shared].connection sendPacket:PT_DELAY_REQ Data:[NSData dataWithBytes:&now length:sizeof(NSTimeInterval)] Mode:GKSendDataUnreliable];

    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
    NSTimeInterval diff = now - from;
    [[Basket shared].connection sendPacket:PT_DELAY_RSP Data:[NSData dataWithBytes:&diff length:sizeof(NSTimeInterval)] Mode:GKSendDataUnreliable];

    [[Basket shared].connection sendPacket:PT_SYNC_NOTIFY Data:[NSData dataWithBytes:&offset length:sizeof(NSTimeInterval)] Mode:GKSendDataReliable];

    //get a first quick measurement, then only measure every 10 seconds
    //basically, a new offset will be published every minute
    if (offset == TS_DELAY_MAX)
        [self performSelector:@selector(startSync) withObject:nil afterDelay:0.5];
        [self performSelector:@selector(startSync) withObject:nil afterDelay:10.0];
    [self sendSyncRequest];

    offset = (t2 - t1)/2.0;
    NSLog(@"TimeSync found delay to be %f", offset);
    NSLog(@"Ping was %f", (t2 + t1)/2.0);
    //reset so we can measure a new drift
    t1 = TS_DELAY_MAX;
    t2 = TS_DELAY_MAX;
    NSLog(@"Notifying server of offset...");
    [self sendSyncNotify];

-(void)processPacketType:(uint8_t)type TimeStamp:(NSTimeInterval)timeStamp
    NSTimeInterval timediff;
    switch (type)
         case PT_SYNC_REQ:
             [self sendTimeSync];
         case PT_TIME_SYNC:
             timediff = [NSDate timeIntervalSinceReferenceDate] - timeStamp;
             if (timediff < t1)
                 t1 = timediff;
             [self sendDelayRequest];
         case PT_DELAY_REQ:
             [self sendDelayResponse:timeStamp];
         case PT_DELAY_RSP:
             if (timeStamp < t2)
                 t2 = timeStamp;


             if (synccount % 5 == 0) //publish the new offset every 5 measurements
                 [self publishOffset];
         case PT_SYNC_NOTIFY:
             offset = -timeStamp;
             NSLog(@"Received notification of offset:%f", offset);

    return offset;

Thursday, September 9, 2010

A Quick Note

I don't have much real news, but I am hard at work on some cool features. And, I'm looking to get support for GameCenter in sooner, rather than later. Yup, that means online multiplayer. I might focus all my work on that to try to get it out there even if it means pushing some other stuff back a bit. I'm excited to see if anyone can beat me at my own game!

Wednesday, August 25, 2010

Submitted 1.2

I submitted version 1.2 for review. Some fun facts:

Championship Ultimate is right now made up of 30,239 lines of code! The biggest file by far is Player.m which is 1699 lines.

Yesterday, August 24th, was the one year anniversary of the beginning of the project. Here are some comparison screenshots:

In a lot of ways, 1.2 is the game I wanted to make from the very beginning. But, I'm glad I didn't wait this long for the first release. I've gotten a lot of great feedback since it came out that has helped it evolve. So, many thanks to all of you for playing the game and spreading the word!

Here's the changelog:

Gameplay Improvements:
Much more realistic flight physics
Can put curve on throws (inside-out and outside-in)
Can alter the angle of attack (changes the height of throws)
Can optionally use simple throwing controls that require no pivoting
Tweak camera to show more action on the near sideline
Throws out of bounds come in where they went out
Pulls out of bounds respect the brick mark
Added Huck drill

AI Improvements:
Poached players cut more aggressively
Tone down AI poach defense and make throwers less conservative
AI will more intelligently chase your hucks
AI has better judgement of whether a huck is open

Graphical Improvements:
Better looking stadium
Added stadium lights
Added camera flyby to game intro
Added nicer looking sky
New buttons
New stall counter

New Teams:
OSU Leadbelly
CHS Varsity
Oberlin Preying Manti

Bug Fixes:
Player numbers looked wrong when pivoting (and related problems)
Holding down throwing arrow might lead to player switch
Other misc. fixes

A few things have been pushed back to 1.3, which should be a pretty exciting release as well.

Saturday, August 14, 2010

iOS 3.1 buttons!

There's a problem with iOS 3.1 and CU version 1.1. I've submitted a fix and it looks like they'll review it on monday. Sorry about that!

Here are the new buttons I've made. I can't decide if they are too colorful. Maybe they should all be gray, and just labeled A,B, or C?