【问题标题】:Making a Canvas game responsive on resize使 Canvas 游戏响应调整大小
【发布时间】:2017-10-08 04:41:51
【问题描述】:

我正在尝试制作一个对调整大小做出响应的乒乓画布游戏,我不确定我缺少什么,以及在不处理繁重的情况下让它响应的最佳方法是什么。我试图在调整大小时删除并重新注入画布,我认为这是一个坏主意,到目前为止,响应能力在加载时有效......非常感谢您的见解,非常感谢

http://jsfiddle.net/ut0hsvd4/1/

var animate = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
  window.setTimeout(callback, 1000 / 60)
};
var canvas = document.createElement("canvas");
var width = document.getElementById('pong').offsetWidth;
var height = document.getElementById('pong').offsetHeight;
canvas.width = width;
canvas.height = height;
var context = canvas.getContext('2d');
var player = new Player();
var computer = new Computer();
var ball = new Ball(width / 2, height / 2);

var keysDown = {};

var render = function() {
  context.fillStyle = "red";
  context.fillRect(0, 0, width, height);
  player.render();
  computer.render();
  ball.render();
};

var update = function() {
  player.update();
  computer.update(ball);
  ball.update(player.paddle, computer.paddle);
};

var step = function() {
  update();
  render();
  animate(step);
};

function Paddle(x, y, width, height) {
  this.x = x;
  this.y = y;
  this.width = width;
  this.height = height;
  this.x_speed = 0;
  this.y_speed = 0;
}

Paddle.prototype.render = function() {
  context.fillStyle = "#0000FF";
  context.fillRect(this.x, this.y, this.width, this.height);
};

Paddle.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  this.x_speed = x;
  this.y_speed = y;
  if (this.x < 0) {
    this.x = 0;
    this.x_speed = 0;
  } else if (this.x + this.width > width) {
    this.x = width - this.width;
    this.x_speed = 0;
  }
};

function Computer() {
  this.paddle = new Paddle(width / 2 - 25, 10, 50, 10);
}

Computer.prototype.render = function() {
  this.paddle.render();
};

Computer.prototype.update = function(ball) {
  var x_pos = ball.x;
  var diff = -((this.paddle.x + (this.paddle.width / 2)) - x_pos);
  if (diff < 0 && diff < -4) {
    diff = -5;
  } else if (diff > 0 && diff > 4) {
    diff = 5;
  }
  this.paddle.move(diff, 0);
  if (this.paddle.x < 0) {
    this.paddle.x = 0;
  } else if (this.paddle.x + this.paddle.width > width) {
    this.paddle.x = width - this.paddle.width;
  }
};

function Player() {
  this.paddle = new Paddle(width / 2 - 25, height - 20, 50, 10);
}

Player.prototype.render = function() {
  this.paddle.render();
};

Player.prototype.update = function() {
  for (var key in keysDown) {
    var value = Number(key);
    if (value == 37) {
      this.paddle.move(-4, 0);
    } else if (value == 39) {
      this.paddle.move(4, 0);
    } else {
      this.paddle.move(0, 0);
    }
  }
};

function Ball(x, y) {
  this.x = x;
  this.y = y;
  this.x_speed = 0;
  this.y_speed = 3;
}

Ball.prototype.render = function() {
  context.beginPath();
  context.arc(this.x, this.y, 5, 2 * Math.PI, false);
  context.fillStyle = "#000000";
  context.fill();
};

Ball.prototype.update = function(paddle1, paddle2) {
  this.x += this.x_speed;
  this.y += this.y_speed;
  var top_x = this.x - 5;
  var top_y = this.y - 5;
  var bottom_x = this.x + 5;
  var bottom_y = this.y + 5;

  if (this.x - 5 < 0) {
    this.x = 5;
    this.x_speed = -this.x_speed;
  } else if (this.x + 5 > width) {
    this.x = width - 5;
    this.x_speed = -this.x_speed;
  }

  if (this.y < 0 || this.y > height) {
    this.x_speed = 0;
    this.y_speed = 3;
    this.x = width / 2;
    this.y = height / 2;
  }

  if (top_y > height / 2) {
    if (top_y < (paddle1.y + paddle1.height) && bottom_y > paddle1.y && top_x < (paddle1.x + paddle1.width) && bottom_x > paddle1.x) {
      this.y_speed = -3;
      this.x_speed += (paddle1.x_speed / 2);
      this.y += this.y_speed;
    }
  } else {
    if (top_y < (paddle2.y + paddle2.height) && bottom_y > paddle2.y && top_x < (paddle2.x + paddle2.width) && bottom_x > paddle2.x) {
      this.y_speed = 3;
      this.x_speed += (paddle2.x_speed / 2);
      this.y += this.y_speed;
    }
  }
};

document.getElementsByClassName('js-pong')[0].appendChild(canvas);
animate(step);

window.addEventListener("keydown", function(event) {
  keysDown[event.keyCode] = true;
});

window.addEventListener("keyup", function(event) {
  delete keysDown[event.keyCode];
});

var resizer = function() {
  document.getElementsByTagName('canvas').remove();
  document.getElementsByClassName('js-pong')[0].appendChild(canvas);
  animate(step);
}

window.addEventListener('resize', resizer);

【问题讨论】:

  • 你可以通过改变 canvas.width、canvas.height 来调整画布的大小,还是我错过了什么?
  • 但这不会更新桨的位置和大小,我想我会是另一种方式,而不是删除并重新初始化整个游戏

标签: javascript css html canvas


【解决方案1】:

不要对动画使用 Resize 事件。

(如果你使用requestAnimationFrame

不要在调整大小事件中添加调整大小。 resize 事件不会与显示同步触发,它也可以比显示速率快很多倍。在拖动窗口大小控件时,这会使调整大小和游戏感觉迟缓。

平滑高效地调整大小

为了最平滑的调整大小,只需检查主循环内的画布大小。如果画布与包含元素的大小不匹配,则调整它的大小。这可确保您仅在需要时调整大小并始终与显示同步调整大小(如果您使用 requestAnimationFrame

例如

// get a reference to the element so you don't query the DOM each time
const pongEl = document.getElementById("pong");

// then in the main loop
function mainLoop() {
    // do first thing inside the render loop
    if(canvas.width !== pongEl.offsetWidth  || canvas.height !== pongEl.offsetHeight ){
        canvas.width = pongEl.offsetWidth;
        canvas.height = pongEl.offsetHeight;   
        // note the above clears the canvas.
    }

    // game code as normal

    requestAnimationFrame(mainLoop);
}

【讨论】:

  • 非常感谢您的回答,我会尝试实施并报告:-)
【解决方案2】:

您必须检测何时使用 JavaScript 调整大小:

window.onresize = function(event) { ... };

并添加一个 CSS 类或属性以使画布宽度为 100%。此外,你必须给它一个最小宽度,以确保没有人可以将它调整到一个非常不舒服的宽度。

【讨论】:

    【解决方案3】:

    这段代码需要在调整大小后再次运行:

    var canvas = document.createElement("canvas");
    var width = document.getElementById('pong').offsetWidth;
    var height = document.getElementById('pong').offsetHeight;
    canvas.width = width;
    canvas.height = height;
    var context = canvas.getContext('2d');
    

    【讨论】:

      猜你喜欢
      • 2015-10-26
      • 2021-11-27
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      • 2021-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多