0

Trying to make my first game this weekend. I finally got my rectangle to appear at the same time as my map. And my rectangle can move! But as soon as I click a button to move it, the map disappears. Is this where I need to make some kind of gameplay loop to keep updating the map on every button click or set a timer on it? Or do I have some other kind of error? Thanks all!

   var canvas = <HTMLCanvasElement>document.getElementById('myCanvas');
var context = canvas.getContext("2d");
var img = new Image();
img.onload = function () {
    context.drawImage(img, 0, 0);
}
img.src = "";



var mapArray =
       ["############################",
        "#      #    #      o      ##",
        "#                          #",
        "#   ####   #####    ##     #",
        "##         #   #    ##     #",
        "###           ##     #     #",
        "#           ###      #     #",
        "#   ####          ###      #",
        "#   ##    #  o             #",
        "# o  #    #    o ###   ### #",
        "#    #    #                #",
        "############################"];

//need to add wall.scource =  and grass.source =
var wall = new Image();
var grass = new Image();
grass.src = "http://vignette2.wikia.nocookie.net/tibia/images/6/60/Grass_(Tile).gif/revision/latest?cb=20080817072800&path-prefix=en";
wall.src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJyofLT0tMSw3QTo6LC87RD84Nzc5OjcBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIACAAIAMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAACAwQFAP/EACkQAAEDAwIDCQEAAAAAAAAAAAECAxEABCESEyMxURQyM0Fhc4GT0QX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8Au/oXDzT2ltZSJxAHKp27242yC5nPxQ3Qm5dVqzOMelI7vNMdYoKm718Jw4c85ApN5cXIbWvdUTtk48qBKkGcgEdaFRT2e4AIPCVQaF+1tvuawAVEQKlVBM8ulHfPoXeunfaKQqJ1ilrW0UnjNfYP2gVoCoURIpdwhoMuhKTG2ZNODiJI3miPcFddvMm1cSHGvDIEKBJoP//Z";


var posX = 0;
var posY = 0;




//for loops set images at given coordinates according to position on mapArray
for (var y = 0; y < mapArray.length; y++) {
    for (var x = 0; x < mapArray[0].length; x++) {

        if (mapArray[y][x] == "") {
            context.drawImage(grass, (32 * x), (32 * y), 32, 32)//last two are size of image )
        }
        if (mapArray[y][x] == "#") {
            context.drawImage(wall, (32 * x), (32 * y), 32, 32)//last two are size of image )
        }
 }
}

context.rect(posX, posY, 32, 32)
context.stroke();//traces path, might not need this


//moves character
function move(e) {//next five lines are newly added. Final line of function is drawimage function that is new as well
    var ctx = canvas.getContext('2d');// create backing canvas
    var backCanvas = document.createElement('canvas');
    backCanvas.width = canvas.width;
    backCanvas.height = canvas.height;
    var backCtx = backCanvas.getContext('2d');

    //alert(e.keyCode);//gives feedback to what each keyCode is
    if (e.keyCode == 39) {
        posX += 5;
    }
    if (e.keyCode == 37) {
        posX -= 5;
    }
    if (e.keyCode == 40) {
        posY += 5;
    }
    if (e.keyCode == 38) {
        posY -= 5;

    }
    canvas.width = canvas.width;//clears the board after each move
    context.rect(posX, posY, 32, 32)
    context.stroke();
    ctx.drawImage(backCanvas, 0, 0);
}    
document.onkeydown = move;
ScottVMeyers
  • 307
  • 3
  • 15

2 Answers2

1

Yes your canvas.width = canvas.width; will clear the canvas and you'll end up with only the rect after moving. Either do all the rendering code in your move function as well, or have a backup canvas for the map that so that you can efficiently render it at the top of your move function without stepping through the mapArray each time. Here they use a backup canvas: html5: copy a canvas to image and back


Code based on the backup canvas idea:

