【问题标题】:Flickering images with Javascript使用Javascript闪烁的图像
【发布时间】:2021-03-03 08:21:17
【问题描述】:

我正在尝试使用 Repl.it 用 Ja​​vascript 制作游戏,但每隔几秒钟,玩家的图像就会闪烁。我无法弄清楚为什么会这样?我正在将一些图像加载到画布上,并且只有在我添加 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();

【问题讨论】:

    标签: javascript html css flicker


    【解决方案1】:

    好吧,您所要做的就是预先加载图像,这样您的 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>
    

    应该让它不会闪烁。

    【讨论】:

    • 可能也应该将所有 JS 包装在 window.load 事件处理程序中。
    • 好吧,它减少了一些闪烁,但不是全部。虽然它不那么分散注意力,但它仍然更好。
    • @ScottMarcus 你会怎么做window.load? (我是 javascript 新手,我不知道那是什么意思)
    • 将所有的 JavaScript 放在 window.addEventListener("load", function(){ // all your JS here }); 中,这样可以确保在所有外部资源完成下载到客户端之前它不会执行。
    【解决方案2】:

    我检查了代码,发现您每次都将图像加载到 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")
    }
    

    如果您在此处使用我的代码,则需要更改代码以改用这些图像。因为现在,每次绘制时,都是在加载图像。像这样,所有图片都存了,我试了一下,不再闪烁。

    【讨论】:

    • 嗯,现在它根本不显示图像。我可能用错了,你能解释一下如何使用它吗?
    • 没关系,我只是忘了删除一个把它搞砸的旧代码行
    猜你喜欢
    • 2010-10-29
    • 1970-01-01
    • 2012-08-22
    • 2015-04-25
    • 2012-05-13
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多