Slick2d, leçon 6 :: Les Triggers

16 février 2014 09:10 Slick2d - Leçons 0-9 Jeux, Slick2d, Tutorial

A cause de mes vacances d'hiver, j'ai pris un peu de retard pour mon 6ieme article. Le code était prêt mais le temps m'as manqué pour le mettre en forme. Aujourd'hui je vous présenterais une de mes solutions pour créer des triggers dans Slick2D sur une carte faite avec Tiled. Pour ce faire j'ajouterai une grotte à notre carte et j'expliquerai comment y entrer ou en sortir.

Préparation

Première chose j'ai ajouté une grotte à notre carte. Je la dessine dans un coin non utilisé de la carte. Bien sur on pourrai utilisé une autre carte mais pour cette exemple ce n'est pas nécessaire. Je complète également le claque logic que nous avons vu dans la leçon précédente.

tuto-slick2d-048-grotte

Un calque vectoriel

Ensuite j'ajoute un calque d'objet que j’appelle trigger de type vectoriel et je dessine dessus à l'aide de l'outil insérer un objet (O) des rectangles qui seront les points d'entrées de ma grotte. Les autre types d'objet vectoriel ne sont pas supporté par slick, cependant le code de slick est simple à corriger si vous le souhaitez .

tuto-slick2d-049-trigger-entree

Ensuite j'édite ces objets et je les appel _eg-1, eg-2 et eg-3 pour entrée grotte 1 (2 et 3). Le nom n'as pas d'importance, mais le type que j'ai définis teleport, lui en aura. J'ajoute également 2 attribut à chaque trigger, dest-x et dest-y, qui sont les coordonnées de téléportation.

tuto-slick2d-050-trigger-entree

A ce stade vous aurez compris que le but est de téléporter le personnage au coordonnées (dest-x, dest-y) quand il rentre dans la zone délimitée par le rectangle. Il ne me reste plus qu’à faire la même chose pour sortir de la grotte.

trigger sortie trigger sortie

Code :: Téléporter

Nous repartons sur le code de la leçon précédente. Nous ajouterons le code de traitement des triggers au début de la méthode update. Le reste ne change pas. Le code est assez simple, on parcourt tous les objets, si le personnage est dans un objet et que celui-ci est de type teleport on récupère les coordonnées dest-x et dest-y pour les assigner au personnage.

@Override
public void update(GameContainer container, int delta) 
        throws SlickException {
    for (int objectID = 0; objectID < map.getObjectCount(0); objectID++) {
        if (x > map.getObjectX(0, objectID)
                && x < map.getObjectX(0, objectID) + map.getObjectWidth(0, objectID)
                && y > map.getObjectY(0, objectID)
                && y < map.getObjectY(0, objectID) + map.getObjectHeight(0, objectID)) {
            if ("teleport".equals(map.getObjectType(0, objectID))) {
                x = Float.parseFloat(map.getObjectProperty(0, objectID, "dest-x", Float.toString(x)));
                y = Float.parseFloat(map.getObjectProperty(0, objectID, "dest-y", Float.toString(y)));
            } 
        }
     }
     // code déplacement du personnage ( cf leçon 3 & 5 ) 
     // code de mise à jour de la caméra ( cf leçon 4 )
}

Arrivé à ce stade normalement votre personnage peu entré et sortir de la grotte.

L'escalier

Dans la grotte vous avez un genre de pente difficile à franchir. En effet dans un jeu, normalement en passant sur ce genre d'obstacle le personnage se déplacera en diagonal tous seul, quand vous le traverserez en horizontal. On va résoudre se problème la aussi avec un trigger de type stair

tuto-slick2d-053-trigger-escalator tuto-slick2d-054-trigger-escalator

Code :: Escalier

Ici on va ajouter un booléen onstair à notre code. Celui-ci indique que le personnage se trouve sur un escalier. Lors du parcourt des triggers on mettra à jour ce booléen.

@Override
public void update(GameContainer container, int delta) 
        throws SlickException {
    onStair = false;
    for (int objectID = 0; objectID < map.getObjectCount(0); objectID++) {
        if (x > map.getObjectX(0, objectID)
                && x < map.getObjectX(0, objectID) + map.getObjectWidth(0, objectID)
                && y > map.getObjectY(0, objectID)
                && y < map.getObjectY(0, objectID) + map.getObjectHeight(0, objectID)) {
            if ("teleport".equals(map.getObjectType(0, objectID))) {
                x = Float.parseFloat(map.getObjectProperty(0, objectID, "dest-x", Float.toString(this.x)));
                y = Float.parseFloat(map.getObjectProperty(0, objectID, "dest-y", Float.toString(this.y)));
            } else if ("stair".equals(map.getObjectType(0, objectID))) {
                 onStair = true;
            }
        }
     }
     // code déplacement du personnage ( cf leçon 3 & 5 ) 
     // code de mise à jour de la caméra ( cf leçon 4 )
}

Ensuite il suffit de modifier la méthode getFuturY() que nous avons vu dans la leçon 5 pour faire en sorte que le personnage se place également sur Y quand il va à gauche ou à droite si celui-ci est sur un escalier.

private float getFuturY(int delta) {
    float futurY = this.y;
    switch (this.direction) {
    case 0: futurY = this.y - .1f * delta; break;
    case 2: futurY = this.y + .1f * delta; break;
    case 1: if (this.onStair) futurY = this.y + .1f * delta; break;
    case 3: if (this.onStair) futurY = this.y - .1f * delta; break;
    }
    return futurY;
}

Ce cas ne prend en compte que les escaliers montant de gauche à droite mais il serai très simple de faire de même pour les autres escaliers.

Code :: Refactoring

Un peu de refactoring car c'est franchement pas joli. On extrait tous ce code dans une méthode updateTrigger

@Override
public void update(GameContainer container, int delta) throws SlickException {
    updateTrigger();
     // code déplacement du personnage ( cf leçon 3 & 5 ) 
     // code de mise à jour de la caméra ( cf leçon 4 )
}

private void updateTrigger() {
    this.onStair = false;
    for (int objectID = 0; objectID < this.map.getObjectCount(0); objectID++) {
        if (isInTrigger(objectID)) {
            if ("teleport".equals(this.map.getObjectType(0, objectID))) {
                teleport(objectID);
            } else if ("stair".equals(this.map.getObjectType(0, objectID))) {
                this.onStair = true;
            }
        }
    }
}

private boolean isInTrigger(int id) {
    return x > map.getObjectX(0, id)
            && x < map.getObjectX(0, id) + map.getObjectWidth(0, id)
            && y > map.getObjectY(0, id)
            && y < map.getObjectY(0, id) + map.getObjectHeight(0, id);
}

private void teleport(int id) {
    this.x = Float.parseFloat(this.map.getObjectProperty(0, id, "dest-x", Float.toString(this.x)));
    this.y = Float.parseFloat(this.map.getObjectProperty(0, id, "dest-y", Float.toString(this.y)));
}

Pour aller plus loin

Je vous est présenté un seul type de trigger de zones. Mais il en existe plein dans des jeux, cela peu être un objet, la fin d'un autre trigger, etc... Dans l'exemple que nous avons vu des triggers ne sont pas très générique, on peu imaginer utiliser un moteur de script comme LUA ou ECMAScript, le script serai dans la carte et serai exécuté lors du déclenchement du trigger. Nous approchons de la fin de ces articles, il ne me reste pas grand chose à vous montrer, la musique ? Le HUD ? et peut être le WebStart ? nous verrons bien.

Ressource

par Shionn, dernière modification le 09 avril 2017 12:37
46 réflexions au sujet de « Slick2d, leçon 6 :: Les Triggers »
  • Romain 17 février 2014 20:41

    Bonjour, je suis actuellement en DUT Informatique, je suis vos leçons pour slick2d, qui j'avoue sont vraiment très bien. Dans cette leçon vous utilisez la méthode :

    • getObjectProperty(0, id, "dest-x"); , quand je l'utilise, il me donne une erreur car il y a normalement 4 paramétrés, comment faire ?

  • Shionn 19 février 2014 22:42

    Nous ne devons pas utilisez la même version de slick. J'utilise le build 237.

    [edit] En effet j'ai fait une erreur dans l’écriture de mon article. Le quatrième argument est la valeur par défaut renvoyé si Slick ne trouve pas la propriété. J'ai mis à jour l'article.

  • nivhell 01 mars 2014 18:27

    Comment faire lorsque qu'on veux se téléporter sur une autre carte car je n'y arrive pas

  • Shionn 01 mars 2014 23:54

    Il y a plusieurs solutions.

    Personnellement j'ajouterai un attribut "dest-map" à mon trigger avec le nom de la carte. Ensuite quand le personnage rentre dans le trigger je charge cette nouvelle carte. As-tu besoin d'un exemple de code ?

  • nivhell 02 mars 2014 03:42

    oui si possible

  • Shionn 02 mars 2014 08:44

    Ok,

    Je te prépare ça et je te l'envoie par mail. Et ça me ferra un sujet pour la semaine prochaine ;)

  • nivhell 02 mars 2014 16:09

    ok merci

  • Quentin 09 mars 2014 10:21

    bonjour,

    pourrai-je avoir l'exemple de code également ? cela m’intéresse beaucoup !

  • Shionn 10 mars 2014 06:47

    Mieux que cela, maintenant l’article sur le changement de carte est disponible c'est la leçon 9.

  • Kévin 26 septembre 2014 09:54

    Bonjour,

    J'ai un problème avec ma map lorsque j'ajoute un objet dans Tiled Map Editor, ma map ne fonctionne plus dans mon programme java. Alors que avant tout fonctionne parfaitement.

    Je code avec NetBeans et j'ai l'erreur suivante :

    Fri Sep 26 10:51:12 CEST 2014 ERROR:For input string: ""
    java.lang.NumberFormatException: For input string: ""
    	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    	at java.lang.Integer.parseInt(Integer.java:504)
    	at java.lang.Integer.parseInt(Integer.java:527)
    	at org.newdawn.slick.tiled.TiledMap$ObjectGroup.(TiledMap.java:1008)
    	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:688)
    	at org.newdawn.slick.tiled.TiledMap.(TiledMap.java:106)
    	at org.newdawn.slick.tiled.TiledMap.(TiledMap.java:90)
    	at classes.Map.init(Map.java:20)
    	at classes.GameState.init(GameState.java:41)
    	at org.newdawn.slick.state.StateBasedGame.init(StateBasedGame.java:171)
    	at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:393)
    	at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:317)
    	at classes.FreeKingdom.main(FreeKingdom.java:37)
    Fri Sep 26 10:51:12 CEST 2014 ERROR:Failed to parse tilemap
    org.newdawn.slick.SlickException: Failed to parse tilemap
    	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:695)
    	at org.newdawn.slick.tiled.TiledMap.(TiledMap.java:106)
    	at org.newdawn.slick.tiled.TiledMap.(TiledMap.java:90)
    	at classes.Map.init(Map.java:20)
    	at classes.GameState.init(GameState.java:41)
    	at org.newdawn.slick.state.StateBasedGame.init(StateBasedGame.java:171)
    	at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:393)
    	at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:317)
    	at classes.FreeKingdom.main(FreeKingdom.java:37)
    Caused by: java.lang.NumberFormatException: For input string: ""
    	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    	at java.lang.Integer.parseInt(Integer.java:504)
    	at java.lang.Integer.parseInt(Integer.java:527)
    	at org.newdawn.slick.tiled.TiledMap$ObjectGroup.(TiledMap.java:1008)
    	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:688)
    	... 8 more
    

    Est-ce que quelqu'un peut m'aider ?

  • Shionn 26 septembre 2014 13:01

    Bien sur envoie moi ta map par email, pour que je regarde.

    Je suis sur que ton problème proviens que tu as mis autre chose que des rectangles en objet. chose que la version courante de slick ne supporte pas :]

  • Schreinemachers Martin 16 novembre 2014 10:00

    Bonjour,

    Je suis en train de suivre ce tutoriel et j'ai eu exactement la même erreur que Kévin et la cause est un peu différente : j'utilise Tiled 0.10.2 et Eclipse Luna (4.4) sous windows 7. L'erreur provient du fait que Tiled ne donne pas (plus ?) de taille au "container" d'objet. Ligne tirée de ton "exemple-avec-grotte.tmx" :

    Ligne tirée de mon code : . En rajoutant une taille (width et height ), ca a réglé le problème.

    J'ai remarqué aussi la présence de l'attribut renderorder dans la balise tout au début mais, elle n'a aucun effet sur la carte.

    Un grand merci pour ces tutoriels ! :)

  • Shionn 17 novembre 2014 08:24

    Bonjour,

    Merci pour ces informations, j'essayerai de reproduire ce problème. Je suis surpris de cette régression ou évolution ? Je pense que je vais finir par brancher Slick2D et maintenir sur une branche public ce genre de bug !

  • Martin Schreinemachers 17 novembre 2014 18:19

    J'ai vu que tu programmais sous linux ? Cela pourrait être une spécificité de la version windows de Tiled.

  • Shionn 17 novembre 2014 21:51

    En effet je code sous linux, par pure feignantise. C'est une bonne piste que tu évoques, mais il n'en est rien. J'utilise simplement une veille version de Tiled (0.9.1 de mémoire)

    Sur le bitbucket de Slick2D. J'ai vu qu'il existait quelques demandes pour corriger le bug que vous évoquez. Peu être un jour cela sera fait ;)

  • Alexandre Fontaine 30 décembre 2014 11:54

    Avez vous résolu ce problème avec les objets dans les maps ?

    Merci d'avance.

  • Shionn 30 décembre 2014 13:25

    Tu parle du probleme exprimee precedement sur les numberformat exception ?

    C'est un probleme au niveau de slick avec les dernieres vesion de tiled. La solution la plus simple consiste a utilise une version plus ancienne de tiled ou alors ajouter les attribut mentionnés precedement.

  • Darkytzal 02 février 2015 20:01

    Je confirme, j'ai le même problème avec les objets, et ça vient bien de la version de Tiled.

    Pour ceux qui ont aussi un problème avec les objets et qui comme moi n'ont pas compris qu'est-ce qu'il rajouter et où, j'ai trouvé un lien de téléchargement de Tiled 0.9.1 : http://sourceforge.net/projects/tiled/files/latest/download (ce lien lance directement le téléchargement). Pour ceux qui ont des doutes sur le lien, je laisse le lien avant le téléchargement : http://sourceforge.net/projects/tiled/ .

  • Shionn 02 février 2015 20:45

    Merci beaucoup pour ces liens.

    Je me rend compte qu'il faut que je mette a jour cet article !

  • Vincent 15 mars 2015 16:59

    Bonjour, j'ai un problème avec ma map lorsque je veux coder le téléport :

    Sun Mar 15 16:57:21 CET 2015 ERROR:Failed to parse tilemap
    org.newdawn.slick.SlickException: Failed to parse tilemap
    	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:695)
    	at org.newdawn.slick.tiled.TiledMap.(TiledMap.java:106)
    	at org.newdawn.slick.tiled.TiledMap.(TiledMap.java:90)
    	at lesson1.WindowGame.init(WindowGame.java:46)
    	at org.newdawn.slick.AppGameContainer.setup(AppGameContainer.java:393)
    	at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:317)
    	at lesson1.WindowGame.main(WindowGame.java:151)
    Caused by: java.lang.NumberFormatException: For input string: ""
    	at java.lang.NumberFormatException.forInputString(Unknown Source)
    	at java.lang.Integer.parseInt(Unknown Source)
    	at java.lang.Integer.parseInt(Unknown Source)
    	at org.newdawn.slick.tiled.TiledMap$ObjectGroup.(TiledMap.java:1008)
    	at org.newdawn.slick.tiled.TiledMap.load(TiledMap.java:688)
    	... 6 more
    

    J'ai pourtant bien utilisé des rectangles en objets .. merci !

  • Shionn 15 mars 2015 17:33

    C'est parce que tu utilise une version de Tiled trop récente. utilise une version plus ancienne, ou édite la carte avec un éditeur text et cherche la balise :

    <objectgroup name="..." >
    

    Ajoute dedans deux attributs comme ceci :

    <objectgroup name="..." width="100" height="100">
    

    Prend les mêmes valeur que pour les balises layer.

  • Johnny Guye 05 avril 2015 11:10

    Bonjour,

    j'ai eu le même problème que Vincent sur les layers Object, et j'aimerais trouver une solution plus durable que de changer manuellement les attributs. Est-il possible de rajouter cela dans le code de Tiled (le must !) ou de changer le code de Slick2D pour qu'il corrige le problème de Tiled ?

    Sinon, excellent tuto, en partant des éléments de base du tuto, j'ai pu coder un PathFinding qui fonctionne bien (même si Slick le fait très bien aussi) et faire une sorte de Zelda où ça se frite sur la map, il me manquait plus que les interactions avec le décors !

    Merci !

  • Shionn 05 avril 2015 15:22

    Salut

    Slick2d comme tiled, sont des projets open-source. Libre a toi de les forker et de corriger ce problème ;)

    Sinon ce fais un moment que je pense a faire mon fork. Ça viendra peut être un jour...

  • MeMeek 13 mai 2015 10:51

    Problème similaire ici : Lorsque j'ajoute un calque d'objet à ma carte, j'obtient un Failed to parse tilemap. J'ai actuellement la version 0.11.0 de TileD et j'avoue rechigner un peu à l'idée de repasser en 0.9.1. Je me suis donc dirigé vers la solution manuelle en attendant la prochaine version de TileD où j'espère que ce bug sera fixé. Toutefois la solution manuelle ne change rien au problème, même s'il manquait effectivement width et height :

    édité carte non lisible

    Est-ce normal au passage que les layers soient compressés en gzip et non l'objectgroup.

    Bref si il y a une idée relativement simple qu'il vous vient à l'esprit n'hésitez pas ^^. Sinon je me dirigerai peut être vers une version antérieure, en vérifiant dans les pacthnotes antérieures que je ne loupe pas de fonctionnalité qui me sera essentielle par la suite.

    Quoi qu'il en soit, très bonne série de tuto, j'ai pu piocher des idées à droite à gauche. C'est clair, concis et bien motivant!

    Cheers!

  • MeMeek 13 mai 2015 12:52

    Aussi bizarre que cela puisse paraître, j'obtiens exactement le même comportement avec Tiled 0.9.1

    ne pose pas de problème (correspond à un calque vide). En revanche :

       
      
     
    

    ne fonctionne pas (que ce soit pour Tiled 0.9.1 ou 0.11.0)

  • MeMeek 13 mai 2015 14:28

    suite ... (désolé pour le roman)

    Bon après avoir utilisé le débugger d'Eclipse et un peu de trial and error, j'ai pu trouver la source du problème : si on regarde TiledMap.java de slick, on s'apperçoit que l'on fait du parseInt sur les paramètres x,y,width et height de l'objet. Or lorsqu'on fait une carte à l'aide de TileD, l'objet (pas le calque d'objet) est représenté par seulement x,y et facultativement type et name.

    Ma confusion venait du fait qu'on avait déjà rencontré le même problème pour le calque d'objet (1 ligne plus haut) à qui il manquait les paramètres width et height.

    Pour régler ça, soit vous le faites manuellement dans le .xml, soit vous allez dans les propriétés de l'objet cliquant droit dessus dans TileEd, et vous fixez un width et un height. Par défaut il semblerait qu'ils soient les deux à 0, et non-inscrits dans le .xml lorsque nuls.

    Le run est ensuite correct. Nouvelle question : à quoi servent ces height et width de l'objet, sachant que l'objet dans mon cas est un triangle que j'aidessiné et dont les valeurs de height et width ont l'air de ne rien changer au niveau de mon triangle.

    Enfin il est possible que j'ai encore raté quelque chose du côté de TileD puisque mon triangle ne s'affiche pas dans le jeu alors que l'objet est censé être visible (info que je ne trouve d'ailleurs pas dans le .xml ...)

    J'espère arriver au fin mot de cette histoire sans passer par un hack/contournement afin de pourvoir synthétiser un peu ça pour que ce soit un problème recensé.

    Cdlt :)

  • MeMeek 13 mai 2015 14:29

    Hors sujet : Une petite fonction de preview du message aiderait sans doute les distraits des balises comme mew :P

  • MeMeek 13 mai 2015 20:06

    Bon voilà le fin mot de l'histoire. Comme dans 95% des cas, le pb vient de l'utilisateur (du moins en grande partie). Les objets rectangulaires ne posent pas de problème car ils génèrent automatiquement leur width et height.

    Mon soucis provient du fait que je veux passer à une collision par polygones, et utiliser les objets comme moyen de délimiter les zones bloquées au lieu des tiles (j'ai commencé par faire comme dans le tuto avec 1 point, puis je suis passé aux 2 points de la face correspondante à la direction de déplacement, et veux maintenant aborder doucement une collision de polygones avec des vecteurs pour rendre plus sympa le déplacement).

    En gros, tant qu'on se limite aux rectangles, les objets de TileD sont correctement interprétés par slick.

    Le problème vient des polygones qui ne sont pas récupérés par la classe TiledMap de Slick. Je me suis baladé un peu partout toute la journée, et j'ai vu la classe TiledMapPlus qui aurait semblé régler ce problème. Seulement voilà, contrairement à ce que prétendent les posts d'il y a 2 - 3 ans, la classe ne fait pas partie du core de slick. Deux options sont donc à considérer :

    • réaliser cette nouvelle classe soi-même afin de réaliser seulement la prise en charge des polygones (un peu dans cette idée : http://joshbyrom.com/?p=667)
    • reprendre les archives qu'on peut trouver à droite à gauche et faire fonctionner TiledMapPlus comme "add-on" de slick (par exemple avec : https://bitbucket.org/liamzebedee/slick/src/a0eb8178620c/trunk/Slick/src/org/newdawn/slick/tiled/?at=development)

    J'ai tenté la 2eme option sans trop de succés, donc je pense plutôt me diriger vers la création de ma propre classe étendant TiledMap, en implémentant nouveau parcours du DOM pour extraires les données des points du polygone.

    Des conseils en la matière ?

  • Shionn 14 mai 2015 07:42

    Comme je l'ai dis dans le tuto :

    Les autre types d’objet vectoriel ne sont pas supporté par slick, cependant le code de slick est simple à corriger si vous le souhaitez .

    Si cela t’ennuie pas je vais faire un peu de ménage dans tes commentaire (les regrouper). Concernant les balise dans les commentaires, c'est le fonctionnement de wordpress.

  • MeMeek 14 mai 2015 13:27

    Oui n'hésites pas à garder que ce que tu trouves nécessaire. Je suis un peu sorti du cas du tuto, surtout qu'en effet tu l'avais précisé (#têtedansleguidon)

    Si jamais tu comptes allez plus loin dans la collision (par exemple faire une collision glissante/rebondissante) je suis preneur. Je le redis : très bon tuto, et ça donne envie d'aller plus loin :P

    Bonne journée!

  • Shionn 18 mai 2015 09:03

    Navré, j'ai pas de conseil à te donner, la seconde solution me semble la plus simple, si tu arrive a extraire le patch git.

  • Louloutre 12 octobre 2015 09:37

    Salut, j'ai eu les mêmes problèmes que les personnes précédentes, corrigé en supprimant ma version de la carte et en rééditant la tienne avec tiled 0.9.1. J'aimerais permettre au personnage de mon jeu de récolter des objets au sol, pour cela j'ai ajouté des triggers (c'est là que j'ai eu un soucis, mais passons) comme étant des points de spawn de ces objets. J'aurais voulu savoir s'il était possible d'ajouter un int à chaque triggers de spawn (ou un booleen) permettant de dire si il y a un objet dessus ou non ?

    Le but du jeu est de récupérer le plus de ces objets (projet de réseau dont l'objectif est plus de faire un jeu multi qu'un jeu élaboré). Donc le lien entre l'objet à récupérer et le joueur est simplement une incrémentation. La classe triggercontroller à été modifiée en conséquence mais ne me permet pas d'effacer l'objet ainsi pris.

    Aurais-tu une idée ou objet de slick qui me permettrait de faire ça ? je n'ai pas trouvé de tuto à ce sujet (ce qui pourtant devrait être répandu dans le développement de jeu...)

    (et au passage super série de tuto)

  • Louloutre 13 octobre 2015 10:39

    J'ai finalement trouvé par moi même, pour ceux que ça interesse :

    J'ai placé un objet aux coordonnées de mes triggers correspondant aux points de spawn (Ils sont donc fixés à la carte et non à la camera), intégré une condition(booleen) au render pour que l'affichage ne se fasse plus lors que le personnage passe sur le trigger tout en ajoutant un cooldown à cette condition pour que l'objet respawn au bout d'une durée entre 100 et 300 cycle (5-15 sec, variable suivant la puissance de l'ordi/fps ? ).

    Voilà, en espérant aider ceux qui passeront sur le sujet :)

  • Shionn 14 octobre 2015 14:17

    Ravi que tu ai trouvé la solution à ton problème.

    Pour résoudre le problème lié à la performance de la machine il faut réfléchir en duré avec la variable delta plutôt qu'avec un nombre de boucle.

  • Hiyori 01 novembre 2015 16:34

    Bonjour,

    J'en suis au début des triggers donc il faut créer un calque objet "trigger" , puis faire les rectangles avec les destination etc. Or, moi juste quand je crée le calque et je lance le projet, l'écran s'allume puis s’éteint, et j'ai pu remarquer que l'erreur vient de la création de se calque , je ne sais pas si SLICK2D supporte le calque objet ou non, quand j'ouvre mon '.tmx', lorsque j'enlève la ligne : tout redeviens normal. Je voudrais savoir comment définir le calque de type vectoriel, je ne sais pas si l'erreur vient de là ou non.

    Cordialement.

  • Hiyori 01 novembre 2015 16:52

    Rebonjour,

    En lisant les commentaires j'ai pu voir que c'était bien la ligne du qui passait pas car il n'y avait pas les tailles.

    Merci

  • Hiyori 01 novembre 2015 16:53

    Désolé pour ce nouveau post mais il semblerait que la ligne avec objectgroup ne veut pas passer. C'est donc bien objectgroup qui ne passe pas dans le fichier .tmx

    Cordialement

  • Shionn 01 novembre 2015 17:08

    Ce point à été abordé plusieurs fois dans les commentaire la solution y est donné et est également rappelé dans la FAQ ici

  • Impa 12 novembre 2016 20:55

    Salut Shionn ! Merci pour ton aide d'hier qui m'a été grandement utile. Je sollicite ton génie une deuxième fois, j'ai quelques soucis concernant les escaliers.

    Je réussis à faire monter ET descendre mon personnage dans un escalier allant de droite à gauche. Cependant, lors de l'implémentation de l'escalier allant de gauche à droite, je peux soit faire monter, soit faire descendre :

    private float getFuturY(int delta) {
      float futurY = this.y;
      switch (this.direction) {
        case 0: futurY = this.y - .1f * delta; break;
        case 2: futurY = this.y + .1f * delta; break;
        /* ESCALIER HORIZ MONTANT DE DROITE A GAUCHE */
        case 1: if (this.onStairRToL) futurY = this.y - .1f * delta; break;
        case 3: if (this.onStairRToL) futurY = this.y + .1f * delta; break;
      }
      /* ESCALIER HORIZ MONTANT DE GAUCHE A DROITE */
      if (this.onStairLToR) {
        futurY = this.y + .1f * delta;
      } else if (this.onStairLToR) {
        futurY = this.y - .1f * delta;
      }
      return futurY;
    }
    

    Le "switch case" avec la droite-> gauche, fonctionne très bien. Cependant, je ne peux pas (pour une raison inconnue) faire des case 4/5 correspondant à gauche-> droite J'ai ainsi compensé grace à mon "IF" qui se trouve après.

    Cependant, c'est là où se trouve la subtilité, quand j'écris

    /* ESCALIER HORIZ MONTANT DE GAUCHE A DROITE */
    if (this.onStairLToR) {
      futurY = this.y + .1f * delta;
    } else if (this.onStairLToR) {
      futurY = this.y - .1f * delta;
    }
    

    le personnage peut DESCENDRE de l'escalier qui monte de la gauche vers la droite A l'inverse,

    if (this.onStairLToR) {
      futurY = this.y - .1f * delta;
    } else if (this.onStairLToR) {
      futurY = this.y + .1f * delta;
    }
    

    Le personnage peut MONTER dans l'escalier qui monte de gauche à droite

    Je souhaiterai que mon personnage puisse aller et venir dans cet escalier qui monte de gauche à droite J'espere que j'ai été assez explicite et je te remercie pour le temps que tu peux m'accorder

  • Shionn 12 novembre 2016 22:43

    Bonjour Impa, Je te prie de m’excuser je me suis permis d'éditer ton commentaire pour le rendre plus lisible.

    Tu fais une grosse erreur dans ton algo, en effet analyse mieux le code du tuto, dans la méthode getFutureY, on ajoute .1fdelta quand on est sur un escalier (if this.onStair) ET qu'on va à gauche (case 1) et a contrario quand est sur un escalier (if this.onStair) ET qu'on va à droite (case 3), la on enlève .1fdelta sur le calcul de Y.

    D’ailleurs je crois que tu as inversé les deux noms de booléen dans ta logique, n'oublie pas que la coordonnée Y pointe vers le bas.

    Petite erreur de ta part mais également ici le bloque du else if inaccessible :

    if (this.onStairLToR) {
      futurY = this.y - .1f * delta;
    } else if (this.onStairLToR) {
      ici on peu pas y entré
      futurY = this.y + .1f * delta;  
    }
    

    Techniquement ce qu'il faut faire : si je vais à gauche ou à droite ET que je suis sur un escalier qui monte je diminue Y (car la coordonnée y est vers le bas) et si je vais à gauche ou à droite ET que je suis sur un escalier qui descend j'augmente Y :

    private float getFuturY(int delta) {
      float futurY = this.y;
      switch (this.direction) {
        // cas ou monte je diminue Y
        case 0: futurY = this.y - .1f * delta; break; 
        // cas ou descend j'augmente Y
        case 2: futurY = this.y + .1f * delta; break;
        // cas ou je vais à gauche
        case 1: 
          // si je suis sur un escalier qui monte
          if (this.onStairRToL) { 
            // je diminue Y
            futurY = this.y - .1f * delta;
            // sinon si je suis sur un escalier qui descend
          } else if (this.onStairLToR) {
            // j'augmente Y
            futurY = this.y + .1f * delta;
          }
          break;
        // cas ou je vais à droite
        case 3: 
          // si je suis sur un escalier qui descend
          if (this.onStairRToL) {
            // j'augmente Y
            futurY = this.y + .1f * delta;
            // sinon si je suis sur un escalier qui monte
          } else if (this.onStairLToR) {
            // je diminue Y
            futurY = this.y - .1f * delta;
          }
          break;
      }
      return futurY;
    }
    

    J'espère t'avoir éclairé, pour le dernier bout de code j'ai repris tes noms de variable mais il n'est pas impossible que j'ai inversé, j'ai essayé de reprendre ta logique de Droite à Gauche mais j'ai comme l'impression qu'il y ai une inversion.

  • Impa 13 novembre 2016 01:20

    Mille mercis ! J'avais mal compris la notion de la variable Y. Tes explications sont claires, précises et extrêmement appréciées.

  • Shionn 14 novembre 2016 10:16

    Merci, j'essaye de faire de mon mieux.

  • Eegan 13 mai 2017 18:44

    Bonjour, Alors j'ai 2 questions:

    1. J'aimerais qu'une zone de téléport soit indisponible, et suite a un évenement devienne disponible. Dois-je ajouter une variable booléenne a certains triggers de la classe "teleport" pour les rendre disponibles/indisponibles? Ou pour changer leur destination?
    2. Je pense savoir comment faire des triggers pour parler avec des PNJ, mais j'aimerais afficher du texte aussi, comment je pourrais faire cela? Merci d'avance =)

  • Shionn 14 mai 2017 07:58

    Salut.

    1. Pour faire un trigger désactivable il y a plein de solution. Le plus simple est en effet d'ajouter un boolean "enable" à ton trigger. Mais il n'est pas possible de le modifier depuis le code. Ce qui signifit que si tu ajout une propriété à ton objet "enable" à false elles sera à jamais à faux. Un autre solution etant donc d'ajouter une "contition" à ton trigger, par exemple "avoir parler à machin" ou "payer X" mais apres faut code tous ca.
    2. Dans la lecon 20, j'explique comment faire une zone de text multiligne.

  • Eegan 15 mai 2017 10:11

    Ah, par exemple, je met une propriété "condition" a mon trigger, et je fais une variable booléenne dans mon code que j'initialise à False, dés que tel évenement ce passe, je met le booléen a True? Et du coup pour les évenements qui doivent se passer une seule fois (par exemple ouvrir un coffre), c'est l'inverse? Ca ferait quand même un sacré paquet de booléens sur le long terme =/

  • Shionn 15 mai 2017 15:46

    Oui cela va te faire un sacré paquet de condition à vérifier. Le plus simple sera de faire un moteur de script mais la c'est super tendu.

    Voila une solution un peu intermédiaire.

    1. Ajoute une Map<String, Boolean> triggerCondition.
    2. Dans les trigger tu ajout ue propriété condition mais tu ne met pas la valeur "true" ou "false" mais "parler-a-toto"
    3. Dans le jeu quand tu parle à un PNJ tu peu faire un triggerCindition.set("parler-a-"+NOM_DU_PNJ, true).
    4. lors du déclenchement des triggers à condition tu vérifie la présence la valeur de "condition" dans la map

    Je ne sais pas si c'est très claire

Laissez un commentaire

Vous pouvez utilisez du markdown pour la mise en forme

Votre adresse de messagerie ne sera pas publiée.

Temporairement, pour lutter contre les bots, il n'est pas permis de mettre http:// dans le commentaire.