var canvas = <HTMLCanvasElement>document.getElementById('myCanvas');
var context = canvas.getContext("2d");
var img = new Image();
img.onload = function () {
    context.drawImage(img, 0, 0);
}
img.src = "";



var mapArray =
       ["############################",
        "#      #    #      o      ##",
        "#                          #",
        "#   ####   #####    ##     #",
        "##         #   #    ##     #",
        "###           ##     #     #",
        "#           ###      #     #",
        "#   ####          ###      #",
        "#   ##    #  o             #",
        "# o  #    #    o ###   ### #",
        "#    #    #                #",
        "############################"];

//need to add wall.scource =  and grass.source =
var wall = new Image();
var grass = new Image();
grass.src = "http://vignette2.wikia.nocookie.net/tibia/images/6/60/Grass_(Tile).gif/revision/latest?cb=20080817072800&path-prefix=en";
wall.src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJyofLT0tMSw3QTo6LC87RD84Nzc5OjcBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIACAAIAMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAACAwQFAP/EACkQAAEDAwIDCQEAAAAAAAAAAAECAxEABCESEyMxURQyM0Fhc4GT0QX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8Au/oXDzT2ltZSJxAHKp27242yC5nPxQ3Qm5dVqzOMelI7vNMdYoKm718Jw4c85ApN5cXIbWvdUTtk48qBKkGcgEdaFRT2e4AIPCVQaF+1tvuawAVEQKlVBM8ulHfPoXeunfaKQqJ1ilrW0UnjNfYP2gVoCoURIpdwhoMuhKTG2ZNODiJI3miPcFddvMm1cSHGvDIEKBJoP//Z";


var posX = 0;
var posY = 0;




//for loops set images at given coordinates according to position on mapArray
for (var y = 0; y < mapArray.length; y++) {
    for (var x = 0; x < mapArray[0].length; x++) {

        if (mapArray[y][x] == "") {
            context.drawImage(grass, (32 * x), (32 * y), 32, 32)//last two are size of image )
        }
        if (mapArray[y][x] == "#") {
            context.drawImage(wall, (32 * x), (32 * y), 32, 32)//last two are size of image )
        }
 }
}

// Here you've rendered the static content and you want to save the state of the canvas in a backup at this point:

// create backing canvas
var backCanvas = document.createElement('canvas');
backCanvas.width = canvas.width;
backCanvas.height = canvas.height;
var backCtx = backCanvas.getContext('2d');

// save main canvas contents
backCtx.drawImage(canvas, 0,0);

context.rect(posX, posY, 32, 32)
context.stroke();//traces path, might not need this


//moves character
function move(e) {

    canvas.width = canvas.width;//clears the board after each move (not really necessary since we'll draw the backCanvas over it...)

    // Render the backup canvas here
    context.drawImage(backCanvas, 0,0);

    //alert(e.keyCode);//gives feedback to what each keyCode is
    if (e.keyCode == 39) {
        posX += 5;
    }
    if (e.keyCode == 37) {
        posX -= 5;
    }
    if (e.keyCode == 40) {
        posY += 5;
    }
    if (e.keyCode == 38) {
        posY -= 5;

    }
    context.rect(posX, posY, 32, 32)
    context.stroke();
}    
document.onkeydown = move;
Community
  • 1
  • 1
andrrs
  • 2,289
  • 3
  • 17
  • 25
  • Thanks, but I can't get either to work. The first doesn't fix the problem, and the second solution has some type errors that visual studio doesn't like, and disables the rectangle's ability to move. – ScottVMeyers Nov 15 '15 at 10:17
  • By the first fix you mean running your mapArray code each time? What type errors did you get in Visual Studio? If it disables the rectangle's movements it sounds like the Javascript breaks in the move function before the rectangle is moved, did you check the browser's console for errors? In your backup canvas, you saved its image before rendering the rectangle for the first time, right? – andrrs Nov 15 '15 at 10:27
  • I'm just working with the backup canvas. I just can't get it to work. I don't think I know which parts of the code go where. I've put it at the top of my move function, i've put some at the top and some at the bottom. I've tried to declare some variables at the start of the page. I just can't get any of it to work, I still lose my walls every time. – ScottVMeyers Nov 15 '15 at 20:58
  • OK, can you copy your current code to the question? – andrrs Nov 15 '15 at 21:07
  • Thanks andrrs. I've updated the code in the original question. – ScottVMeyers Nov 15 '15 at 21:49
  • Hi @ScottVMeyers: I've added some code in my answer to show the order in which I think things must be drawn using the backupCanvas. Haven't tested it myself so might have typos, but the general idea is there. – andrrs Nov 16 '15 at 08:47
1

jsFiddle : https://jsfiddle.net/j353agny/3/

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

var mapArray = ["############################",
    "#      #    #      o      ##",
    "#                          #",
    "#   ####   #####    ##     #",
    "##         #   #    ##     #",
    "###           ##     #     #",
    "#           ###      #     #",
    "#   ####          ###      #",
    "#   ##    #  o             #",
    "# o  #    #    o ###   ### #",
    "#    #    #                #",
    "############################"];

//need to add wall.scource =  and grass.source =
var wall = new Image();
var grass = new Image();
grass.src = "http://vignette2.wikia.nocookie.net/tibia/images/6/60/Grass_(Tile).gif/revision/latest?cb=20080817072800&path-prefix=en";
wall.src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJyofLT0tMSw3QTo6LC87RD84Nzc5OjcBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIACAAIAMBIgACEQEDEQH/xAAYAAADAQEAAAAAAAAAAAAAAAACAwQFAP/EACkQAAEDAwIDCQEAAAAAAAAAAAECAxEABCESEyMxURQyM0Fhc4GT0QX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8Au/oXDzT2ltZSJxAHKp27242yC5nPxQ3Qm5dVqzOMelI7vNMdYoKm718Jw4c85ApN5cXIbWvdUTtk48qBKkGcgEdaFRT2e4AIPCVQaF+1tvuawAVEQKlVBM8ulHfPoXeunfaKQqJ1ilrW0UnjNfYP2gVoCoURIpdwhoMuhKTG2ZNODiJI3miPcFddvMm1cSHGvDIEKBJoP//Z";

// Player position

var posX = 0;
var posY = 0;

//moves character
function move(e) {

    //alert(e.keyCode);//gives feedback to what each keyCode is
    if (e.keyCode == 39) {
        posX += 5;
    }
    if (e.keyCode == 37) {
        posX -= 5;
    }
    if (e.keyCode == 40) {
        posY += 5;
    }
    if (e.keyCode == 38) {
        posY -= 5;

    }
}

document.onkeydown = move;

// every 3 miliseconds re-draw the stage with the player
setInterval(function () {
    console.log("REDRAW");
    // Clear the canvas and redraw
    context.fillStyle = "#FFF";
    context.fillRect(0,0,800,600);

    //for loops set images at given coordinates according to position on mapArray
    for (var y = 0; y < mapArray.length; y++) {
        for (var x = 0; x < mapArray[0].length; x++) {

            if (mapArray[y][x] == "") {
                context.drawImage(grass, (32 * x), (32 * y), 32, 32) //last two are size of image )
            }
            if (mapArray[y][x] == "#") {
                context.drawImage(wall, (32 * x), (32 * y), 32, 32) //last two are size of image )
            }
        }
    }
    context.fillStyle = "#00F";
    context.fillRect(posX, posY, 32, 32)
}, 3);

What you can do is just use a setInterval which will run every 3 miliseconds. Basically every 3 miliseconds I get the canvas to redraw your walls and then redraw your player. This will stop any weird drawing issues you have.

P.S. you could use requestAnimationFrame instead of setInterval just to let you know

Canvas
  • 5,779
  • 9
  • 55
  • 98