Superpowers UI : Les bases + faire un bouton !

Salut et Bienvenue sur mon tout premier article. Nous y verrons les bases de la création d'une interface utilisateur sur Superpowers, qui sont bien souvent pas super-simple à faire !

Bon passons au vif du sujet :


Chapitre 1 : Les bases


Tout d'abord, il nous faut une caméra orthographique à l'intérieur de notre scène :

Antarka-Superpowers

Si votre jeu est 3D, il n'y a aucun mal à avoir une caméra Perspective et Orthographique dans la même scène, assurez-vous seulement que les deux caméras soient assez éloignées l'une de l'autre.

Souvent le hud est en Vector3( 0 , 0 , 10000 )

Ensuite, il nous faut créer un script que nous allons nommer "HUD" et remplissez le comme ceci :

class HUDBehavior extends Sup.Behavior {  
  awake() {
    Sup.log("HUD Awake!");
  }

  update() {
  }
}
Sup.registerBehavior(HUDBehavior);  

Relié ce script à la caméra présente dans notre scène :

Antarka-Superpowers

Dernier point : N'oubliez pas de configurer votre scène en startup scene dans les settings de superpowers.

Vérifier que le jeu ce lance bien et que dans votre console il y a un HUD Awake!


Chapitre 2 : Rayon et bouton


Maintenant attaquons les choses sérieuses. Je vais vous apprendre à créer un behavior bouton (vous n'aurez plus qu'à le mettre où vous voulez et configurer les actions comme bon vous semble, sans refaire 20 fois le même script).

Pour ce chapitre il vous faut un sprite qui fera office de bouton ainsi qu'une Font pour mettre un label à votre bouton. (J'utilise personnellement Exo dans ce tutoriel).

Antarka-Superpowers

Image du bouton : https://i.imgur.com/OH29cX2.png

Lien de la font Exo : https://www.google.com/fonts/specimen/Exo


Etape 1 : Création d'un rayon sur le script HUD

Nous allons créer un rayon qui va nous permettre de savoir si la souris est au-dessus de notre sprite/acteur. Ceci nous servira un peu plus tard dans le script bouton.

Ouvrez votre behavior "HUD" et remplissez le comme ceci :

var Rayon : Sup.Math.Ray; // on crée une variable global pour l'utiliser dans le behavior button

class HUDBehavior extends Sup.Behavior {  
  awake() {
    Rayon = new Sup.Math.Ray(this.actor.getPosition(),new Sup.Math.Vector3(0,0,-1)); // -1z ou 1z en fonction de la position de la caméra, le plus souvent -1z.
    Rayon.setFromCamera(this.actor.camera,Sup.Input.getMousePosition());
  }
  update() {
    Rayon.setFromCamera(this.actor.camera,Sup.Input.getMousePosition()); // Le rayon prend la direction de la souris par rapport à notre caméra.
  }
}
Sup.registerBehavior(HUDBehavior);  

La variable Rayon déclarée en global est très importante. Notez qu'elle peut être déclarée dans un script tout en haut de votre projet.


Etape 2 : Notre bouton

Maintenant vous allez créer un behavior "Button" et le lié à votre bouton présent dans la scène. Ouvrez ce script et développons ensemble étape par étape. Tout d'abord, propriétés et méthode awake :

class ButtonBehavior extends Sup.Behavior {

  public isHover : boolean = false;

  awake() {
    // Définissons nos actions ici !
    this.actor["onclick"] = null;
    this.actor["hover"] = null;
    this.actor["unhover"] = null;
  }

}
Sup.registerBehavior(ButtonBehavior);  

La propriété isHover est un boolean qui nous permet de savoir si la souris est sur le bouton.

Ensuite, il nous faut lier les actions de nos choix à l'acteur.

Maintenant il nous faut créer une méthode qui va être capable d'appeler nos actions seulement si elles existent.

private call(action: string) : void {  
  if(this.actor[action] && this.actor[action] instanceof Function) { // On vérifie que l'action existe bien.
    this.actor[action](this); // => On passe le behavior en argument du callback.
  }
}

Nous vérifions que l'action n'est pas undefined ou null et que l'action est bien une instance d'une fonction.

Vous pouvez renvoyer tous ce que vous voulez à votre callback.

Passons à la boucle update, tout d'abord il nous faut savoir si la souris intersect notre acteur ou non :

update() {  
  // Lorsque le rayon est sur notre sprite
  if(Rayon.intersectActor(this.actor,false).length > 0) { 

  }
  else { // => Lorsque la souris n'est pas sur notre sprite

  }
}

Pour finir nous allons y ajouter nos actions :

update() {  
  if(Rayon.intersectActor(this.actor,false).length > 0) {
    // Si hover == false, alors on re-déclare isHover a true
    if(!this.isHover) {
      this.isHover = true;
      this.call("hover");
    }

    // Lorsque l'on click notre bouton : 
    if(Sup.Input.wasMouseButtonJustPressed(0)) { 
      this.call("onclick");
    }
  }
  else { 
    // Si hover == true alors on re-déclare isHover a false
    if(this.isHover) {
      this.isHover = false;
      this.call("unhover");
    }
  }
}

Le tout fonctionne très simplement grâce à notre boolean isHover !


Le script entier :

class ButtonBehavior extends Sup.Behavior {

  public isHover : boolean = false;

  awake() {
    this.actor["onclick"] = null;
    this.actor["hover"] = null;
    this.actor["unhover"] = null;
  }

  private call(action: string) : void {
    if(this.actor[action]) { 
      this.actor[action](this); 
    }
  }

  update() {
    if(Rayon.intersectActor(this.actor,false).length > 0) {
      if(!this.isHover) {
        this.isHover = true;
        this.call("hover");
      }
      if(Sup.Input.wasMouseButtonJustPressed(0) && this.isHover) {
        this.call("onclick");
      }
    }
    else { 
      if(this.isHover) {
        this.isHover = false;
        this.call("unhover");
      }
    }
  }
}
Sup.registerBehavior(ButtonBehavior);  

Pour finir

Retournez dans votre script "HUD" et ajouter la méthode start :

start() {  
  let button : Sup.Actor = Sup.getActor("button");
  button["hover"] = (self: ButtonBehavior) => {
    Sup.log("Hover button!");
  }
  button["onclick"] = (self: ButtonBehavior) => {
    Sup.log("Clicked!");
  }
}

Et voilà vous avez un behavior "button" et vous pouvez éditer les actions de vos boutons de n'importe quel scripts !

Si vous avez besoin d'aide trouver moi sur twitter @fraxken

Bye bye!