Orthello – Atlas Data doesn’t populate

Slowly went batshit trying to figure this out.

There’s a fairly nice walk through on making 2d games with Unity3D but I ran into a weird problem. While trying to setup a SpriteAtlas, I could set the fields for Texture and Atlast Data, but nothing happened ( it’s supposed to populate the contents of the sprite atlas… but doesn’t).

The images below show the initial import of an Orthello SpriteAtlas, after dragging the Texture and atlas data to their appropriate spots, AND last bit occurred after I typed in an arbitrary number into the “size” field. After that the widgets internal logic kicked into gear and populated the atlas as desired.

Also, if reading just ain’t your thing OR you need a sanity check on getting started with Unity3D, this great video tutorial of making a 2D game was really helpful.

Google Discovery service

I am dumbfounded I haven’t heard of this service before, it’s pretty clever. Anyone familiar with WSDL or Soap is going to instantly grok this.

For example, here’s the Google Analytics API discovery document https://www.googleapis.com/discovery/v1/apis/analytics/v3/rest

With this data set, it’s relatively trivial to auto-generate an interface / command pattern instance to make the user feel like they’re actually using the API directly.  Furthermore the discovery document provides a fairly good reference breakdown of required arguments, argument types, and basic validation type hints to developers.

A trivial example, here’s how to grab the first profile for the currently authenticated user in  analytics:

analytics = client.discovered_api("analytics",'v3')
 
#Grab the first profile
result = client.execute(analytics.management.accounts.list)
print result.data.items[0]

Until I called discover on analytics, my client had no idea how to deal with the Analytics API, but now it not only knows how to work with the remote service but can provide basic validations, some advanced error handling ( bad/wrong input, connectivity issues) and in an interactive console in Ruby or Python I can explorer the api as needed.

Follow up on Google API with service accounts and ruby

refer to the previous post on this subject

Using analytics.data.qa.get doesn’t work as desired, so instead you need to do something like:

visitCount = client.execute(analytics.to_h["analytics.data.ga.get"], {
                              :ids=>"ga:" + YOUR_PROFILE_NUMBER,
                              "start-date" => "2012-06-12",
                              "end-date" => "2012-07-01",
                              :metrics => "ga:visits"}
                            )

Note the part of using to_h[‘analytics.data.ga.get”] to get the right signature to pass onto the APIClient execute method. That will work and works well. To make it easier to formulate queries against GA, I’d recommend using Google’s query explorer tool here http://ga-dev-tools.appspot.com/explorer/

Service accounts with Ruby and the google api client

  1. Goto https://code.google.com/apis/console
  2. Create a new project
  3. Under services, select Google Analytics
  4. Goto API Access of a new project
  5. generate a new oAuth credential, selecting “service account”.
  6. Download your p12 cert file

 

In Google analytics, use the service account email address and assign it as a new administrator to the desired GA profile.

On ALL servers destined to use the service account to GA, install and syncronized with ntp.  If your even 500ms off, you’re going to have a bad time with “Grant_invalid” messages.

In a testbed project, make 2 files: Gemfile & testbed1.rb ( you’re going to create a lot of these testbed files on your own ).

Gemfile

source "http://rubygems.org"
gem 'google-api-client'
gem 'pry'

testbed1.rb

require 'pry'
require 'rubygems'
require 'google/api_client'
 
keyFile = "SOME_KEY_GOES_HERE-privatekey.p12"
 
cID = "YOUR_SOOPA_SECRET_SA"
 
scope = 'https://www.googleapis.com/auth/analytics.readonly'
email = 'YOUR_EMAIL_GOES_HERE@developer.gserviceaccount.com'
 
 
#Normally it would be bad to put the passphrase here, but aftet talking to several dozen devs, everyone's pass phrase is not a secret
key = Google::APIClient::PKCS12.load_key(keyFile, "notasecret")
 
asserter = Google::APIClient::JWTAsserter.new(
   email,
   scope,
   key)
 
puts asserter.authorize()
 
binding.pry

If all goes well, the JWTAsserter instance will get a valid token and no exceptions/errors will be thrown. If you’ve followed all of the steps listed earlier and things are still breaking, troubleshooting paths are: Verify your machine time is correct, verify your service account email address is bound to google analytics, and lastly you might need to wait until Google platform catches up with the changes. For myself, it took 9 hours until my account finally authenticated through. Google has potentially a million or more servers organized into cells, the fact that they seem to cooperate well doesn’t mean they’re perfectly in sync at all times.

Otherwise if all else fails, I recommend stalking this guy Nick https://groups.google.com/d/msg/google-analytics-data-export-api/maa_fyjD2cM/sT8tDDh0wNsJ – It seems like he’s a Google employee on the service account dev/implementation team and generally stuff gets fixed if he says it’s getting fixed.

As I run into any more troubles, I will update and add more notes.

My business DSL connection was out this evening, so I wrote up a quick script to track how long exactly it was out for.

import envoy
import time
 
roller = 0
Limit = 50
while Limit > 0:
    rs = envoy.run("ping google.com")
    if rs.status_code != 1:
        print "PING %s" % time.ctime()
        Limit -= 1
        time.sleep(10)        
 
    roller += 1
    if roller % 100:
        print "PONG %s" % time.ctime()

