canvas javascript, déplacer le personnage

Default
,

Bonjour,

Je suis bloqué sur une partie dans mon code je vous explique, je suis en train de faire un jeux en html avec la balise canvas , j'arrive à générer une map qui se place dans un canvas avec comme id canvasMap et mon joueur se trouve sur un autre canvas par dessus afin d'éviter de regénérer la map en permanance dans ma boucle de jeux étant donné qu'elle contient plus de 1800 cellules c'est gourmant à refaire jusque la tout va bien. La ou je suis bloqué c'est sur la partie joueur, j'ai initialisé la position de mon joueur au chargement et quand je clique ça donne la position final du joueur. Afin de le déplacer j'ai crée une fonction de pathfinding qui stock les coordonnées x et y du chemin que le joueur doit parcourir dans un tableau et j'aimerais déplacer le joueur sauf que ma boucle de jeux est basée sur un setInterval avec une attente de 1000/FPS

et je ne sais pas comment mouvoir le personnage , en espérant avoir été claire, je vous remercie d'avance.

63 Réponse

1 3 4
Default
, Il a répondu à ma question !

voici la boucle principale

function boucle()
{
    timer = setInterval(function()
    {
      //on efface le perso
      contextJoueur.clearRect(0, 0, canvasJoueur.width, canvasJoueur.height);  

      //redessine le perso  
      dessinerPersonnage(initPosXplayer,initPosYplayer,contextJoueur,largeurJoueur,hauteurJoueur);
    },1000/fps);
}

le tableau qui contient les couples de coordonnées

var parcours = [];
 //acceder au position  : parcours[indice].x  et parcours[indice].y

le souci c'est que si je parcours le tableau dans la boucle ca va trop vite et du coup on ne voit pas le déplacement du joueur au clique il se retrouve directement dans la destination final.

112438
, Il a répondu à ma question !

mouai :)
englober ton setinterval dans une function je trouve ça louche...
ftps c une variable globale ?
t'utilise un object contextJoueur pour effacer ton sprite mais pas pour le redessinner : étrange...
ton parcours est lourd de sens ;)

bref, je capte pas grand chose...
donc je ne fais qu'imaginer : tu veux qu'un sprite suive un chemin (peut-être un labyrinthe ?) mais pas trop vite, pour qu'on puisse le voir ?
c'est ça ? :)

Default
, Il a répondu à ma question !

il est englobé dans une fonction car au debut j'initialise tout (charger les images etc) et une fois chargé j'apelle cette fonction pour lancer le jeux et si je le redessine avec dessinerPersonnage

var canvasJoueur = document.getElementById('canvasJoueur');
var contextJoueur = canvasJoueur.getContext('2d');
var parcours = [];
hauteurCellule = 106;
largeurCellule = 106;
hauteurJoueur = 159;
largeurJoueur = 106;
var initPosXplayer = 5;
var initPosYplayer = 4;
var fps = 35;
function initialisation()
{
  //charge les tuiles de la map
  chargerImageCarte(terrain,contextMap,largeurCellule,hauteurCellule);

  //charge la tuile du joueur
  chargementPersonnage(initPosXplayer,initPosYplayer,contextJoueur,largeurJoueur,hauteurJoueur);
}
function boucle()
{
   timer = setInterval(function()
    {
      //on efface le perso
      contextJoueur.clearRect(0, 0, canvasJoueur.width, canvasJoueur.height); 
      dessinerPersonnage(initPosXplayer,initPosYplayer,contextJoueur,largeurJoueur,hauteurJoueur);
    },1000/fps);
}
function dessinerPersonnage(x,y,context,largeurCellule,hauteurCellule)
{
    var posX,posY;
    var coefAjustement = hauteurCellule-((hauteurCellule*106)/hauteurCellule);
    for(var i = 0 ; i < listCase.length ; i++)
    {
        if(listCase[i].id==y+"-"+x)
        {
            posX = listCase[i].x;
            posY = listCase[i].y-hauteurCellule+coefAjustement;
            break;
        }
    }
    context.drawImage(personnage,posX,posY,largeurCellule,hauteurCellule);
}
function start()
{
  initialisation();
  boucle();
}
Default
, Il a répondu à ma question !

donc si ce que je fait à du sens tu n'as juste pas tout le code tout simplement et oui je voudrais qu'il suive un chemin qui est contenu dans le tableau parcours et pas trop vite pour qu'on puisse le voir

Default
, Il a répondu à ma question !

j'ai retiré la fonction boucle pour le moment étant donné qu'elle sert uniquement pour afficher l'état du joueur et je l'ai mise dans l'évènement clique en changeant la tempo

112438
, Il a répondu à ma question !

hello,
tout d'abord il y a quelques erreurs dans ton code (liste non exaustive) :

  • .getContext n'est pas une méthode d'un élément dom (utilise la console)
  • et si je ne me trompe ((x*106)/x) = 106, bref ton coefAjustement sera toujours = à 0 et je vois pas trop à quoi il sert....

cela, dit, avant de suivre un parcours as-tu déjà déplacé une div de manière fluide et visible ?
car il est inutile de l'effacer tu modifies juste son left et top

var canvasJoueur = document.getElementById('canvasJoueur'); // qui a position absolute
canvasJoueur.style.left = 300 + 'px';
canvasJoueur.style.top = 200 + 'px';
Default
, Il a répondu à ma question !

j'ai mis une valeur fixe de 106 tout simplement, ca va être modifié plus tard il servait à placer le perso il y a un produit en croix à faire enfin bref c'est du test en gros, deplacer une div j'y est pensé sauf que la map depasse de la taille du canvas mais est quand même généré du coup si je deplace la div ca ne deplacera pas la map on aura le même visuel simplement deplacé

Default
, Il a répondu à ma question !

Et je débute je n'avais jamais joué avec la balise canvas, donc quitte à avoir une liste complète de mes erreurs je suis prenneur ;)

Default
, Il a répondu à ma question !

en revanche j'ai lu quelque chose tout à l'heure context.translate(x,y); qui pour le coup pourrait peut-être servir

112438
, Il a répondu à ma question !

en effet translate peut t'être utile.
je ne sais pas trop ce que tu appelles canvas et context...
je vais me répéter : commence par un truc simple, genre :
html

<div class="map">
    <div id="sprite"></div>
</div>

css :

.map{position:relative;width:600px;height:600px;margin:auto;border:1px solid #000;}
#sprite{position:absolute;width:50px;height:50px;background:tomato;left:0:top:0;}

et enfin un ti js

var sprite = document.querySelector('#sprite');
var posInitial = {x:0, y:0};
var pos = posInitial;
var posFinal = {x:200, y:100};

// je sais po si c top mais bon
var dx = (posFinal.x - posInitial.x) / (posFinal.y - posInitial.y);
var dy = (posFinal.y - posInitial.y) / (posFinal.x - posInitial.x);

var interval = setInterval(function(){
    if(pos.x > posFinal.x || pos.y > posFinal.y)clearInterval(interval);
    pos.x+=dx; pos.y+=dy;
    sprite.style.left = pos.x +'px';
    sprite.style.top = pos.y + 'px';
}, 5);
Default
, Il a répondu à ma question !

Canvas fait référence à la balise du HTML5 canvas :

<canvas id="canvasJoueur" width="500" height="500">
            Message pour les navigateurs ne supportant pas encore canvas.
</canvas>

une balise pour dessiner comme svg par exemple

et le contexte est pour savoir dans quel contexte de dessin (2D ou 3D) le script va pouvoir agir qui en fonction de 2D ou 3D va nous donner accès à certaines fonction de dessin.

112438
, Il a répondu à ma question !

ok, j'en apprends tous les jours ;)
donc laisse tomber tout ce que g écrit précédemment, j'avais pas compris ton pb, sorry ;)

Default
, Il a répondu à ma question !

Pas de souci ;), faut dire aussi que je n'ai pas été très explicite non plus sur les techno employés etc..

Default
, Il a répondu à ma question !

mais du coup j'ai réfléchi(oui ca m'arrive) et je pense avoir réussi donc en gros dans la boucle de jeux principal j'efface le dessin et je redessine le joueur , et dans la fonction de clique je parcours le tableau du chemin avec un setInterval de 1s et je modifie les coordonnées du joueur étant donné que la boucle principal est plus rapide que celle du parcours le personnage ce déplace la ou je ne comprends pas c'est pour arrêter l'interval

var timer2;
  i=0;
 timer2 = setInterval(function(){
            initPosXplayer=path[i].x;
            initPosYplayer=path[i].y;
            if(i==path.length){clearInterval(timer2);i=0;}
            i++;
 },vitesseDeplacement);

Mais le souci est que je rentre bien dans la condition

 if(i==path.length){clearInterval(timer2);i=0;}

mais ca n'arrête pas le timer il continu et comme le tableau est vide il génère des erreurs dans la console , l'arrêt fonctionne bien à l'exterieur de l'interval mais pas dans l'interval lui même

112438
, Il a répondu à ma question !

essaie :

if(i>path.length){clearInterval(timer2);i=0;}

j'imagine que tu as lu ça
c génial !!

Default
, Il a répondu à ma question !

Oui en effet j'ai pas mal potassé ce site ou la documentation est très bien fourni ! effectivement le souci venait de la merci

Default
, Il a répondu à ma question !

Bonjour je viens vers vous car je suis de nouveau confronté à un problème tout bête.......

function Terrain(map)
{
        //tableau à deux dimensions
        this.map = map;
}

Terrain.prototype.Charger = function()
{
    //afficher une fois tuile chargé
}

Terrain.prototype.Afficher = function()
{
}

Comment fait-on pour appeler Afficher dans Charger ?

112438
, Il a répondu à ma question !

hello, je te conseille ce tuto.
mais en gros, tu as créé une "class" Terrain avec ta function, donc il faut tout d'abord l'instancier :

var myTerrain = new Terrain(map);

et ensuite tu pourras appelé tes méthodes :

myTerrain.Charger();
Default
, Il a répondu à ma question !

Très bien, merci je découvre la poo qui faut le dire est très pratique pour ce que je fait ^^

Default
, Il a répondu à ma question !

pour ce qui est de créer une classe j'y arrive mais c'est surtout comment appeler une méthod d'une classe dans une autre méthod de celle-ci. Dans mon cas j'aimerais appeler la méthod Afficher dans la méthod Charger

function Terrain(map)
{
        //tableau à deux dimensions
        this.map = map;
}

Terrain.prototype.Charger = function()
{
    //appeler méthod Afficher
}

Terrain.prototype.Afficher = function()
{
}
1 3 4