2015-10-19 7 views
2

У меня есть изометрический движок, который я строй:Плавного движения персонажа на изометрической карте

http://jsfiddle.net/neuroflux/09h43kz7/1/

(клавиши со стрелками для перемещения).

Я обновляю Engine.player.x и Engine.player.y для перемещения персонажа, но (очевидно) игрок просто «выскакивает» из одной плитки в другую.

Я задавался вопросом, был ли способ заставить его «скользить» от плитки до плитки? Или еще лучше, свободное движение ...

Я потянув меня за волосы, пытаясь.

Вот соответствующий код:

var Engine = { 

    // canvas variables 
    canvas: null, 
    ctx: null, 

    // map 
    map: [ 
     [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2], 
     [2,1,1,1,1,1,1,1,1,1,1,1,1,1,2], 
     [2,1,1,0,0,1,1,1,1,0,0,0,1,1,2], 
     [2,2,1,0,0,0,0,1,0,0,0,0,1,1,2], 
     [2,2,1,1,1,1,0,0,0,0,1,0,0,1,2], 
     [2,2,2,2,2,1,0,0,0,1,0,0,0,1,2], 
     [2,2,1,1,1,1,0,0,0,0,0,0,0,1,2], 
     [2,1,1,0,1,0,0,0,0,1,1,0,0,1,2], 
     [2,1,0,0,0,0,0,1,0,0,0,0,0,1,2], 
     [2,1,0,0,0,0,0,0,0,0,1,0,0,1,2], 
     [2,1,0,0,0,0,1,0,0,0,0,0,0,1,2], 
     [2,1,0,1,1,0,0,0,0,1,0,0,0,1,2], 
     [2,1,0,0,0,0,0,0,0,0,1,0,1,1,2], 
     [2,1,1,1,1,1,1,1,1,1,1,1,1,1,2], 
     [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2] 
    ], 

    // player info 
    player: { 
     x:1, 
     y:1 
    }, 

    // tile size 
    tileH: 31, 
    tileW: 63, 

    // map position 
    mapX: window.innerWidth/2, 
    mapY: window.innerHeight/3, 

    // tile images 
    tileSources: [ 
     "images/stone.png", 
     "images/grass.png", 
     "images/water.png", 
     "images/ralph.png" 
    ], 

    // for pre-loading 
    tileGraphics: [], 
    tilesLoaded: 0, 

    // image preloader 
    loadImages: function() { 
     for (var i = 0; i < Engine.tileSources.length; i++) { 
      Engine.tileGraphics[i] = new Image(); 
      Engine.tileGraphics[i].src = Engine.tileSources[i]; 
      Engine.tileGraphics[i].onload = function() { 
       Engine.tilesLoaded++; 
       if (Engine.tilesLoaded === Engine.tileSources.length) { 
        Engine.draw(); 
       } 
      } 
     } 
    }, 

    // update logic 
    update: function() { 
     Engine.draw(); 
    }, 

    // draw the scene 
    draw: function() { 
     Engine.ctx.clearRect(0, 0, Engine.canvas.width, Engine.canvas.height); 
     var drawTile; 
     for (var i = 0; i < Engine.map.length; i++) { 
      for (var j = 0; j < Engine.map[i].length; j++) { 
       drawTile = Engine.map[i][j]; 
       Engine.ctx.drawImage(Engine.tileGraphics[drawTile], (i - j) * Engine.tileH + Engine.mapX, (i + j) * Engine.tileH/2 + Engine.mapY); 
       if (Engine.player.x === i && Engine.player.y === j) { 
        Engine.ctx.drawImage(Engine.tileGraphics[3], (i - j) * Engine.tileH + Engine.mapX, (i + j) * Engine.tileH/2 + Engine.mapY - Engine.tileH + 10); 
       } 
      } 
     } 
     Engine.gameLoop(); 
    }, 

    // game loop 
    gameLoop: function() { 
     Engine.gameTimer = setTimeout(function() { 
      requestAnimFrame(Engine.update, Engine.canvas); 
     }, 1); 
    }, 

    // start 
    init: function() { 
     Engine.canvas = document.getElementById("main"); 
     Engine.canvas.width = window.innerWidth; 
     Engine.canvas.height = window.innerHeight; 
     Engine.ctx = Engine.canvas.getContext("2d"); 
     document.addEventListener("keyup", function(e) { 
      //console.log(e.keyCode); 
      switch(e.keyCode) { 
       case 38: 
        if (Engine.map[Engine.player.x-1][Engine.player.y] !== 2) { 
         Engine.player.x--; 
        } 
        break; 
       case 40: 
        if (Engine.map[Engine.player.x+1][Engine.player.y] !== 2) { 
         Engine.player.x++; 
        } 
        break; 
       case 39: 
        if (Engine.map[Engine.player.x][Engine.player.y-1] !== 2) { 
         Engine.player.y--; 
        } 
        break; 
       case 37: 
        if (Engine.map[Engine.player.x][Engine.player.y+1] !== 2) { 
         Engine.player.y++; 
        } 
        break; 
      } 
     }); 
     Engine.loadImages(); 
    } 

} 


