Создание игры Canvas, реагирующей на изменение размера

Я пытаюсь сделать так, чтобы игра понг-холста реагировала на изменение размера, я не уверен, что мне не хватает, и что было бы лучшим способом сделать так, чтобы она реагировала, но при этом еще не обрабатывать много. я пытался удалить и повторно вставить холст при изменении размера, что является плохой идеей, я думаю, отзывчивость работает на нагрузку до сих пор... большое спасибо за идеи, высоко ценится

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);

3 ответа

Решение

Не используйте событие Resize для анимации.

(если вы используете requestAnimationFrame )

Не добавляйте изменение размера к событию изменения размера. Событие изменения размера не запускается синхронно с дисплеем, а также может срабатывать во много раз быстрее, чем скорость отображения. Это может привести к замедлению изменения размера и игры при перетаскивании элементов управления размером окна.

Плавное и эффективное изменение размера

Для более плавного изменения размера просто проверьте размер холста внутри основного цикла. Если холст не соответствует размеру содержащего элемента, измените его размер. Это гарантирует, что вы изменяете размер только при необходимости и всегда изменяете размер в синхронизации с дисплеем (если вы используете 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);
}

Этот кусок кода должен быть запущен снова после изменения размера:

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');

Вы должны определить, когда изменение размера происходит с JavaScript:

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

и добавьте класс или свойства CSS, чтобы ширина холста составила 100%. Также вы должны задать минимальную ширину, чтобы убедиться, что никакое тело не сможет изменить его размеры до действительно неудобной ширины.

Другие вопросы по тегам