Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
183 views
in Technique[技术] by (71.8m points)

javascript - Making a Canvas game responsive on resize

I am trying to make a pong canvas game responsive on resize, i am nor sure what i am missing and what would be the best way to have it responsive while still not being to process heavy. i tried to delete and reinject the canvas on resize what is a bad idea i think, the responsiveness works on load so far... thanks a lot for the insights, much appreciated

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);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Dont use the Resize event for animations.

(if you use requestAnimationFrame)

Do not add a resize to the resize event. The resize event does not fire in sync with the display, and it can also fire many time quicker than the display rate. This can make the resize and game feel sluggish while dragging at the window size controls.

Smooth and efficient resizing

For the smoothest resize simply check the canvas size inside the main loop. If the canvas does not match the containing element size then resize it. This ensures you only resize when needed and always resize in sync with the display (if you use requestAnimationFrame)

Eg

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...