Spec-Zone.ru › Web APIs

Падающие прямоугольники

  • Предыдущая
  • Следующая

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

Анимация и взаимодействие с пользователем с помощью обрезки

Это простая игра. Цель: поймать как можно больше падающих прямоугольников, нажимая на них. В этом примере мы используем объектно-ориентированный подход для отображаемых прямоугольников, что помогает организовать состояние прямоугольника (его положение, цвет и т. д.) в одном месте и сделать код в целом более компактным и повторно используемым.

Этот пример сочетает очистку буфера отрисовки сплошными цветами и операциями обрезки. Это предварительный просмотр полной графической программы, которая управляет различными фазами графического конвейера WebGL и его состоянием.

Кроме того, пример демонстрирует, как интегрировать вызовы функции WebGL в цикл игры. Цикл игры отвечает за отрисовку кадров анимации и за сохранение отзывчивости анимации на пользовательский ввод. Здесь цикл игры реализован с помощью таймаутов.

window.addEventListener("load", setupAnimation, false);
let gl;
let timer;
let rainingRect;
let scoreDisplay;
let missesDisplay;
function setupAnimation(evt) {
  window.removeEventListener(evt.type, setupAnimation, false);
  if (!(gl = getRenderingContext())) return;
  gl.enable(gl.SCISSOR_TEST);

  rainingRect = new Rectangle();
  timer = setTimeout(drawAnimation, 17);
  document
    .querySelector("canvas")
    .addEventListener("click", playerClick, false);
  [scoreDisplay, missesDisplay] = document.querySelectorAll("strong");
}

let score = 0;
let misses = 0;
function drawAnimation() {
  gl.scissor(
    rainingRect.position[0],
    rainingRect.position[1],
    rainingRect.size[0],
    rainingRect.size[1],
  );
  gl.clear(gl.COLOR_BUFFER_BIT);
  rainingRect.position[1] -= rainingRect.velocity;
  if (rainingRect.position[1] < 0) {
    misses += 1;
    missesDisplay.textContent = misses;
    rainingRect = new Rectangle();
  }
  // We are using setTimeout for animation. So we reschedule
  // the timeout to call drawAnimation again in 17ms.
  // Otherwise we won't get any animation.
  timer = setTimeout(drawAnimation, 17);
}

function playerClick(evt) {
  // We need to transform the position of the click event from
  // window coordinates to relative position inside the canvas.
  // In addition we need to remember that vertical position in
  // WebGL increases from bottom to top, unlike in the browser
  // window.
  const position = [
    evt.pageX - evt.target.offsetLeft,
    gl.drawingBufferHeight - (evt.pageY - evt.target.offsetTop),
  ];
  // If the click falls inside the rectangle, we caught it.

  // Increment score and create a new rectangle.
  const diffPos = [
    position[0] - rainingRect.position[0],
    position[1] - rainingRect.position[1],
  ];
  if (
    diffPos[0] >= 0 &&
    diffPos[0] < rainingRect.size[0] &&
    diffPos[1] >= 0 &&
    diffPos[1] < rainingRect.size[1]
  ) {
    score += 1;
    scoreDisplay.textContent = score;
    rainingRect = new Rectangle();
  }
}

function Rectangle() {
  // Keeping a reference to the new Rectangle object, rather
  // than using the confusing this keyword.
  const rect = this;
  // We get three random numbers and use them for new rectangle
  // size and position. For each we use a different number,
  // because we want horizontal size, vertical size and
  // position to be determined independently.
  const randNums = getRandomVector();
  rect.size = [5 + 120 * randNums[0], 5 + 120 * randNums[1]];
  rect.position = [
    randNums[2] * (gl.drawingBufferWidth - rect.size[0]),
    gl.drawingBufferHeight,
  ];
  rect.velocity = 1.0 + 6.0 * Math.random();
  rect.color = getRandomVector();
  gl.clearColor(rect.color[0], rect.color[1], rect.color[2], 1.0);
  function getRandomVector() {
    return [Math.random(), Math.random(), Math.random()];
  }
}

Исходный код этого примера также доступен на GitHub.

  • Предыдущая
  • Следующая

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/By_example/Raining_rectangles

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API