// loaded 
window.onload = function() { 
    Engine.init(); 
}; 


// request animation frame 
window.requestAnimFrame = (function(){ 
    return window.requestAnimationFrame || 
    window.webkitRequestAnimationFrame || 
    window.mozRequestAnimationFrame || 
    window.oRequestAnimationFrame || 
    window.msRequestAnimationFrame || 
    function (callback, element){ 
    fpsLoop = window.setTimeout(callback, 1000/60); 
    }; 
}()); 

Заранее спасибо!

+0

По тому, что я видел, когда игрок двигается, только 1 раз координаты X и Y, и этим он должен появиться? – Hydro

+0

Когда вы двигаетесь - он перемещает персонажа прямо к новой плите. Но я бы хотел, чтобы он плавно скользил к следующей плитке. –

+0

Если возможно, попробуйте сделать интервал, который будет немного увеличивать проигрыватель X/Y, когда он переместится на другую плиту, после чего игрок будет над плитой, очистите интервал. Это, например, «Я здесь, я двигаюсь, 1, 2, 3, я здесь» – Hydro

ответ

2

Вы рисуете персонажа на полях плитки. Вы хотите просто добавить второй набор координат для символа, представляющего его пункт назначения. Чтобы плавно перемещаться, вы можете установить положение персонажей во фракциях плитки. Например, player.x = 2.5 символ находится на полпути между плитками 2 и 3.

Также вы хотите избавиться от беспорядка в изометрическом пространстве. Off загружает преобразование из 2d в изометрическое с помощью функции draw, вместо того, чтобы делать это вручную при каждом обращении к игровому полю.

Создать функцию отрисовки

// add to the Engine object. 
// img is the image to draw. x and y are the tile locations. 
// offsetX and offsetY [optional] are pixel offsets for fine tuning; 
drawImageIso:function (img,x,y,offsetX,offsetY){ 
    offsetX = offsetX === undefined ? 0: offsetX; // so you dont have to 
    offsetY = offsetY === undefined ? 0: offsetY; // add the offset if you 
                // are not using it; 
    Engine.ctx.drawImage( // draw the image 
     img, 
     (x - y) * Engine.tileH + Engine.mapX + offsetX, 
     (x + y) * Engine.tileH/2 + Engine.mapY - Engine.tileH+offsetY 
    ); 
}, 

Изменить объект игрок

player: { 
    x:1, 
    y:1, 
    destX:1, // the destination tile 
    destY:1, 
    playerAtDest:true, // true if the player has arrived  
}, 

Добавьте это Befor плитки визуализации Loops

var p = Engine.player; // because I am lazy and dont like typing. 
    var dx = p.destX; 
    var dy = p.destY; 
    var maxPlayerSpeed = 0.1; // max speed in tiles per frame 
    var mps = maxPlayerSpeed; // because I am lazy 
    // check if the player needs to move 
    if(Math.abs(p.x - dx) > mps || Math.abs(p.y - dy) > mps){ 
     p.x += Math.max(-mps , Math.min(mps , dx - p.x)); // move to destination clamping speed; 
     p.y += Math.max(-mps , Math.min(mps , dy - p.y));    
     p.playerAtDest = false; // flag the player is on the way 
    }else{ 
     // player directly over a till and not moving; 
     p.x = dx; // ensure the player positioned correctly; 
     p.y = dy; 
     p.playerAtDest = true; // flag the player has arrived 
    } 

Добавьте следующую команду, где вы использовали, чтобы рисовать игрок. Используйте назначение x, y, чтобы определить, когда рисовать или использовать Math.round(Engine.player.x) и y, чтобы определить, когда.

// now draw the player at its current position 
    Engine.drawImageIso(Engine.tileGraphics[3] , p.x , p.y , 0 , 10); 

Вам нужно будет изменить интерфейс, чтобы переместить пункт назначения игрока, а не x и y. Вы также можете отложить движение до тех пор, пока игрок не достигнет текущего пункта назначения.

Это охватывает основы.

+0

Это потрясающе, спасибо большое. Прекрасно работает. Но теперь у меня проблема с zOrdering с деревьями :(http://jsfiddle.net/vvu4ydxo/1/ –

+0

Рад, что это вам помогло. Лучший способ справиться с Z-порядком - рисовать из-за спины. может привести к некоторой двусмысленности относительно того, что происходит спереди. Это обычная проблема, поэтому попробуйте найти существующий ответ. Если вы можете найти один вопрос, задайте другой вопрос. – Blindman67

 Смежные вопросы

  • Нет связанных вопросов^_^