JavaScript для детей — страница 37 из 48

move, вот такого:

218 Часть III. Графика

Ball.prototype.move = function () {

this.x += this.xSpeed;

this.y += this.ySpeed;

};

Мы используем команду this.x += this.xSpeed,

чтобы прибавить значение горизонтальной скорости

к this.x. Аналогично this.y += this.ySpeed при-

бавляет вертикальную скорость к this.y. Например,

в самом начале анимации мяч находится в позиции

(100, 100), this.xSpeed равняется −2, this.ySpeed

равняется 3. Метод move при его вызове вычтет 2

из значения x и прибавит 3 к значению y, в результате

чего мяч окажется в позиции (98, 103), то есть пере-

местится на 2 пикселя влево и на 3 пикселя вниз, как

показано на рис. 14.6.

Шаг 1

(100, 100)

−2 +3

Шаг 2

(98, 103)

−2 +3

Шаг 3

(96, 106)

Рис. 14.6. Первые три шага анимации.

Показано, как меняются значения свойств x и y

Отскоки мяча

На каждом шаге анимации нужно проверять, не стол-

кнулся ли мяч с границей «холста». Если столкнулся,

следует обновить свойство xSpeed или ySpeed,

инвертировав его значение (то есть умножив на −1).

Например, при столкновении с нижней границей мы

должны инвертировать this.ySpeed: если в this.

ySpeed находится значение 3, его надо поменять

на −3. А если в this.ySpeed уже значение −3, то

инвертирование, напротив, поменяет его на 3.

Мы дадим этому методу имя checkCollision

(проверка столкновения):

14 . Анимации с помощью canvas 219

Ball.prototype.checkCollision = function () {

 if (this.x < 0 || this.x > 200) {

this.xSpeed = -this.xSpeed;

}

 if (this.y < 0 || this.y > 200) {

this.ySpeed = -this.ySpeed;

}

};

В строке  мы выясняем, не столкнулся ли мяч с левой или правой

границей, сравнивая свойство x с 0 (если x меньше 0, мяч столкнулся

с левой границей) и с 200 (если x больше 200, мяч столкнулся с правой

границей). Если любая из этих проверок даcт true, значит мяч начал

выходить за пределы «холста» и его горизонтальное направление нужно

инвертировать. Мы делаем это, задавая свойству this.xSpeed значение

-this.xSpeed. Например, если this.xSpeed равняется −2 и мяч стол-

кнулся с левой границей, this.xSpeed примет значение 2.

В строке  мы выполняем аналогичную проверку для верхней

и нижней границ. Если this.y меньше 0 или больше 200, значит мяч

столкнулся или с верхней, или с нижней границей соответственно.

В этом случае мы задаем this.ySpeed значение -this.ySpeed.

На рис. 14.7 показано, что произойдет при столкновении мяча с ле-

вой границей. Сначала значение this.xSpeed равняется −2, но после

столкновения оно меняется на 2. Однако в this.ySpeed по-прежнему

остается значение 3.

Шаг 1

(3, 50)

−2 +3

Шаг 2

(1, 53)

−2 +3

Шаг 3

(−1, 56)

+2 +3

Шаг 4

(1, 59)

+2 +3

Шаг 5

(3, 62)

Рис. 14.7. Так меняется this.xSpeed после столкновения с левой границей

Как видно по рис. 14.7, на третьем шаге мяч сталкивается с грани-

цей — его центральная точка уходит за границу «холста». При этом часть

мяча станет невидимой, однако этот кадр промелькнет столь быстро,

что во время анимации будет едва заметным.

220 Часть III. Графика

Анимация мяча

Теперь можно написать код, отвечающий за анимацию. Этот код соз-

дает объект-мяч и с помощью setInterval вызывает методы отрисовки

и обновления позиции мяча на каждом шаге анимации.

var canvas = document.getElementById("canvas");

var ctx = canvas.getContext("2d");

 var ball = new Ball();

 setInterval(function () {

 ctx.clearRect(0, 0, 200, 200);

 ball.draw();

ball.move();

ball.checkCollision();

 ctx.strokeRect(0, 0, 200, 200);

 }, 30);

Как обычно, сначала мы получаем элемент canvas и кон-

текст рисования. Затем в строке  создаем объект-мяч вызовом

new Ball() и сохраняем его в переменной ball. Далее в строке 

мы вызываем setInterval, передавая первым аргументом функ-

цию, а вторым (в строке ) — число 30. Как нам уже известно,

это означает «вызывай эту функцию каждые 30 миллисекунд».

Функция, которую мы передаем setInterval, выполняет несколько

задач. Сначала в строке  она очищает «холст» командой ctx.clearRect(0,

0, 200, 200). После этого, начиная со строки , она вызывает методы объ-

екта ball: draw, move, и checkCollision. Метод draw рисует мяч в его

текущей позиции ( x, y). Метод move обновляет позицию мяча на основе

