Using Parse to login via Facebook and retrieve Profile and Friends

I’m using parse.com to handle user authentication, either via Facebook or custom user type with email and password.

If a user signs up via Facebook we want to request access to their profile and friend list and use that information to find FB friends who are already playing our game (Just Picture It).

This example doesn’t include a lot of the prerequisite steps to get your parse app working with Facebook – see the parse.com docs for more details on that.

An example of an initial call to parse to login to Facebook with a specific set of permissions.

NSArray *permissionsArray = [NSArray arrayWithObjects:@"user_about_me",
@"user_relationships",@"user_birthday",@"user_location",
@"offline_access", @"email", @"publish_stream", nil];

[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {

if (!user) {
   NSLog(@"Uh oh. The user cancelled the Facebook login.");

   [self doFacebookUserHasCanceled];

   } else {

     [self performSelector:@selector(doFaceBookUserHasLoggedIn) withObject:nil afterDelay:0.1];
     }
}];

A successful login and permission request approval by the user to Facebook sends us to the function doFaceBookUserHasLoggedIn.

NSString *requestPath = @"me/?fields=name,location,gender,birthday,relationship_status,picture,email,id";

PF_FBRequest *request = [[PF_FBRequest alloc] initWithSession:[PFFacebookUtils session] graphPath:requestPath];

[request startWithCompletionHandler:^(PF_FBRequestConnection *connection, id result, NSError *error) {
    if (!error) {
       NSDictionary *userData = (NSDictionary *)result; // The result is a dictionary

       NSString *name = [userData objectForKey:@"name"];

       NSString *email = [userData objectForKey:@"email"];

       NSString *sID = [userData objectForKey:@"id"];

       // get the FB user's profile image
       NSDictionary *dicFacebookPicture = [userData objectForKey:@"picture"];   
       NSDictionary *dicFacebookData = [dicFacebookPicture objectForKey:@"data"];       
       NSString *sUrlPic= [dicFacebookData objectForKey:@"url"];
       UIImage* imgProfile = [UIImage imageWithData:
                                [NSData dataWithContentsOfURL:
                                 [NSURL URLWithString: sUrlPic]]];

       //do something interesting with this data...

       //...

       // now request FB friend list
       PF_FBRequest *request = [[PF_FBRequest alloc] initWithSession:[PFFacebookUtils session] graphPath:@"me/friends"];

       [request startWithCompletionHandler:^(PF_FBRequestConnection *connection, id result, NSError *error) {
          if (!error) {
             NSArray *data = [result objectForKey:@"data"];

             if (data) {
                //we now have an array of NSDictionary entries contating friend data
                for (NSMutableDictionary *friendData in data) {
                    // do something interesting with the friend data...

                    }
                }

             }
          }];
   }
}];

 

New iOS social game ‘Just Picture It’ launched in the App Store

Image

The social image sharing game that we developed in partnership with Mason Software Company has just been launched in the Apple App Store – it is called Just Picture It.

The iOS game uses Parse.com and Amazon AWS as the primary back-end components for storing data and sharing images.

It is free and quite a bit of fun to play with friends – please download and give it a try…

TorchShips Launch

Just launched the TorchShips site with the first post – Inspiration and why ‘Real’ Space Combat.

TorchShips is a 3-D tactical space combat game based on real physics with procedurally generated single and multi-player missions. It will be initially released for Windows & Mac, with iOS version to follow.

TorchShips is also on facebook and twitter.

If you’re interested in the game or just want to support us please link to the site, like via Facebook,  and/or follow the twitter feed. We’re gearing up for a kickstarter project as well that should start within a week.

Thanks

Initial Impressions of Unity3D

After evaluating 3d engines for iOS development I’ve decided we’re going to go with Unity3D.

I would prefer a native Objective-C engine but the ability to deliver for multiple platforms is very attractive (Unity can deploy to Android, iOS, Mac, Linux, XBox 360, and the Wii).

Unity development so far has been straight forward – scripts can be in c# or javascript – I’ve created several 3d scenes, used the extensive resources from the forum and Unity Answers to create a ship that uses realistic physics to move in orbit. The Unity Asset store has thousands of additional resources for Unity3D dev. Initially I’m using atmospheric planets and vectrosity for line drawing.

Unity3d scene

We play tested the game as turn based and real time multi-player – I was initially planning on a turn based approach using Apple’s Game Center for iOS but the game plays much better in real time. We evaluated several multi-player network solutions and are going to go with Photon Cloud  – very well integrated with Unity, a great price, and should be able to scale.

3D engines for iOS Development

I’m evaluating several different 3d engines for our planned iOS space combat game Torchships.

I found good overviews at Never Read Passively, Open Source iPhone game engine comparison, and The Commercial iPhone Game Engine Comparison (3D and 2D).

