When trying to draw an image on an obstacle in an html canvas game I get this error message: Uncaught InvalidStateError: Failed to execute 'drawimage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.
The obstacle is invisible but the game still stops if the player collides with where it should be. The other stationary obstacles' images in the game are visible. What do I do?
I tried uploading the images in my html to let them load before using them but it still doesn't work. Other articles about similar situations do not cover this same context and do not help me who is quite new to programming.
Here is the code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" type="text/css" href="stylesheet.css"> <link/>
</head>
<body onload="startGame()">
<h2> My Lost Game </h2>
<p>Press the 'up', 'down', 'left' and 'right' keys on your keyboard to move. Avoid the obstacles and reach the goal.</p><br>
<p></p>
<script>
var myObstacle = [];
function startGame() {
myGameArea.start();
myGameGoal = new component(75, 95, "player2.jpg", 710, 215, "image");
myGamePiece = new component(75, 95, "player.jpg", 10, 215, "image");
myObstacle2 = new component (110, 150, "obstacle2.jpg", 350, 0, "image");
myObstacle3 = new component (110, 150, "obstacle3.jpg", 530, 350, "image");
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 800;
this.canvas.height = 500;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[4]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function (e) {
myGameArea.keys = (myGameArea.keys || []);
myGameArea.keys[e.keyCode] = true;
})
window.addEventListener('keyup', function (e) {
myGameArea.keys[e.keyCode] = 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") {
this.image = new Image();
this.image.src = color;
}
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
if (type == "image") {
ctx.drawImage(this.image,
this.x,
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;
}
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 < myObstacle.length; i += 1) {
if (myGamePiece.crashWith(myObstacle[i])) {
myGameArea.stop();
return;
}
}
myGameArea.clear();
myGameArea.frameNo += 1;
if (myGameArea.frameNo == 1 || everyinterval(150)) {
x = 200;
y = 300;
myObstacle.push(new component(110, 150, "obstacle1.jpg", x, y, "image"));
}
for (i = 0; i < myObstacle.length; i += 1) {
myObstacle[i].y += -1;
myObstacle[i].update();
}
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.keys && myGameArea.keys[37]) {myGamePiece.speedX = -3; }
if (myGameArea.keys && myGameArea.keys[39]) {myGamePiece.speedX = 3; }
if (myGameArea.keys && myGameArea.keys[38]) {myGamePiece.speedY = -3; }
if (myGameArea.keys && myGameArea.keys[40]) {myGamePiece.speedY = 3; }
myObstacle2.update();
myObstacle3.update();
myGameGoal.update();
myGamePiece.newPos();
myGamePiece.update();
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
return false;
}
</script>
</body>
</html>