Services pour iOS

Actuellement, il existe deux API iOS partiellement implémentées, GameCenter et Storekit. Toutes deux utilisent le même modèle d'appels asynchrones expliqué ci-dessous.

Méthodes asynchrones

Lors de la demande d'une opération asynchrone, la méthode ressemblera à ceci :

Error purchase(Variant p_params);

Le paramètre sera généralement un Dictionnaire, avec les informations nécessaires pour faire la requête, et l'appel aura deux phases. Tout d'abord, la méthode retournera immédiatement une valeur d'erreur. Si l'erreur n'est pas 'OK', l'opération d'appel est terminée, avec une erreur probablement causée localement (pas de connexion internet, API mal configurée, etc). Si la valeur d'erreur est 'OK', un événement de réponse est produit et ajouté à la file d'attente des 'pending events'. Exemple :

func on_purchase_pressed():
    var result = InAppStore.purchase( { "product_id": "my_product" } )
    if result == OK:
        animation.play("busy") # show the "waiting for response" animation
    else:
        show_error()

# put this on a 1 second timer or something
func check_events():
    while InAppStore.get_pending_event_count() > 0:
        var event = InAppStore.pop_pending_event()
        if event.type == "purchase":
            if event.result == "ok":
                show_success(event.product_id)
            else:
                show_error()

N'oubliez pas que lorsqu'un appel renvoie OK, l'API produira toujours un événement via l'interface pending_event, même s'il s'agit d'une erreur, ou d'un dépassement de temps du réseau, etc. Vous devriez pouvoir, par exemple, bloquer en toute sécurité l'interface en attente d'une réponse du serveur. Si l'une des API ne se comporte pas de cette manière, cela doit être traité comme un bogue.

L'interface des événements en attente se compose de deux méthodes :

  • get_pending_event_count() Renvoie le nombre d'événements en attente dans la file d'attente.
  • Variant pop_pending_event() Extrait(pops) le premier événement de la file d'attente et le renvoie.

Kit de magasin

Implémenté dans platform/iphone/in_app_store.mm.

L'API du kit de magasin est accessible par le singleton "InAppStore" (sera toujours disponible à partir de gdscript). Elle est initialisée automatiquement. Il existe trois méthodes d'achat :

  • Error purchase(Variant p_params);
  • Error request_product_info(Variant p_params);
  • Error restore_purchases();

et l'interface pending_event

int get_pending_event_count();
Variant pop_pending_event();

acheter

Achète un identifiant de produit par l'intermédiaire de l'API du kit de magasin.

Paramètres

Prend un dictionnaire comme paramètre, avec un champ, product_id, une chaîne de caractère(string) avec votre identifiant de produit. Exemple :

var result = InAppStore.purchase( { "product_id": "my_product" } )

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En cas d'erreur :

{
  "type": "purchase",
  "result": "error",
  "product_id": "the product id requested"
}

En cas de succès :

{
  "type": "purchase",
  "result": "ok",
  "product_id": "the product id requested"
}

request_product_info

Demande l'information sur le produit dans une liste d'identifiants de produits.

Paramètres

Prend un dictionnaire comme paramètre, avec un champ, product_ids, un tableau de chaînes de caractères avec une liste d'identifiants de produits. Exemple :

var result = InAppStore.request_product_info( { "product_ids": ["my_product1", "my_product2"] } )

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

{
  "type": "product_info",
  "result": "ok",
  "invalid_ids": [ list of requested ids that were invalid ],
  "ids": [ list of ids that were valid ],
  "titles": [ list of valid product titles (corresponds with list of valid ids) ],
  "descriptions": [ list of valid product descriptions ] ,
  "prices": [ list of valid product prices ],
  "localized_prices": [ list of valid product localized prices ],
}

restore_purchases

Restaure les achats effectués précédemment sur le compte de l'utilisateur. Cela créera des événements de réponse pour chaque identifiant de produit acheté précédemment.

Événement de réponse

Les événements de réponse seront des dictionnaires avec les champs suivants :

{
  "type": "restore",
  "result": "ok",
  "product id": "product id of restored purchase"
}

Game Center

Implémenté dans platform/iphone/game_center.mm.

The Game Center API is available through the "GameCenter" singleton. It has 9 methods:

  • Error authenticate();
  • bool is_authenticated();
  • Error post_score(Variant p_score);
  • Error award_achievement(Variant p_params);
  • void reset_achievements();
  • void request_achievements();
  • void request_achievement_descriptions();
  • Error show_game_center(Variant p_params);
  • Error request_identity_verification_signature();

plus l'interface standard d'événement en attente.

authenticate

Authenticates a user in Game Center.

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En cas d'erreur :

{
  "type": "authentication",
  "result": "error",
  "error_code": the value from NSError::code,
  "error_description": the value from NSError::localizedDescription,
}

En cas de succès :

{
  "type": "authentication",
  "result": "ok",
  "player_id": the value from GKLocalPlayer::playerID,
}

post_score

