Copy the Playtomic folder and everything in it to your game's folder.
Add these frameworks to your game by clicking the project, then selecting the target -> build phases -> expanding Link Binary with Libraries.
Before you do anything else you must initialize the API using your credentials from the dashboard. Once you have done that, you can log the view when the player opens your game or resumes it.
// Get your credentials from the Playtomic dashboard (add or select game then go to API page)
[[Playtomic alloc] initWithGameId:gameid andGUID:@"guid" andAPIKey: @"apikey"];
[[Playtomic Log] view];
Premium users can use SSL for all API communication by calling this method before logging the view:
[Playtomic setSSL];
If you are using the ARC mode for your project you need to use the playtomic framework.
Please download the precompiled version
If you are compiling from github, you will need to:
1) Compile LibPlaytomic project (Inside the Playtomic folder with all the Playtomic API source files)
2) Drag and drop the framework from the build folder to your project.
Also since you are using ARC you need to keep the pointer to the Playtomic instance you create.
A view occurs whenever somebody views your game. This should go somewhere very early in your code, like before the pre-loader.
[[Playtomic Log] view];
Note: We are currently changing the naming to Sessions as it is more appropriate today. Changes will be applied in next API version.
This occurs wherever you feel a player has become engaged in your game. It's subjective, previously we recommended putting it on the play button but that is less suitable in a mobile environment so you should use this at some point early in your game where you feel a player has decided to really play your game rather than open it.
Note: We are currently changing the naming to Engages. Changes will be applied in next API version.This data is logged automatically when you send other events.
-(void) startedGame
{
[[Playtomic Log] play];
// continue starting game
...
Note: This is inherited from the Flash version which runs on a single thread, and is unlikely to be necessary in iOS games.
Events are sent in batches each time the play timer updates (every 30 seconds after the first minute). If you want to ensure an event gets sent:
[[Playtomic Log] forceSend];
Some games are very resource-intensive and the API might send off a batch of events at exactly the wrong time. You can freeze and unfreeze the logging at any time by:
[[Playtomic Log] freeze];
[[Playtomic Log] unfreeze];
When logging is frozen all events are queued but not sent until you unfreeze the API.
You must add a call to freeze in the method applicationWillResignActive of your UIApplicationDelegate to let the Playtomic API stop the timer when your application is becoming inactive and consequently you must add a call to unfreeze in the method applicationDidBecomeActive to let the Playtomic API restart the timer.
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
// we must freeze Playtomic before get suspended
[[Playtomic Log] freeze];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
// we must unfreeze Playtomic after became active
[[Playtomic Log] unfreeze];
}
When a connection to internet is not active all log are saved to be sent later. The maximum size of this cache is 1 MB. You can change this to a lower value using the method setOfflineQueueMaxSizeInKbytes.
+ (void)setOfflineQueueMaxSizeInKbytes:(NSInteger)size;
This cache persists even when your game is closed. The log will be sent the next time your game runs and internet is active.
Custom metrics allow you to track how many people do something in your game. For instance, how many play on easy, medium or hard, or how many play in English vs. Spanish, or how many view the tutorial or skip it. Anything you think can help you improve your game can be defined in custom metrics.
You can define custom metrics directly in your game and they will be added to Playtomic automatically. Groups can be automatically assigned via an optional second parameter or set up later in the dashboard.
You can also limit custom metrics to unique-per-view occurances with a third parameter.
[[Playtomic Log] customMetricName:@"ViewedCredits" andGroup:nil andUnique:NO]; // metric, names must be alphanumeric
[[Playtomic Log] customMetricName:@"Credits" andGroup:@"Screens" andUnique:NO]; // metric in a group, groups must be alphanumeric
[[Playtomic Log] customMetricName:@"ClickedLink" andGroup:@"Links" andUnique:NO]; // unique metric with group
Level metrics track events on a per-level basis so you can drill down into your difficulty and retention by identifying which levels have problems and what those problems are.
There are three types of level metrics - counters (like custom metrics), ranged-value and average-value.
Note that you can pass either an integer level number or a string name of the level. If your game is not using numeric levels (eg an escape game) then you would pass the name of each screen / area as a level.
You can define level metrics directly in your game and they will be added to Playtomic automatically.
Level metrics support unique-per-play occurrances via an optional second parameter. If the player starts a new game they will be tracked again.
These metrics track how many times something occurs in your levels, for instance deaths and restarts.
One of the most valuable pieces of data you can track is how many people begin each level, this allows you to see where you lose players.
[[Playtomic Log] levelCounterMetricName:@"Began" andLevel:@"named" andUnique:NO]; // level names must be alphanumeric
[[Playtomic Log] levelCounterMetricName:@"Restarts" andLevelNumber:1 andUnique:NO]; // level numbers are integers
These metrics track the average of something in your levels, for instance the average time to finish a level or the average number of retries. It also tracks the minimum and maximums.
[[Playtomic Log] levelAverageMetricName:@"name" andLevel:@"areaname" andValue:100 andUnique:NO];
[[Playtomic Log] levelAverageMetricName:@"name" andLevelNumber:1 andValue:100 andUnique:NO];
These metrics track metrics with values, for instance in a golf game you might track how many shots it takes to complete each level, or you might track the % of coins collected on each level.
[[Playtomic Log] levelRangedMetricName:@"Shots" andLevel:@"field" andTrackValue:10 andUnique:NO];
[[Playtomic Log] levelRangedMetricName:@"PercentCoinsCollected" andLevelNumber:1 andTrackValue:78 andUnique:NO];
Heatmaps allow you to map activity (clicks, deaths, first deaths, or anything else you want) against an image you upload in the dashboard.
[[Playtomic Log] heatmapName:@"metric" andGroup:@"heatmap" andX:10 andY:50];
In the dashboard you upload a background image for the heatmap, and then it is shared by any metrics using it.
Link tracking allows you to keep track of how many people open URLs in your game, providing you information on unique and total clicks that can be fully audited to allow you to identify good sources of traffic.
Link tracking does not change your URL or redirect traffic through a different url!
You track a link just by passing a URL and some other information to the API.
[[Playtomic Link] trackUrl:(NSString*)url andName:(NSString*)name andGroup:(NSString*)group];
[[Playtomic Link] trackUrl:@"http://armorgames.com/" andName:@"armorgames" andGroup:@"sponsor"];
When you track a link it automatically also tracks the totals for the domain in a group it creates called DomainTotals. The DomainTotals allows you to see how many unique, total and failed clicks occurred for a single domain even if you have multiple, different links to it (eg walkthrough or differently-structured sponsor links).
Objective C users can use Parse directly through their own iOS SDK.
You can do pretty much anything you want with a custom database, including:
The level sharing API provides a way to store and retrieve user-generated content for your game. It can operate anonymously or authenticated via any 3rd party service you're already using.
Saving and listing levels uses this class to represent a level.
| Property | Type | Accessor | Description |
|---|---|---|---|
| playerName | NSString | getPlayerName | The name of the player (or "anonymous", "guest", etc), or the name provided by any 3rd party API. |
| playerId | NSString | getPlayerId | If you're working under a 3rd party API you can include the player's user id |
| playerSource | NSString | getPlayerSource | If you're working under a 3rd party API you can specify which, eg "gamersafe" or "mochicoins" |
| name | NSString | getName | The name of the level |
| data | NSString | getData | The data for the level. You can Base 64 encode a ByteArray to a string if necessary. |
| votes | NSInteger | getVotes | The number of votes the level has |
| score | NSInteger | getScore | The sum of all votes the level has |
| plays | NSInteger | getPlays | The number of plays the level has |
| rating | NSDecimalNumber | getRating | The rating the level has (score / votes) |
| date | NSDate | getDate | The date of the level, determined automatically by Playtomic |
| relativeDate | NSString | getRelativeDate | The relative date of the level eg "7 minutes ago", determined automatically by Playtomic |
| customData | NSMutableDictionary | getCustomData | Any additional data you want to (or have) attached to a level. |
| NSString | getThumbnailUrl | Returns the URL of a thumbnail. | |
| NSMutableData | getThumbnail | Returns the thumbnail if you included them when listing. | |
| NSString | getCustomValue | Retrieves a custom property. | |
| NSString | addCustomValue | Adds a custom property. |
For some methods there are two versions: one synchronous and one asynchronous. We recomend you to use the asynchronous one because it is not going to freeze your game while the call is executed. Calling the synchronous version is more easy to code and is there for games which are not resource-intensive.
To call the asynchronous methods the caller must implement the protocol PlaytomicDelegate. All the methods in this protocol are optional so you only need to implement the methods you actualy use.
[[Playtomic PlayerLevels] saveAsyncLevel:level andDelegate:self];
| Parameter | Type | Description |
|---|---|---|
| level | PlaytomicLevel | An instance of PlaytomicLevel holding the level data |
| delegate | id<PlaytomicDelegate> | A reference to an object which implements the method requestSavePlayerLevelsFinished from the protocol PlaytomicDelgate |
To call this method your class must implement the method requestSavePlayerLevelsFinished from the protocol PlaytomicDelegate:
- (void)requestSavePlayerLevelsFinished:(PlaytomicResponse*)response;
Example saving level:
- (void)levelSaveAsync
{
NSLog(@"Level save asynchronous");
PlaytomicLevel *level = [[PlaytomicLevel alloc] initWithName:@"level name"
andPlayerName:@"player name"
andPlayerId:0
andData:@"r=-152&i0=13,440,140&i1=24,440,140&i2=25,440,140&i3=37,440,140,ie,37,450,150"];
[[Playtomic PlayerLevels] saveAsyncLevel:level andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestSavePlayerLevelsFinished:(PlaytomicResponse*)response
{
if([response success])
{
self.levelid = [response getValueForName:@"LevelId"];
NSLog(@"Save asynchronous succeeded: %@", levelid);
}
else
{
NSLog(@"Save asynchronous failed because of errorcode #%d", [response errorCode]);
}
}
[[Playtomic PlayerLevels] saveLevel:level];
| Parameter | Type | Description |
|---|---|---|
| level | PlaytomicLevel | An instance of PlaytomicLevel holding the level data |
Example saving level:
PlaytomicLevel *level = [[PlaytomicLevel alloc] initWithName:@"level name"
andPlayerName:@"ben"
andPlayerId:0
andData:@"r=-152&i0=13,440,140&i1=24,440,140&i2=25,440,140&i3=37,440,140"];
PlaytomicResponse *response = [[Playtomic PlayerLevels] saveLevel:level];
if([response success])
{
NSLog(@"Save succeeded");
}
else
{
NSLog(@"Save failed because of errorcode #%d", [response errorCode]);
}
Levels can be rated 1 - 10 by players. Rating can be done anonymously with some protection against repeat voting, or bound to PlayerIds if you specify them.
[[Playtomic PlayerLevels] rateAsyncLevelid:levelid andRating:8 andDelegate:self];
| Parameter | Type | Description |
|---|---|---|
| levelid | NSString | A level id, which you can retrieve via [level getLevelId] |
| rating | NSInteger | 1 - 10 |
| delegate | id<PlaytomicDelegate> | A reference to an object which implements the method requestRatePlayerLevelsFinished from the protocol PlaytomicDelgate |
To call this method your class must implement the method requestRatePlayerLevelsFinished from the protocol PlaytomicDelegate:
- (void)requestRatePlayerLevelsFinished:(PlaytomicResponse*)response;
Example rating level:
- (void)levelRateAsync
{
[[Playtomic PlayerLevels] rateAsyncLevelid:levelid andRating:8 andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestRatePlayerLevelsFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"Rate asynchronous succeeded");
}
else
{
NSLog(@"Rate asynchronous failed because of errorcode #%d", [response errorCode]);
}
}
PlaytomicResponse *response = [[Playtomic PlayerLevels] rateLevelid:levelid andRating:id];
| Parameter | Type | Description |
|---|---|---|
| levelid | NSString | A level id, which you can retrieve via [level getLevelId] |
| rating | NSInteger | 1 - 10 |
Example rating level:
PlaytomicResponse *response = [[Playtomic PlayerLevels] rateLevelid:[level getLevelId] andRating:8];
if([response success])
{
NSLog(@"Rate succeeded");
}
else
{
NSLog(@"Rate failed because of errorcode #%d", [response errorCode]);
}
Listing levels can be done by popular or newest, with optional filtering by date ranges and/or custom Playtomic.Data.
[[Playtomic PlayerLevels] listModeAsync:@"popular"
andPage:1
andPerPage:10
andIncludeData:NO
andIncludeThumbs:NO
andCustomFilter:nil
andDelegate:self];
[[Playtomic PlayerLevels] listAsyncMode:@"popular"
andPage:1
andPerPage:10
andIncludeData:NO
andIncludeThumbs:NO
andCustomFilter:nil
andDateMin:fromDate
andDateMax:toDate
andDelegate:self];
| Parameter | Type | Description |
|---|---|---|
| mode | NSString | popular or newest |
| andPage: | NSInteger | 1, or determine it yourself |
| andPerPage: | NSInteger | Number of levels to return |
| andIncludeData | Boolean | Return the level data with the lists. This lets you go directly into levels without requesting them individually, but if you are displaying a large list there will be less data to transmit without it. |
| andIncludeThumbs | Boolean | Returns Base64'd strings of the PNG thumbnails if they're provided. You may not use thumbnails, or you may generate them directly from the data. |
| andCustomFilter | NSDictionary | Filter levels based on custom data you stored with them (eg theme or anything else). |
| andDateMin | NSDate | The minimum creation date, eg if you wanted popular levels made this week. |
| andDateMax | NSDate | The maximum creation date, eg if you wanted popular levels made last month. |
| delegate | id<PlaytomicDelegate> | A reference to an object which implements the method requestListPlayerLevelsFinished from the protocol PlaytomicDelgate |
To call this method your class must implement the method requestListPlayerLevelsFinished from the protocol PlaytomicDelegate:
- (void)requestListPlayerLevelsFinished:(PlaytomicResponse*)response;
An example listing levels:
- (void)levelListAsync
{
NSLog(@"Level list asynchronous");
[[Playtomic PlayerLevels] listAsyncMode:@"popular"
andPage:1
andPerPage:10
andIncludeData:NO
andIncludeThumbs:NO
andCustomFilter:nil
andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestListPlayerLevelsFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"%d levels were returned:", [response getNumResults]);
for(PlaytomicLevel *level in [response data])
{
NSLog(@"%@ by %@ on %@ (%@) with %d votes and %d score and %@ rating and %d plays and levelid %@"
, [level getName]
, [level getPlayerName]
, [level getDate]
, [level getRelativeDate]
, [level getVotes]
, [level getScore]
, [level getRating]
, [level getPlays]
, [level getLevelId]);
if([[level getCustomData] count] > 0)
{
NSDictionary *data = [level getCustomData];
for(id x in data)
{
NSLog(@" with custom data %@ = %@", x, [data objectForKey:x]);
}
}
}
}
else
{
NSLog(@"Level list asynchronous failed to load because of errorcode #%d", [response errorCode]);
}
}
PlaytomicResponse *response = [[Playtomic PlayerLevels] listMode:@"popular"
andPage:1
andPerPage:10
andIncludeData:NO
andIncludeThumbs:NO
andCustomFilter:nil];
PlaytomicResponse *response = [[Playtomic PlayerLevels] listMode:@"popular"
andPage:1
andPerPage:10
andIncludeData:NO
andIncludeThumbs:NO
andCustomFilter:nil
andDateMin:fromDate
andDateMax:toDate];
| Parameter | Type | Description |
|---|---|---|
| mode | NSString | popular or newest |
| andPage: | NSInteger | 1, or determine it yourself |
| andPerPage: | NSInteger | Number of levels to return |
| andIncludeData | Boolean | Return the level data with the lists. This lets you go directly into levels without requesting them individually, but if you are displaying a large list there will be less data to transmit without it. |
| andIncludeThumbs | Boolean | Returns Base64'd strings of the PNG thumbnails if they're provided. You may not use thumbnails, or you may generate them directly from the data. |
| andCustomFilter | NSDictionary | Filter levels based on custom data you stored with them (eg theme or anything else). |
| andDateMin | NSDate | The minimum creation date, eg if you wanted popular levels made this week. |
| andDateMax | NSDate | The maximum creation date, eg if you wanted popular levels made last month. |
An example listing levels:
PlaytomicResponse *response = [[Playtomic PlayerLevels] listMode:@"popular"
andPage:1
andPerPage:10
andIncludeData:NO
andIncludeThumbs:NO
andCustomFilter:nil];
if([response success])
{
NSLog(@"%d levels were returned:", [response getNumResults]);
for(PlaytomicLevel *level in [response data])
{
NSLog(@"%@ by %@ on %@ (%@) with %d votes and %d score and %@ rating and %d plays and levelid %@"
, [level getName]
, [level getPlayerName]
, [level getDate]
, [level getRelativeDate]
, [level getVotes]
, [level getScore]
, [level getRating]
, [level getPlays]
, [level getLevelId]);
if([[level getCustomData] count] > 0)
{
NSDictionary *data = [level getCustomData];
for(id x in data)
{
NSLog(@" with custom data %@ = %@", x, [data objectForKey:x]);
}
}
}
}
else
{
NSLog(@"Level list failed to load because of errorcode #%d", [response errorCode]);
}
If you do not include the data when you load lists of levels then you can request it seperately:
[[Playtomic PlayerLevels] loadAsyncLevelid:levelid];
| Parameter | Type | Description |
|---|---|---|
| levelid | NSString | [level getLevelId] |
To call this method your class must implement the method requestLoadPlayerLevelsFinished from the protocol PlaytomicDelegate:
- (void)requestLoadPlayerLevelsFinished:(PlaytomicResponse*)response;
An example loading a single level
- (void)levelLoadAsync
{
NSLog(@"Level load asynchronous");
[[Playtomic PlayerLevels] loadAsyncLevelid:self.levelid andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestLoadPlayerLevelsFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"%d level was returned:", [response getNumResults]);
for(PlaytomicLevel *level in [response data])
{
NSLog(@"%@ by %@ on %@ (%@) with %d votes and %d score and %@ rating and %d plays and levelid %@"
, [level getName]
, [level getPlayerName]
, [level getDate]
, [level getRelativeDate]
, [level getVotes]
, [level getScore]
, [level getRating]
, [level getPlays]
, [level getLevelId]);
if([[level getCustomData] count] > 0)
{
NSDictionary *data = [level getCustomData];
for(id x in data)
{
NSLog(@" with custom data %@ = %@", x, [data objectForKey:x]);
}
}
NSLog(@" with data %@", [level getData]);
}
}
else
{
NSLog(@"Level failed to load because of errorcode #%d", [response errorCode]);
}
}
PlaytomicResponse *response = [[Playtomic PlayerLevels] loadLevelid:levelid];
| Parameter | Type | Description |
|---|---|---|
| levelid | NSString | [level getLevelId] |
An example loading a single level
PlaytomicResponse *response = [[Playtomic PlayerLevels] loadLevelid:[level getLevelId]];
if([response success])
{
NSLog(@"%d level was returned:", [response getNumResults]);
for(PlaytomicLevel *level in [response data])
{
NSLog(@"%@ by %@ on %@ (%@) with %d votes and %d score and %@ rating and %d plays and levelid %@"
, [level getName]
, [level getPlayerName]
, [level getDate]
, [level getRelativeDate]
, [level getVotes]
, [level getScore]
, [level getRating]
, [level getPlays]
, [level getLevelId]);
if([[level getCustomData] count] > 0)
{
NSDictionary *data = [level getCustomData];
for(id x in data)
{
NSLog(@" with custom data %@ = %@", x, [data objectForKey:x]);
}
}
NSLog(@" with data %@", [level getData]);
}
}
else
{
NSLog(@"Level failed to load because of errorcode #%d", [response errorCode]);
}
The leaderboards API gives you very flexible high and low score Playtomic.Leaderboards. They can be created in your game dynamically or set up in the edit leaderboards page.
The leaderboards use the PlaytomicScore object for representing the players' scores.
| Property | Type | Accessor | Description |
|---|---|---|---|
| name | NSString | getName | The player name. This can be by the player or provided by any 3rd party |
| points | NSInteger | getPoints | The player's score |
| rank | NSInteger | getRank | The player's rank based on the listing criteria you use. |
| date | NSDate | getDate | The date of the score, determined automatically by Playtomic |
| relativeDate | NSString | getRelativeDate | The relative date of the score eg "7 minutes ago", determined automatically by Playtomic |
| customData | NSDictionary | getCustomData | Any additional data you want to (or have) attached to a score, like the level the player reached or what character they used |
| NSString | getCustomValue | Retrieves a custom property. | |
| NSString | addCustomValue | Adds a custom property. |
For some methods there are two versions: one synchronous and one asynchronous. We recomend you to use the asynchronous one because it is not going to freeze your game while the call is executed. Calling the synchronous version is more easy to code and is there for games which are not resource-intensive.
To call the asynchronous methods the caller must implement the protocol PlaytomicDelegate. All the methods in this protocol are optional so you only need to implement the methods you actualy use.
Score submission is handled by:
[[Playtomic Leaderboards] saveAsyncTable:@"High scores"
andScore:score
andHighest:YES
andAllowDuplicates:YES
andDelegate:self];
| Parameter | Type | Description |
|---|---|---|
| table | NSString | The score table to submit to, alphanumeric |
| score | PlaytomicScore | An instance of PlayerScore which contains score information |
| highest | Boolean | Leaderboard tables can be created dynamically from within your game so you specify the mode. |
| allowduplicates | Boolean | If you don't allow duplicates new, worse scores will not be saved by a player. |
| delegate | id<PlaytomicDelegate> | A reference to an object which implements the method requestSaveLeaderboardFinished from the protocol PlaytomicDelgate |
To call this method your class must implement the method requestSaveLeaderboardFinished from the protocol PlaytomicDelegate:
- (void)requestSaveLeaderboardFinished:(PlaytomicResponse*)response;
An example submitting an score
- (void)leaderboardSaveAsync
{
NSLog(@"Leaderboard SaveAsync");
PlaytomicScore *score = [[PlaytomicScore alloc] initNewScoreWithName:@"Ben" andPoints:2000000];
[score addCustomValue:@"customdata" andValue:@"this is the custom data"];
[[Playtomic Leaderboards] saveAsyncTable:@"High scores"
andScore:score
andHighest:YES
andAllowDuplicates:YES
andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestSaveLeaderboardFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"Score saved successfully");
}
else
{
NSLog(@"Leaderboard save failed to load because of errorcode #%d", [response errorCode]);
}
}
Score submission is handled by:
PlaytomicResponse *response = [[Playtomic Leaderboards] saveTable:@"High scores"
andScore:score
andHighest:YES
andAllowDuplicates:YES];
| Parameter | Type | Description |
|---|---|---|
| table | NSString | The score table to submit to, alphanumeric |
| score | PlaytomicScore | An instance of PlayerScore which contains score information |
| highest | Boolean | Leaderboard tables can be created dynamically from within your game so you specify the mode. |
| allowduplicates | Boolean | If you don't allow duplicates new, worse scores will not be saved by a player. |
An example submitting an score
PlaytomicScore *score = [[PlaytomicScore alloc] initNewScoreWithName:@"Ben" andPoints:2000000];
[score addCustomValue:@"character" andValue:@"barbarian"];
PlaytomicResponse *response = [[Playtomic Leaderboards] saveTable:@"HighScores"
andScore:score
andHighest:NO
andAllowDuplicates:NO];
if([response success])
{
NSLog(@"Score saved successfully");
}
else
{
NSLog(@"Leaderboard save failed to load because of errorcode #%d", [response errorCode]);
}
Scores are loaded via a simple method that returns an array of PlayerScore objects to your function where you can display the data in your leaderboard.
[[Playtomic Leaderboards] listAsyncTable:@"High scores"
andHighest:YES
andMode:@"alltime"
andPage:1
andCustomFilter:nil
andDelegate:self];
| Parameter | Type | Description |
|---|---|---|
| table | String | Your leaderboard table name |
| highest | Boolean | If the table does not exist it will be created with this mode. |
| mode | NSString |
The list mode can return scores from:
|
| delegate | id<PlaytomicDelegate> | A reference to an object which implements the method requestListLeaderboardFinished from the protocol PlaytomicDelgate |
To call this method your class must implement the method requestListLeaderboardFinished from the protocol PlaytomicDelegate:
- (void)requestListLeaderboardFinished:(PlaytomicResponse*)response;
An example showing scores
- (void)leaderboardListAsync
{
[[Playtomic Leaderboards] listAsyncTable:@"High scores"
andHighest:YES
andMode:@"alltime"
andPage:1
andPerPage:20
andCustomFilter:nil
andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestListLeaderboardFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"%d scores were returned:", [response getNumResults]);
for(PlaytomicScore *score in [response data])
{
NSLog(@"%@ scored %d on %@"
, [score getName]
, [score getPoints]
, [score getRelativeDate]);
if([[score getCustomData] count] > 0)
{
NSDictionary *data = [score getCustomData];
for(id x in data)
{
NSLog(@" with custom data %@ = %@", x, [data objectForKey:x]);
}
}
}
}
else
{
NSLog(@"Leaderboard listAsync failed to load because of errorcode #%d", [response errorCode]);
}
}
PlaytomicResponse *response = [[Playtomic Leaderboards] listTable:@"High scores"
andHighest:YES
andMode:@"alltime"
andPage:1
andPerPage:20
andCustomFilter:nil];
| Parameter | Type | Description |
|---|---|---|
| table | String | Your leaderboard table name |
| highest | Boolean | If the table does not exist it will be created with this mode. |
| mode | NSString |
The list mode can return scores from:
|
An example showing scores
PlaytomicResponse *response = [[Playtomic Leaderboards] listTable:@"HighScores"
andHighest:NO
andMode:@"alltime"
andPage:1
andPerPage:20
andCustomFilter:nil];
if([response success])
{
NSLog(@"%d scores were returned:", [response getNumResults]);
for(PlaytomicScore *score in [response data])
{
NSLog(@"%@ scored %d on %@", [score getName], [score getPoints], [score getRelativeDate]);
if([[score getCustomData] count] > 0)
{
NSDictionary *data = [score getCustomData];
for(id x in data)
{
NSLog(@" with custom data %@ = %@", x, [data objectForKey:x]);
}
}
}
}
else
{
NSLog(@"Leaderboard list failed to load because of errorcode #%d", [response errorCode]);
}
You can now submit scores and at the same time return the leaderboard page that that score is on.
This combines the Save and List approaches from above:
[[Playtomic Leaderboards] saveAndListAsyncTable:table
andScore:score
andHighest:highest
andAllowDuplicates:allowduplicates
andMode:mode
andPerPage:perpage
andCustomFilter:customfilter
andDelegate:self
PlaytomicResponse *response = [[Playtomic Leaderboards] saveAndListTable:table
andScore:score
andHighest:highest
andAllowDuplicates:allowduplicates
andMode:mode
andPerPage:perpage
andCustomFilter:customfilter
Some important notes:
Scores are no longer available directly via URL as they expect POST data now. You will need to use the HTML5 / JavaScript API for showing scores on your web page, or the Flash or other APIs for embedding them in a SWF or other container.
GameVars let you change the value of key variables in your game any time you want. They must be configured on the edit GameVars page in advance.
You store a bunch of data in Playtomic, have it in your game as a backup for when there's no client connectivity, and then whenever possible, the player can use the most recent values.
For some methods there are two versions: one synchronous and one asynchronous. We recomend you to use the asynchronous one because it is not going to freeze your game while the call is executed. Calling the synchronous version is more easy to code and is there for games which are not resource-intensive.
To call the asynchronous methods the caller must implement the protocol PlaytomicDelegate. All the methods in this protocol are optional so you only need to implement the methods you actualy use.
It is called via:
[[Playtomic GameVars] loadAsync];
You can load variables individually, for instance if you are caching the GameVars you can check a 'version' GameVar to decide whether to reload the full collection.
[[Playtomic GameVars] loadSingleAsync: @"name"];
To call this method your class must implement the method requestLoadGameVarsFinished from the protocol PlaytomicDelegate:
- (void)requestLoadGameVarsFinished:(PlaytomicResponse*)response;
A complete example:
- (void)loadGameVarsAsync
{
NSLog(@"Loading GameVarsAsync");
[[Playtomic GameVars] loadAsync:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestLoadGameVarsFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"%@ = %@", @"GameVar1", [response getValueForName:@"GameVar1"]);
NSLog(@"%@ = %@", @"GameVar2", [response getValueForName:@"GameVar2"]);
}
else
{
NSLog(@"GameVarsAsync failed to load because of errorcode #%d", [response errorCode]);
}
}
PlaytomicResponse *gamevars = [[Playtomic GameVars] load];
PlaytomicResponse *gamevars = [[Playtomic GameVars] loadSingle];
A complete example:
PlaytomicResponse *gamevars = [[Playtomic GameVars] load];
if([gamevars success])
{
NSLog(@"%@ = %@",@"myVar", [gamevars getValue:@"myVar"]);
NSLog(@"%@ = %@",@"otherVar", [gamevars getValue:@"otherVar"]);
}
else
{
NSLog(@"GameVars failed to load because of errorcode #%d", [gamevars errorCode]);
}
The GeoIP service identifies which country the player is from, returning their country code and name.
For some methods there are two versions: one synchronous and one asynchronous. We recomend you to use the asynchronous one because it is not going to freeze your game while the call is executed. Calling the synchronous version is more easy to code and is there for games which are not resource-intensive.
To call the asynchronous methods the caller must implement the protocol PlaytomicDelegate. All the methods in this protocol are optional so you only need to implement the methods you actualy use.
It is called via:
[[Playtomic GeoIP] loadGeoIPAsync];
To call this method your class must implement the method requestLoadGeoIPFinished from the protocol PlaytomicDelegate:
- (void)requestLoadGeoIPFinished:(PlaytomicResponse*)response;
A complete example:
- (void)loadGeoIPAsync
{
NSLog(@"Loading GeoIPAsync");
[[Playtomic GeoIP] loadAsync:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestLoadGeoIPFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"Location code: %@, name: %@"
, [response getValueForName:@"Code"]
, [response getValueForName:@"Name"]);
}
else
{
NSLog(@"GeoIPAsync failed to load because of errorcode #%d", [response errorCode]);
}
}
PlaytomicResponse *lookup = [[Playtomic GeoIP] loadGeoIP];
Using it is very simple:
PlaytomicResponse *lookup = [[Playtomic GeoIP] loadGeoIP];
if([lookup success])
{
NSLog(@"Location code:%@, name:%@", [lookup getValue:@"Code"], [lookup getValue:@"Name"]);
}
else
{
NSLog(@"GeoIP failed to load because of errorcode #%d", [lookup errorCode]);
}
Note: You must enable this functionality in each game's settings. By default it is disabled becaue it can expose your game data.
The Data class in the API allows you to retrieve any of your game data to display in your game.
Each function for retrieving data takes an optional parameters object for day, month and year, with default values of 0.
When the request succeeds the returned data is available via:
[the_response getValue:@"key"];
For some methods there are two versions: one synchronous and one asynchronous. We recomend you to use the asynchronous one because it is not going to freeze your game while the call is executed. Calling the synchronous version is more easy to code and is there for games which are not resource-intensive.
To call the asynchronous methods the caller must implement the protocol PlaytomicDelegate. All the methods in this protocol are optional so you only need to implement the methods you actualy use.
The Views, Plays and PlayTime functions returns this data to you for processing:
To call these methods your class must implement the methods requestViewsDataFinished, requestPlaysDataFinished and requestPlaytimeDataFinished from the protocol PlaytomicDelegate:
- (void)requestViewsDataFinished:(PlaytomicResponse*)response;
- (void)requestPlaysDataFinished:(PlaytomicResponse*)response;
- (void)requestPlaytimeDataFinished:(PlaytomicResponse*)response;
A complete example:
- (void)getViewsAsync
{
NSLog(@"get views asynchronous");
[[Playtomic Data] viewsAsync:self];
[[Playtomic Data] viewsAsyncMonth:1 andYear:2010 andDelegate:self];
[[Playtomic Data] viewsAsyncDay:1 andMonth:1 andYear:2010 andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestViewsDataFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"view data was returned: %@", [response getValueForName:@"Value"]);
}
else
{
NSLog(@"view data failed to load asynchronous because of errorcode #%d", [response errorCode]);
}
}
- (void)getPlaysAsync
{
NSLog(@"get plays asynchronous");
[[Playtomic Data] playsAsync:self];
[[Playtomic Data] playsAsyncMonth:1 andYear:2010 andDelegate:self];
[[Playtomic Data] playsAsyncDay:1 andMonth:1 andYear:2010 andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestPlaysDataFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"play data was returned: %@", [response getValueForName:@"Value"]);
}
else
{
NSLog(@"play data failed to load asynchronous because of errorcode #%d", [response errorCode]);
}
}
- (void)getPlaytimeAsync
{
NSLog(@"get playtime asynchronous");
[[Playtomic Data] playtimeAsync:self];
[[Playtomic Data] playtimeAsyncMonth:1 andYear:2010 andDelegate:self];
[[Playtomic Data] playtimeAsyncDay:1 andMonth:1 andYear:2010 andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestPlaytimeDataFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"playtime data was returned: %@", [response getValueForName:@"Value"]);
}
else
{
NSLog(@"playtime data failed to load asynchronous because of errorcode #%d", [response errorCode]);
}
}
Available keys are:
The CustomMetric function returns data about a custom metric to your function, which receives the same parameters as views/plays/play time above.
To call this method your class must implement the method requestCustomMetricDataFinished from the protocol PlaytomicDelegate:
- (void)requestCustomMetricDataFinished:(PlaytomicResponse*)response;
A complete example:
- (void)getCustomAsync
{
NSLog(@"get custom asynchronous");
[[Playtomic Data] customMetricAsyncName:@"hi" andDelegate:self];
[[Playtomic Data] customMetricAsyncName:@"hi" andMonth:1 andYear:2010 andDelegate:self];
[[Playtomic Data] customMetricAsyncName:@"hi" andDay:1 andMonth:1 andYear:2010 andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestCustomMetricDataFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"custom data was returned: %@", [response getValueForName:@"Value"]);
}
else
{
NSLog(@"custom data failed to load asynchronous because of errorcode #%d", [response errorCode]);
}
}
Available keys are:
Retrieving level metrics is the same as retrieving custom metrics with an additional property for the level name or number.
To call these methods your class must implement the methods requestLevelMetricCounterDataFinished, requestLevelMetricAverageDataFinished and requestLevelMetricRangeDataFinished from the protocol PlaytomicDelegate:
- (void)requestLevelMetricCounterDataFinished:(PlaytomicResponse*)response;
- (void)requestLevelMetricAverageDataFinished:(PlaytomicResponse*)response;
- (void)requestLevelMetricRangeDataFinished:(PlaytomicResponse*)response;
A complete example:
- (void)getMetricAsync
{
NSLog(@"get counter metric asynchronous");
[[Playtomic Data] levelCounterMetricAsyncName:@"hi" andLevel:@"level 1" andDelegate:self];
[[Playtomic Data] levelAverageMetricAsyncName:@"hi" andLevelNumber:@"level 1" andMonth:1 andYear:2010 andDelegate:self];
[[Playtomic Data] levelRangedMetricAsyncName:@"hi" andLevel:@"level 1" andDay:1 andMonth:1 andYear:2010 andDelegate:self];
}
// PlaytomicDelegate protocol implementation
- (void)requestLevelMetricCounterDataFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"counter data was returned: %@", [response getValueForName:@"Value"]);
}
else
{
NSLog(@"counter data failed to load asynchronous because of errorcode #%d", [response errorCode]);
}
}
// PlaytomicDelegate protocol implementation
- (void)requestLevelMetricAverageDataFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"average data was returned: %@", [response getValueForName:@"Value"]);
}
else
{
NSLog(@"average data failed to load asynchronous because of errorcode #%d", [response errorCode]);
}
}
// PlaytomicDelegate protocol implementation
- (void)requestLevelMetricRangeDataFinished:(PlaytomicResponse*)response
{
if([response success])
{
NSLog(@"range data was returned: %@", [response getValueForName:@"Value"]);
}
else
{
NSLog(@"range data failed to load asynchronous because of errorcode #%d", [response errorCode]);
}
}
Available keys are:
The Views, Plays and PlayTime functions returns this data to you for processing:
PlaytomicResponse *views_total = [[Playtomic Data] views]
PlaytomicResponse *views_on_month = [[Playtomic Data] viewsMonth:1 andYear:2010]
PlaytomicResponse *views_on_date = [[Playtomic Data] viewsDay:1 andMonth:1 andYear:2010]
PlaytomicResponse *plays_total = [[Playtomic Data] plays]
PlaytomicResponse *plays_on_month = [[Playtomic Data] playsMonth:1 andYear:2010]
PlaytomicResponse *plays_on_date = [[Playtomic Data] playsDay:1 andMonth:1 andYear:2010]
PlaytomicResponse *playtime_total = [[Playtomic Data] playtime]
PlaytomicResponse *playtime_on_month = [[Playtomic Data] playtimeMonth:1 andYear:2010]
PlaytomicResponse *playtime_on_day = [[Playtomic Data] playtimeDay:1 andMonth:1 andYear:2010]
Available keys are:
The CustomMetric function returns data about a custom metric to your function, which receives the same parameters as views/plays/play time above.
PlaytomicResponse *views_total = [[Playtomic Data] customMetricName:@"hi"]
PlaytomicResponse *views_on_month = [[Playtomic Data] customMetricName:@"hi" andMonth:1 andYear:2010]
PlaytomicResponse *views_on_date = [[Playtomic Data] customMetricName:@"hi" andDay:1 andMonth:1 andYear:2010]
Available keys are:
Retrieving level metrics is the same as retrieving custom metrics with an additional property for the level name or number.
PlaytomicResponse *views_total = [[Playtomic Data] levelCounterMetricName:@"hi" andLevel:@"level 1"]
PlaytomicResponse *views_on_month = [[Playtomic Data] levelAverageMetricName:@"hi" andLevelNumber:@"level 1" andMonth:1 andYear:2010]
PlaytomicResponse *views_on_date = [[Playtomic Data] levelRangedMetricName:@"hi" andLevel:@"level 1" andDay:1 andMonth:1 andYear:2010]
Available keys are:
When a Playtomic service is unreachable or has an error it will return a numeric error code. This table describes those errors:
These errors may be returned from any service.
| Code | Meaning |
|---|---|
| 0 | No error |
| 1 | General error, this typically means the player is unable to connect to the Playtomic servers |
| 2 | Invalid game credentials. Make sure you use your SWFId and GUID from the "API" section in the dashboard. |
| 3 | Request timed out. |
| 4 | Invalid request. This means the request wasn't formed right, probably because the API key wasn't provided or was incorrect. |
| Code | Meaning |
|---|---|
| 100 | GeoIP API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| Code | Meaning |
|---|---|
| 200 | Leaderboard API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| 201 | The source URL or name weren't provided when saving a score. Make sure the player specifies a name and the game is initialized before anything else using the code in the "Set your game up" section. |
| 202 | Invalid auth key. You should not see this normally, players might if they tamper with your game. |
| 203 | No Facebook user id on a score specified as a Facebook submission. |
| 204 | Table name wasn't specified for creating a private leaderboard. |
| 205 | Permalink structure wasn't specified: http://website.com/game/whatever?leaderboard= |
| 206 | Leaderboard id wasn't provided loading a private leaderboard. |
| 207 | Invalid leaderboard id was provided for a private leaderboard. |
| 208 | Player is banned from your leaderboard. |
| 209 | SaveAndList only. The score was not the player's best score. You can message the player, highlight their best via the SubmittedOrBest boolean property of scores, or override this by setting allowduplicates to true. |
| Code | Meaning |
|---|---|
| 300 | GameVars API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| Code | Meaning |
|---|---|
| 400 | Level sharing API has been disabled. This may occur if your game is faulty or overwhelming the Playtomic servers. |
| 401 | Invalid rating value (must be 1 - 10). |
| 402 | Player has already rated that level. |
| 403 | The level name wasn't provided when saving a level. |
| 404 | Invalid image auth. You should not see this normally, players might if they tamper with your game. |
| 405 | Invalid image auth (again). You should not see this normally, players might if they tamper with your game. |
| 406 | The level already exists. This is determined via a hash of the game id, level name, player ip address and name, and source url. |
| Code | Meaning |
|---|---|
| 500 | Data API has been disabled. This may occur if the Data API is not enabled for your game, or your game is faulty or overwhelming the Playtomic servers. |
| Code | Meaning |
|---|---|
| 600 | You have not configured your Parse.com database. Sign up at Parse and then enter your API credentials in your Playtomic dashboard. |
| 601 | No response was returned from Parse. If you experience this a lot let us know exactly what you're doing so we can sort out a fix for it. |
| 6021 | Parse's servers had an error. |
| 602101 | Object not found. Make sure you include the classname and objectid and that they are correct. |
| 602102 | Invalid query. If you think you're doing it right let us know what you're doing and we'll look into it. |
| 602103 | Invalid classname. |
| 602104 | Missing objectid. |
| 602105 | Invalid key name. |
| 602106 | Invalid pointer. |
| 602107 | Invalid JSON. |
| 602108 | Command unavailable. |
Friends, Playtomic has come to an end. Part of this service will live on at Playtomic.org as a self-hosted, open source platform I am continuing to develop in my spare time. The rest is unfortunately finished.