图片未显示,但显然正在加载(Javascript 游戏托管在 Wordpress 上)
Images are not being displayed, but they are clearly being loaded (Javascript Game being hosted on Wordpress)
所以这是交易。我创建了这个 Sonic 主题 "Brick Breaker" 风格的游戏,我想在 Wordpress 网站上托管它。最初游戏有 8 个 JS 文件,一个 CSS 文件和一个 HTML 文件,但出于 wordpress 的目的,我将所有内容都放在一个文件中。
我的第一个问题是 JavaScript 没有加载,但图像在页面的一角显示为静态。经过一些重新排列(基本上我的脚本必须按特定顺序加载)我能够让 JavaScript 工作。
现在我遇到了最奇怪的问题 --- PNG 图像(索尼克与指环)没有显示给用户,但它们显然在游戏启动时被加载。我怎么知道的?我知道这一点是因为当我将桨向左移动并让它 运行 并且游戏最终结束时,屏幕右下角的 UI 会倒数生命。
基本上,图像只是没有显示在 canvas 上 --- 好像它们是不可见的?
是的,我已经尝试更改 "none" 的显示类型(无论如何它们应该使用绘图功能绘制到 canvas 上,所以这不是解决方案)。
这是我的代码:
<!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>
有人知道这里会发生什么吗?
图片标签应该使用 src 属性而不是 href 属性。
没有
<img href=""/>
是
<img src=""/>
此外,对图像的引用通常类似于
https://hostname.com/images/my-image.png
这些天协议通常是 https
,或者可能是 http
(气馁)。您的 url 中有一个 sftp
协议,它不起作用。
如果您将图像存储在您的 Wordpress 资产区域中,您应该能够进入该图像的详细视图和该资产的 copy/paste 可见 url。
或者,您可以右键单击图像,然后 'Open Image in New Tab' 在单独的浏览器选项卡中查看浏览器地址 window 中的单个图像 url。如果您在浏览器中看到图像,您就知道它是一个有效的 url,因此 copy/paste 并将其添加到 src
属性的值中。
所以这是交易。我创建了这个 Sonic 主题 "Brick Breaker" 风格的游戏,我想在 Wordpress 网站上托管它。最初游戏有 8 个 JS 文件,一个 CSS 文件和一个 HTML 文件,但出于 wordpress 的目的,我将所有内容都放在一个文件中。
我的第一个问题是 JavaScript 没有加载,但图像在页面的一角显示为静态。经过一些重新排列(基本上我的脚本必须按特定顺序加载)我能够让 JavaScript 工作。
现在我遇到了最奇怪的问题 --- PNG 图像(索尼克与指环)没有显示给用户,但它们显然在游戏启动时被加载。我怎么知道的?我知道这一点是因为当我将桨向左移动并让它 运行 并且游戏最终结束时,屏幕右下角的 UI 会倒数生命。
基本上,图像只是没有显示在 canvas 上 --- 好像它们是不可见的?
是的,我已经尝试更改 "none" 的显示类型(无论如何它们应该使用绘图功能绘制到 canvas 上,所以这不是解决方案)。
这是我的代码:
<!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>
有人知道这里会发生什么吗?
图片标签应该使用 src 属性而不是 href 属性。
没有
<img href=""/>
是
<img src=""/>
此外,对图像的引用通常类似于
https://hostname.com/images/my-image.png
这些天协议通常是 https
,或者可能是 http
(气馁)。您的 url 中有一个 sftp
协议,它不起作用。
如果您将图像存储在您的 Wordpress 资产区域中,您应该能够进入该图像的详细视图和该资产的 copy/paste 可见 url。
或者,您可以右键单击图像,然后 'Open Image in New Tab' 在单独的浏览器选项卡中查看浏览器地址 window 中的单个图像 url。如果您在浏览器中看到图像,您就知道它是一个有效的 url,因此 copy/paste 并将其添加到 src
属性的值中。