Envoy is probably one of my favorite utility libraries after the Http Request library. Github repo is here https://github.com/kennethreitz/envoy/blob/master/README.rst

Ubuntu 11.10 Google native client dependancies

sudo apt-get install ia32-libs
sudo apt-get install gcc-multilib g++-multilib libsdl1.2-dev texinfo libcrypto++-dev libssl-dev lib32ncurses5-dev m4 libelf-dev

This is about 300Mb of stuff, some of it can be culled but I didn’t feel like messing around with that.

Allows for pepper 19 examples to be compiled successfully.

CraftJS; interesting potential

The other month/week I resumed some dabbling/hacking experiments in working with HTML5’s canvas. This go around, I decided to give CraftyJS a try.

The short version of my experiments, CraftyJS has a lot of potential if it can get it’s memory leaks under control, which might be a daunting task.

Here’s the example Pong game implementation that can be found on CraftyJS’s website:

 
Crafty.init(600,300);
Crafty.background("rgb(127,127,127)");
 
//Paddles
Crafty.e("Paddle, 2D, DOM, Color, Multiway")
    .color('rgb(255,0,0)')
    .attr({ x: 20, y: 100, w: 10, h: 100 })
    .multiway(4, { W: -90, S: 90 });
 
Crafty.e("Paddle, 2D, DOM, Color, Multiway")
    .color('rgb(0,255,0)')
    .attr({ x: 580, y: 100, w: 10, h: 100 })
    .multiway(4, { UP_ARROW: -90, DOWN_ARROW: 90 });
 
//Ball
Crafty.e("2D, DOM, Color, Collision")
    .color('rgb(0,0,255)')
    .attr({ x: 300, y: 150, w: 10, h: 10,
            dX: Crafty.math.randomInt(2, 5),
            dY: Crafty.math.randomInt(2, 5) })
    .bind('EnterFrame', function () {
        //hit floor or roof
        if (this.y <= 0 || this.y >= 290)
            this.dY *= -1;
 
        if (this.x > 600) {
            this.x = 300;
            Crafty("LeftPoints").each(function () {
                this.text(++this.points + " Points") });
        }
        if (this.x < 10) {
            this.x = 300;
            Crafty("RightPoints").each(function () {
                this.text(++this.points + " Points") });
        }
 
        this.x += this.dX;
        this.y += this.dY;
    })
    .onHit('Paddle', function () {
    this.dX *= -1;
})
 
//Score boards
Crafty.e("LeftPoints, DOM, 2D, Text")
    .attr({ x: 20, y: 20, w: 100, h: 20, points: 0 })
    .text("0 Points");
Crafty.e("RightPoints, DOM, 2D, Text")
    .attr({ x: 515, y: 20, w: 100, h: 20, points: 0 })
    .text("0 Points");

Now I will break this down.

Crafty.init(600,300);
Crafty.background("rgb(127,127,127)");

Relatively straight forward; this generates a HTML5 canvas element of 600×300 pixels, sets the color to a neutral color range.

Crafty.e("Paddle, 2D, DOM, Color, Multiway")
    .color('rgb(255,0,0)')
    .attr({ x: 20, y: 100, w: 10, h: 100 })
    .multiway(4, { W: -90, S: 90 });

Part of Crafty’s cleverness is in it’s component based entity system. The first line tells the Crafty library that you’re defining a new entity called “Paddle” which is a 2D, DOM behavior like, color’d objected that reacts to multiple user inputs. Break down:

.color(…) defines the paddles color
.attr(…) defines the entities dimensions AND position.
.multiway(…) is a clear API method which states
the entities movement speed, and then which direction a triggered keyboard input will send the entitiy. So in the above case W is north, and S is south.

Skipping the other paddle, we come to the ball in a pong game.

Crafty.e("2D, DOM, Color, Collision")
    .color('rgb(0,0,255)')
    .attr({ x: 300, y: 150, w: 10, h: 10,
            dX: Crafty.math.randomInt(2, 5),
            dY: Crafty.math.randomInt(2, 5) })
    .bind('EnterFrame', function () {
        //hit floor or roof
        if (this.y <= 0 || this.y >= 290)
            this.dY *= -1;
 
        if (this.x > 600) {
            this.x = 300;
            Crafty("LeftPoints").each(function () {
                this.text(++this.points + " Points") });
        }
        if (this.x < 10) {
            this.x = 300;
            Crafty("RightPoints").each(function () {
                this.text(++this.points + " Points") });
        }
 
        this.x += this.dX;
        this.y += this.dY;
    })
    .onHit('Paddle', function () {
    this.dX *= -1;
})

Something I glossed over, Crafty’s e(…) function is actually a Javascript prototype class generator. It’s important to note that because of the interplay between .attr() and every other post e(…) method call.

In the above

.attr({ x: 300, y: 150, w: 10, h: 10,
            dX: Crafty.math.randomInt(2, 5),
            dY: Crafty.math.randomInt(2, 5) })

