Вивчаємо CreateJS на прикладі створення гри Пінг-Понг
() translation by (you can also view the original English article)
Веб-технології розвиваються швидкими темпами – настільки, що наш оригінальний посібник по EaselJS вже не актуальний. У цьому посібнику ви дізнаєтеся, як використовувати найновіший набір бібліотек CreateJS, на прикладі створення простої копії гри Пінг-Понг.
Попередній перегляд кінцевого результату
Давайте подивимося на кінцевий результат, до якого будемо наближатися.
Ця робота заснована на посібнику Carlos Yanez «Create a Pong Game in HTML5 With EaselJS», що в свою чергу засновано на його «Getting Started With EaselJS». Всі графічні дані та звукові ефекти взяті з вищезазначеного посібника.
Крок 1: Створіть index.html
Далі наводиться його вміст:
1 |
<!DOCTYPE html> |
2 |
<html> |
3 |
<head> |
4 |
<title>Pong</title> |
5 |
|
6 |
<style>/* Removes Mobile Highlight */ *{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> |
7 |
|
8 |
<script src="http://code.createjs.com/easeljs-0.4.2.min.js"></script> |
9 |
<script src="http://code.createjs.com/tweenjs-0.2.0.min.js"></script> |
10 |
<script src="http://code.createjs.com/soundjs-0.2.0.min.js"></script> |
11 |
<script src="http://code.createjs.com/preloadjs-0.1.0.min.js"></script> |
12 |
<script src="http://code.createjs.com/movieclip-0.4.1.min.js"></script> |
13 |
<script src="assets/soundjs.flashplugin-0.2.0.min.js"></script> |
14 |
<script src="Main.js"></script> |
15 |
|
16 |
</head> |
17 |
<body onload="Main();"> |
18 |
<canvas id="PongStage" width="480" height="320"></canvas> |
19 |
</body> |
20 |
</html> |
Як ви бачите, він доволі короткий і головним чином містить рядки для скачування бібліотек CreateJS.
З моменту виходу CreateJS нам більше немає необхідності завантажувати файли та розміщувати їх на власному сервері; тепер файли розміщуються на CDN (* content delivery network – мережа доставки (розповсюдження) контенту. Тут і далі примітка перекладача), завдяки якій ми можемо завантажувати ці файли віддалено на максимальній швидкості.
Давайте проглянемо код:
1 |
<style>/* Removes Mobile Highlight */ *{-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style> |
У цьому рядку ми прибираємо підсвічування, що може виникнути при спробі пограти у гру на телефоні. (Завдяки цьому не буде підсвічуватися об'єкт canvas, що відбувається на телефонах при русі пальців).
Далі йдуть бібліотеки для завантаження бібліотек CreateJS:
1 |
<script src="http://code.createjs.com/easeljs-0.4.2.min.js"></script> |
2 |
<script src="http://code.createjs.com/tweenjs-0.2.0.min.js"></script> |
3 |
<script src="http://code.createjs.com/soundjs-0.2.0.min.js"></script> |
4 |
<script src="http://code.createjs.com/preloadjs-0.1.0.min.js"></script> |
5 |
<script src="http://code.createjs.com/movieclip-0.4.1.min.js"></script> |
Завдяки цьому коду відбувається завантаження файлів JS з CDN для CreateJS і у нас є можливість використовувати будь-які функції CreateJS у нашому коді.
Далі ми завантажуємо плаґін Flash (* мультимедійна програмна платформа компанії Adobe Systems для створення веб-додатків, рекламних банерів, анімацій, ігор, десктопних застосувань і також для виконання на веб-сторінках відео- та аудіозаписів. У липні 2017 року Adobe визнала технологію Flash застарілою, її життєвий цикл буде завершено наприкінці 2020 року, коли Adobe припинить підтримку та розповсюдження Flash) SoundJS, що забезпечує підтримку звуку для браузерів, що не підтримують HTML5 Audio. Вона реалізується за допомогою використання SWF (* Small Web Format) (об'єкта Flash) для завантаження звуків.
1 |
<script src="assets/soundjs.flashplugin-0.2.0.min.js"></script> |
У цьому випадку ми не будемо використовувати CDN; замість цього ми завантажимо бібліотеку SoundJS з http://createjs.com/#!/SoundJS/download та розмістимо файли soundjs.flashplugin-0.2.0.min.js
та FlashAudioPlugin.swf
до локальної бібліотеки під назвою assets
.
Останнім з файлів JS ми завантажимо файл Main.js
, в якому буде розташовано весь код для нашої гри:
1 |
<script src="Main.js"></script> |
І, нарешті, давайте помістимо об'єкт Canvas на нашу сцену.
1 |
<body onload="Main();"> |
2 |
<canvas id="PongStage" width="480" height="320"></canvas> |
3 |
</body> |
Тепер ми можемо почати працювати над кодом для гри.
Крок 2: Змінні
Код нашої гри буде знаходитися у файлі під назвою Main.js
, так що зараз створіть та збережіть його.
Для початку давайте визначимо змінні для всіх графічних об'єктів у грі:
1 |
var canvas; //Will be linked to the canvas in our index.html page |
2 |
var stage; //Is the equivalent of stage in AS3; we'll add "children" to it |
3 |
|
4 |
// Graphics
|
5 |
//[Background]
|
6 |
|
7 |
var bg; //The background graphic |
8 |
|
9 |
//[Title View]
|
10 |
|
11 |
|
12 |
var main; //The Main Background |
13 |
var startB; //The Start button in the main menu |
14 |
var creditsB; //The credits button in the main menu |
15 |
|
16 |
//[Credits]
|
17 |
|
18 |
|
19 |
var credits; //The Credits screen |
20 |
|
21 |
//[Game View]
|
22 |
|
23 |
|
24 |
var player; //The player paddle graphic |
25 |
var ball; //The ball graphic |
26 |
var cpu; //The CPU paddle |
27 |
var win; //The winning popup |
28 |
var lose; //The losing popup |
Я додав коментар до кожної змінної, щоб ви знали, що буде поміщатися до неї.
Далі переходимо до рахування очок:
1 |
//[Score]
|
2 |
|
3 |
var playerScore; //The main player score |
4 |
var cpuScore; //The CPU score |
5 |
var cpuSpeed=6; //The speed of the CPU paddle; the faster it is the harder the game is |
Нам будуть необхідні змінні для зберігання значень швидкості м'яча:
1 |
// Variables
|
2 |
|
3 |
var xSpeed = 5; |
4 |
var ySpeed = 5; |
Ви можете змінювати ці значення на будь-які, якщо ви захочете ускладнити або спростити гру.
Якщо ви – розробник на Flash, то знаєте, що метод onEnterFrame
Flash дуже корисний при розробці ігор, оскільки є події, які повинні відбуватися у кожному фреймі. (Якщо ви не знайомі з цією ідеєю, то ознайомтеся зі статтею про Game Loop)
Ми маємо еквівалент для onEnterFrame
в CreateJS – об'єкт ticker
, завдяки якому можна виконувати код кожну долю секунди. Давайте створимо змінну, у якій буде посилання на нього:
1 |
var tkr = new Object; |
Далі йдуть змінні для попереднього завантажувача, що буде використовувати методи нової бібліотеки PreloadJS.
1 |
//preloader
|
2 |
var preloader; |
3 |
var manifest; |
4 |
var totalLoaded = 0; |
- в
preloader
буде міститися об'єкт PreloadJS. - в
manifest
(* список вантажів та пасажирів літака або поїзда) буде знаходитися список файлів, що нам необхідно завантажити. - в
totalLoaded
буде міститися кількість вже завантажених файлів.
Остання, але не менш важлива, ніж решта, змінна в нашому списку – TitleView
, в якій будуть знаходитися зображення для їх сумісного відображення (подібно DisplayObjectContainer
во Flash).
1 |
var TitleView = new Container(); |
Давайте перейдемо до функції Main ...
Крок 3: Функція Main()
Ця функція виконується першою після завантаження всіх файлів JS, що вказані в index.html.
Де вона викликається?
Що ж, пам'ятаєте рядок в index.html
?
1 |
<body onload="Main();"> |
У цьому фрагменті коду повідомляється, що одразу після завантаження HTML (і бібліотек JS) повинна бути виконана функція Main
.
Давайте проглянемо її:
1 |
function Main() |
2 |
{
|
3 |
/* Link Canvas */
|
4 |
|
5 |
canvas = document.getElementById('PongStage'); |
6 |
stage = new Stage(canvas); |
7 |
|
8 |
stage.mouseEventsEnabled = true; |
9 |
|
10 |
|
11 |
/* Set The Flash Plugin for browsers that don't support SoundJS */
|
12 |
SoundJS.FlashPlugin.BASE_PATH = "assets/"; |
13 |
if (!SoundJS.checkPlugin(true)) { |
14 |
alert("Error!"); |
15 |
return; |
16 |
}
|
17 |
|
18 |
manifest = [ |
19 |
{src:"bg.png", id:"bg"}, |
20 |
{src:"main.png", id:"main"}, |
21 |
{src:"startB.png", id:"startB"}, |
22 |
{src:"creditsB.png", id:"creditsB"}, |
23 |
{src:"credits.png", id:"credits"}, |
24 |
{src:"paddle.png", id:"cpu"}, |
25 |
{src:"paddle.png", id:"player"}, |
26 |
{src:"ball.png", id:"ball"}, |
27 |
{src:"win.png", id:"win"}, |
28 |
{src:"lose.png", id:"lose"}, |
29 |
{src:"playerScore.mp3|playerScore.ogg", id:"playerScore"}, |
30 |
{src:"enemyScore.mp3|enemyScore.ogg", id:"enemyScore"}, |
31 |
{src:"hit.mp3|hit.ogg", id:"hit"}, |
32 |
{src:"wall.mp3|wall.ogg", id:"wall"} |
33 |
];
|
34 |
|
35 |
|
36 |
|
37 |
preloader = new PreloadJS(); |
38 |
preloader.installPlugin(SoundJS); |
39 |
preloader.onProgress = handleProgress; |
40 |
preloader.onComplete = handleComplete; |
41 |
preloader.onFileLoad = handleFileLoad; |
42 |
preloader.loadManifest(manifest); |
43 |
|
44 |
/* Ticker */
|
45 |
|
46 |
Ticker.setFPS(30); |
47 |
Ticker.addListener(stage); |
48 |
}
|
Давайте проаналізуємо кожну частину:
1 |
canvas = document.getElementById('PongStage'); |
2 |
stage = new Stage(canvas); |
3 |
|
4 |
stage.mouseEventsEnabled = true; |
Тут ми присвоюємо до змінної canvas об'ект Canvas PongStage
із файлу index.html
і потім з його допомогою створюємо об'єкт класу Stage . (Завдяки ій ми зможемо розміщувати об'єкти на canvas)
Завдяки mouseEventsEnabled
ми можемо скористатися подіями, що виникають при діях з мишкою, для реагування на рухи та кліки мишки.
1 |
/* Set The Flash Plugin for browsers that don't support SoundJS */
|
2 |
SoundJS.FlashPlugin.BASE_PATH = "assets/"; |
3 |
if (!SoundJS.checkPlugin(true)) { |
4 |
alert("Error!"); |
5 |
return; |
6 |
}
|
Тут ми налаштовуємо розміщення плаґіна для звуку Flash для тих браузерів, що не підтримують HTML5 Audio.
1 |
manifest = [ |
2 |
{src:"bg.png", id:"bg"}, |
3 |
{src:"main.png", id:"main"}, |
4 |
{src:"startB.png", id:"startB"}, |
5 |
{src:"creditsB.png", id:"creditsB"}, |
6 |
{src:"credits.png", id:"credits"}, |
7 |
{src:"paddle.png", id:"cpu"}, |
8 |
{src:"paddle.png", id:"player"}, |
9 |
{src:"ball.png", id:"ball"}, |
10 |
{src:"win.png", id:"win"}, |
11 |
{src:"lose.png", id:"lose"}, |
12 |
{src:"playerScore.mp3|playerScore.ogg", id:"playerScore"}, |
13 |
{src:"enemyScore.mp3|enemyScore.ogg", id:"enemyScore"}, |
14 |
{src:"hit.mp3|hit.ogg", id:"hit"}, |
15 |
{src:"wall.mp3|wall.ogg", id:"wall"} |
16 |
];
|
У змінній manifest ми розміщуємо масив файлів, які хочемо завантажити (і задаємо для кожного унікальний ID). Кожний звук представлено у двох форматах – MP3 та OGG – оскільки браузери підтримують різні формати.
1 |
preloader = new PreloadJS(); |
2 |
preloader.installPlugin(SoundJS); |
3 |
preloader.onProgress = handleProgress; |
4 |
preloader.onComplete = handleComplete; |
5 |
preloader.onFileLoad = handleFileLoad; |
6 |
preloader.loadManifest(manifest); |
Тут ми налаштовуємо об'єкт preloader за допомогою PreloadJS. PreloadJS – новий додаток до бібліотеки CreateJS, і доволі корисний.
Ми створюємо новий об'єкт PreloadJS і поміщаємо його до змінної preloader
, потім задаємо метод для оброблення кожної події (onProgress
, onComplete
, onFileLoad
). Нарешті, ми використовуємо preloader
для завантаження раніше створеного списку файлів.
1 |
Ticker.setFPS(30); |
2 |
Ticker.addListener(stage); |
Тут ми додаємо об'єкт Ticker на сцену та задаємо частоту зміни кадрів рівною 30 FPS (* frame per second – кадрів за секунду); ми будемо її використовувати пізніше у грі для реалізації функціональності enterFrame
.
Крок 4: Створення функції для реалізації попереднього завантаження
1 |
function handleProgress(event) |
2 |
{
|
3 |
//use event.loaded to get the percentage of the loading
|
4 |
}
|
5 |
|
6 |
function handleComplete(event) { |
7 |
//triggered when all loading is complete
|
8 |
}
|
9 |
|
10 |
function handleFileLoad(event) { |
11 |
//triggered when an individual file completes loading
|
12 |
|
13 |
switch(event.type) |
14 |
{
|
15 |
case PreloadJS.IMAGE: |
16 |
//image loaded
|
17 |
var img = new Image(); |
18 |
img.src = event.src; |
19 |
img.onload = handleLoadComplete; |
20 |
window[event.id] = new Bitmap(img); |
21 |
break; |
22 |
|
23 |
case PreloadJS.SOUND: |
24 |
//sound loaded
|
25 |
handleLoadComplete(); |
26 |
break; |
27 |
}
|
28 |
}
|
Давайте проглянемо функцію:
-
handleProgress
- у цій функції ви зможете прослідкувати за процентом ходу завантаження за допомогою цього параметра:event.loaded
. Ви могли би використовувати його для створення індикатора виконання ходу завдання. -
handleComplete
- ця функція викликається одразу після завантаження всіх файлів (на випадок, якщо ви помістили до неї щось). -
handleFileLoad
– оскільки ми завантажуємо два види файлів – зображення та звук – у нас є ця функція для оброблення їх окремо один від одного. Якщо це – зображення, то ми створюємо растрове зображення та поміщаємо його до змінної (з тою ж назвою, що й в ID завантаженого зображення), а потім викликаємо функціюhandleLoadComplete
(яку напишемо далі); якщо ж це – звук, то ми одразу викликаємоhandleLoadComplete
.
Тепер давайте обговоримо тільки-но згадану handleLoadComplete
:
1 |
function handleLoadComplete(event) |
2 |
{
|
3 |
|
4 |
totalLoaded++; |
5 |
|
6 |
if(manifest.length==totalLoaded) |
7 |
{
|
8 |
addTitleView(); |
9 |
}
|
10 |
}
|
У ній доволі все зрозуміло: ми збільшуємо значення змінної totalLoaded
(в якій міститься кількість ресурсів, завантажених на даний момент) і потім перевіряємо, чи співпадає кількість елементів у manifest з кількістю завантажених ресурсів, і якщо так, то переходимо до екрану Main Menu (* Головне меню).
Крок 5: Створення Main Menu



1 |
function addTitleView() |
2 |
{
|
3 |
//console.log("Add Title View");
|
4 |
startB.x = 240 - 31.5; |
5 |
startB.y = 160; |
6 |
startB.name = 'startB'; |
7 |
|
8 |
creditsB.x = 241 - 42; |
9 |
creditsB.y = 200; |
10 |
|
11 |
TitleView.addChild(main, startB, creditsB); |
12 |
stage.addChild(bg, TitleView); |
13 |
stage.update(); |
14 |
|
15 |
// Button Listeners
|
16 |
|
17 |
startB.onPress = tweenTitleView; |
18 |
creditsB.onPress = showCredits; |
Тут нема нічого особливого. Ми розміщуємо зображення для фону, кнопок Start та Credits (* список розробників) на сцені і задаємо обробники події onPress
для кнопок Start та Credits.
Нижче наведено функції для показу та видалення екрану Credits та tweenTitleView
, із запуску якої починається гра:
1 |
function showCredits() |
2 |
{
|
3 |
// Show Credits
|
4 |
|
5 |
credits.x = 480; |
6 |
|
7 |
stage.addChild(credits); |
8 |
stage.update(); |
9 |
Tween.get(credits).to({x:0}, 300); |
10 |
credits.onPress = hideCredits; |
11 |
}
|
12 |
|
13 |
// Hide Credits
|
14 |
|
15 |
function hideCredits(e) |
16 |
{
|
17 |
Tween.get(credits).to({x:480}, 300).call(rmvCredits); |
18 |
}
|
19 |
|
20 |
// Remove Credits
|
21 |
|
22 |
function rmvCredits() |
23 |
{
|
24 |
stage.removeChild(credits); |
25 |
}
|
26 |
|
27 |
// Tween Title View
|
28 |
|
29 |
function tweenTitleView() |
30 |
{
|
31 |
// Start Game
|
32 |
|
33 |
Tween.get(TitleView).to({y:-320}, 300).call(addGameView); |
34 |
}
|
Крок 6: Код гри



Ми підійшли до головної частини цього посібника – до коду самої гри.
Для початку нам необхідно додати всі необхідні ресурси на сцену, що ми й робимо у функції addGameView
:
1 |
function addGameView() |
2 |
{
|
3 |
// Destroy Menu & Credits screen
|
4 |
|
5 |
stage.removeChild(TitleView); |
6 |
TitleView = null; |
7 |
credits = null; |
8 |
|
9 |
// Add Game View
|
10 |
|
11 |
player.x = 2; |
12 |
player.y = 160 - 37.5; |
13 |
cpu.x = 480 - 25; |
14 |
cpu.y = 160 - 37.5; |
15 |
ball.x = 240 - 15; |
16 |
ball.y = 160 - 15; |
17 |
|
18 |
// Score
|
19 |
|
20 |
playerScore = new Text('0', 'bold 20px Arial', '#A3FF24'); |
21 |
playerScore.x = 211; |
22 |
playerScore.y = 20; |
23 |
|
24 |
cpuScore = new Text('0', 'bold 20px Arial', '#A3FF24'); |
25 |
cpuScore.x = 262; |
26 |
cpuScore.y = 20; |
27 |
|
28 |
stage.addChild(playerScore, cpuScore, player, cpu, ball); |
29 |
stage.update(); |
30 |
|
31 |
// Start Listener
|
32 |
|
33 |
bg.onPress = startGame; |
34 |
}
|
Знову у функції доволі все зрозуміло: відбувається розміщення об'єктів на екрані та додавання mouseEvent (* обробника подій, що виникають при виконанні дій із мишкою) до фонового зображення, завдяки чому при кліку його користувачем починається гра (буде викликано функцію startGame
).
Давайте проглянемо функцію startGame
:
1 |
function startGame(e) |
2 |
{
|
3 |
bg.onPress = null; |
4 |
stage.onMouseMove = movePaddle; |
5 |
|
6 |
Ticker.addListener(tkr, false); |
7 |
tkr.tick = update; |
8 |
}
|
Тут, як ви бачите, окрім додавання обробника для події onMouseMove
, завдяки якому відбувається рух нашої ракетки, ми додаємо обробник для події tick
, завдяки чому буде викликано функцію update
для кожного фрейма.
Давайте розглянемо функції movePaddle
та reset
:
1 |
function movePaddle(e) |
2 |
{
|
3 |
// Mouse Movement
|
4 |
player.y = e.stageY; |
5 |
}
|
6 |
|
7 |
/* Reset */
|
8 |
|
9 |
function reset() |
10 |
{
|
11 |
ball.x = 240 - 15; |
12 |
ball.y = 160 - 15; |
13 |
player.y = 160 - 37.5; |
14 |
cpu.y = 160 - 37.5; |
15 |
|
16 |
stage.onMouseMove = null; |
17 |
Ticker.removeListener(tkr); |
18 |
bg.onPress = startGame; |
19 |
}
|
У movePaddle
ми власне розміщуємо ракетку користувача до координати y миші.
У reset
ми здійснюємо дещо подібне, що робили в addGameView
, проте тут ми не додаємо ніяких графічних елементів, оскільки вони вже знаходяться на екрані.
За допомогою функції alert
ми показуємо повідомлення про програш або перемогу.
1 |
function alert(e) |
2 |
{
|
3 |
Ticker.removeListener(tkr); |
4 |
stage.onMouseMove = null; |
5 |
bg.onPress = null |
6 |
|
7 |
if(e == 'win') |
8 |
{
|
9 |
win.x = 140; |
10 |
win.y = -90; |
11 |
|
12 |
stage.addChild(win); |
13 |
Tween.get(win).to({y: 115}, 300); |
14 |
}
|
15 |
else
|
16 |
{
|
17 |
lose.x = 140; |
18 |
lose.y = -90; |
19 |
|
20 |
stage.addChild(lose); |
21 |
Tween.get(lose).to({y: 115}, 300); |
22 |
}
|
23 |
}
|
Крок 7: Ігровий цикл
Тепер переходимо до останньої частини нашого посібника, де розглянемо функцію update
(яка виконується для кожного фрейма гри – подібно onEnterFrame
Flash).
1 |
function update() |
2 |
{
|
3 |
// Ball Movement
|
4 |
|
5 |
ball.x = ball.x + xSpeed; |
6 |
ball.y = ball.y + ySpeed; |
7 |
|
8 |
// Cpu Movement
|
9 |
|
10 |
if(cpu.y < ball.y) { |
11 |
cpu.y = cpu.y + 4; |
12 |
}
|
13 |
else if(cpu.y > ball.y) { |
14 |
cpu.y = cpu.y - 4; |
15 |
}
|
16 |
|
17 |
// Wall Collision
|
18 |
|
19 |
if((ball.y) < 0) { ySpeed = -ySpeed; SoundJS.play('wall'); };//Up |
20 |
if((ball.y + (30)) > 320) { ySpeed = -ySpeed; SoundJS.play('wall');};//down |
21 |
|
22 |
/* CPU Score */
|
23 |
|
24 |
if((ball.x) < 0) |
25 |
{
|
26 |
xSpeed = -xSpeed; |
27 |
cpuScore.text = parseInt(cpuScore.text + 1); |
28 |
reset(); |
29 |
SoundJS.play('enemyScore'); |
30 |
}
|
31 |
|
32 |
/* Player Score */
|
33 |
|
34 |
if((ball.x + (30)) > 480) |
35 |
{
|
36 |
xSpeed = -xSpeed; |
37 |
playerScore.text = parseInt(playerScore.text + 1); |
38 |
reset(); |
39 |
SoundJS.play('playerScore'); |
40 |
}
|
41 |
|
42 |
/* Cpu collision */
|
43 |
|
44 |
if(ball.x + 30 > cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75) |
45 |
{
|
46 |
xSpeed *= -1; |
47 |
SoundJS.play('hit'); |
48 |
}
|
49 |
|
50 |
/* Player collision */
|
51 |
|
52 |
if(ball.x <= player.x + 22 && ball.x > player.x && ball.y >= player.y && ball.y < player.y + 75) |
53 |
{
|
54 |
xSpeed *= -1; |
55 |
SoundJS.play('hit'); |
56 |
}
|
57 |
|
58 |
/* Stop Paddle from going out of canvas */
|
59 |
|
60 |
if(player.y >= 249) |
61 |
{
|
62 |
player.y = 249; |
63 |
}
|
64 |
|
65 |
/* Check for Win */
|
66 |
|
67 |
if(playerScore.text == '10') |
68 |
{
|
69 |
alert('win'); |
70 |
}
|
71 |
|
72 |
/* Check for Game Over */
|
73 |
|
74 |
if(cpuScore.text == '10') |
75 |
{
|
76 |
alert('lose'); |
77 |
}
|
78 |
}
|
Виглядає застрашливо, чи не так? Не турбуйтеся, ми розглянемо кожну частину та обговоримо її.
1 |
// Ball Movement
|
2 |
|
3 |
ball.x = ball.x + xSpeed; |
4 |
ball.y = ball.y + ySpeed; |
У кожному фреймі м'яч буде рухатися згідно з його значенням швидкості по x та y.
1 |
// Cpu Movement
|
2 |
|
3 |
if((cpu.y+32) < (ball.y-14)) { |
4 |
cpu.y = cpu.y + cpuSpeed; |
5 |
}
|
6 |
else if((cpu.y+32) > (ball.y+14)) { |
7 |
cpu.y = cpu.y - cpuSpeed; |
8 |
}
|
Тут у нас представлено базовий AI (* artificial intelligence – штучний інтелект) комп'ютера, завдяки якому ракетка комп'ютера просто слідкує за м'ячем без будь-якої спеціальної логіки. Ми просто порівнюємо положення центру ракетки (чому ми і додаємо 32 пікселі до значення Y cpu) з положенням м'яча (з невеликим відступом) та рухаємо ракетку в необхідному напрямку: вниз або вгору.
1 |
if((ball.y) < 0) { //top |
2 |
ySpeed = -ySpeed; |
3 |
SoundJS.play('wall'); |
4 |
};
|
5 |
if((ball.y + (30)) > 320) { //bottom |
6 |
ySpeed = -ySpeed; |
7 |
SoundJS.play('wall'); |
8 |
};
|
Якщо м'яч зіштовхується з верхньою або нижньою границею, то м'яч змінює свій напрямок і ми програємо звук Wall Hit (* звук зіткнення з границею).
1 |
/* CPU Score */
|
2 |
if((ball.x) < 0) |
3 |
{
|
4 |
xSpeed = -xSpeed; |
5 |
cpuScore.text = parseInt(cpuScore.text + 1); |
6 |
reset(); |
7 |
SoundJS.play('enemyScore'); |
8 |
}
|
9 |
/* Player Score */
|
10 |
if((ball.x + (30)) > 480) |
11 |
{
|
12 |
xSpeed = -xSpeed; |
13 |
playerScore.text = parseInt(playerScore.text + 1); |
14 |
reset(); |
15 |
SoundJS.play('playerScore'); |
16 |
}
|
Реалізувати вивід очок просто: якщо м'яч перетинає ліву або праву границі, то відбувається збільшення кількості очка гравця або супротивника, програвання звуку та скидання значень положення об'єктів за допомогою функції reset
, яку ми раніше обговорювали:
1 |
|
2 |
/* CPU collision */
|
3 |
if(ball.x + 30 > cpu.x && ball.x + 30 < cpu.x + 22 && ball.y >= cpu.y && ball.y < cpu.y + 75) |
4 |
{
|
5 |
xSpeed *= -1; |
6 |
SoundJS.play('hit'); |
7 |
}
|
8 |
/* Player collision */
|
9 |
if(ball.x <= player.x + 22 && ball.x > player.x && ball.y >= player.y && ball.y < player.y + 75) |
10 |
{
|
11 |
xSpeed *= -1; |
12 |
SoundJS.play('hit'); |
13 |
}
|
Тут ми маємо справу із зіткненням м'яча з ракетками; кожного разу після зіткнення м'яча з однією з ракеток м'яч змінює свій напрямок та програється відповідний звук.
1 |
if(player.y >= 249) |
2 |
{
|
3 |
player.y = 249; |
4 |
}
|
Якщо ракетка гравця виходить за межі, то ми повертаємо її назад.
1 |
/* Check for Win */
|
2 |
if(playerScore.text == '10') |
3 |
{
|
4 |
alert('win'); |
5 |
}
|
6 |
/* Check for Game Over */
|
7 |
if(cpuScore.text == '10') |
8 |
{
|
9 |
alert('lose'); |
10 |
}
|
У даному фрагменті коду ми перевіряємо, чи досягла кількість очок когось із гравців 10, і якщо це так, то показуємо користувачеві повідомлення про перемогу або програш (відповідно до його результатів).
Завершення
От і все, ви створили повноцінну гру Пінг-Понг за допомогою CreateJS. Дякую за проявлену зацікавленість!