Javascript 的闪烁图像
Flickering images with Javascript
我正在尝试使用 Repl.it 在 Javascript 中制作游戏,但玩家的图像每隔几秒就会闪烁。我不明白为什么会这样?我正在将一些图像加载到 canvas 上,并且在我添加 animate()
函数并开始更改图像后它才开始闪烁。有人可以解释一下吗? (去这个网站看忽悠也玩游戏:https://advanced-chrome-dino-game.isaacroot.repl.co/)我的代码:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var ground_size = 75;
var up = false;
var game_over = false;
const start_speed = 8;
var score = 0;
function randBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
class Player {
constructor(x_pos) {
this.color = "black";
this.image = "dino_1.png"
this.img = new Image();
this.width = 120;
this.height = 120;
this.x = x_pos;
this.y = c.height - ground_size - this.height;
this.speed = 0;
this.jump_power = 22.5;
this._gravity = 1;
this.an_time = 7;
this.an_count = 0;
}
ground_height() {
return c.height - ground_size - this.height;
}
on_ground() {
if (this.y == this.ground_height()) {
return true;
} else {
return false;
}
}
jump() {
if (this.on_ground()) {
this.speed = this.jump_power;
this.image = "dino_jump.png";
}
}
gravity() {
this.speed -= this._gravity;
}
animate() {
if (this.an_count <= 0) {
if (this.image == "dino_1.png") {
this.image = "dino_2.png";
} else {
if (this.image == "dino_2.png") {
this.image = "dino_1.png"
}
}
this.an_count = this.an_time;
} else {
this.an_count -= 1;
}
}
react() {
this.y -= this.speed
if (this.y > this.ground_height()) {
this.y = this.ground_height();
this.speed = 0;
}
if (this.on_ground() && this.image == "dino_jump.png") {
this.image = "dino_1.png"
}
}
rect() {
return [this.x, this.y, this.width, this.height]
}
}
class Obstacle {
constructor(x_pos, speed) {
this.color = "red";
this.img = new Image();
this.img.src = "cactus_big.png";
this.width = 52 * 1.5;
this.height = 75 * 1.5;
this.x = x_pos;
this.y = c.height - ground_size - this.height;
this.speed = speed;
}
ground_height() {
return c.height - ground_size - this.height;
}
on_ground() {
if (this.y == this.ground_height()) {
return true;
} else {
return false;
}
}
react() {
if (this.x <= 0 - this.width) {
this.x = randBetween(c.width, c.width + 500);
}
this.x -= this.speed;
}
rect() {
return [this.x, this.y, this.width, this.height]
}
}
player = new Player(75);
obstacle1 = new Obstacle(c.width, start_speed);
function inRect(rect1, rect2) {
var rect1_left = rect1[0];
var rect1_right = rect1[0] + rect1[2];
var rect1_top = rect1[1];
var rect1_bottom = rect1[1] + rect1[3];
var rect2_left = rect2[0];
var rect2_right = rect2[0] + rect2[2];
var rect2_top = rect2[1];
var rect2_bottom = rect2[1] + rect2[3];
var horizontal = false;
var vertical = false;
if (rect1_right > rect2_left && rect2_right > rect1_left) {
horizontal = true;
}
if (rect1_bottom > rect2_top && rect2_bottom > rect1_top) {
vertical = true;
}
return (vertical && horizontal);
}
function draw() {
ctx.beginPath();
ctx.fillStyle = "white";
ctx.fillRect(0, 0, c.width, c.height);
ctx.fillStyle = "#4b4b4b";
ctx.fillRect(0, c.height - ground_size, c.width, c.height);
ctx.fillStyle = player.color;
// ctx.fillRect(player.x, player.y, player.width, player.height);
player.img.src = player.image;
ctx.drawImage(player.img, player.x, player.y, player.width, player.height)
ctx.fillStyle = obstacle1.color;
// ctx.fillRect(obstacle1.x, obstacle1.y, obstacle1.width, obstacle1.height);
ctx.drawImage(obstacle1.img, obstacle1.x, obstacle1.y, obstacle1.width, obstacle1.height)
ctx.fillStyle = "black";
ctx.font = "30px Arial";
ctx.fillText("Score: " + Math.round(score / 25).toString(), 20, 50);
if (game_over) {
ctx.font = "80px Arial";
}
ctx.stroke();
}
document.addEventListener('keydown', (event) => {
if (event.key == 'ArrowUp' || event.key == 'Spacebar') {
up = true;
} else if (event.key == 'ArrowDown') {
//pass
}
});
document.addEventListener('keyup', (eventt) => {
if (eventt.key == 'ArrowUp') {
up = false;
} else if (event.key == 'ArrowDown') {
//pass
}
});
function update_speed() {
obstacle1.speed += 0.001;
}
function run() {
if (up == true) {
player.jump()
}
player.gravity();
player.react();
player.animate();
obstacle1.react();
if (inRect(player.rect(), obstacle1.rect())) {
game_over = true
}
score += obstacle1.speed
draw();
update_speed();
if (game_over == false) {
requestAnimationFrame(run);
}
}
run();
好吧,您所要做的就是预加载图像,这样您的 index.html 应该看起来像:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Block Runner</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<link rel="preload" href="cactus_big.png" as="image">
<link rel="preload" href="dino_1.png" as="image">
<link rel="preload" href="dino_2.png" as="image">
<link rel="preload" href="dino_jump.png" as="image">
<link rel="preload" href="ground.png" as="image">
</head>
<body>
<canvas id="myCanvas" width="900" height="600" style="border:0px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<script src="script.js"></script>
</body>
</html>
这样应该不会闪烁。
我检查了代码,发现您每次都将图像加载到 player.img
变量中。
function createImage(path){
let image = new Image();
image.src = path;
return image;
}
var images = {
dino:[
createImage("dino_1.png"),
createImage("dino_2.png"),
createImage("dino_jump.png")
],
cactus:createImage("cactus_big.png")
}
如果您在此处使用我的代码,则需要更改代码以改为使用这些图像。因为现在,每次绘制时,您都在加载图像。就这样,所有的图片都存起来了,我试了下,不闪烁了。
我正在尝试使用 Repl.it 在 Javascript 中制作游戏,但玩家的图像每隔几秒就会闪烁。我不明白为什么会这样?我正在将一些图像加载到 canvas 上,并且在我添加 animate()
函数并开始更改图像后它才开始闪烁。有人可以解释一下吗? (去这个网站看忽悠也玩游戏:https://advanced-chrome-dino-game.isaacroot.repl.co/)我的代码:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var ground_size = 75;
var up = false;
var game_over = false;
const start_speed = 8;
var score = 0;
function randBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
class Player {
constructor(x_pos) {
this.color = "black";
this.image = "dino_1.png"
this.img = new Image();
this.width = 120;
this.height = 120;
this.x = x_pos;
this.y = c.height - ground_size - this.height;
this.speed = 0;
this.jump_power = 22.5;
this._gravity = 1;
this.an_time = 7;
this.an_count = 0;
}
ground_height() {
return c.height - ground_size - this.height;
}
on_ground() {
if (this.y == this.ground_height()) {
return true;
} else {
return false;
}
}
jump() {
if (this.on_ground()) {
this.speed = this.jump_power;
this.image = "dino_jump.png";
}
}
gravity() {
this.speed -= this._gravity;
}
animate() {
if (this.an_count <= 0) {
if (this.image == "dino_1.png") {
this.image = "dino_2.png";
} else {
if (this.image == "dino_2.png") {
this.image = "dino_1.png"
}
}
this.an_count = this.an_time;
} else {
this.an_count -= 1;
}
}
react() {
this.y -= this.speed
if (this.y > this.ground_height()) {
this.y = this.ground_height();
this.speed = 0;
}
if (this.on_ground() && this.image == "dino_jump.png") {
this.image = "dino_1.png"
}
}
rect() {
return [this.x, this.y, this.width, this.height]
}
}
class Obstacle {
constructor(x_pos, speed) {
this.color = "red";
this.img = new Image();
this.img.src = "cactus_big.png";
this.width = 52 * 1.5;
this.height = 75 * 1.5;
this.x = x_pos;
this.y = c.height - ground_size - this.height;
this.speed = speed;
}
ground_height() {
return c.height - ground_size - this.height;
}
on_ground() {
if (this.y == this.ground_height()) {
return true;
} else {
return false;
}
}
react() {
if (this.x <= 0 - this.width) {
this.x = randBetween(c.width, c.width + 500);
}
this.x -= this.speed;
}
rect() {
return [this.x, this.y, this.width, this.height]
}
}
player = new Player(75);
obstacle1 = new Obstacle(c.width, start_speed);
function inRect(rect1, rect2) {
var rect1_left = rect1[0];
var rect1_right = rect1[0] + rect1[2];
var rect1_top = rect1[1];
var rect1_bottom = rect1[1] + rect1[3];
var rect2_left = rect2[0];
var rect2_right = rect2[0] + rect2[2];
var rect2_top = rect2[1];
var rect2_bottom = rect2[1] + rect2[3];
var horizontal = false;
var vertical = false;
if (rect1_right > rect2_left && rect2_right > rect1_left) {
horizontal = true;
}
if (rect1_bottom > rect2_top && rect2_bottom > rect1_top) {
vertical = true;
}
return (vertical && horizontal);
}
function draw() {
ctx.beginPath();
ctx.fillStyle = "white";
ctx.fillRect(0, 0, c.width, c.height);
ctx.fillStyle = "#4b4b4b";
ctx.fillRect(0, c.height - ground_size, c.width, c.height);
ctx.fillStyle = player.color;
// ctx.fillRect(player.x, player.y, player.width, player.height);
player.img.src = player.image;
ctx.drawImage(player.img, player.x, player.y, player.width, player.height)
ctx.fillStyle = obstacle1.color;
// ctx.fillRect(obstacle1.x, obstacle1.y, obstacle1.width, obstacle1.height);
ctx.drawImage(obstacle1.img, obstacle1.x, obstacle1.y, obstacle1.width, obstacle1.height)
ctx.fillStyle = "black";
ctx.font = "30px Arial";
ctx.fillText("Score: " + Math.round(score / 25).toString(), 20, 50);
if (game_over) {
ctx.font = "80px Arial";
}
ctx.stroke();
}
document.addEventListener('keydown', (event) => {
if (event.key == 'ArrowUp' || event.key == 'Spacebar') {
up = true;
} else if (event.key == 'ArrowDown') {
//pass
}
});
document.addEventListener('keyup', (eventt) => {
if (eventt.key == 'ArrowUp') {
up = false;
} else if (event.key == 'ArrowDown') {
//pass
}
});
function update_speed() {
obstacle1.speed += 0.001;
}
function run() {
if (up == true) {
player.jump()
}
player.gravity();
player.react();
player.animate();
obstacle1.react();
if (inRect(player.rect(), obstacle1.rect())) {
game_over = true
}
score += obstacle1.speed
draw();
update_speed();
if (game_over == false) {
requestAnimationFrame(run);
}
}
run();
好吧,您所要做的就是预加载图像,这样您的 index.html 应该看起来像:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Block Runner</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<link rel="preload" href="cactus_big.png" as="image">
<link rel="preload" href="dino_1.png" as="image">
<link rel="preload" href="dino_2.png" as="image">
<link rel="preload" href="dino_jump.png" as="image">
<link rel="preload" href="ground.png" as="image">
</head>
<body>
<canvas id="myCanvas" width="900" height="600" style="border:0px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<script src="script.js"></script>
</body>
</html>
这样应该不会闪烁。
我检查了代码,发现您每次都将图像加载到 player.img
变量中。
function createImage(path){
let image = new Image();
image.src = path;
return image;
}
var images = {
dino:[
createImage("dino_1.png"),
createImage("dino_2.png"),
createImage("dino_jump.png")
],
cactus:createImage("cactus_big.png")
}
如果您在此处使用我的代码,则需要更改代码以改为使用这些图像。因为现在,每次绘制时,您都在加载图像。就这样,所有的图片都存起来了,我试了下,不闪烁了。