HTML5 - Creating a viewport for canvas

后端 未结 1 683
感情败类
感情败类 2021-02-03 12:07

I have a 2D array that is 30 across, 20 down. However, the viewport only paints 15 across and 10 down. I had a game like that originally and I\'ve been trying to achieve somethi

1条回答
  •  有刺的猬
    2021-02-03 12:16

    Here I've made a rudimentary viewport for you:

    http://jsfiddle.net/kmHZt/

    You have to keep track of the viewport X and Y (vX, vY) that represent where you are in the world at large. I also kept the viewport width and height as vars instead of hard coding them in.

    You can use the arrow keys to change the viewport X and Y which will scroll the map, drawing only the correct tiles.

    Hope that helps! Let me know if you have any questions!

    EDIT: example of viewport moving with player: http://jsfiddle.net/kmHZt/10/

    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);
        }
    });
    

    0 讨论(0)
提交回复
热议问题