Thứ năm, 03/10/2019 | 00:00 GMT+7

Ảnh động với API Canvas - Phần 2: Các va chạm cơ bản


Trong Phần 1 của loạt bài này, ta đã xem xét các khái niệm cơ bản về cách hiển thị các đối tượng có thể tái sử dụng lên canvas, sử dụng GUI của ta để có các điều khiển trực quan hơn và tạo ảo giác về chuyển động cơ bản với vòng lặp hoạt ảnh của ta . Trong phần này, ta sẽ thấy thoải mái với việc tạo hiệu ứng va chạm với một quả bóng đơn giản có thể thay đổi màu sắc khi nó chạm vào đường viền của canvas của ta .

bản mẫu

Ta chỉ có thể sử dụng dự án của bạn từ Part 1 làm điểm khởi đầu cho hầu hết các hoạt ảnh của ta .

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>HTML Canvas</title>
  </head>
  <body>

    <canvas></canvas>

  </body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
  <script src="./canvas.js"></script>
</html>
canvas.js
// Get canvas element
const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');

// Make canvas fullscreen
canvas.width = innerWidth;
canvas.height = innerHeight;
addEventListener('resize', () => {
  canvas.width = innerWidth;
  canvas.height = innerHeight;
});

// Control Panel
const gui = new dat.GUI();

const controls = {
  dx: 0,
  dy: 0,
};

gui.add(controls, 'dx', 0, 10);
gui.add(controls, 'dy', 0, 10);

// New Object
class Ball {
  constructor(x, y, radius, color) {
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.color = color;
  }
}

Ball.prototype.draw = function () {
  c.beginPath();
  c.fillStyle = this.color;
  c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
  c.fill();
  c.closePath();
};

Ball.prototype.update = function () {
  this.x += controls.dx;
  this.y += -controls.dy;
  this.draw();
};

const ball = new Ball(innerWidth / 2, innerHeight / 2, 50, 'red');

// Render new instances
const init = () => ball.draw();

// Handle changes
const animate = () => {
  requestAnimationFrame(animate);

  c.clearRect(0, 0, canvas.width, canvas.height);

  ball.update();
};

init();
animate();

Bảo vệ quán bar

Bạn có thể xem trước kết quả cuối cùng của ta tại đây .

Để thay đổi hành vi của ta khi va chạm, ta chỉ cần thêm một điều kiện vào phương pháp update của ta để thay đổi hành vi của quả bóng khi nào nó chạm biên, trong trường hợp này là đảo ngược hướng của nó. Lưu ý trình duyệt đang nhìn vào tâm đối tượng của ta để biết vị trí của nó, vì vậy ta luôn muốn đưa bán kính vào tính toán.

canvas.js
Ball.prototype.update = function() {
  if (this.y + this.radius > canvas.height || this.y - this.radius < 0) {
    controls.dy = -controls.dy;
  }
  this.y -= controls.dy;

  if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {
    controls.dx = -controls.dx;
  }
  this.x += controls.dx;

  this.draw();
};

Màu sắc

Bây giờ ta hãy thêm một số hành vi thú vị hơn khi ta đánh một thứ gì đó, chẳng hạn như thay đổi màu sắc của quả bóng. Đầu tiên, ta cần một mảng màu để lựa chọn và một chức năng để chọn ngẫu nhiên một màu cho ta . Khi nào ta chạm vào một đường viền, ta có thể gán lại giá trị màu của bạn cho một giá trị ngẫu nhiên mới.

Tôi khuyên bạn nên xem Kuler để tạo bảng màu cho riêng bạn.

// Returns a color between 0 and the length of our color array
const randomColor = colors => colors[Math.floor(Math.random() * colors.length)];

const colors = [
  '#e53935',
  '#d81b60',
  '#8e24aa',
  '#5e35b1',
  '#3949ab',
  '#1e88e5',
  '#039be5',
  '#00acc1',
  '#00897b',
  '#43a047',
  '#ffeb3b',
  '#ef6c00'
];

// Re-assign color on contact
Ball.prototype.update = function () {
  if (this.y + this.radius > canvas.height || this.y - this.radius < 0) {
    this.color = randomColor(colors);
    controls.dy = -controls.dy;
  };
  this.y -= controls.dy;

  if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {
    this.color = randomColor(colors);
    controls.dx = -controls.dx;
  };
  this.x += controls.dx;

  this.draw();
};

// Make it start with a random color
const newBall = new Ball(innerWidth / 2, innerHeight / 2, 50, randomColor(colors));

Đuôi

Bây giờ ta đã có chức năng cơ bản tại chỗ, ta có thể làm cho nó thú vị hơn một chút về mặt hình ảnh bằng cách thêm một cái đuôi màu chạy theo sau nó. Ta có thể làm điều này bằng cách xóa clearRect và lấp đầy toàn bộ khung của ta bằng giá trị RGBA tối. Điều này tạo ra hiệu ứng 'cặn' từ bất kỳ thứ gì di chuyển qua nó và ta có thể kiểm soát cường độ của cặn bằng độ mờ của nền.

const animate = () => {
  requestAnimationFrame(animate);

  c.fillStyle = `rgba(33, 33, 33, ${-controls.tail / 10})`; // Lower opacity creates a longer tail
  c.fillRect(0, 0, canvas.width, canvas.height);

  newBall.update();
};

// We also need to update our controls with some default values
const controls = {
  dx: 5,
  dy: 5,
  tail: -5
};

gui.add(controls, 'dx', 0, 10);
gui.add(controls, 'dy', 0, 10);
gui.add(controls, 'tail', -10, 0);

Kết luận

Cứ như vậy, bây giờ ta có một hệ thống va chạm rất cơ bản với một số hiệu ứng đặc biệt. Trong Phần 3 sắp tới của loạt bài này, ta sẽ sử dụng các khái niệm được đề cập ở đây để tạo hoạt ảnh mưa năng động này.

Nếu bạn gặp sự cố nào sau đây, một ví dụ làm việc có sẵn trên Codepen . Hãy chia sẻ nó và chia sẻ những gì bạn đã làm.


Tags:

Các tin liên quan