So here's the deal. I created this Sonic themed "Brick Breaker" style game that I wanted to host on a Wordpress site. Originally the game had 8 JS files, a CSS file and an HTML file but for the purposes of wordpress I threw everything into one file.
My first issue was that the JavaScript wasn't loading, but the images were being displayed as static in the corner of the page. After some rearranging (basically my scripts had to load in a certain order) I was able to get the JavaScript working.
Now I am having the most bizarre issue --- the PNG images (Sonic and the Rings) are not being displayed to the user, but they are CLEARLY being loaded when the game boots. How do I know this? I know this because the UI in lower right hand corner of the screen counts DOWN lives when I move the paddle to the left and let it run and the game eventually ends.
Basically, the images just aren't showing up on the canvas --- it's like they are invisible?
And yes, I have already tried changing the display type from "none" (they are supposed to be drawn onto the canvas using the draw function anyway, so that's not the solution).
Here's my code:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Sonic's Ring Grabber (Still In Dev)</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<style>
#gameScreen {
border: 1px double black;
}
img {
display: none;
}
</style>
<canvas id="gameScreen" width=800 height=600></canvas>
<img href='sftp://u99508072@access810531165.webspace-data.io/clickandbuilds/BehaviorsSpace/sonicballgame/assets/SpinballSonicJP.png' width="10%" id="sonicBall"/>
<img href='sftp://u99508072@access810531165.webspace-data.io/clickandbuilds/BehaviorsSpace/sonicballgame/assets/sonicring2.png' id="rings"/>
<script>
class Ring {
constructor(game, position) {
this.image = document.getElementById('rings');
this.markedForDeletion = false;
this.game = game;
this.position = position;
this.width = 40;
this.height = 40;
}
update() {
if (detectCollision(this.game.ball, this)) {
this.markedForDeletion = true;
}
}
draw(ctx) {
ctx.drawImage(this.image, this.position.x, this.position.y, this.width, this.height);
}
}
class Ball {
constructor(game) {
this.image = document.getElementById('sonicBall');
this.gameWidth = game.gameWidth;
this.gameHeight = game.gameHeight;
this.size = 60;
this.reset();
this.game = game;
}
reset() {
this.speed = {
x: 2,
y: 2
};
this.position = {
x: 250,
y: 400,
};
}
draw(ctx) {
ctx.drawImage(this.image, this.position.x, this.position.y, this.size, this.size);
}
update(deltaTime) {
this.position.x += this.speed.x;
this.position.y += this.speed.y;
//wall on left and right
if (this.position.x + this.size > this.gameWidth || this.position.x < 0) {
this.speed.x = -this.speed.x;
}
// wall on top and bottom
if (this.position.y < 0) {
this.speed.y = -this.speed.y;
}
if (this.position.y + this.size > this.gameHeight) {
this.game.tries--;
this.reset();
}
//check collision with paddle
if (detectCollision(this, this.game.paddle)) {
this.speed.y = -this.speed.y;
this.position.y = this.game.paddle.position.y - this.size;
}
}
}
class Paddle {
constructor(game) {
this.width = 150;
this.height = 20;
this.maxSpeed = 5;
this.speed = 0;
this.position = {
x: game.gameWidth / 2 - this.width / 2,
y: game.gameHeight - this.height - 10,
};
}
moveLeft() {
this.speed = -this.maxSpeed;
}
moveRight() {
this.speed = +this.maxSpeed;
}
stop() {
this.speed = 0;
}
draw(ctx) {
ctx.fillStyle = "green";
ctx.fillRect(this.position.x, this.position.y, this.width, this.height);
}
update(deltaTime) {
this.position.x += this.speed;
if (this.position.x < 0) this.position.x = 0;
if (this.position.x > 650) this.position.x = 650;
}
}
class InputHandler {
constructor(paddle, game) {
document.addEventListener('keydown', event => {
switch (event.keyCode) {
case 37:
paddle.moveLeft();
break;
case 39:
paddle.moveRight();
break;
case 13:
game.togglePause();
break;
case 32:
game.toggleStart();
break;
case 89:
game.toggleRestart();
break;
}
});
document.addEventListener('keyup', event => {
switch (event.keyCode) {
case 37:
if (paddle.speed < 0)
paddle.stop();
break;
case 39:
if (paddle.speed > 0)
paddle.stop();
break;
}
});
}
}
function buildLevel(game, level) {
let rings = [];
level.forEach((row, rowIndex) => {
row.forEach((ring, ringIndex) => {
if (ring === 1) {
let position = {
x: 82 * ringIndex,
y: 40 + 35 * rowIndex
}
rings.push(new Ring(game, position));
}
});
});
return rings;
}
const level1 = [
[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, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
const level2 = [
[0, 1, 0, 1, 0, 1, 0, 1, 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, 1, 1, 1]
];
const level3 = [
[1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
function detectCollision(ball, gameObject) {
let leftOfBall = ball.position.x;
let rightOfBall = ball.position.x + ball.size;
let topOfBall = ball.position.y;
let bottomOfBall = ball.position.y + ball.size;
let leftOfObject = gameObject.position.x;
let rightOfObject = gameObject.position.x + gameObject.width;
let topOfObject = gameObject.position.y;
let bottomOfObject = gameObject.position.y + gameObject.height;
if (leftOfBall < rightOfObject &&
rightOfBall > leftOfObject &&
topOfBall < bottomOfObject &&
bottomOfBall > topOfObject) {
return true;
} else {
return false;
}
}
const GAMESTATE = {
PAUSED: 0,
RUNNING: 1,
MENU: 2,
GAMEOVER: 3
}
class Game {
constructor(gameWidth, gameHeight) {
this.gameWidth = gameWidth;
this.gameHeight = gameHeight;
this.gamestate = GAMESTATE.MENU;
this.ball = new Ball(this);
this.paddle = new Paddle(this);
this.rings = [];
this.gameObjects = [];
this.tries = 3;
this.levels = [level1, level2, level3]
this.currentLevel = 0;
new InputHandler(this.paddle, this);
}
start() {
this.rings = buildLevel(this, this.levels[this.currentLevel]);
this.gameObjects = [this.ball, this.paddle];
}
update(deltaTime) {
if (this.tries === 0) this.gamestate = GAMESTATE.GAMEOVER;
if (this.gamestate === GAMESTATE.PAUSED || this.gamestate === GAMESTATE.MENU || this.gamestate === GAMESTATE.GAMEOVER)
if (this.rings.length === 0) {
this.currentLevel++;
this.ball.reset();
this.start();
}
[...this.gameObjects, ...this.rings].forEach(object => object.update(deltaTime));
this.gameObjects.forEach((object) => object.update(deltaTime));
this.rings = this.rings.filter(object => !object.markedForDeletion);
}
draw(ctx) {
[...this.gameObjects, ...this.rings].forEach(object => object.draw(ctx));
this.gameObjects.forEach(object => object.draw(ctx));
if (this.gamestate == GAMESTATE.PAUSED) {
ctx.rect(0, 0, this.gameWidth, this.gameHeight);
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.fill();
ctx.font = "30px Arial";
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText("GAME PAUSED", this.gameWidth / 2, this.gameHeight / 2);
}
if (this.gamestate == GAMESTATE.MENU) {
ctx.rect(0, 0, this.gameWidth, this.gameHeight);
ctx.fillStyle = "rgba(0,0,0)";
ctx.fill();
ctx.font = "30px Arial";
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.fillText("TO START, PRESS SPACEBAR", this.gameWidth / 2, this.gameHeight / 2);
ctx.fillText("WHILE PLAYING, PRESS ENTER TO PAUSE", this.gameWidth / 2, this.gameHeight / 1.5);
}
if (this.gamestate == GAMESTATE.GAMEOVER) {
ctx.rect(0, 0, this.gameWidth, this.gameHeight);
ctx.fillStyle = "rgba(0,0,0)";
ctx.fill();
ctx.font = "30px Arial";
ctx.fillStyle = "white";
ctx.textAlign = "center";
ctx.fillText("GAME OVER", this.gameWidth / 2, this.gameHeight / 2);
ctx.fillText("PRESS Y TO TRY AGAIN", this.gameWidth / 2, this.gameHeight / 1.5);
}
if (this.gamestate == GAMESTATE.RUNNING) {
ctx.font = "20px Arial";
ctx.fillStyle = "black";
ctx.textAlign = "right";
ctx.fillText("LIVES: " + this.tries, this.gameWidth, this.gameHeight);
}
}
togglePause() {
if (this.gamestate == GAMESTATE.PAUSED) {
this.gamestate = GAMESTATE.RUNNING;
} else {
this.gamestate = GAMESTATE.PAUSED;
}
}
toggleStart() {
if (this.gamestate == GAMESTATE.MENU) {
this.gamestate = GAMESTATE.RUNNING;
this.rings = [];
this.tries = 3;
this.levels = [level1, level2, level3]
this.currentLevel = 0;
new InputHandler(this.paddle, this);
}
}
toggleRestart() {
if (this.gamestate == GAMESTATE.GAMEOVER) {
this.gamestate = GAMESTATE.MENU;
this.ball = new Ball(this);
this.paddle = new Paddle(this);
this.rings = [];
this.gameObjects = [];
this.tries = 3;
this.levels = [level1, level2, level3]
this.currentLevel = 0;
new InputHandler(this.paddle, this);
}
}
}
let canvas = document.getElementById("gameScreen");
let ctx = canvas.getContext('2d');
const GAME_WIDTH = 800;
const GAME_HEIGHT = 600;
let game = new Game(GAME_WIDTH, GAME_HEIGHT);
game.start();
let lastTime = 0;
//images
function gameLoop(timeStamp) {
let deltaTime = timeStamp - lastTime;
lastTime = timeStamp;
ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
game.update(deltaTime);
game.draw(ctx);
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
</script>
</body>
</html>
Anyone have any idea what might be happening here?
The image tag should use the src attribute not the href attribute.
no
<img href=""/>
yes
<img src=""/>
Also the reference to the image is typically something like
https://hostname.com/images/my-image.png
The protocol is typically https
these days or maybe http
(discouraged). You have an sftp
protocol in your url which won't work.
If you are storing your image in your Wordpress assets area you should be able to go to the detail view for that image and copy/paste a visible url for that asset.
Alternatively you can right-click on the image and 'Open Image in New Tab' to see the individual image's url in the browser address window in a separate browser tab. If you see the image in the browser you know it is a working url so copy/paste that and add it to the src
attribute's value.