Створення гри «Слова із Слова»

Добрий день! Хочу представити Вашій увазі проект-гру «Слова, Слова». Відносно недавно я став вивчати web-програмування і, так як найкращий вчитель — це практика, вирішив написати свій варіант досить-таки відомої гри «Слова, Слова». Основна мета — використання чистого Javascript без підключення додаткових бібліотек.

image
Вид ігрового поля

Опис гри
Завдання гравця – з букв представленого на екрані слова складати інші. Складене слово повинно бути загальним ім'ям іменником в однині, зменшувально-пестливі форми, а також скорочення не приймаються. Мінімальна довжина – 3 літери. За кожне отгаданное слово нараховуються очки в залежності від його довжини (базова ставка за кожну букву, умножаемая на коефіцієнт). Базова ставка дорівнює десяти очками. Коефіцієнт розраховується наступним чином:

  • три букви – 1;
  • від чотирьох до п'яти букв – 1.25;
  • від шести до семи літер – 1.5;
  • від восьми до дев'яти літер – 1.75;
  • більше дев'яти літер – 2.
На кожному рівні гравець може заробити додаткові очки, виконуючи певні умови:

  • відгадати 40 проц. можливих слів на рівні (1 000 очок);
  • відгадати три слова, що починаються на ту ж букву, що і слово рівня (500 очок);
  • відгадати всі можливі слова на рівні (50 000 очок).
Відгадані гравцем слова відображаються на ігровому полі в алфавітному порядку, згруповані по кількості букв в слові. Гравець може подивитися значення кожного, натиснувши на нього. Результати охороняються кожен раз після вірно отгаданного слова.

Використані техніки і прийоми
В ході роботи над додатком використовувалися елементи підходу MVC (model view controller). В окремі компоненти також винесено керування звуком, обробка результатів гри і загальні методи для всього програми.

Загальна структура програми
GAME = {
"utils":{}, // загальні інструменти
"sounds":{}, // обробка звуків
"view":{}, // подання
"controller":{}, // обробка поведінки
"model":{}, // основні дані
"results":{} // обробка результатів
}
GAME.init(place) // ініціалізація програми
GAME.namespace(ns_string) // створення просторів імен


У процесі розробки відчув всі переваги використання замикань і негайно викликаються функцій. Так, їх використання позбавило від постійного пошуку елементів на сторінці допомогою getElementById і т. п.

Приклад використання замикань
controller.play = (function () {
// блокування множинного натискання
var cancelClick = false;

return function (letter) {
if (cancelClick) return;

cancelClick = true;

setTimeout(function () {
cancelClick = false;
}, 200)

//код функції
})()


Етапи виконання програми
В процесі ініціалізації додатка створюються всі необхідні елементи html, формуються об'єкти-списки для спрощення доступу до них.

Вміст html до ініціалізації
<body>
<div id="gamefield"></div>
<div id="help">
<h2>Правила</h2>
<div class='textGuide'>
<p>Необхідно складати слова з показаного на екрані слова. Слово повинно бути загальним ім'ям іменником в однині. Зменшувально-пестливі форми, а також скорочення не приймаються. Мінімальна довжина слова - 3 літери.</p>
</div>
<h2>Керування</h2>
<div class='textGuide'>
<p>Щоб вибрати літеру, клікніть мишкою. Повторне натискання останньої вибраної букві знімає виділення.</p>
<p>Клавіша Esc скасовує введення всього слова.</p>
<p>Клавіша Backspace (←) скасовує введення останньої букви.</p>
</div>
<h2>Ігрові бонуси</h2>
<div class="textGuide">
<p>Перша зірка - відгадати 40% можливих слів на рівні. Бонус: 1 000 очок.</p>
<p>Друга зірка - відгадати три слова, що починаються на ту ж букву, що і слово рівня. Бонус: 500 очок.</p>
<p>Третя зірка - відгадати всі можливі слова на рівні. Бонус: 50 000 очок.</p>
</div>
<h2>Підказки</h2>
<div>
<img src="images/icons/tips/definition.png">
<p>Показати визначення неотгаданного слова. Вартість підказки: 100 очок</p>
</div>
<div>
<img src="images/icons/tips/word.png">
<p>Показати неотгаданное слово. Вартість підказки: 500 очок.</p>
</div>
<h2>Елементи інтерфейсу</h2>
<div>
<img src="images/icons/buttons_small/soundON.png">
<p>Керування звуком.</p>
</div>
<div>
<img src="images/icons/buttons_small/menuButton.png">
<p>Виклик ігрового меню.</p>
</div>
<div>
<progress max="10" value="3"></progress>
<p>Прогрес на рівні.</p>
</div>
</div>
</body>


Вміст html після ініціалізації
<body>
<div id="gamefield" style="position: relative;">
<div>
<div class="gameInfo">
<!-- Область інформації про поточної сесії ігри -->
<h1>Слова із слова</h1>
<div class="userName">Гравець: <span>123</span></div>
<div class="currentLevel">Рівень: <span>1</span></div>
<div class="menuLevel">
<!-- Переходи по рівнях-->
<div class="menuLabel">Карта рівнів ⇩</div>
<div class="levelMap" style="display: none;">
<a class="reached levelButton">1</a>
<a class="levelButton">2</a>
<a class="levelButton">3</a>
<a class="levelButton">4</a>
</div>
</div>
<div class="score">Окуляри: <span>0</span></div>
<progress max="31" value="0" title="Відгадане 0 з 31 слів"></progress>
<div class="tips">
<h2>Підказки:</h2>
<img id="wordDefinition" title="Показати визначення неотгаданного слова." alt="Показати визначення неотгаданного слова." src="images/icons/tips/definition_gray.png">
<img id="holeWord" title="Показати неотгаданное слово цілком." alt="Показати неотгаданное слово цілком." src="images/icons/tips/word_gray.png"></div>
</div>
<!-- Ігрова область-->
<div class="gameField">
<div class="missions">
<img src="images/icons/missions/incomplete.png" alt="Перша зірка" title="Відгадайте більше 40% слів">
<img src="images/icons/missions/incomplete.png" alt="Друга зірка" title="Відгадайте 3 слова на букву "р"">
<img src="images/icons/missions/incomplete.png" alt="Третя зірка" title="Відгадайте 100% слів">
</div>
<div class="buttonGroup">
<img src="images/icons/buttons_small/soundON.png" alt="Вимкнути звук" title="Вимкнути звук">
<img src="images/icons/buttons_small/menuButton.png" alt="Меню" title="Ігрове меню">
<img src="images/icons/buttons_small/help.png" title="Допомога" alt="Допомога">
</div>
<!-- Відображення вводиться гравцем слова -->
<div class="userWord"></div>
<div class="levelWord">
<!-- Букви основного слова -->
<div class="letter" data-order="0">р</div>
<div class="letter" data-order="0"></div>
<div class="letter" data-order="0"></div>
<div class="letter" data-order="0"></div>
<div class="letter" data-order="0">н</div>
<div class="letter" data-order="0"></div></div>
<!-- контейнер для знайдених слів -->
<div class="foundWords"></div>
</div>
</div>
</div>
</body>

Вся інформація про проходження гравцем рівня зберігається в об'єкті GAME.model.level

Зберігання інформації про проходження
level = {
"1":{
"wordForLevel":"батьківщина",
"foundWords":["рід","анод","аїр"],
"missions": {
"progress":3,
"firstStar":true,
"secondStar":true,
"thirdStar":true
}
}
}

Для того, щоб зберігати прогрес і не задіяти при цьому серверні скрипти і бази даних, був обраний спосіб збереження в localStorage браузера. Крім того, реалізував «таблицю рекордів» для гравців, які використовують цю програму в одному і тому ж браузері

Метод збереження
/**
* Збереження результатів.
* @method GAME.controller.storeResults
* @param {string} name
* Ім'я гравця.
*/
controller.storeResults = function (name) {
var results = {
level: GAME.utils.createClone(model.level),
score: model.score
}
results = JSON.stringify(results);
window.localStorage.setItem(name, results);
}

Таким чином, представляю Вам на обговорення мій проект. Буду радий вислухати конструктивну критику та пропозиції у коментарях, так і в особистому спілкуванні. Якщо цікавлять подробиці, із задоволенням розповім про процесі написання докладніше.

Посилання на репозиторій GitHub
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.