【问题标题】:Why are my blocks only spawning and disappearing, instead of falling?为什么我的方块只会生成和消失,而不是掉落?
【发布时间】:2021-08-18 15:01:32
【问题描述】:

此代码的目的是让玩家在游戏中,黄色方块必须在场地周围移动以收集红苹果并在执行此操作时避开黑色石头。所以方块应该落到底部,然后在碰到玩家或底部边界时消失。

当我运行此代码时,生成的块,即显示屏顶部的红色和黑色的东西,应该会慢慢开始下降,但结果是它们出现了,被删除了,然后又出现了。

为什么积木不会像他们应该的那样掉下来? 我在更新块代码中添加了循环,以便创建的块实际上可以下落,但它们只是在更新的位置生成,而不是缓慢下落到该位置。

应该使积木掉落的代码由 drawbBlock 和 updateBlock 函数组成。 updateBlock 函数获取重力并将其乘以 dt,然后将其添加到块的当前高度,这应该会降低块的高度。一旦变量发生变化,drawBlock 应该在新的高度重新绘制块。

在调试我的代码时,我发现在游戏循环中,问题是方块位置变量每隔几毫秒就会更改一次,但我仍然不确定如何让方块不断下落并添加新方块。

这是我的游戏的代码。

var lastFrame = performance.now();
var requestAnimationFrameId;
var FPS = 1;
var alpha = 0.1;

function stopGameLoop() {
    window.cancelAnimationFrame(requestAnimationFrameId);
}

function gameLoop(timestamp) {
    requestAnimationFrameId = window.requestAnimationFrame(gameLoop);

    if (timestamp < lastFrame + (1000 / 60)) {
        return;
    }

    var dt = (timestamp - lastFrame) / 1000;
    lastFrame = timestamp;
    FPS = FPS + (1 - alpha) * (1/dt - FPS);
    var block_ent = Math.floor(Math.random() * 18) + 1;
    var block = { x: block_ent * BOX_SIZE, y: 0 * BOX_SIZE };

    updateBlock(dt, block);

    drawMap();
    drawBlock(block);
}

requestAnimationFrameId = window.requestAnimationFrame(gameLoop);

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var BOX_SIZE = 20;
var MAP_W = 20;
var MAP_H = 13;

function drawBox(color, x, y, w, h) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, w || BOX_SIZE, h || BOX_SIZE);
}

var map = [
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
];

function drawMap() {
  for (var i = 0; i < MAP_H; i++) {
    for (var j = 0; j < MAP_W; j++) {
      var color = map[i * MAP_W + j] ? "#5d995d" : "lightblue";
      drawBox(color, BOX_SIZE * j, BOX_SIZE * i);
    }
  }
}

function drawBlock(block){
  var block_type = Math.floor(Math.random() * 2);
  if (block_type == 0) {
        drawBox('red', block.x, block.y);
  }
  else if (block_type == 1) {
    drawBox('black', block.x, block.y);
  }
}
function updateBlock(dt, block) {
  // The player moves at 70px per second.
  for(l=0; l<90; l++)
  {
    var GRAVITY = 70;
    // Vertical velocity of the player.
    var by = 0;
    by = GRAVITY * dt;

    block.y += by;
   }
}
&lt;canvas id="canvas" height="260" width="400" tabindex="1"&gt;&lt;/canvas&gt;

【问题讨论】:

  • 请删除与问题不直接相关的所有内容(例如,player 以及当您询问不坠落框时与之交互的任何内容都不相关),并说明“坠落”的位置" 发生在代码中以及您在调试代码时发现的内容。
  • “但是发生的情况是它们出现了,被删除了,然后又出现了。” 因为var block = { x: block_ent * BOX_SIZE, y: 0 * BOX_SIZE };
  • @Andreas PS - 用minimal reproducible example 回滚 OP 的初始代码做得很好 - 现在一切都更有意义了 :)

标签: javascript canvas


【解决方案1】:

您的gameLoop 函数在每次重新绘制地图时都会创建一个新块

function gameLoop(timestamp) {
  // ...

  var block = { x: block_ent * BOX_SIZE, y: 0 * BOX_SIZE };

  // ...
}

您只需要一个新块,当当前块到达地图底部时。
block 移出gameLoop() 并且仅当块的y 坐标为“在底部或低于底部”(或第一次执行时0 “循环”)

var block = { x: 0, y: 0 };

function gameLoop(timestamp) {
  // ...

  if (block.y === 0 || block.y >= ((MAP_H - 1) * BOX_SIZE)) {
    block.x = (Math.floor(Math.random() * 18) + 1) * BOX_SIZE;
    block.y = 0;
  }

  // ...
}

有了这个(以及对dt 的计算的小调整),你得到了你的缓慢下降的块

var lastFrame = performance.now();
var requestAnimationFrameId;
var FPS = 1;
var alpha = 0.1;

function stopGameLoop() {
  window.cancelAnimationFrame(requestAnimationFrameId);
}

var block = { x: 0, y: 0 };


function gameLoop(timestamp) {
  requestAnimationFrameId = window.requestAnimationFrame(gameLoop);

  if (timestamp < lastFrame + (1000 / 60)) {
    return;
  }

  var dt = (timestamp - lastFrame) / 10000;
  lastFrame = timestamp;
  FPS = FPS + (1 - alpha) * (1 / dt - FPS);
  
  if (block.y === 0 || block.y >= ((MAP_H - 1) * BOX_SIZE )) {
    block.x = (Math.floor(Math.random() * 18) + 1) * BOX_SIZE;
    block.y = 0;
  }

  drawMap();
  drawBlock(block);

  updateBlock(dt, block);
}

requestAnimationFrameId = window.requestAnimationFrame(gameLoop);

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var BOX_SIZE = 20;
var MAP_W = 20;
var MAP_H = 13;

function drawBox(color, x, y, w, h) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, w || BOX_SIZE, h || BOX_SIZE);
}

var map = [
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
];

function drawMap() {
  for (var i = 0; i < MAP_H; i++) {
    for (var j = 0; j < MAP_W; j++) {
      var color = map[i * MAP_W + j] ? "#5d995d" : "lightblue";
      drawBox(color, BOX_SIZE * j, BOX_SIZE * i);
    }
  }
}

function drawBlock(block) {
  var block_type = Math.floor(Math.random() * 2);
  if (block_type == 0) {
    drawBox('red', block.x, block.y);
  } else if (block_type == 1) {
    drawBox('black', block.x, block.y);
  }
}

function updateBlock(dt, block) {
  // The player moves at 70px per second.
  for (l = 0; l < 90; l++) {
    var GRAVITY = 70;
    // Vertical velocity of the player.
    var by = 0;
    by = GRAVITY * dt;

    block.y += by;
  }
}
&lt;canvas id="canvas" height="260" width="400" tabindex="1"&gt;&lt;/canvas&gt;

【讨论】:

  • 检查 OPs 问题的第一个版本(修订历史)
  • 你的演示结果在画布上产生了非常奇怪的东西
  • 我合并了您的代码,但现在每次将块重绘到左上角。你能帮忙解决这个问题吗?
  • @zaaferkhan "进入左上角" 将是 x: 0, y: 0,这是初始设置。这应该在if (block.y === 0 || ...) { ... } 块中进行更改。也许您要快速复制我的解决方案。在第一个版本中,我忘记了block.y === 0 部分:/
  • @zaaferkhan 当您将初始设置修改为{ x: 0, y: Number.MAX_VALUE } 时,它也应该在没有block.y === 0 的情况下工作
猜你喜欢
  • 1970-01-01
  • 2013-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
  • 2018-08-04
相关资源
最近更新 更多