defines additional properties of the entity. x/y & w/h are already used by the 2D and DOM components to determine the entities position on but in the later .bind(“EnterFrame”) notice that the logic involved is referencing this attributes.

So inside the EnterFrame handler for the Ball are two crucial sections.

if (this.x > 600) {
            this.x = 300;
            Crafty("LeftPoints").each(function () {
                this.text(++this.points + " Points") });
        }
        if (this.x < 10) {
            this.x = 300;
            Crafty("RightPoints").each(function () {
                this.text(++this.points + " Points") });
        }
<pre>
 
These two if clauses handle bounds check's and then depending on position award the appropriate side a point.
 
Notice the Crafty("") calls.  In this case Crafty("LeftPoints") calls up the appropriate entity or entities ( in this case there are only 1 per side ) and applies a closure to increment the winning side's this.points and body text.
 
 
The other crucial section is the 2 line closure 
 
<pre lang="javascript">
.onHit('Paddle', function () {
    this.dX *= -1;
}

A fairly cool concept in Crafty is that collision detection between almost any entity is dealt with by Crafty, so to determine if the Ball hits a paddle, you just have to ask Crafty.

Summary

I was fairly impressed with CraftyJS, it is very much the spiritual relative of jQuery for a dirt simple and comfortably clever API. Unfortunately Crafty can blind side you with it’s cleverness if you’re not careful. What I mean is that in experimenting with CraftyJS I found it fairly easy to create non-obvious memory leaks and or abuse closures to much.

Still it’s a fairly nice library and though this post is slightly long, I am only covering a thin scratch of the depth that is in CraftJS. This could be a fantastic building stage for making a slew of quick and dirty games.

Trial’s & Tribulations with Apple push notification

So far really not impressed with Apple’s APN service, especially it’s sandbox/development tier.

To get started, I recommend reading the Founder/CTO of Server Density’s recipe/guide to getting started with APN, here ( http://blog.serverdensity.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/ )

Because of how many times I had to clean slate my dev. environment, I tried to streamline the process of converting the APN certificate and my private key. In the process of converting the private key to pem format, you do have to provide a pass phrase.

echo "Convert certificate"
openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
 
echo "Converting key"
echo "You must provide a PEM phrase, it will be stripped out in next step"
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
 
echo "Stripping off PEM phrase"
openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
 
echo "Concatenating keys"
cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

One SERIOUS word of warning about APN is a scenario where you *known* beyond a shadow of a doubt that your APN requests are properly formed and the TLS connection works as expected but nothing happens. To repeat, everything looks like it works but you don’t get any APN’s to your device. My advice is to delete your APN certificate from your keychain and re-download the APN certificate, convert it again, and try again.

To verify your key is correct, the command line openssl utility is somewhat invaluable

 openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert apns-dev-cert.pem -key apns-dev-key-noenc.pem

There should be no errors and the console should hang immediately after the — line until you type in some garbage.

Apple: Anti-developer

As I said earlier, I am really not impressed with APN for one specific reason. I lost about 4-5 hours of my life yesterday trying various different APN libraries for PHP, Ruby, Python, and objective-c. My payload to APN was correct, my token ID was triple verified, and I was sure I was sending the data down the wire. Meanwhile I got no error messages or warnings that my certificate was out of date/order and because of that my APN requests were being ignored.

The worst technology on the planet isn’t that what gives ambigious/cryptic error messages but that which just silently fails with no means to diagnose the problem. Hell it’s worse that the infamous “There was an error, somewhere, sometime.” joke.

Selective Dropbox sync for Ubuntu

  1. Find a good tutorial to setup the CLI Dropbox agent – This one is the most concise IMO
  2. Grab this http://www.dropbox.com/download?dl=packages/dropbox.py
  3. `dropbox.py exclude add` is the command you need

Say I’ve got 30+ directories in my dropbox but I only want “md”

  find -maxdepth 1 -type d | cut -b3 | grep -v md | xargs python md/dropbox.py exclude add

That will add everything else to the exclusion list AND clean out the local Dropbox path for you. One point to note is that .dropbox-cache/ gets hoovered into the exclusion list, which is redundant and doesn’t appear to cause any harm.

I’ve increasingly been using Dropbox as a low-security transfer protocol ( critical things like ssh keys, password dictionaries, and certificates are handled separately ) and now with the selective sync it’s becoming fairly trivial to keep my horde of virtual servers both in house and running on AWS synced. One thing I’ve been trying out is using the autostart functionality to kick on when I login to a box. I am not sure but if Dropbox could kick on only when I am logged in would be fairly nice.

PyCon 2012 Day 1 itinerary

Graph Processing in Python
Scalability at YouTube
Practical Machine Learning in Python
LUNCH
Code Generation in Python: Dismantling Jinja
The Magic of Metaprogramming
Throwing Together Distributed Services With Gevent
Putting Python in PostgreSQL

And I think that ends day 1 of the conference. Mostly I am hoping to combine what I learn in the Graph processing and Practical ML talks, while having an overview of code generation might be a solution ( or a new problem ) to my current client’s issues. As for metaprogramming, gevent, and postgreSQL; those just seem fun.