значений xSpeed и ySpeed. И наконец, метод checkCollision меняет

направление движения мяча, если тот столкнулся с границей «холста».

Последнее, что делает вызываемая через setInterval функция, —

в строке  рисует вокруг «холста» рамку коман-

дой ctx.strokeRect(0, 0, 200, 200) — чтобы

границы, от которых отскакивает мяч, были

видимы.

Когда вы запустите этот код, мяч сразу же

начнет двигаться вниз и влево. Затем он вре-

жется в нижнюю границу и отскочит вверх

и влево. И так он будет летать по «холсту»,

отскакивая от границ, пока вы не закроете

окно браузера.

14 . Анимации с помощью canvas 221

Что мы узнали

В этой главе мы объединили наши знания об анимации из главы 11

с навыками рисования на «холсте», создав несколько анимаций на основе

элемента canvas. Начали мы с простого двигающегося и меняющего

размер квадратика. Затем мы научили пчелу случайным образом пере-

мещаться по экрану и, наконец, создали анимацию отскакивающего

от стен мяча.

Все эти анимации устроены одинаково: мы рисуем фигуру опреде-

ленного размера в определенной позиции, потом изменяем этот размер

или позицию, а потом очищаем «холст» и перерисовываем фигуру. Кроме

того, нужно следить за x- и y-координатами движущихся по «холсту» объ-

ектов. В примере с пчелой мы изменяли x- и y-координаты, складывая

их со случайным значением. А в случае с отскакивающим мячом — при-

бавляли к координатам значения xSpeed и ySpeed. В следующей главе

мы добавим нашим экспериментам с «холстом» интерактивности, что

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

222 Часть III. Графика

УПРА ЖНЕНИЯ

Вот некоторые идеи по усовершенствованию анимации отскаки-

вающего мяча из этой главы.

#1. Увеличение размеров «холста»

Наш «холст» размером 200 × 200 пикселей как-то маловат. Что

если увеличить его до 400 × 400 пикселей?

Вместо того чтобы вводить числовые размеры «холста»

в тексте программы, можно создать переменные для ширины

и высоты и брать их значения из объекта canvas. Используйте

следующий код:

var width = canvas.width;

var height = canvas.height;

Если везде в программе использовать эти переменные вме-

сто чисел, вам останется лишь изменить атрибуты элемента

canvas в HTML-коде, чтобы опробовать новый размер «холста».

Попробуйте сделать его шириной в 500 пикселей и высотой

в 300. Ну как, программа все еще работает?

#2. Случайные значения this.xSpeed и this.ySpeed

Чтобы анимация была интереснее, в конструкторе Ball зада-

вайте свойствам this.xSpeed и this.ySpeed разные случай-

ные значения в диапазоне от −5 до 5.

#3. Больше мячиков!

Вместо анимации одного мячика создайте пустой массив

и в цикле for добавьте в него 10 мячей. Теперь измените функ-

цию, вызываемую по setInterval, использовав цикл for для

перемещения и проверки столкновений каждого из мячей.

#4. Цветные мячи

Как насчет разноцветных отскакивающих мячиков? Задайте

в конструкторе Ball новое свойство color (цвет) и используйте

его для задания цвета в методе draw. Воспользуйтесь функцией

pickRandomWord из восьмой главы, чтобы задать каждому

из мячей случайный цвет из такого массива:

var colors = ["Red", "Orange", "Yellow", "Green", "Blue", "Purple"];

15

У П РА В Л Е Н И Е А Н И М А Ц И Я М И

С К Л А В И АТ У Р Ы

Мы уже научились работать с «холстом», рисовать и раскрашивать

объекты, заставлять их двигаться, отскакивать и увеличиваться

в размере. Теперь давайте оживим наши программы, добавив в них

интерактивности!

Из этой главы вы узнаете, как научить анимации реагировать

на нажатия кнопок клавиатуры — чтобы игрок мог управлять анимацией

с помощью клавиш-стрелок или иных заданных в программе клавиш

(скажем, общепринятого для игр сочетания W, A, S, D). Например, вместо

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

можность управлять его перемещениями с помощью клавиш-стрелок.

События клавиатуры

Состояние клавиатуры можно отслеживать в JavaScript с помощью собы-

тийклавиатуры. Каждый раз, когда пользователь нажимает клавишу,

генерируется событие, во многом напоминающее события мышки, о кото-

рых мы говорили в десятой главе. Тогда мы использовали jQuery, чтобы

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

определения нажатой клавиши при возникновении события клавиатуры

также можно воспользоваться jQuery. Например, в этой главе мы на

-

учимся перемещать мяч влево, вправо, вверх или вниз, когда пользователь

нажимает на клавиатуре стрелку влево, вправо, вверх или вниз.

Key down —

Мы будем отслеживать событие keydown, которое возникает при

нажатая

нажатии клавиши, используя jQuery для задания обработчика этого