В этом мини-задании будет реализована игра Flabby bird на базе библиотеки из задания про рисование единорога.

Должна получиться игра аналогичная этой. (играть не больше 15 секунд!)

1) Обновление состояния

Тривиальная заготовка с фоном цвета неба и линией нарисованной по центру под углом:

function setup() {
    createCanvas(640, 480);     // Указываем размер холста
    background(54, 187, 205);   // Указываем цвет фона
}

function draw() {
    translate(320, 240);        // Смещаем центр системы координат в центр экрана
    rotate(PI/6);               // Поворачиваем систему координат вокруг ее текущей точки отсчета
    line(-50, 0, 50, 0);        // Рисуем линию в текущей системе координат
}

Игра предполагает что птица летит, а значит требуется обновлять состояние мира с некоторой периодичностью. В используемой библиотеке есть функция frameRate(N); с единственным аргументом - желаемое число кадров в секунду. Ее вызов на этапе настройки игры (внутри функции setup) приведет к тому, что draw будет вызываться в секунду столько раз, сколько сказано в вызове функции frameRate.

Чтобы проверить это предлагается вращать линию в центре холста. Для увеличения угла наклона от отрисовки к отрисовке потребуется глобальная переменная:

var angle = 0;

function draw() {
    ...
    angle = angle + PI/30;
    rotate(angle);
    ...
}

P.S. альтернативный пример обновления состояния.

Чтобы очищать экран от отрисовки к отрисовке - надо перенести вызов background из функции setup (которая вызывается один раз при запуске программы) в функцию draw.

Теперь отрезок вращается.

2) Состояние и отрисовка птички

Птица немного сложнее вращающегося отрезка. Подумаем из чего состоит описание состояния птицы:

  • Высота положения птицы
  • Вертикальная скорость птицы

Еще для определения гравитации потребуется константа ускорения свободного падения:

var birdHeight = 240.0;
var birdVerticalSpeed = 0.0;

var gravityAcceleration = 1.0;

Создайте функцию отрисовки положения птицы drawBird, которая на основе значения birdHeight нарисует круг (что-то вроде ellipse(0, 0, 20, 20);), который представляет нашу условную птицу. И вызовите эту функцию из функции draw.

3) Управление птицей

Хочется как-то управлять происходящим - нажатием кнопки/мышки придавать птице толчек вверх.

В документации обработка нажатия кнопок описана здесь.

Достаточно наряду с setup() и draw() реализовать функцию обработки нажатия кнопки keyPressed():

function keyPressed() {
    var spaceKeyCode = 32;          // Это кодовое число соответствующее кнопке пробел
    if (keyCode === spaceKeyCode) { // Есть специальная переменная keyCode, в которой хранится код нажатой кнопки. Пусть птица поднимается выше только когда нажимается пробел
        birdHeight -= 10;           // Выше птица - меньше координата, т.к. в системе координат графики y-ось направлена вниз
    }
}

Но заметим, что на самом деле положение птицы в этой функции мы не должны менять, т.е. предложенное только что решение плохое, т.к. мы просто телепортируем птицу вверх при каждом нажатии - что не естественно.

На самом деле передвижение и вниз, и вверх должно быть плавным, т.е. происходит с каждым кадром, поэтому давайте заведем функцию updateBird() и будем вызывать ее при каждом выполнении draw:

function updateBird() {
    birdHeight = birdHeight + birdVerticalSpeed;
    birdVerticalSpeed += gravityAcceleration;
}

Теперь птица падает с некоторым ускорением. Подгоните константы так, чтобы это выглядело естественно.

Чем же мы управляем, если не высотой птицы? Нажатие пробела должно приводить к “толчку” птицы вверх, птица начинает лететь вверх когда ее скорость направлена вверх. Т.е. нажатие пробела должно влиять на значение birdVerticalSpeed.

4) Препятствия

Надо сделать так, чтобы одна за другой справа набегали стены с дырами. Для упрощения реализуем сначала так, чтобы на экране была видна ровно одна стена.

Она описывается:

  • Размер дыры в стене, в которую хочет проскочить птица
  • Высота дыры в стене
  • Координата стены по x-оси

Заводим для этих параметров аналогично описанию птицы глобальные переменные (вида var someName = 239;).

Теперь надо реализовать отрисовку стены в функции drawWall():

Воспользуемся функцией rect(fromX, fromY, width, height). Первые два аргумента - координаты начала прямоугольника. Последние два аргумента - знаковые ширина и высота прямоугольника. Т.е. указав положительную высоту прямоугольник будет рисоваться “вниз” от начальных координат (т.к. система координат так ориентирована), указав же отрицательную высоту - прямоугольник будет рисоваться “вверх” от начальных координат.

P.S. Чтобы не смешать изменения системы координат отрисовки птицы и отрисовки стены пригодятся push() и pop() использованные в прошлом задании.

Итак рисование стены было сделано. Теперь необходимо двигать стену. Для этого надо реализовать updateWall(), который будет уменьшать координату стены по x-оси, но кроме этого: когда стена пройдет весь экран необходимо создать новую случайную стену.

Чтобы создать новую случайную стену полезен вызов Math.random(), который вернет случайное число от 0.0 до 1.0.

Итого updateWall() принимает приблизительно такой вид:

function updateWall() {
    if (x < ...) {          // Если координата x стены вышла за пределы экрана
        nextWallX = ...;    // крайнее правое положение
        nextHoleY = 50.0 + Math.random() * 240.0;
    } else {
        nextWallX -= wallSpeed; // двигаем стену влево
    }
}

5) Коллизии

При обновлении положения птицы надо так же проверить, не врезалась ли она в стену, и если врезалась - можно например менять цвет эллипса-птицы на другой.

7) Картинка вместо эллипса

Например окружность-птицу можно заменить на картинку. Можно взять любую, например одну из этих двух:

Unicorn

Flabby bird

И теперь вместо отрисовки эллипса методом ellipse(...) вам надо делать по аналогии с этим примером. Обратите внимание, что вместо assets/moonwalk.jpg вам надо указать путь к картинке. В частности вы можете указать адрес одной из этих двух картинок (например http://polarnick239.github.io/static/flabby_bird/unicorn.png). Или вы можете создать папку images рядом с файлом index.html, сохранить туда картинку, и обращаться к ней по пути images/unicorn.png.

8) Наклонять Единорога

Если в данный момент скорость направлена вниз - то игровой персонаж должен быть наклонен соответствующе (по часовой стрелке), если вверх - то наоборот. Соответственно можно рисовать картинку персонажа повернутой пропорционально текущей вертикальной скорости. Напоминание: для поворота системы координат надо использовать функцию rotate.

9) Улучшения

Добавьте что-то из этого списка:

  • Счет
  • Больше одной стены
  • Пауза или перезапуск игры при врезании