Jim7
24 posts
|
Note: The following information is out of date. Please refer to our new API Documentation here: http://www.kongregate.com/pages/kongregate_api
Overview
Kongregate’s Content Sharing API makes it easier than ever for developers to add features like custom level sharing to your games. The new API gives your players the ability to:
▪ Save in-game content like levels, characters and game customizations to Kongregate’s servers for easy retrieval any time and from any computer.
▪ Browse publicly shared, user-generated content through Kongregate hosted UI (see example)
▪ Share in-game content easily via direct links, email or by posting to top social media sites. (No more copying and pasting of long, ugly text strings!)
This API is available to use now, and we urge you all to check out the first integration of level sharing in Hexiom: Connect and grab the complete documentation here.
Connecting to the new API is very easy – in fact, the Content Sharing API is built on top of the same Kongregate API that you’ve been connecting to for statistics! Note though that it’s only available in the AS3 API and you must load the API manually – the component loading method will not work with Content Sharing. When using this service, it is important that you register content load listeners prior to calling connect() on Kongregate API.
Example
Typical Kongregate API loader with load listeners added for Shared Content:
import flash.display.LoaderInfo;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;
// Pull the API path from the FlashVars
var paramObj:Object = LoaderInfo(root.loaderInfo).parameters;
// The API path. The debug version ("shadow" API) will load if testing locally.
var api_url:String = paramObj.api_path || "http://api.kongregate.com/flash/API_AS3_Local.swf";
// Debugging info
trace ("API path: " + api_url);
// Load the API
var request:URLRequest = new URLRequest ( api_url );
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onApiLoaded);
loader.load(request);
this.addChild(loader);
// Kongregate API reference
var kongregate:*
// Called when API swf finishes loading
function onApiLoaded(e:Event):void {
// Save Kongregate API reference
kongregate = e.target.content;
// Register the shared content load listener before connecting to Kongregate services
kongregate.sharedContent.addLoadListener('Level', onLoadLevel);
// Connect
kongregate.services.connect();
}
Each game may save up to 10 different types of shared content, so the possibilities of what you can do with this API are nearly endless.
|
|
|
Jim7
24 posts
|
Public Methods
addLoadListener() method
public function addLoadListener(contentType:String, callback:Function):void
Adds an event listener to be triggered when content of the specified type is loaded by the user
Parameters
▪ contentType:String — Type of content to listen for
▪ callback:Function — Function to call when content load request has been made
▪ callback( params:Object )
▪ params:Object format: { id:Number, name:String, permalink:String, content:String, label:String }
Example
Add a load listener for Contraptions:
kongregate.sharedContent.addLoadListener("Contraption", onContraptionLoad);
function onContraptionLoad(params:Object) {
var id:Number = params.id;
var name:String = params.name;
var permalink:String = params.permalink;
var content:String = params.content;
var label:String = params.label;
trace("Contraption " + id + " [" + label + "] loaded: " + content);
}
browse() method
public function browse(contentType:String, sortOrder:String = null, label:String = null):void
Brings up a list of shared contents in the user’s browser
Parameters
▪ contentType:String — Type of content to browse
▪ sortOrder:String (default = null) — A constant specifying the sort order of the shared content browser
▪ BY_NEWEST – Newest content first. This is the default if no method is specified.
▪ BY_RATING – Highest-rated content first.
▪ BY_LOAD_COUNT – Most-viewed content first.
▪ BY_FRIENDS – Only show content made by friends (newest first).
▪ BY_OWN – Only show your own content (newest first).
▪ label:String (default = null) — Optional, only browse content saved with the specified label
Example
Bring up a Shared Content browser for Contraptions, only showing those by your friends with the “Level 3 Solution” label:
kongregate.sharedContent.browse('Contraption', kongregate.sharedContent.BY_FRIENDS, 'Level 3 Solution');
save() method
public function save(contentType:String, content:String, callback:Function, thumbnail:DisplayObject = null, label:String = null):void
Submits shared content to the server
Parameters
▪ contentType:String — Type of content the user wishes to save (ie. Level, Contraptions, etc)
▪ Limited to 12 characters
▪ content:String — Value of content to be saved. We strongly recommend keeping these values under 100K since the game will hang until the content is sent, which can lead to a poor user experience if the content is too large.
▪ callback:Function — Function to call when save has finished
▪ callback( params: Object )
▪ params:Object format: { success:Boolean, id:Number, name:String, permalink:String, content:String, label:String }
▪ If params.success is not true, other attributes will not be included
▪ thumbnail:DisplayObject (default = null) — Highly Recommended! Send us a DisplayObject that we will snapshotted and used as a thumbnail for the content. If this is not provided we will take a picture of the entire stage and use that as the thumbnail.
▪ label:String (default = null) — Optional, label for sub-classing the shared content.
Example
Send some shared content to be saved as a contraption with the contents “x1y3z10”, calling back onContraptionSave using myContraptionEditor for the thumbnail and with the lable “Level 3 Solution”:
kongregate.sharedContent.save('Contraption', 'x1y3z10', onContraptionSaved, myContraptionEditor, 'Level 3 Solution');
Example
Set up the callback function to be called when content save is completed:
function onContraptionSaved(params:Object) {
if (params.success) {
// The shared content was saved successfully.
var id:Number = params.id;
var name:String = params.name;
var permalink:String = params.permalink;
var content:String = params.content;
var label:String = params.label;
}
else {
// The shared content was not saved.
// The most likely cause of this is that the User dismissed the save dialog
}
}
|
|
|
Jim7
24 posts
|
Saving shared content on sites other than Kongregate
You may submit shared content created in versions of your game hosted on sites other than Kongregate. The API simply consists of a set of URL parameters you pass along with a GET request to your game’s URL on Kongregate.
The relevent query parameters are type, content, and optionally, label. Note that this method is more limited in terms of the size of the content due to browser limitations with passing through a URL – they need to be limited to under 2,000 characters after encoding in order to ensure that it will work.
Additionally, a trailing &z must be appended to the URL to indicate the content was not truncated.
Example
This snippet is a simple function that accepts the relevant arguments and forwards them to Kongregate.
var saveRemote:Function = function(kongregateGameUrl:String, contentType:String, content:String, label:String = null):void {
var toQueryString:Function = function(params:Object):String {
var q:Array = [];
for (var p:String in params) q.push(encodeURIComponent(p) + '=' + encodeURIComponent(params[p]));
return q.join('&');
}
var loc:String = kongregateGameUrl + "?" + toQueryString({
'type': contentType,
'content': content,
'label': label
}) + '&z';
// This &z sigil indicates that no content was truncated from the URL by a nasty browser
// and is required for your level to be saved when a user visits the game
// Make sure your URL isn't going to be too long to send through a browser
if (loc.length < 2000)
navigateToURL(new URLRequest(loc), '_blank');
// else...
// You will need to provide some error handling in cases where the content is too large
}
|
|
|
Jabor
11382 posts
|
Awesome. A couple of questions, though:
We strongly recommend keeping these values under 100K since the game will hang until the content is sent
Was it not possible to use an asynchronous mechanism to handle this sort of thing?
The API simply consists of a set of URL parameters you pass along with a GET request to your game’s URL on Kongregate.
Note that this method is more limited in terms of the size of the content due to browser limitations with passing through a URL
Similarly, wouldn’t it be preferable to POST the data, ignoring that size limitation?
|
|
|
andrew
45 posts
|
On sending the game content, I’d be very surprised if someone has shared content larger than 100k, but if it becomes an issue we could look into it. The issue is that local connection messages have a 40k limit so we have to break up the messages.
A POST to the game page won’t work because of our cross domain policy. We could make a separate post action for it, but we wanted to keep the API as simple as possible.
|
|
|
bLasTamos
545 posts
|
Wow, this is awesome. I may not need a third party web host after all.
Are you sure you didn’t steal my idea of level sharing/rating/play-count? :p
|
|
|
jonathanasdf
3837 posts
|
We strongly recommend keeping these values under 100K since the game will hang until the content is sent
Was it not possible to use an asynchronous mechanism to handle this sort of thing?
yeah…
|
|
|
Kinsman
109 posts
|
One thing developers should remember is that a game can be loaded at any time, not just after a browse() command. Players can use the ‘Levels’ link in the bar above the game, or even start the game with a level request if they came to your game through someone’s profile page.
This means that your level request function should know how to shut down a game in progress – and if you have important initialization tasks when your game starts, you should hold off on setting up your listener until the game is ready.
EDIT: Then again, if the listener function just feeds you information, it’s easy enough to just put the information somewhere safe until your game is ready to use it.
|
|
|
Kinsman
109 posts
|
Here’s a tip:
You can use something like a JSON encoding/decoding library to serialize objects or arrays into text – which can give you a complex level format without having to do your own figuring how to turn your information into strings.
AS3 Core Lib contains a good JSON library.
|
|
|
Kinsman
109 posts
|
What is the ideal size for a thumbnail – one that’ll scale in a 1:1 fashion when converted?
EDIT: With Sketch’s content sharing up, it looks like the thumbnails will scale to be 60 px in height, and the width will vary according to its original proportions.
|
|
|
UnknownGuardian
6214 posts
|
Can’t this API be “misused” as an online .sol. It will automatically create a “level”, aka, a file on your name that stores important information about your game progress? Then they just have to include a username string checker so that other users can’t click on it and use it.
|
|
|
SavageWolf
2884 posts
|
Will this API be upgraded to AS2?
|
|
|
locos
128 posts
|
There’s a small typo in the Kongregate API loader example:
loader.load(request));
|
|
|
locos
128 posts
|
In Hexiom I’ve made a test level, is it possible to remove it ?
Edit: Ok, I’ve seen the delete button lol :P , plus I’ve alredy integrated it in my latest game if you wanna try it
|
|
|
locos
128 posts
|
Originally posted by Kinsman:
Here’s a tip:
You can use something like a JSON encoding/decoding library to serialize objects or arrays into text – which can give you a complex level format without having to do your own figuring how to turn your information into strings.
AS3 Core Lib contains a good JSON library.
I’m trying to serialize a Bitmap (casted to Object) with JSON but it doesn’t let me do it, it says:
Illegal read of write-only property blendShader on flash.display.Bitmap.
How could I encode a Bitmap (which originally was a Sprite) in a string to send to the server ?
|
|
|
Kinsman
109 posts
|
Originally posted by locos:
I’m trying to serialize a Bitmap (casted to Object) with JSON but it doesn’t let me do it, it says:
Illegal read of write-only property blendShader on flash.display.Bitmap.
How could I encode a Bitmap (which originally was a Sprite) in a string to send to the server ?
Yeah, JSON is more useful for objects and arrays you make yourself out of primitive data types.
Sending a Bitmap takes a bit more planning. You can use bitmapData.getPixels() to turn its content into a ByteArray, and then find a Base64 encoder/decoder to turn the ByteArray into a String and back.
There’s Base64 libraries in more than one place on the Internet, here’s one I searched at random:
http://dynamicflash.com/goodies/base64/
|
|
|
Phoenix00017
7300 posts
|
Originally posted by Kinsman:
What is the ideal size for a thumbnail – one that’ll scale in a 1:1 fashion when converted?
EDIT: With Sketch’s content sharing up, it looks like the thumbnails will scale to be 60 px in height, and the width will vary according to its original proportions.
Just asked the devs about this one: actual size is apparently 93×74 (yeah, kinda random, I know). Your aspect ratio will be maintained and padded to fill out the thumbnail.
Originally posted by SavageWolf:
Will this API be upgraded to AS2?
I don’t think we have any plans to downgrade this to AS2 at this point. :-P You’d have to ask the developers exactly what the challenge is involved with that – I’m not sure if it would have to do with the event handlers or something with the communications with our server. I think we’d probably also consider this to be impetus to learn AS3, which really is worthwhile anyway, plus it’s been out since 2006. ;-)
Originally posted by locos:
There’s a small typo in the Kongregate API loader example:
loader.load(request));
Thanks! Fix’d.
Originally posted by UnknownGuardian:
Can’t this API be “misused” as an online .sol. It will automatically create a “level”, aka, a file on your name that stores important information about your game progress? Then they just have to include a username string checker so that other users can’t click on it and use it.
I hesitate to call that “misusing” – it actually sounds rather clever. :-) I wonder if we shouldn’t consider making that a quick extension in the API. While ideally we would want a true .sol save on our servers, this might be a nice short-term solution that would work as long as a developer would integrate it themselves. I’ll mention this to the developers.
EDIT: The update is that the API lacks the ability to select a level for you, meaning that you could do this, but the user would have to select the level from the lightbox themselves. Still functional, but not quite as slick. No word on whether we have plans to create an actual GameSave API at this point. Would be nice, but is yet another project in our very very long list of them.
|
|
|
UnknownGuardian
6214 posts
|
As long as its easier to manipulate then .sols. I find them a bit confusing.
|
|
|
Phoenix00017
7300 posts
|
Well, it would have to be a new API if we did it, and we don’t have any specific plans to do so at this point. While developers can certainly find ways to use the LevelSharing as a way to do savegames, it’s not something that we’re intending to offer any official support or functions for. It would be cool eventually, but the gold standard is certainly being able to just handle real .sol’s on our server since then all games would work without developer integration. Whether that’s feasible I don’t know.
|
|
|
locos
128 posts
|
Thanks Kinsman for the tip :D now it’s possible to upload drawings
I had a problem when a user wanted to upload a thumbnail with nothing in it (width and height both 0).
The solution is to check width and height of the thumbnail before passing it.
|
|
|
bLasTamos
545 posts
|
Ok I have tried to implement this but it’s not working.
First of, it gives me an error offline, saying the shadow API doesn’t have the sharedContent property.
Also when I use the save function it just hangs there. And the browse function does nothing. :o
And now it seems the score submission is also screwed up. Is anything wrong with this?
var paramObj:Object = LoaderInfo(root.loaderInfo).parameters;
var api_url:String = paramObj.api_path || "http://api.kongregate.com/flash/API_AS3_Local.swf";
var request:URLRequest = new URLRequest(api_url);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, kongregateLoaded);
loader.load(request);
addChild(loader);
public function kongregateLoaded(e:Event):void {
_kongregate = e.target.content;
_kongregate.sharedContent.addLoadListener("Level", sharedLevelFunction);
_kongregate.services.connect();
}
|
|
|
UnknownGuardian
6214 posts
|
Why don’t you upload it without publishing it? Then if possible(not sure if possible), trace anything into a text box on screen.
|
|
|
bLasTamos
545 posts
|
|
|
|
Phoenix00017
7300 posts
|
Well, do you have this in your code?
// Debugging info
trace ("API path: " + api_url);
It will trace the path that you’re trying to connect to. Are you developing in CS3 or CS4?
EDIT: Actually, I’m getting that error too…looking into it. Perhaps we didn’t update the local API.
EDIT 2: Ok, so thanks for pointing this out. We have some kinks to work out with the shadow services for local testing. It should no longer generate the error that you saw, but you may still get a few more when you try to browse and such. We’re working on cleaning that up, but the actual live, online version of the API is still good to go.
|
|
|
Arkatufus
20 posts
|
Its easier to use Alcon if you need to trace and debug a deployed swf.
http://blog.hexagonstar.com/alcon/
Just remember to take the debug function out of the game when you’re ready to publish it.
|