Thursday, April 11, 2013

Showing a Kongregate user's avatar image in a Unity 3D game

I decided that the game I'm currently working on is going to be tied to Kongregate, and since I'm doing that, might as well try to use as many features of the API as I can.

One of the features I'm trying to integrate in my game is the ability to render a Kongregate user's avatar in the game itself. For this tutorial, I will be using Kongregate's JSON REST API to fetch user data.

After skimming through the Kongregate API documentation, I found the page about the user-info REST call.

The url for a user-info call is formatted as follows: http://www.kongregate.com/api/user_info.json?username=<username> where username is obviously the username for the user account you're searching for.

This provides you with a response such as the following:

{
   "friends":[],
   "muted_users":[],
   "friend_ids":[],
   "muted_user_ids":[],
   "user_id":3590097,
   "username":"agnt666",
   "private":false,
   "page_num":1,
   "num_pages":1,
   "success":true,
   "user_vars":{
      "username":"agnt666",
      "level":3,
      "points":165,
      "avatar_url":"http://cdn4.kongcdn.com/assets/resize-image/50x50/assets/avatars/defaults/ant.png",
      "chat_avatar_url":"http://cdn4.kongcdn.com/assets/resize-image/16x16/assets/avatars/defaults/ant.png",
      "developer":false,
      "moderator":false,
      "admin":false,
      "gender":"Male",
      "age":25,
      "game_title":"Typocalypse 3D",
      "game_url":"http://www.kongregate.com/games/agnt666/typocalypse-3d"
   }
}

And the above response provides me with what I needed; the avatar url:

"avatar_url" : "http://cdn4.kongcdn.com/assets/resize-image/50x50/assets/avatars/defaults/ant.png"


Getting the avatar url in C#
Getting the username of the current Kongregate logged-in user is beyond the scope of this post (TODO: maybe in another one), so for this code I'm assuming you already have it.

public UITexture kongregateTexture;

IEnumerator FetchUserDetails(string username) {
    // Build the url for the REST call
    var detailsUrl = String.Format("/api/user_info.json?username={0}", username);

    // Do the call 
    var www = new WWW(detailsUrl);

    // ...and wait until we get back a response
    yield return www;

    // Get the JSON response text
    var responseText = www.text;

    // Deserialize it into a statically typed object to read to be able to read it's contents
    // For this demo, I'm using this JSON deserializer script: https://raw.github.com/gist/1411710/MiniJSON.cs
    var deserialized = MiniJSON.Json.Deserialize(responseText) as Dictionary<string,object>;

    //// TODO: a null check would be nice here

    // Get the user_vars object
    var userVars = deserialized["user_vars"] as Dictionary<string,object>;

    // Read the avatar url
    var avatar_url = user_vars["avatar_url"].ToString(); // http://cdn4.kongcdn.com/assets/resize-image/50x50/assets/avatars/defaults/ant.png

    //// Do the same routine to fetch the image
    var wwwAvatar = new WWW(avatar_url);
    yield return wwwAvatar;

    // And now we have the texture!
    Texture2D avatarTexture = wwwAvatar.texture;

    // Render the texture (I'm using an NGUI SimpleTexture widget)
    kongregateTexture.mainTexture = avatarTexture;
}

And this is the result with a shitty border I made around it:


Possible exception: Security Exception: No valid crossdomain policy available to allow access
Notice that in the above code, to build the url of the REST call, I used Kongregate's relative url: "/api/user-info.json...".

If I had used this instead String.Format("http://www.kongregate.com/api/user_info.json?username={0}", username);, I would have received this exception when running the game and looking at the debug log (console):


This error is thrown when reading the text field of the WWW instance (get_text).

So be very careful about that when doing the REST calls; always use relative urls! ...and this of course works because the game is hosted on http://www.kongregate.com.