我正在看freeCodeCamp的一个关于flappy bird游戏的教程https://www.youtube.com/watch?v=pufko5eg8nc
但我正在使用一个类来学习更多关于它的知识。
问题是,图像没有加载到draw()函数的循环中。如果我将drawImage()放在循环之外(像其他图像一样),那么它们就可以工作。
控制台中没有错误,for循环中的两个图像没有出现,我只是不明白为什么>://
下面是HTML代码,我是在类中编写的:
const canvas = document.querySelector("#canvas");
class Game {
constructor(c) {
this.c = c; //canvas
this.ctx = c.getContext("2d"); // context
this.sprites = 5;
this.loadedSprites = 0;
this.score = 0;
this.gravity = 1.5
this.player = new Image(); // define images
this.player.reference = this;
this.bg = new Image();
this.bg.reference = this;
this.fg = new Image();
this.fg.reference = this;
this.north = new Image();
this.north.reference = this;
this.south = new Image();
this.south.reference = this;
//obstacle coordinates
this.obstacle = [];
this.obstacle[0] = {
x: this.c.width,
y: 0,
// reference: this
}
this.obstacle.reference = this;
this.pX = 10; // player starting location
this.pY = 150;
// set sprite locations and load.
this.player.onload = this.draw;
this.player.src = "images/crab.png";
this.bg.onload = this.draw;
this.bg.src = "images/bg.png";
this.fg.onload = this.draw;
this.fg.src = "images/fg.png";
this.north.onload = this.draw;
this.north.src = "images/obstacle.png";
this.gap = 85;
this.constant = this.north.height + this.gap;
this.south.onload = this.draw;
this.south.src = "images/obstacle.png";
console.log(`AAA: ${this.obstacle[0].x}`);
console.log(`LAUNCH is: ${this.obstacle[0]}`);
$(document).on('keydown', (e) => { this.moveUp(e.key) });
console.log("Game constructor:", this);
}
loadObstacle() {
return this.obstacle;
}
saveObstacle(obstacle) {
this.obstacle = obstacle;
}
draw() {
let ref = this.reference;
ref.loadedSprites += 1;
if (ref.loadedSprites >= ref.sprites) {
let constant = ref.gap + ref.north.height;
let obstacle = ref.loadObstacle(); // this is actually not needed, since ref.obstacle odes the same thing. Just thought I'd try something else
for (var i = 0; i < obstacle.length; i++) {
ref.ctx.drawImage(ref.north, obstacle[i].x, obstacle[i].y);
ref.ctx.drawImage(ref.south, obstacle[i].x, obstacle[i].y + constant);
// ref.ctx.drawImage(ref.north, 250, 0); even adding these two from below, they do not show up
// ref.ctx.drawImage(ref.south, 250, 0 + constant);
obstacle[i].x--;
if (obstacle[i].x == 125) {
obstacle.push({
x: 512,
y: Math.floor(Math.random() * ref.north.height)
});
}
ref.saveObstacle(obstacle);
console.log(obstacle[0].x); // the values are right, but they do not appear?
}
ref.ctx.drawImage(ref.bg, 0, 0);
// ref.ctx.drawImage(ref.north, 250, 0); uncommenting this makes it show up
// ref.ctx.drawImage(ref.south, 250, 0 + constant);
ref.ctx.drawImage(ref.fg, 0, ref.c.height - ref.fg.height);
ref.ctx.drawImage(ref.player, ref.pX, ref.pY);
ref.pY += ref.gravity
window.requestAnimationFrame(ref.draw.bind(this));
}
}
moveUp(e) {
if (e == "w" || e == " " || e == "ArrowUp") {
this.pY -= 30;
console.log(this.obstacle);
}
}
}
let game = new Game(canvas);
我的代码看起来如何
下面是我跟踪的视频中的工作JS代码:
var cvs = document.getElementById("canvas");
var ctx = cvs.getContext("2d");
// load images
var bird = new Image();
var bg = new Image();
var fg = new Image();
var pipeNorth = new Image();
var pipeSouth = new Image();
bird.src = "images/crab.png";
bg.src = "images/bg.png";
fg.src = "images/fg.png";
pipeNorth.src = "images/obstacle.png";
pipeSouth.src = "images/obstacle.png";
// some variables
var gap = 85;
var constant;
var bX = 10;
var bY = 150;
var gravity = 1.5;
var score = 0;
// on key down
document.addEventListener("keydown", moveUp);
function moveUp() {
bY -= 25;
}
// pipe coordinates
var pipe = [];
pipe[0] = {
x: cvs.width,
y: 0
};
// draw images
function draw() {
ctx.drawImage(bg, 0, 0);
for (var i = 0; i < pipe.length; i++) {
constant = pipeNorth.height + gap;
ctx.drawImage(pipeNorth, pipe[i].x, pipe[i].y);
ctx.drawImage(pipeSouth, pipe[i].x, pipe[i].y + constant);
pipe[i].x--;
if (pipe[i].x == 125) {
pipe.push({
x: cvs.width,
y: Math.floor(Math.random() * pipeNorth.height) - pipeNorth.height
});
}
// detect collision
// if (bX + bird.width >= pipe[i].x && bX <= pipe[i].x + pipeNorth.width && (bY <= pipe[i].y + pipeNorth.height || bY + bird.height >= pipe[i].y + constant) || bY + bird.height >= cvs.height - fg.height) {
// location.reload(); // reload the page
// }
// if (pipe[i].x == 5) {
// score++;
// scor.play();
// }
}
ctx.drawImage(fg, 0, cvs.height - fg.height);
ctx.drawImage(bird, bX, bY);
bY += gravity;
ctx.fillStyle = "#000";
ctx.font = "20px Verdana";
ctx.fillText("Score : " + score, 10, cvs.height - 20);
requestAnimationFrame(draw);
}
draw();
工作代码看起来如何
首先,也是最重要的一点:你在这里混合了两种完全不同的东西。
this.player.onload = this.draw;
而且
window.requestAnimationFrame(ref.draw.bind(this));
两者执行相同的功能。从技术上讲,这当然是可能的,但这会让事情变得有点混乱。我建议为onload事件设置一个附加函数,这样当所有图像完成加载后,您就可以在那里触发requestAnimationFrame。
this.player = new Image();
this.player.reference = this;
this.player.onload = this.loaded;
loaded() {
let ref = this.reference;
ref.loadedSprites += 1;
if (ref.loadedSprites >= ref.sprites) {
// continue
}
}
其次,需要将this关键字的正确“上下文”传递给.bind()函数。它应该始终是游戏类的对象。因此将上面的//contine
替换为:
window.requestAnimationFrame(ref.draw.bind(ref));
现在需要对draw()
函数进行一些修改。由于我们为this关键字提供了适当的上下文,因此我们不再需要使用引用--我们现在可以简单地使用它。
下面是完整的示例:
null
const canvas = document.querySelector("#canvas");
class Game {
constructor(c) {
this.c = c; //canvas
this.ctx = c.getContext("2d"); // context
this.sprites = 5;
this.loadedSprites = 0;
this.score = 0;
this.gravity = 1.5
this.player = new Image();
this.player.reference = this;
this.bg = new Image();
this.bg.reference = this;
this.fg = new Image();
this.fg.reference = this;
this.north = new Image();
this.north.reference = this;
this.south = new Image();
this.south.reference = this;
//obstacle coordinates
this.obstacle = [];
this.obstacle[0] = {
x: this.c.width,
y: 0,
// reference: this
}
this.obstacle.reference = this;
this.pX = 10; // player starting location
this.pY = 150;
// set sprite locations and load.
this.player.onload = this.loaded;
this.player.src = "https://picsum.photos/id/237/20/20";
this.bg.onload = this.loaded;
this.bg.src = "https://picsum.photos/id/22/20/20";
this.fg.onload = this.loaded;
this.fg.src = "https://picsum.photos/id/30/20/20";
this.north.onload = this.loaded;
this.north.src = "https://picsum.photos/id/37/20/20";
this.gap = 85;
this.constant = this.north.height + this.gap;
this.south.onload = this.loaded;
this.south.src = "https://picsum.photos/id/137/20/20";
console.log(`AAA: ${this.obstacle[0].x}`);
console.log(`LAUNCH is: ${this.obstacle[0]}`);
$(document).on('keydown', (e) => {
this.moveUp(e.key)
});
console.log("Game constructor:", this);
}
loadObstacle() {
return this.obstacle;
}
saveObstacle(obstacle) {
this.obstacle = obstacle;
}
loaded() {
let ref = this.reference;
ref.loadedSprites += 1;
if (ref.loadedSprites >= ref.sprites) {
window.requestAnimationFrame(ref.draw.bind(ref));
}
}
draw() {
let constant = this.gap + this.north.height;
let obstacle = this.loadObstacle();
for (var i = 0; i < obstacle.length; i++) {
this.ctx.drawImage(this.north, obstacle[i].x, obstacle[i].y);
this.ctx.drawImage(this.south, obstacle[i].x, obstacle[i].y + constant);
obstacle[i].x--;
if (obstacle[i].x == 125) {
obstacle.push({
x: 512,
y: Math.floor(Math.random() * this.north.height)
});
}
this.saveObstacle(obstacle);
}
this.ctx.drawImage(this.bg, 0, 0);
this.ctx.drawImage(this.fg, 0, this.c.height - this.fg.height);
this.ctx.drawImage(this.player, this.pX, this.pY);
this.pY += this.gravity
window.requestAnimationFrame(this.draw.bind(this));
}
moveUp(e) {
if (e == "w" || e == " " || e == "ArrowUp") {
this.pY -= 30;
console.log(this.obstacle);
}
}
}
let game = new Game(canvas);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas" width="512" height="512">
</canvas>
问题内容: 我有以下代码- 但这给了我输出- 我不明白这一点,为什么不消除它,但是在这种情况下我只尝试了一种。当我最后添加少量内容时,我不会从中删除。为什么? 问题答案: 删除第一个“ Meg”时,即为索引。然后增加,但是由于“ Meg”之一已被删除,因此现在是“ Brain”。因此,您实际上没有检查第二个“ Meg”。 解决问题。您可以在删除元素时减少索引:
我有以下代码-
我一直在研究的一个函数有一个问题。这个函数的目的是取两组文本输入框中的日期,计算两者之间的差异,然后将该天数放入第三组框中。我的函数如下所示。 变量在开头引用的三个数组只包含我希望访问的表单元素的名称。我已经用一个警告框测试了start、end和out变量,如果代码中没有Show Difference注释下的行,循环运行良好。我也检查了所有的名字,确保他们都匹配。此外,我已经手动运行页面八次(有八
这个方法的问题是它总是返回零。看起来没有使用它的参数。然而,如果我按照下面的方式来写,那么一切都运行得很好。有没有人知道为什么第一种方法不起作用?
我想做的是制作一个快速而肮脏的幻灯片。我的想法是让master div包含一个空白的“master”img标记和一组div,每个div都包含自己的img和span标记。每个图像的源依次设置为主img的源。因此,我开始迭代每个图像,并尝试使用setTimeout()和2秒延迟将其源设置为主img的源。我遇到的问题是,编写代码似乎要等待两秒钟,并且只显示序列中的最后一幅图像。 如果我能得到第二双眼睛来
问题内容: 我在一起有多个循环,而在最内部的循环中有一个睡眠。例如: 如果您运行该代码,则可能需要等待1秒钟然后再次休眠直到结束,才能获得价值。 但是结果是不同的,它等待10秒钟并打印整行,然后再次等待打印下一行。 我发现打印末尾的逗号导致了此问题。我该如何解决? 问题答案: 由于存在逗号,因此输出缓冲到a为止。 您应在每次打印或使用后冲洗并冲洗缓冲区。 定义您的打印方法: 在行的末尾打印一个