This week I’m digging more into Unity and cocos3d to get a better understanding of the pros and cons. Unity looks very nice but I’m not sure I want to go with a non-iOS-native solution.

Here is the list of 3D engines I’ve looked at so far…

<>

UDK – Unreal Development Kit for iOS – PC & iOS

The same toolset used to make Gears of War and Infinity Blade.

+ Beautiful graphics

+ Industry Standard, high performance

+ Completely integrated development system

– Development on PC only

– proprietary scripting

Unity 3D – web, flash, iOS, Android, PC & Mac, Wii, PS3, xBox 360

Very popular 3d engine that supports a large number of platforms.

+Large developer base and very active community

+Very nice 3d Graphics, physics, and particle effects.

+Integrated editor and asset pipeline

+Largest number of platforms available

+Javascript or C#

+Mac native development

-Not a native iOS app, all new iOS features may not be available right away

Marmalade

Engine to create of richer apps and games on iOS, Android and other platforms.

+based on c++

-based on c++ 🙂

Shiva3d

3D game engine with a graphical editor to create applications and games for Windows, MacOS, Linux, iPhone, iPad, Android, BlackBerry QNX, WebOS, Marmalade and Wii

SIO2

An OpenGLES based cross-platform 2D and 3D game engine for iOS, Android, MacOS and Windows

cocos3d

An extension to cocos2d. A sophisticated 3D application development framework for the iOS platform.

+open source

+based on and can integrate with the very powerful and popular cocos2d library

+native iOS

ISGL 3D

iSGL3D (iOS Scene Graph Library) is a 3D framework for the iPhone, iPad and iPod touch written in Objective-C, enabling the creativity of developers to flourish in a 3D world without the complexities of OpenGL.

+based on OpenGL

+iOS native

-author is not actively supporting, looking for new contributors

Web2PY , Google App Engine, and DatastoreTimeoutException

While web2py runs great on the Google App Engine there are several gotchas that can cause a lot of headache if you aren’t aware of them. [Note to readers – this post assumes an advanced understanding of web2py and python.]

Google App Engine will throw a timeout error (DatastoreTimeoutException ) if your web2py function takes too long to execute. This can happen with a long database update or query. The average time to trigger a timeout appears to be about 30 seconds.

One approach to resolve this, if you can’t refactor your query or update operation to guarantee it will stay under 30 seconds or 1,000 records, is to create a progress display page that periodically calls a web2py function to incrementally perform the operation you are attempting.

The example I’ll use is a fairly complex report that works against a large number of records that can take several minutes to execute.

We have a summary_report view that allows the user to choose multiple filter options (year, school, etc). On submit the controller summary_reports is called, the request.vars from the user selections are saved as session variables and the view summary_report_display is called. The variable session.summary_m is our chunk size for our query, you can increase it to speed up the report but going too high can cause the process to hit the 30 second limit.


@auth.requires_login()
def summary_reports():

    if request.vars.teacher_select:

        #stores running values from report generator
        session.dictGraphVariables={}

        #user selections
        session.year_select=request.vars.year_select
        session.school_select=request.vars.school_select
        session.class_select=request.vars.class_select
        session.teacher_select=request.vars.teacher_select
        session.semester_select=request.vars.semester_select
        session.observer_select=request.vars.observer_select
        session.datestart=request.vars.datestart
        session.dateend=request.vars.dateend

        session.includearchive=request.vars.includearchive

        #used in the partial query
        session.summary_i=0
        session.summary_m=300
        session.summary_break=0

        #counter for number of report results
        session.summary_overallcount=0

        redirect(URL('summary_report_display'))

    return dict()

Our summary_report_display view has a javascript function defined that calls our web2py function get_progress_on_summary_report every 3 seconds, the get_progress_on_summary_report does the heavy lifting.


{{extend 'layout.html'}}</pre>
<h1>Generating Reports</h1>
<h2>This may take a while if you have a lot of walkthroughs - but you can monitor progress below...</h2>
<pre></pre>
<div id="progress"></div>
<div id="summary_report_show"></div>
<pre>

Here is the code in the web2py controller for summary_report_display that sets up the progress bar display and the javascript call to get_progress_on_summary_report every 3 seconds.

progress = DIV(_id="progress")
wrapper = DIV(progress,_style="width:400px;")
summary_report_show = DIV(_id="summary_report_show")

@auth.requires_login()
def summary_report_display():

    page.include("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js")
    page.include("http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-darkness/jquery-ui.css")
    callback = js.call_function(get_progress_on_summary_report)
    page.ready(jq(progress).progressbar( dict(value=request.now.second) )() )
    page.ready(js.timer(callback,3000))
    return dict(wrapper=wrapper)

The get_progress_on_summary_report function in the web2py controller does most of the work.


def get_progress_on_summary_report():

    if session.summary_break==0:

        queries=[]

        #base query includes all walkthroughs
        queries.append(db.t_walkthrough.id>0)

        #build the query list based on user selections

        #if user hasn't selected 'All' for an individual search/filter term, then add to the query
        if session.school_select!='All':
            queries.append(db.t_walkthrough.school==int(session.school_select))

        if session.semester_select!='All':
            queries.append(db.t_walkthrough.semester==session.semester_select)

        if session.year_select!='All':
            queries.append(db.t_walkthrough.f_year==session.year_select)

        if session.class_select!='All':
            queries.append(db.t_walkthrough.t_class==int(session.class_select))

        if session.teacher_select!='All':
            queries.append(db.t_walkthrough.teacher==int(session.teacher_select))

        if session.observer_select!='All':
            queries.append(db.t_walkthrough.observer==int(session.observer_select))

        #handle start / end date if user entered same
        if len(session.datestart)>0:
            date_object = datetime.datetime.strptime(str(session.datestart), '%Y-%m-%d')
            queries.append(db.t_walkthrough.f_date>=date_object)

        if len(session.dateend)>0:
            date_objectEnd = datetime.datetime.strptime(str(session.dateend), '%Y-%m-%d')
            queries.append(db.t_walkthrough.f_date
        #create query from list
        summary_report_query = reduce(lambda a,b:(a&b),queries)

        rows = db(summary_report_query).select(limitby=(session.summary_i*session.summary_m,(session.summary_i+1)*session.summary_m))

        for r in rows:

            # do something with r
            session.summary_overallcount+=1
            list_walkthrough_result=db(db.t_walkthrough_result.walkthrough==r.id).select()
            for w_record_result in list_walkthrough_result:
                if not type(w_record_result.f_result) is NoneType:
                    if w_record_result.f_result==None:
                        #do nothing
                        testvalue='none'
                    else:
                        if w_record_result.f_result in session.dictGraphVariables:
                            session.dictGraphVariables[w_record_result.f_result]+=1.0
                        else:
                            session.dictGraphVariables[w_record_result.f_result]=1.0

        if len(rows)
<a href="summary_reports_complete">Click Here to View Graphs</a>'
            else:
                return_value='Report generation complete - there are ' + str(session.summary_overallcount) + ' results.

'

            return jq(summary_report_show).html(return_value)()
        else:
            return

The core of the the iterative process is the query below, it pulls a chunk of rows (size defined by summary_m) each cycle.

rows = db(summary_report_query).select(limitby=(session.summary_i*session.summary_m,(session.summary_i+1)*session.summary_m))

This performs our operation in chunks, once there are no more rows the function changes state and then returns a link to the summary_report_show view page which will parse the results and present them to the user, if no results are produced then the operation tells the user.

This approach will let you perform queries or db updates against an very large set of records without triggering the timeout.

Using Parse to add a backend to your iOS app

We’ve had to write over a dozen server back ends for iOS applications. There is a lot of manual work involved, no matter what platform you choose (we’ve used Google App engine or custom php solutions based on Joomla). There is the code and database development on the server side, plus a lot of code on the iOS side to handle the calls to the server, error handling, etc. It’s a royal pain and something we’d like to avoid in the future if possible.

Parse is a new service that simplifies back end development for iOS immensely – it can take literally minutes to add a simple server side component to your iOS app.

Pricing is free in Beta and looks very reasonable going forward as well.

We recently used Parse to add server functionality to an iOS Math application for YourTeacher.com. The app stores user preferences to a simple Parse object. Adding Parse to our project, testing, and deploying took less than an hour. Performance is good – besides being able to save and retrieve standard dictionary objects you can use Parse to store and manipulate remote files and geo location objects.

They have a very good overview of the integration process for iOS, plus the API is available as a REST service and for the Android as well.

Highly Recommended

iOS Game – Torchships

One of the very nice new features of iOS 5 from Apple is that GameCenter will handle all of the mechanics and hosting for multiplayer turn based games. This creates an opportunity to build a very feature-rich multiplayer game without a lot of infrastructure costs.

Accordingly we’re going to design and develop a 3d turn based space combat game for the iPhone and iPad with realistic physics. The game will be ad-supported and free to download and play. We will release rapid iterations and add features as we go….

  • Using iSGL3D for the 3d graphics.
  • 4 gameplay modes – tutorial/training, hotseat (same device), peer to peer (wifi/bluetooth via gamekit), game center hosted
  • Realistic Newtonian physics.
  • Weapons include – gamma ray lasers, missiles, and kinetic launchers.
  • Terrain – terran planets, moons, asteroid fields, ring systems, dust and debris clouds.

Working title for the game is Torchships.

If you’re interested in following our progress follow this blog (see the right hand pane of this page to sign up)

If you’d like to help beta-test Torchships then please sign up at our TestFlight page – you will need an iPad, iPhone, or next generation iTouch to participate.