Affiche un score dans le classement du Game Center.

Paramètres

Prend un dictionnaire comme paramètre, avec deux champs :

  • Le score est un nombre flottant
  • category une chaîne de caractères avec le nom de la catégorie

Exemple :

var result = GameCenter.post_score( { "score": 100, "category": "my_leaderboard", } )

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En cas d'erreur :

{
  "type": "post_score",
  "result": "error",
  "error_code": the value from NSError::code,
  "error_description": the value from NSError::localizedDescription,
}

En cas de succès :

{
  "type": "post_score",
  "result": "ok",
}

award_achievement

Modifie la progression d'un achèvement du Game Center.

Paramètres

Prend un dictionnaire comme paramètre, avec 3 champs :

  • name (chaîne de caractères) le nom de l'achèvement
  • progress (float) de l'avancement de l'achèvement de 0,0 à 100,0 (passée à GKAchievement::percentComplete)
  • show_completion_banner (bool) si le Game Center doit afficher une bannière d'achèvement en haut de l'écran

Exemple :

var result = award_achievement( { "name": "hard_mode_completed", "progress": 6.1 } )

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En cas d'erreur :

{
  "type": "award_achievement",
  "result": "error",
  "error_code": the error code taken from NSError::code,
}

En cas de succès :

{
  "type": "award_achievement",
  "result": "ok",
}

reset_achievements

Efface tous les achèvements du Game Center. La fonction ne prend aucun paramètre.

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En cas d'erreur :

{
  "type": "reset_achievements",
  "result": "error",
  "error_code": the value from NSError::code
}

En cas de succès :

{
  "type": "reset_achievements",
  "result": "ok",
}

request_achievements

Demandez tous les achèvements du Game Center sur lesquelles le joueur a progressé. La fonction ne prend aucun paramètre.

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En cas d'erreur :

{
  "type": "achievements",
  "result": "error",
  "error_code": the value from NSError::code
}

En cas de succès :

{
  "type": "achievements",
  "result": "ok",
  "names": [ list of the name of each achievement ],
  "progress": [ list of the progress made on each achievement ]
}

request_achievement_descriptions

Demandez la description de toutes les achèvements du Game Center, quel que soit le progrès réalisé. La fonction ne prend aucun paramètre.

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En cas d'erreur :

{
  "type": "achievement_descriptions",
  "result": "error",
  "error_code": the value from NSError::code
}

En cas de succès :

{
  "type": "achievement_descriptions",
  "result": "ok",
  "names": [ list of the name of each achievement ],
  "titles": [ list of the title of each achievement ]
  "unachieved_descriptions": [ list of the description of each achievement when it is unachieved ]
  "achieved_descriptions": [ list of the description of each achievement when it is achieved ]
  "maximum_points": [ list of the points earned by completing each achievement ]
  "hidden": [ list of booleans indicating whether each achievement is initially visible ]
  "replayable": [ list of booleans indicating whether each achievement can be earned more than once ]
}

show_game_center

Affiche la superposition intégrée du Game Center montrant les classements, les achèvements et les défis.

Paramètres

Prend un dictionnaire comme paramètre, avec deux champs :

  • view (chaîne de caractère) (facultatif) le nom de la vue à présenter. Accepte "default", "leaderboards", "achievements" ou "challenges". La valeur par défaut est "default".
  • leaderboard_name (chaîne de caractère) (optionnel) le nom du classement à présenter. Utilisé uniquement lorsque "view" est "leaderboards" (ou "default" est configuré pour afficher les classements). S'il n'est pas spécifié, le Game Center affichera le classement global.

Exemples :

var result = show_game_center( { "view": "leaderboards", "leaderboard_name": "best_time_leaderboard" } )
var result = show_game_center( { "view": "achievements" } )

Événement de réponse

L'événement de réponse sera un dictionnaire avec les champs suivants :

En clôture :

{
  "type": "show_game_center",
  "result": "ok",
}

Jeux multi-plateformes

Lorsque vous travaillez sur un jeu multi-plateforme, vous n'aurez pas toujours le singleton "GameCenter" à disposition (par exemple lorsque vous travaillez sur PC ou Android). Comme le compilateur gdscript recherche les singletons au moment de la compilation, vous ne pouvez pas vous contenter d'interroger les singletons pour voir et utiliser ce dont vous avez besoin à l'intérieur d'un bloc conditionnel, vous devez également les définir comme des identifiants valides (variable locale ou membre de classe). Voici un exemple de la manière de contourner ce problème dans une classe :

var GameCenter = null # define it as a class member

func post_score(p_score):
    if GameCenter == null:
        return
    GameCenter.post_score( { "value": p_score, "category": "my_leaderboard" } )

func check_events():
    while GameCenter.get_pending_event_count() > 0:
        # do something with events here
        pass

func _ready():
    # check if the singleton exists
    if Globals.has_singleton("GameCenter"):
        GameCenter = Globals.get_singleton("GameCenter")
        # connect your timer here to the "check_events" function