Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Canvas] Tuto "Créer un mini-rpg !"

Sujet résolu
    10 décembre 2011 à 16:33:06

    Bonjour la compagnie ! :p

    Bon j'ai fini le tuto "Créer un mini-rpg avec canvas !" et il fonctionne parfaitement. :)
    Cependant, le tuto n'est pas fini et pour faire mon MMORPG, j'ai besoin de modifier le système et je ne sais pas comment faire certaines choses. :(

    Voici mes questions :

    - Comment faire en sorte que l'image ne se déforme pas lorsqu'on agrandit la map ?
    - Comment faire en sorte qu'à certains moment, une image soit dessinée au-dessus ou en dessous d'une autre ?
    - Comment faire pour que ce soit la map qui bouge et non le personnage (personnage centré) ?


    Je pose ses questions car c'est la première fois que j'utilise un Canvas, et je ne vois pas comment m'y prendre ! ^^

    Merci d'avance de vos réponses ! :)
    • Partager sur Facebook
    • Partager sur Twitter
      10 décembre 2011 à 17:42:42

      Ah, tu te décides à te mettre à Canvas ? Je vais essayer de répondre à tes questions, même si les explications là dessus ne sont pas mon fort.

      Premièrement : Je n'ai pas bien compris ta première question, mais si tu veux ragrandir la map il suffit d'afficher plus de tiles ( la taille des tiles étant fixe, normalement ils ne se déforment pas ). Pour cela suffit de faire le ratio taille de ton canvas / taille du tile le tout en pixel pour savoir le nombre de tiles sur la largeur ou la hauteur. ( Ce qui est d'ailleurs fait dans le tutoriel si mes souvenirs sont bons )

      Deuxièmement : Pour dessiner une image au dessus d'une autre il suffit de la dessiner après, quand tu dessines un element après un autre celui ci est affiché au dessus de l'autre. C'est le cas pour le personnage dans ce même tutoriel, il est dessiné après la map.

      Troisièmement : Pour bouger la map et non le personnage il suffit de faire un système de caméra qui calcule des décalages X et Y en fonction de la position du personnage, il suffit ensuite d'afficher la map en fonction de ces décalages et d'afficher le personnage au centre.

      Si jamais tu as d'autres questions, ou que tu n'as pas compris quelque chose, demande. Je me ferais un plaisir de te répondre. ( Surtout que là je dois bien dire que tu poses tes questions de façon très polis par rapport à certains ).
      • Partager sur Facebook
      • Partager sur Twitter
        10 décembre 2011 à 18:37:55

        En faite pour la première chose, je crois que c'est du faite que j'ai défini une taille pour le Canvas, du coup quand j'obtiens pas pile la même taille, l'image est déformée ! :(

        Comment faire ? :o
        • Partager sur Facebook
        • Partager sur Twitter
          10 décembre 2011 à 18:49:52

          On pourrait pas avoir un screen pour voir ? As tu bien gardé le même tileset ?

          Fin bon, dans le tutoriel le calcul du nombre de tiles en largeur et en hauteur est calculé à partir de la taille de ton canvas. Il suffit de changer cela en prenant la vrai taille de la map, c'est à dire la taille du tableaux de tiles de la map.

          Edit : Dans l'objet gérant le tileset
          Edit 2 : Ce que j'ai dit est complétement HS, sans screen je ne peux pas vraiment voir d'où pourrait venir le problème vu que je n'ai pas beaucoup étudié le code du cours. Il n'y a normalement aucune raison que ça soit déformé à moins que tu es touché au code de manière à ce que ça le soit ou que tu es changé de tileset ( Largeur / Hauteur des tiles ).
          • Partager sur Facebook
          • Partager sur Twitter
            10 décembre 2011 à 18:58:56

            C'est bon j'ai réussi, j'ai mis le Canvas dans un div, c'est donc la div qui a la taille donc l'image n'est plus déformée, et j'ai mis un overflow: hidden pour ne pas voir ce qui dépasse.

            Pour le système "camera", je pense pouvoir trouver mais pour redessiner par dessus un élément, comment je peux faire ? :o

            Voici mon code :
            // Code supprimé
            
            • Partager sur Facebook
            • Partager sur Twitter
              10 décembre 2011 à 19:04:53

              Citation : Auryn

              C'est bon j'ai réussi, j'ai mis le Canvas dans un div, c'est donc la div qui a la taille donc l'image n'est plus déformée, et j'ai mis un overflow: hidden pour ne pas voir ce qui dépasse.


              Ce n'est clairement pas une bonne solution, tu utilises du CSS pour cacher un défaut que tu as en JS.

              Après pour redessiner un élément par dessus un autre je l'ai déjà dit, suffit de le dessiner après l'autre. Si tu parlais de redessiner un élément par dessus un autre précisément il te suffit de connaître la position de l'autre et d'afficher ton élément aux même positions et ça après l'affichage de l'autre.
              • Partager sur Facebook
              • Partager sur Twitter
                11 décembre 2011 à 12:22:28

                Non non c'était bien un problème de css. ^^

                Sinon j'ai bien compris qu'il fallait redessiner après l'autre mais comment je peux m'y prendre pour savoir qu'il faut redessiner un élément ? En le stockant dans un Array que je redessine en boucle ? :o
                • Partager sur Facebook
                • Partager sur Twitter
                  11 décembre 2011 à 12:30:52

                  Cela dépend du contexte, si tu nous en dis pas plus on ne pourra pas t'aider plus. Normalement à chaque tour de boucle de jeu tu re-affiches à chaque fois tout ce qui est présent dans canvas. Donc normalement tu as juste besoin de dire ce qui est a afficher à la méthode qui affiche tous ça ... Fin bon comme je te l'ai dit, ça dépend du contexte et de ce que tu veux réellement faire.

                  Edit : Un jeu vidéo étant une boucle de jeu ( infini du moment que le joueur ne quitte pas, en Javascript avec un setInterval ) qui execute des actions en fonction des précédents tours ou des actions du joueur ( appuie sur une touche ), et qui finalement affiche le tout. Il faut donc penser "boucle de jeu" et non élément a part même que ce soit du Javascript qui est asynchrone.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    11 décembre 2011 à 13:21:37

                    Voici la méthode qui s'occupe de dessiner :
                    this.dessinerMap = function (context) {
                    	    for (var i = 0, l = this.terrain.length; i < l; i++) {
                    		var ligne = this.terrain[i];
                    		var y = i * 32;
                    		for (var j = 0, k = ligne.length; j < k; j++) {
                    		    this.tileset.dessinerTile(ligne[j], context, j * 32, y);
                    		}
                    	    }
                    	    for (var i = 0, l = this.personnages.length; i < l; i++) {
                    		this.personnages[i].dessinerPersonnage(context);
                    	    }
                                setTimeout(function() {
                                    map.dessinerMap(context);
                                },1);
                    	}
                    


                    Le joueur est le premier de l'array personnages, pour le dessiner par dessous, c'est bon, pour le dessiner par dessus il faudrait inverser l'array :
                    for (var i = this.personnages.length; i >= 0; i--) {
                    	this.personnages[i].dessinerPersonnage(context);
                    }
                    


                    Cependant, voilà, comment savoir s'il faut exécuté la boucle à l'endroit ou à l'envers.
                    Il faudrait que j'utilise les positions donc que je crée un array et que je mette une condition, c'est une bonne idée ? :o
                    • Partager sur Facebook
                    • Partager sur Twitter
                      11 décembre 2011 à 14:37:45

                      Normalement il n'y a aucun problème avec ton premier code. Le personnage sera toujours dessiné par dessus ta map, peu importe sa place dans l'array personnages. Après je doute que sur ta map plusieurs personnages soit au même endroit, non ? Donc je vois pas pourquoi tu veux faire pour que ton personnage soit affiché au dessus des autres si ils ne sont jamais l'un sur l'autre.
                      • Partager sur Facebook
                      • Partager sur Twitter
                        11 décembre 2011 à 21:49:40

                        En faite, les personnages sont plus grand que les cases, du coup, à un moment, la tête du personnage passe au-dessus des jambes de l'autre et à un autre moment, les pieds du personnage doivent passer en dessous de la tête de l'autre ! :)

                        De plus je rencontre une autre difficulté, pour le système "camera", comment bouger l'image ? :o
                        L'image se comporte-t-elle comme un background ?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          11 décembre 2011 à 22:01:28

                          Dans ce cas là il faut afficher les personnages en fonction de leur position, de haut en bas. Les personnages étant plus loin sur la map étant affiché derrière les personnages plus près ( plus bas ).

                          Après pour la caméra il faut modifier le code actuel pour y permettre un décalage x et y des tiles. Il ne faut donc pas bouger canvas comme un background mais blitter ( afficher ) les tiles à un autre endroit selon un décalage x et y donné par la caméra.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            11 décembre 2011 à 22:43:13

                            Ah c'est bon je pense avoir trouvé pour le système camera ! :D

                            Sinon, c'est intéressant comme idée mais un peu impossible, il faudrait que j'ordonne l'array personnages par y dans l'ordre croissant, or comment faire cela ? o_O
                            • Partager sur Facebook
                            • Partager sur Twitter
                              11 décembre 2011 à 22:53:09

                              Tu tries ton array sur la position y de ton personnage, pour cela il te faut utiliser un sort avec une fonction de callback ( Je te laisse te renseigner sur comment utiliser sort ).
                              Ou alors tu réorganises le code pour faire un tableau multi-dimensionel de tes personnages sur les positions x et y.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                11 décembre 2011 à 23:55:44

                                Voici ce que j'ai modifié :

                                - pour dessiner dans l'ordre en fonction de y :
                                this.dessinerMap = function (context) {
                                	    for (var i = 0, l = this.terrain.length; i < l; i++) {
                                		var ligne = this.terrain[i];
                                		var y = i * 32;
                                		for (var j = 0, k = ligne.length; j < k; j++) {
                                		    this.tileset.dessinerTile(ligne[j], context, j * 32, y);
                                		}
                                	    }
                                            this.personnages.sort();
                                	    for (x in this.personnages) {
                                		for (y in this.personnages[x].sort()) {
                                                    this.personnages[x][y].dessinerPersonnage(context);
                                                }
                                	    }
                                            setTimeout(function() {
                                                map.dessinerMap(context);
                                            },1);
                                	}
                                	this.personnages = new Array();
                                	this.addPersonnage = function(perso,x,y) {
                                	    if (!this.personnages[x]) {
                                                this.personnages[x] = [];
                                            }
                                            this.personnages[x][y] = perso;
                                	}
                                


                                - pour modifier x et y du personnage jouable dans le tableau personnages :
                                this.deplacer = function(direction, map) {
                                            if(this.etatAnimation >= 0) {
                                	        return false;
                                            }
                                	    this.direction = direction;
                                	    var prochaineCase = this.getCoordonneesAdjacentes(direction);
                                	    if(prochaineCase.x < 0 || prochaineCase.y < 0 || prochaineCase.x >= map.getLargeur() || prochaineCase.y >= map.getHauteur()) {
                                		return false;
                                	    }
                                            this.etatAnimation = 0;
                                	    this.x = prochaineCase.x;
                                	    this.y = prochaineCase.y;
                                            map.personnages[X][Y] = '';
                                	    switch(direction) {
                                		case DIRECTION.BAS : 
                                		    Y++;
                                	            break;
                                	        case DIRECTION.GAUCHE : 
                                		    X--;
                                		    break;
                                		case DIRECTION.DROITE : 
                                		    X++;
                                		    break;
                                		case DIRECTION.HAUT : 
                                		    Y--;
                                		    break;
                                	    }
                                            joueur = new Personnage("http://www.rpg-maker.fr/ressources/characters/hommes/bb92509a941e27b1d4c371e85de4.jpeg.png", X, Y, DIRECTION.BAS);
                                            map.addPersonnage(joueur, X, Y);
                                	    return true;
                                        }
                                



                                Cependant, j'ai une erreur dans le deuxième code donné, à la ligne "map.personnages[X][Y] = '';", ça me dit :

                                Citation : Console


                                "map.personnages[X]" Undefined



                                Comment faire ? :o
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  12 décembre 2011 à 8:25:09

                                  Ton code est pas très propre mais ton erreur vient du fait que dans ta fonction déplacer X et Y ne sont pas déclarés. Tu ne parlais pas plutôt de this.x et this.y ?
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    12 décembre 2011 à 10:36:28

                                    Non non, X et Y sont déclarés au tout début du code... :(

                                    EDIT :
                                    J'ai compris, en faite ça vient du this.personnages.sort(), du coup le Array et ré-ordonné et map.personnages[X] n'existe plus par contre map.personnages[1] existe alors qu'il n'a jamais été déclaré.
                                    Donc comment faire pour garder l'array d'origine et trier en même temps ? :o
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      12 décembre 2011 à 17:03:03

                                      Salut, pour cloner un array tu peux faire :
                                      monArrayCloner = monArray.slice(0)

                                      Du coup quand tu trie monArrayCloner ça ne change pas monArray.

                                      Pour l'ordre des dessins, personnellement j'utilise de nombreux objets, c'est objets comprennent tous une méthode z-index qui me retourne un entier.
                                      Ensuite dans ma fonction draw je fais un sort sur tous les objets à dessiner en fonction de leur z-index et j'appelle les draw correspondant.
                                      Ca permet de créer des "calques" et de reproduire un peu ce qui se passe en css avec la propriété z-index
                                      Voilà je trouve ça plus propre, un peu plus orienté POO :)

                                      Bon courage
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        12 décembre 2011 à 18:01:04

                                        J'ai réussi ! ^^

                                        Par contre je me pose une question, comment je pourrais faire pour que les autres joueurs se déplacent ? :o
                                        Je veux dire de la même façon que notre joueur ?

                                        Voici mon code :
                                        // Code supprimé
                                        
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          12 décembre 2011 à 18:50:24

                                          En faite tu comptes demander pour chaque problème que tu rencontres une solution ? Si tu fais comme ça tu n'apprendras jamais à faire quelque chose de complexe tout seul. Mais je vais quand même te donner des pistes ...

                                          Récupération des joueurs et de leurs actions : Ajax / Websockets
                                          Création d'un objet personnage pour chaque joueurs.
                                          Affichage de celui ci sur la map ( avec animation ).
                                          Etc ...
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            12 décembre 2011 à 19:06:45

                                            Oui ça je sais bien, désolé si je m'exprime mal ! ^^

                                            En faite je stocke les joueurs dans un array, puis si la position est différente de la précédente, j'utilise la méthode "deplacer()" pour le faire bouger, mais comment faire pour comparer les valeurs x et y des joueurs, utiliser deux Array comme ceci serait une bonne idée ? :o
                                            joueur_x[id_du_joueur];
                                            joueur_y[id_du_joueur];
                                            


                                            (Je préfère demander plutôt que de coder comme un bourrin parce que dieu sait si je ne pense pas toujours à la meilleure solution ! ^^ )
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              12 décembre 2011 à 19:09:48

                                              Ce n'est pas vraiment ça qu'il faut faire. Il faut mettre à jour la position x et y de ton personnage ainsi que ses variables d'états d'animation. Ainsi tous ce qui se passe chez un autre client se passe aussi sur le client de l'utilisateur. Enfin en théorie, vu que tous le monde n'as pas le même débit.

                                              Ainsi tu laisses ta méthode d'affichage faire tout le travail d'affichage.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                12 décembre 2011 à 19:51:35

                                                Donc ceci fonctionnerai ?

                                                if (joueurs[id].x !== reponse_ajax_x || joueurs[id].y !== reponse_ajax_y) {
                                                    joueurs[id].x = reponse_ajax_x;
                                                    joueurs[id].y = reponse_ajax_y;
                                                    joueurs[id].etatAnimation = 0;
                                                }
                                                


                                                Bien sûr tout cela dans une boucle sur les données reçues par Ajax.
                                                En théorie ça marcherait donc ? :o
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  12 décembre 2011 à 19:55:08

                                                  Non.

                                                  Tu récupéres le x, le y et l'état de l'animation. Tu les stockes dans ton objet Personnage. Fin bon faudrait aussi faire quelques autres modifications mais le principe est là. ( Pas besoin de condition, peut importe ce que tu récupéres tu modifies, toute façon tu perds rien à modifier des attributs d'un objet avec les mêmes valeurs ).
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    12 décembre 2011 à 23:26:05

                                                    J'ai réussi à gérer le deplacement des autres joueurs, mais j'ai un petit problème, je n'arrive pas à retirer les anciennes collisions des joueurs.
                                                    Je m'explique, on veut aller sur la case du joueur on ne peut pas, le joueur se deplace, on veut aller sur sa case, on ne peut pas, mais quand on veut aller sur son ancienne case, on ne peut pas non plus, alors que normalement on peut ! :(

                                                    Voici mon code :
                                                    // Code supprimé
                                                    
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      13 décembre 2011 à 8:08:31

                                                      C'est normal ... Pour les collisions tu regardes si une case dans le tableau de personnages existe à tel ou tel position x et y. Or quand tu déplaces un personnages tu fais comme ça :
                                                      map.personnages[Y][X] = '';
                                                      

                                                      Et ensuite tu en recrées un, ce n'est pas comme ça qu'il faut faire pour supprimer une case de tableau en JS, il faut faire un delete :
                                                      delete map.personnages[Y][X];
                                                      

                                                      Après je trouve quand même ton code pas très propre par rapport à celui que tu avais avant du tutoriel ...
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        13 décembre 2011 à 8:53:57

                                                        J'ai remplacer comme tu as dit par des deletes dans gestion() et dans deplacement().

                                                        Toujours le même problème ! :(
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          13 décembre 2011 à 19:11:57

                                                          Dans ce cas là je ne sais pas, mais essaye de savoir avec du debugguage quel return retourne false dans deplacer ou dans quel méthode à quel endroit ça bloque, car juste comme ça je ne vois pas trop. Faudrait que je regarde plus en profondeurs mais j'ai pas le temps pour ça.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            14 décembre 2011 à 16:56:21

                                                            Voilà j'ai enfin réussi à obtenir ce que je souhaitais ! :p

                                                            Il reste un petit problème à régler, une fois sur deux j'ai l'erreur suivante que je ne comprends absolument pas ! :(

                                                            Citation

                                                            JavaScript Erreur à la ligne 58.
                                                            INDEX_SIZE_ERR : DOM Exeption 1 : Index or size was negative, or greater than the allowed value.



                                                            Comment régler ce problème ? :o

                                                            Par ailleurs, si vous avez des idées d'amélioration de mon code, je suis tout ouïe ! ^^

                                                            Voici mon code :
                                                            // Code supprimé
                                                            
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              14 décembre 2011 à 20:00:44

                                                              A quel ligne correspond la ligne 58 ? Et l'erreur dit clairement que tu accèdes à un élément de tableau qui n'existe pas ( pas le bon index d'accès ).
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              [Canvas] Tuto "Créer un mini-rpg !"

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown