Partage
  • Partager sur Facebook
  • Partager sur Twitter

Erreur tutoriel Moteur de rendu Isométrique

Sujet résolu
    22 juillet 2016 à 0:31:21

    Bonsoir à tous !

    Je suis face à un petit soucis qui m'agace.

    J'ai trouvé sur le net un tutoriel qui permet de réaliser un petit moteur de rendu isométrique en JavaScript, HTML5, CSS3. (http://forums.mediabox.fr/wiki/tutoriaux/flashplatform/jeux/tbg_js)

    Le tutoriel propose en annexe de rajouter au moteur de base la possibilité de gérer le déplacement à la souris en implémentant un algorithme de pathfinding. Et c'est là que ça se corse. Lorsque je suis le tuto jusqu'au bout et que je tente de tester mon exemple réalisé avec, le déplacement ne se fait pas et j'ai une erreur à la console qui est la suivante : "Uncaught TypeError: Cannot read property 'waitingList' of undefined". Je ne comprends pas le pourquoi de cette erreur...

    L'erreur fait référence à la ligne 101 de mon fichier map.js ci-joint :

    var Map = function () {};
    
    var p = Map.prototype = new Container();
    
    p.tiles = [];
    p.tilesWidth = 128;
    p.tilesHeight = 64;
    p.offsetX = 0;
    p.offsetY = 0;
    p.player = null;
    
    p.addTile = function ( $tile, $x, $y, $z ) {
    	$tile.posX = $x;
    	$tile.posY = $y;
    	$tile.posZ = $z;
    	$tile.map = this;
    
    	this.tiles.push ( $tile );
    	this.addChild ( $tile.content );
    	this.update ();
    
    	$tile.content.onClick = function () {
    		this.tile.map.movePlayer ( this.tile.posX, this.tile.posY );
    	};
    };
    
    p.removeTile = function ( $tile ) {
    	var index = this.tiles.indexOf ( $tile );
    
    	if ( index === -1 ) {
    		throw new Error ( 'Map.removeTile : la tuile à supprimer ne fait pas partie de la carte !' );
    	}
    
    	this.removeChild ( $tile.content );
    	this.tiles.splice ( index, 1 );
    	$tile.dispose();
    };
    
    p.getTileAt = function ( $x, $y, $z ) {
    	var r_tile = null;
    	this.tiles.forEach ( function($tile) {
    		if ( $tile.posX === $x && $tile.posY === $y && $tile.posZ === $z ) {
    			r_tile = $tile;
    		}
    	});
    
    	return r_tile;
    };
    
    p.update = function () {
    	this.updatePos();
    	this.updateDepth();
    };
    
    p.updatePos = function () {
    	this.tiles.forEach ( function($tile) {
    		$tile.content.x = ( $tile.posY - $tile.posX ) * ($tile.map.tilesWidth/2) + ($tile.offsetX + $tile.map.offsetX);
    		$tile.content.y = ( $tile.posY + $tile.posX ) * ($tile.map.tilesHeight/2) + ($tile.offsetY + $tile.map.offsetY);
    		$tile.content.tile = $tile;
    	});
    };
    
    p.updateDepth = function () {
    	this.sortChildren (function($a,$b) {
    		$n_a = 5 * ($a.tile.posX + $a.tile.posY) + $a.tile.posZ;
    		$n_b = 5 * ($b.tile.posX + $b.tile.posY) + $b.tile.posZ;
    
    		if ( $n_a > $n_b ) {
    			return 1;
    		} else if ( $n_a < $n_b ) {
    			return -1;
    		} else {
    			return 0;
    		}
    	});
    };
    
    p.getGraph = function () {
    	var graph = [];
    
    	for ( var i = 0, max = this.tiles.length; i < max; i++ ) {
    		var tile = this.tiles[i];
    
    		if ( graph[tile.posX] === undefined ) {
    			graph[tile.posX] = [];
    		}
    
    		graph[tile.posX][tile.posY] = new Node ( tile.posX, tile.posY, tile.walkable );
    	}
    
    	return graph;
    };
    
    p.movePlayer = function ( $x, $y ) {
    	if ( this.player === null ) {
    		return;
    	}
    
    	var playerX, playerY;
    
     if ( this.player.waitingList.length === 0 ) {
    		playerX = this.player.posX;
    		playerY = this.player.posY;
    	} else {
    		playerX = this.player.waitingList[this.player.waitingList.length-1][0];
    		playerY = this.player.waitingList[this.player.waitingList.length-1][1];
    	}
    
    	var graph = this.getGraph();
    	var start = graph[playerX][playerY];
    	var end = graph[$x][$y];
    
    	var path = Pathfinder.findPath ( graph, start, end );
    
    	while ( path.length !== 0 ) {
    		var toTile = path.shift ();
    		this.player.smoothMove ( toTile.line, toTile.col );
    	}
    };
    
    p.dispose = function () {
    	while ( this.tiles.length > 0 ) {
    		this.removeTile ( this.tiles[0] );
    	}
    	this.tiles = null;
    	this.tilesWidth = null;
    	this.tilesHeight = null;
    	this.offsetX = null;
    	this.offsetY = null;
    };

    et je vous met également l'intégralité du code afin d'avoir une vue d'ensemble :

    core.js :

    var gameview = document.getElementById('gameview'), stage;
    stage = new Stage(gameview);
    Ticker.setFPS(24);
    Ticker.addListener(stage);
     
    var myMap = new Map ();
     
    myMap.offsetX = 400;
    myMap.offsetY = 200;
    myMap.player = player;
     
    stage.addChild ( myMap );
     
    var player = new Player ( TileType.DRAW, gfx.mur ( 255, 0, 0 ), true );
    myMap.addTile ( player, 3, 3, 1 );
     
    var map = [     [0, 1, 0, 1, 0],
                    [0, 0, 0, 0, 0],
                    [0, 0, 0, 1, 0],
                    [0, 1, 0, 0, 0],
                    [0, 1, 0, 0, 0]];
     
     
    for ( var i = 0; i < 5; i++ )
    {
       for ( var j = 0; j < 5; j++ )
       {
               if ( map[i][j] === 0 )
               {
                       myMap.addTile ( new Tile ( TileType.DRAW, gfx.solTAlea(200,200,128), true ), i, j, 0 );
               }
               else
               {
                       myMap.addTile ( new Tile ( TileType.DRAW, gfx.murTAlea(128,128,128), false ), i, j, 2 );
               }
       }
    }

    node.js

    var Node = function ( $x, $y, $walkable ) {
    	this.construct ( $x, $y, $walkable );
    };
    
    var p = Node.prototype;
    
    p.g = 0;
    p.h = 0;
    p.f = 0;
    p.col = 0;
    p.line = 0;
    p.walkable = true;
    p.parent = null;
    
    p.construct = function ( $x, $y, $walkable ) {
    	this.line = $x;
    	this.col = $y;
    	this.walkable = $walkable;
    	this.parent = this;
    };

    pathfinder.js

    var Pathfinder = {
    	NODE_DISTANCE_VALUE: 100,
    	openList: null,
    	closeList: null,
    
    	findPath: function ( $graph, $start, $end ) {
    		this.openList = [];
    		this.closeList = [];
    
    		var finalPath = [];
    		var currentNode = null;
    
    		this.addToOpenList( $start );
    
    		while ( this.openList.length > 0 ) {
    			currentNode = this.getCurrentNode ();
    
    			if ( currentNode === $end ) { break; }
    
    			this.addToCloseList ( currentNode );
    
    			var neighbours = this.getNeighbours ( currentNode, $graph );
    
    			for ( var i = 0, max = neighbours.length; i < max; ++i ) {
    				var node = neighbours[i];
    
    				if ( !(this.isOnCloseList( node ) || node.walkable === false) ) {
    
    					var newG=node.parent.g + this.NODE_DISTANCE_VALUE;
    					var newH=(Math.abs($end.line-node.line)+Math.abs($end.col-node.col))*this.NODE_DISTANCE_VALUE;
    					var newF=newH+newG;
    
    					if ( this.isOnOpenList( node ) ) {
    						if ( newG < node.g ) {
    							node.g = newG;
    							node.h = newH;
    							node.f = newF;
    							node.parent = currentNode;
    						}
    					} else {
    						node.g = newG;
    						node.h = newH;
    						node.f = newF;
    						node.parent = currentNode;
    
    						this.addToOpenList ( node );
    					}
    				}
    			}
    		}
    
    		if ( this.openList.length === 0 ) { return finalPath; }
    
    		var lastNode = $end;
    
    		while ( lastNode !== $start ) {
    			finalPath.push ( lastNode );
    			lastNode = lastNode.parent;
    		}
    		return finalPath.reverse();
    	},
    
    	removeFromCloseList: function ( $node ) {
    		var index = this.closeList.indexOf ( $node );
    
    		if ( index !== -1 ) { this.closeList.splice ( index, 1 ); }
    	},
    
    	removeFromOpenList: function ( $node ) {
    		var index = this.openList.indexOf ( $node );
    
    		if ( index !== -1 ) { this.openList.splice ( index, 1 ); }
    	},
    
    	addToCloseList: function ( $node ) {
    		this.removeFromOpenList ( $node );
    		this.closeList.push ( $node );
    	},
    
    	addToOpenList: function ( $node ) {
    		this.removeFromCloseList ( $node );
    		this.openList.push ( $node );
    	},
    
    	getCurrentNode: function () {
    		var min_f = 1000000;
    		var current_node = null;
    
    		for ( var i = 0, max = this.openList.length; i < max; ++i ) {
    			var node = this.openList[i];
    
    			if ( node.f < min_f ) {
    				min_f = node.f;
    				current_node = node;
    			}
    		}
    		return current_node;
    	},
    
    	getNeighbours: function ( $node, $graph ) {
    		var neighbours = [];
    
    		if ( $node.line > 0 ) { neighbours.push ( $graph[$node.line - 1][$node.col] ); }
    		if ( $node.line + 1 < $graph.length ) { neighbours.push ( $graph[$node.line + 1][$node.col] ); }
    		if ( $node.col > 0 ) { neighbours.push ( $graph[$node.line][$node.col - 1] ); }
    		if ( $node.col + 1 < $graph[0].length ) { neighbours.push ( $graph[$node.line][$node.col + 1] ); }
    
    		return neighbours;
    	},
    
    	isOnOpenList: function ( $node ) {
    		return ( this.openList.indexOf ( $node ) !== -1 );
    	},
    
    	isOnCloseList: function ( $node ) {
    		return ( this.closeList.indexOf ( $node ) !== -1 );
    	}
    };

    tile.js

    var Tile = function ( $type, $content, $walkable, $offsetX, $offsetY )
    {
            this.construct ( $type, $content, $walkable, $offsetX, $offsetY );
    };
    
    var p = Tile.prototype;
    
    p.type = TileType.DRAW;
    p.content = null;
    p.walkable = true;
    p.offsetX = 0;
    p.offsetY = 0;
    p.map = null;
    p.posX = 0;
    p.posY = 0;
    p.posZ = 0;
    
    p.construct = function ( $type, $content, $walkable, $offsetX, $offsetY )
    {
            if ( $type === TileType.PNG )
            {
                    this.type = $type;
            }
            
            if ( $walkable === false )
            {
                    this.walkable = false;
            }
            
            if ( typeof $offsetX === typeof 0 )
            {
                    this.offsetX = $offsetX;
            }
            
            if ( typeof $offsetY === typeof 0 )
            {
                    this.offsetY = $offsetY;
            }
            
            if ( $content && $content.visible )
            {
                    this.content = $content;
            }
    };
    
    p.dispose = function ()
    {
            this.map = null;
            this.type = null;
            this.content = null;
            this.walkable = null;
            this.offsetX = null;
            this.offsetY = null;      
    };

    tiletype.js

    var TileType =
    {
            PNG: "PNG",
            DRAW: "DRAW"
    };

    player.js

    var Player = function ( $type, $content, $walkable, $offsetX, $offsetY )
    {
            this.construct ( $type, $content, $walkable, $offsetX, $offsetY );
     
            Ticker.addListener ( this, true );
    };
     
    var p = Player.prototype = new Tile ();
    
    p.waitingList = [];
    p.decalX = 0;
    p.decalY = 0;
    p.needUpdate = false;
    
    
    p.smoothMove = function ( $x, $y )
    {
            this.waitingList.push ( [ $x, $y ] );
    };
    
    p.tick = function ( $e )
    {
            if ( this.decalX !== 0 || this.decalY !== 0 )
            {
                    if ( this.decalX > 0 )
                    {
                            this.decalX -= 8;
                            this.content.x += 8;
                    }
                    else if ( this.decalX < 0 )
                    {
                            this.decalX += 8;
                            this.content.x -= 8;
                    }
     
                    if ( this.decalY > 0 )
                    {
                            this.decalY -= 4;
                            this.content.y += 4;
                    }
                    else if ( this.decalY < 0 )
                    {
                            this.decalY += 4;
                            this.content.y -= 4;
                    }
            }
            else if ( this.needUpdate )
            {
                    this.map.updateDepth();
                    this.needUpdate = false;
            }
            else if ( this.waitingList.length !== 0 )
            {
                    var position = this.waitingList.shift();
     
                    if ( this.posX - position[0] > 0 || this.posY - position[1] > 0 )
                    {
                            this.needUpdate = true;
                    }
     
                    this.posX = position[0];
                    this.posY = position[1];
     
                    if ( !this.needUpdate )
                    {
                            this.map.updateDepth ();
                    }
     
                    var toTile = this.map.getTileAt ( this.posX, this.posY, 0 );
     
                    this.decalX = toTile.content.x - this.content.x;
                    this.decalY = toTile.content.y - this.content.y;
            }
    };
    
    p.move = function ( $x, $y )
    {
            if ( this.map.getTileAt( this.posX + $x, this.posY + $y, 0 ).walkable )
            {
                    this.posX += $x;
                    this.posY += $y;
                    this.map.update ();
            }
    };

    gfx.js :

    var gfx = {};
    
    gfx.sol = function ( $r, $g, $b )
    {
            if ( (!$r && $r !== 0) || (!$g && $g !== 0) || (!$b && $b !== 0) )
            {
                    $color = "#CCCCCC";
            }
            else
            {
                    $color = Graphics.getRGB ( $r, $g, $b );
            }
            
            this.gfx = new Shape();
            this.gfx.name = $color;
            this.gfx.graphics.beginFill($color)
                             .moveTo(64,0)
                             .lineTo(0,-32)
                             .lineTo(-64,0)
                             .lineTo(0,32)
                             .lineTo(64,0)
                             .closePath();
            return this.gfx;
    };
    
    gfx.mur = function ( $r, $g, $b )
    {
    	if ( (!$r && $r !== 0) || (!$g && $g !== 0) || (!$b && $b !== 0) ) { $r = $g = $b = 200; }
            this.gfx = new Shape();
    
            $color = Graphics.getRGB ( $r, $g, $b );
            $color_g = Graphics.getRGB ( Math.round(0.8 * $r), Math.round(0.8 * $g), Math.round(0.8 * $b) );
            $color_d = Graphics.getRGB ( Math.round(0.6 * $r), Math.round(0.6 * $g), Math.round(0.6 * $b) );
    
    	this.gfx.graphics.beginFill($color_d);
            this.gfx.graphics.moveTo(0,-18).lineTo(0,32).lineTo(64,0).lineTo(64,-50).lineTo(0,-18);
    
            this.gfx.graphics.beginFill($color);
            this.gfx.graphics.moveTo(64,-50).lineTo(0,-82).lineTo(-64,-50).lineTo(0,-18).lineTo(64,-50);
    
            this.gfx.graphics.beginFill($color_g);
            this.gfx.graphics.moveTo(-64,-50).lineTo(-64,0).lineTo(0,32).lineTo(0,-18).lineTo(-64,-50).beginFill();
            this.gfx.graphics.closePath();
            
    	return this.gfx;
    };
    
    gfx.solAlea = function ()
    {
            var r = Math.round(Math.random()*255), g = Math.round(Math.random()*255), b = Math.round(Math.random()*255);
            
            return this.sol ( r, g, b );
    };
    
    gfx.solTAlea = function ( $r, $g, $b )
    {
            var r = $r - Math.round(Math.random()*40), g = $g - Math.round(Math.random()*40), b = $b - Math.round(Math.random()*40);
            
            return this.sol ( r, g, b );
    };
    
    gfx.murTAlea = function ( $r, $g, $b )
    {
            var r = $r - Math.round(Math.random()*10), g = $g - Math.round(Math.random()*10), b = $b - Math.round(Math.random()*10);
            
            return this.mur ( r, g, b );
    };
    
    gfx.murAlea = function ()
    {
            var r = Math.round(Math.random()*255), g = Math.round(Math.random()*255), b = Math.round(Math.random()*255);
            
            return this.mur ( r, g, b );
    };
    
    gfx.play = function()
    {
            this.text = new Text("Jouer", "30px Arial Black", "#ffff00");
            this.text.textAlign = "center";
    	this.text.textBaseline = "top";
    	this.text.lineHeight = 32;
    	this.text.lineWidth = 134;
    	this.text.setTransform(71,0.8);
    	this.text.shadow = new Shadow("#ff0000",0,0,10);
            
    	this.gfx = new Shape();
    	this.gfx.graphics.lf(["#ff6600","#ffff00"],[0,1],-11.6,-35.2,-11.6,28.7)
                    .p("AKNi2QqciHp2CHQiBC0CBCzQJTCVK/iVQB1ikh1jD").f()
                    .s("#ff6600").ss(2.5,1,1,3)
                    .p("AKNi2QB1DDh1CkQq/CVpTiVQiBizCBi0QJ2iHKcCH").cp();
            this.gfx.setTransform(71.1,25.1);
    
            this.container = new Container ();
            this.container.addChild ( this.gfx, this.text );
    
    	return this.container;
    };

    et enfin l'index :

    <!DOCTYPE html>
    
    <html>
    	<head>
    		<meta charset="utf-8" />
    		<style>
                    body
                    {
                       	background-color: black;
                    	text-align: center;
                    }
                    </style>
                    
                    <script src="http://code.createjs.com/easeljs-0.4.1.min.js"></script>
    		<title>TBG HTML/JS</title>
    	</head>
    
    	<body>
    		<canvas id="gameview" width="800" height="600">
      			Désolé, votre navigateur ne supporte pas la technologie Canvas.
    		</canvas>
    
    		<script type="text/javascript" src="src/tiletype.js"></script>
    		<script type="text/javascript" src="src/tile.js"></script>		
    		<script type="text/javascript" src="src/player.js"></script>
    		<script type="text/javascript" src="src/map.js"></script>
    		<script type="text/javascript" src="src/node.js"></script>
    		<script type="text/javascript" src="src/pathfinder.js"></script>
    
    		<script type="text/javascript" src="assets/gfx.js"></script>
    		<script type="text/javascript" src="assets/core.js"></script>
    	</body>
    
    </html>











    • Partager sur Facebook
    • Partager sur Twitter
      22 juillet 2016 à 10:38:25

      c'est quoi cette ligne 101 ??
       
      <strong><span style="color:#ff0000;"> if ( this.player.waitingList.length === 0 ) {</span></strong>

      essaye

      if ( this.player.waitingList.length === 0 ) {

      • Partager sur Facebook
      • Partager sur Twitter
        22 juillet 2016 à 23:06:45

        Effectivement ça peut paraître bizare. les balises HTML sont là juste parce que je voulais colorer la ligne de code qui m'embête et le code n'a pas été interprété mais affiché.

        Donc la ligne qui ne va pas c'est bien juste

        if ( this.player.waitingList.length === 0 ) {
        • Partager sur Facebook
        • Partager sur Twitter
          23 juillet 2016 à 13:07:36

          Bonjour,

          Dans le fichier Core.js, le player est assigné à la map avant d'avoir été créé.

          Il reste donc à undefined :)

          Voici une correction :

          var gameview = document.getElementById('gameview'), stage;
          stage = new Stage(gameview);
          Ticker.setFPS(24);
          Ticker.addListener(stage);
            
          var myMap = new Map ();
            
          myMap.offsetX = 400;
          myMap.offsetY = 200;
          
          var player = new Player ( TileType.DRAW, gfx.mur ( 255, 0, 0 ), true );
          myMap.addTile ( player, 3, 3, 1 );
          myMap.player = player;
            
          stage.addChild ( myMap );
            
          var map = [     [0, 1, 0, 1, 0],
                          [0, 0, 0, 0, 0],
                          [0, 0, 0, 1, 0],
                          [0, 1, 0, 0, 0],
                          [0, 1, 0, 0, 0]];
            
            
          for ( var i = 0; i < 5; i++ )
          {
             for ( var j = 0; j < 5; j++ )
             {
                     if ( map[i][j] === 0 )
                     {
                             myMap.addTile ( new Tile ( TileType.DRAW, gfx.solTAlea(200,200,128), true ), i, j, 0 );
                     }
                     else
                     {
                             myMap.addTile ( new Tile ( TileType.DRAW, gfx.murTAlea(128,128,128), false ), i, j, 2 );
                     }
             }
          }



          • Partager sur Facebook
          • Partager sur Twitter
            23 juillet 2016 à 14:42:57

            Effectivement. Comment ais-je pu rater ça !

            Du coup là ça fonctionne ^^ Merci  !

            • Partager sur Facebook
            • Partager sur Twitter

            Erreur tutoriel Moteur de rendu Isométrique

            × 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