1

このJSFiddleでわかるように、矢印キーを使用して赤い四角形を移動すると、タイル間の遷移が非常に途切れ途切れになり、見栄えがよくありません。

1 つのスムーズな動きのように見えるように、タイル間のスムーズな移行を実現する方法があるかどうか疑問に思っています。

var canvas, context, board, imageObj, tiles, board, display;
var NUM_OF_TILES = 2;

// viewport
var vX = 0,
    vY = 0,
    vWidth = 15,
    vHeight = 10;

var playerX = 0,
    playerY = 0;

var worldWidth = 29,
    worldHeight = 19;

function loadMap(map) {
    if (map == 1) {
        return [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0], [0, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0], [0, 1, 1, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0], [0, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0], [0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 0], [0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
    }
}

$(document).ready(function() {


    canvas = document.getElementById("canvas");
    context = canvas.getContext("2d");

    canvas.tabIndex = 0;
    canvas.focus();
    canvas.addEventListener('keydown', function(e) {
        console.log(e);
        var key = null;
        switch (e.which) {
        case 37:
            // Left
            if (playerX > 0) playerX--;
            break;
        case 38:
            // Up
            if (playerY > 0) playerY--;
            break;
        case 39:
            // Right
            if (playerX < worldWidth) playerX++;
            break;
        case 40:
            // Down
            if (playerY < worldHeight) playerY++;
            break;
        }
        // Okay! The player is done moving, now we have to determine the "best" viewport.
        // Ideally the viewport centers the player,
        // but if its too close to an edge we'll have to deal with that edge

        vX = playerX - Math.floor(0.5 * vWidth);
        if (vX < 0) vX = 0;
        if (vX+vWidth > worldWidth) vX = worldWidth - vWidth;


        vY = playerY - Math.floor(0.5 * vHeight);
        if (vY < 0) vY = 0;
        if (vY+vHeight > worldHeight) vY = worldHeight - vHeight;


        draw();
    }, false);

    var board = [];

    canvas.width = 512;
    canvas.height = 352;

    board = loadMap(1);
    imageObj = new Image();
    tiles = [];

    var loadedImagesCount = 0;
    for (x = 0; x <= NUM_OF_TILES; x++) {
        var imageObj = new Image(); // new instance for each image
        imageObj.src = "http://mystikrpg.com/canvas/img/tiles/t" + x + ".png";

        imageObj.onload = function() {
            // console.log("Added tile ... "+loadedImagesCount);
            loadedImagesCount++;
            if (loadedImagesCount == NUM_OF_TILES) {
                // Onces all tiles are loaded ...
                // We paint the map
                draw();
            }
        };
        tiles.push(imageObj);
    }


    function draw() {
        context.clearRect(0,0,canvas.width, canvas.height);
        for (y = 0; y <= vHeight; y++) {
            for (x = 0; x <= vWidth; x++) {
                theX = x * 32;
                theY = y * 32;
                context.drawImage(tiles[board[y+vY][x+vX]], theX, theY, 32, 32);
            }
        }
        context.fillStyle = 'red';
        context.fillRect((playerX-vX)*32, (playerY-vY)*32, 32, 32);
    }
});
4

1 に答える 1

2

私は少し遊んで、何かが機能するようになりました:

    case 39:
       // Right
       if (playerX < worldWidth) {
           var start = playerX;
           var end   = Math.round(playerX + 1);
           $({ i : start }).animate({ i: end}, {
                duration: 400,
                step: function(now) {
                   playerX = now;
                   draw();
                }
            });
        }
        break;

値の間を補間するために、jqueryanimate関数を使用します。描画関数が1回だけ呼び出されることに気付きました。アニメーションを取得するには、ステップごとに呼び出す必要がありました。

再センタリングのエラーを回避するために、Math.round()そこでも使用します。

    vX = Math.round(playerX) - Math.floor(0.5 * vWidth);
    if (vX < 0) vX = 0;
    if (vX+vWidth > worldWidth) vX = worldWidth - vWidth;


    vY = Math.round(playerY) - Math.floor(0.5 * vHeight);
    if (vY < 0) vY = 0;
    if (vY+vHeight > worldHeight) vY = worldHeight - vHeight;

もちろん、追加の作業を行う必要があります。たとえば、開始点と停止点はこのように変化する可能性があります。提案されているように、charにはタイルではなくピクセル位置を使用する必要があります。しかし、私はあなたの意図を知りません。

チェックしてタイルが「フル」位置にあるかどうかをチェックすることで、キーダウンでスタックするのを回避できます。

if (playerY < worldHeight && playerY % 1 == 0) {...
于 2013-03-02T22:40:47.497 に答える