Skip to content

Instantly share code, notes, and snippets.

@arextar
Created August 7, 2012 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arextar/3288302 to your computer and use it in GitHub Desktop.
Save arextar/3288302 to your computer and use it in GitHub Desktop.
Pine API ideas
/* Notes:
* Methods that modify the progress of the achievement have a notify option.
This option tells whether or not the user should be notified about the
achievement by the native UI (some sort of popup in the corner and maybe
a sound)
* The plan for this API is to perform network IO asynchrnously in the
background while using data cached by the Pine library to make the
API feel synchronous. Essentially, the progress of each achievement
will be loaded when the game is loaded and will be used for any
get operations with this API. An async request is put out when an
achievement is changed to change it in the database, and the data
cached in the Pine library is updated as well for future gets.
*/
// pine.getAchievements([query])
var achievements = pine.getAchievements({
complete: false // Search for incomplete achievements
}) // => [pine.Achievement]
var achieve = achievements[0]
achieve.title // => string : title of achievment
achieve.desc // => string : description of achievment
achieve.icon // => string : path to icon of achievement
achieve.progress // => number : progress to goal
achieve.goal // => number : goal of achievement
achieve.complete // => bool : whether the achievement is completed
// pine.Achievement#incr(amount[, config])
achieve.incr(5, {notify: false}) // => bool : whether achievement was unlocked by this call
// pine.Achievement#set(amount[, config])
achieve.set(5, {notify: false}) // => bool : whether achievement was unlocked by this call
// pine.Achievement#unlock([config])
achieve.unlock()
// pine.incrAchievement(name, amount[, config])
pine.incrAchievement("kill_10_zombies", 5, {notify: false}) // => false (true if unlocked)
// pine.setAchievement(name, amount[,config])
pine.setAchievement("kill_10_zombies", 9, {notify: false}) // => false (true if unlocked)
// pine.unlockAchievement(name[, config])
pine.unlockAchievement("kill_10_zombies")
// pine.getAchievement(name)
pine.getAchievement("kill_10_zombies") // => 10
// pine.completedAchievement(name)
pine.completedAchievement("kill_10_zombies") // => true
// Triggered whenever an achievement is unlocked (overrides native notifications)
pine.on('achievement', function (achieve) {
achieve.title // => string : title of achievement
achieve.desc // => string : description of achievement
achieve.icon // => string : path to achievement icon
})
// Returns an array of pine.Friend
var friends = pine.getFriends({
online: true, // Search for friends who are online...
connected: false // and are not currently connected with you on multiplayer.
})
var friend = friends[0]
friend.name // => string : username of friend
friend.online // => boolean : true if friend is online
friend.connected // => boolean : true if connected with the friend over multiplayer (note: this does not necessarily reflect that there is a connection to the friend from the player, only that they are in a multiplayer room with the player)
// Triggered whenever a friend comes online/offline (overrides native notifications if present)
pine.on('friend', function (friend) {
// friend is an instance of pine.Friend
})
/*
This is a very rough outline for the API because I would
like to get some feedback on the basic idea before making
a more formal documentation
*/
// Set up room
function init_room (room) {
prepare_screen_for_multiplayer()
// Send initiation data
room.init({
appearance: player.appearance()
})
// 'user' is an object containing information about the joined user (instance of pine.Friend)
// 'init' holds information sent as a handshake to the rest of the players.
// 'events' is an emitter listening for events on that player
room.on('join', function (user, init, events) {
var character = render_new_user(user.name, init.appearance)
// 'events'
events.on('move', function (x, y) {
character.moveTo(x, y)
})
})
// The 'emits' method on emitters returns a function to emit the given event using the passed arguments
// (essentially pipes the event in this case)
player.on('move', room.emits('move'))
}
function invite_friends () {
var room = pine.createRoom()
// Invite all friends online, but only accept the first 5
room.invite(pine.getFriends({online: true}), "{me} has invited you to play a game", 5)
init_room(room)
}
// listen for an invite (over-rides native UI)
pine.on('invite', function (host, message, cb) {
display_invite_notification(message, function (confirm) {
cb(confirm, function (success) {
if (!success) display_failure_notification()
})
})
})
pine.on('multiplayer', init_room)
/*
This API is for storing arbitrary data associated with the game that
is saved on the local device and may, in the future, be backed up and
synced to other devices. It uses simple key, value storage, and it
supports the concept of multiple save files. All the data is saved
in the background as it's set.
*/
var profile = pine.getProfile('save_1')
// profile.sub creates a sub-store and makes it easier to namespace
var player = profile.sub('player')
player.set('name', 'Joe')
// profile.sub only prefixes the key, so the data is still accessible from the main profile object
player.get('name') // => 'Joe'
profile.get('player.name') // => 'Joe'
// profile.subArray creates an object for storing an array of data
var inventory = player.subArray('inventory')
// Add items
inventory.push({id: 'apple'})
inventory.push({id: 'sandwich'})
// Get data from array
inventory.at(0).id // => 'apple'
inventory.length // => 2
@jeremyckahn
Copy link

Overall this seems really solid. I just have a few remarks:

  • When you say that this API is synchronous, do you mean that that it is making synchronous AJAX calls? If so, we need to find a way around that. Having the game hang on network requests is going to cause perceived performance issues, so we need to find a way to handle asynchronous network IO.
  • I like the API in achievements.js, but I have a suggestion: instead of many formal parameters, how about a string (for the achievement name) and a configuration Object? We could follow this pattern for all of the achievements APIs. This gives us a consistent API, as well as the freedom to add to any of the APIs without breaking anything for developers as they upgrade.

The rest looks good to me, but I think @lstebner should have a look as well.

@jeremyckahn
Copy link

An example of my API suggestion, for clarity:

pine.incrAchievement("kill_10_zombies", { amount: 5, notify: false })

@arextar
Copy link
Author

arextar commented Aug 8, 2012

I agree with the idea of a config object, but I don't think amount should be in it. I've updated the gist with your suggestions by adding the config object and clarifying what I meant by synchronous.

@jeremyckahn
Copy link

/* This API is currently synchronous because it's simpler that way. My plan
   is that the data management will be handled asynchronously in the background,
   and that data is loaded up and cached when the game starts to allow sync gets.
   This is a pattern I'd like to replicate in other Pine APIs.
*/

Looks like you mistyped the end of the second sentence, so it's unclear what you mean. Could you please reword that?

@arextar
Copy link
Author

arextar commented Aug 9, 2012

I hope that clears things up. I was trying to write the plans concisely, but I think this just needed more explanation than I was trying to give. The API just gives the appearance of being synchronous using caching. I think this will make code look better and be more performant than getting the data asynchronously every time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment