简体   繁体   中英

How do I make an image appear above the background in html canvas?

I'm trying to make a very simple mini-game where a character moves with keys. Multiple obstacles come at you from the right and you have to avoid them.

The problem is that the obstacles in the myObstacles array appear behind the background image. Why is it doing that and is there an easy fix that I'm missing?

Let me know if anything is unclear or I left out information. First time posting a question on here:)

var myGamePiece;
var myObstacles = [];
var myBackground;

function startGame() { 
    myGamePiece = new component(50, 50, "still.png", 10, 120, "image");
    myBackground = new component(1600, 400, "gamebkg.png", 0, 0, "background");
    myGameArea.start();
}


//board
var myGameArea = {
    canvas : document.createElement("canvas"),
    start : function() {
        this.canvas.width = 600;
        this.canvas.height = 600;
        this.context = this.canvas.getContext("2d");
        this.context.translate(0.5, 0.5);
        this.context.imageSmoothingQuality = "high";
        document.body.insertBefore(this.canvas, document.body.childNodes[0]);
        this.frameNo = 0;
        this.interval = setInterval(updateGameArea, 20);
        //keys to move
        window.addEventListener('keydown', function (e) {
        myGameArea.key = e.keyCode;
        })
        window.addEventListener('keyup', function (e) {
        myGameArea.key = false;
        })
    },
    clear : function() {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    },
    stop : function() {
        clearInterval(this.interval);
    }
}



function component(width, height, color, x, y, type) {
    this.type = type;
    if (type == "image" || type == "background") {
        this.image = new Image();
        this.image.src = color;
    }
    this.width = width;
    this.height = height;
    this.speedX = 0;
    this.speedY = 0;    
    this.x = x;
    this.y = y;    
    this.update = function() {
        ctx = myGameArea.context;
        if (type == "image" || type == "background") {
            ctx.drawImage(this.image, 
                this.x, 
                this.y,
                this.width, this.height);
        if (type == "background") {
            ctx.drawImage(this.image, 
                this.x + this.width, 
                this.y,
                this.width, this.height);
        }
        } else {
            ctx.fillStyle = color;
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
    }
    this.newPos = function() {
        this.x += this.speedX;
        this.y += this.speedY;
        if (this.type == "background") {
            if (this.x == -(this.width)) {
                this.x = 0;
            }
        }
    }    
    this.crashWith = function(otherobj) {
        var myleft = this.x;
        var myright = this.x + (this.width);
        var mytop = this.y;
        var mybottom = this.y + (this.height);
        var otherleft = otherobj.x;
        var otherright = otherobj.x + (otherobj.width);
        var othertop = otherobj.y;
        var otherbottom = otherobj.y + (otherobj.height);
        var crash = true;
    if ((mybottom < othertop) ||
        (mytop > otherbottom) ||
        (myright < otherleft) ||
        (myleft > otherright)) {
        crash = false;
    }
    return crash;
  }
}

function updateGameArea() {
   var x, y;
   for (i = 0; i < myObstacles.length; i += 1) {
        if (myGamePiece.crashWith(myObstacles[i])) {
            myGameArea.stop();
            return;
        }
    }

    myGameArea.clear();
    myGameArea.frameNo += 1;

    if (myGameArea.frameNo == 1 || everyinterval(150)) {
        x = myGameArea.canvas.width;
        y = myGameArea.canvas.height - 500;
        myObstacles.push(new component(30, 30, "feesh.png", x, y, "image"))
    }

    for (i = 0; i < myObstacles.length; i += 1) {
        myObstacles[i].x += -1;
        myObstacles[i].update();
    }

    myGamePiece.speedX = 0;
    myGamePiece.speedY = 0;
        if (myGameArea.key && myGameArea.key == 37) {myGamePiece.speedX = -5; }
        if (myGameArea.key && myGameArea.key == 39) {myGamePiece.speedX = 5; }
        if (myGameArea.key && myGameArea.key == 38) {myGamePiece.speedY = -5; }
        if (myGameArea.key && myGameArea.key == 40) {myGamePiece.speedY = 5; }
    myBackground.speedX = -1;
    myBackground.newPos();    
    myBackground.update();
    
    myGamePiece.newPos();    
    myGamePiece.update();
  
}

function everyinterval(n) {
    if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
    return false;
}

Building on the comment from @AHaworth :

you need to be careful about the order in which things are drawn!

The problem I see in your code is on function updateGameArea() the background should be at the top of the stuff you do, see my fix below.

 var myGamePiece; var myObstacles = []; var myBackground; function startGame() { myGamePiece = new component(50, 50, "red", 10, 60, "rect"); myBackground = new component(1600, 400, "blue", 0, 0, "rect"); myGameArea.start(); } function updateGameArea() { myGameArea.clear(); myGameArea.frameNo += 1; myBackground.speedX = -1; myBackground.newPos(); myBackground.update(); if (myGameArea.frameNo == 1 || everyinterval(150)) { myObstacles.push(new component(30, 30, "pink", myGameArea.canvas.width, 50, "rect")) } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].x += -0.5; myObstacles[i].update(); } myGamePiece.speedX = 0; myGamePiece.speedY = 0; myGamePiece.newPos(); myGamePiece.update(); } //board var myGameArea = { canvas: document.createElement("canvas"), start: function() { this.canvas.width = 400; this.canvas.height = 150; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.frameNo = 0; this.interval = setInterval(updateGameArea, 20); }, clear: function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.newPos = function() { this.x += this.speedX; this.y += this.speedY; } } function everyinterval(n) { return ((myGameArea.frameNo / n) % 1 == 0) } startGame()

I reduced a lot of your code to get a working snippet, you should do the same when posting question, that helps you focus on the error 90% of the time you will fix it before you post a question and also helps other debug your code.

If you are serious about it use a game engine, there a lot of good Open Source ones: https://github.com/collections/javascript-game-engines

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM