Практика 14
Карточная игра
Что предстоит сделать?
Сегодня вы потренируетесь использовать классы и вспомните как работать с модулями в js.
Задача состоит в том, чтобы добавлять в карточную игру новые типы карт с новым функционалом.
Возьмите код игры из репозитория: https://gitlab.com/nsk-front-school/practice-14
Задание на практику
1. Установите зависимости проекта и запустите http сервер - npm run start. Игра доступна по адресу http://localhost:8080.
Понаблюдайте, как игра играет сама в себя.
В файле index.js создаются колоды карты и запускается игра. В заданиях следует править только этот файл, если явно не сказано менять другие файлы. Также можете создавать свои файлы под классы.
Загляните в файлы Game.js и Card.js, посмотрите на стадии хода, какие действия происходят с картой, какие возможности по расширению заложены.
2. Сейчас все скрипты подключены в index.html по одному. Воспользуйтесь тем, что Chrome уже поддерживает использование модулей ECMAScript из коробки и сделайте так, чтобы все скрипты подключались с помощью конструкций import и export:
- Уберите из index.html все скрипты кроме index.js: <script type="module" src="index.js"></script>
- В других файлах со скриптами допишите в конце export default с той сущностью, которую нужно экспортировать по-умолчанию.
- Используйте ошибки в консоле Developer Tools, чтобы понять, в каком модуле чего не хватает и импортируйте недостающее конструкцией import.
- В результате игра снова должна работать без ошибок.
3. Во всем коде типы определены по-старому, через прототипы. Изоляция кода при этом обеспечивает за счет техники IIFE. Благодаря использованию модулей ECMAScript каждый файл изолирован и IIFE больше не нужны.
Новый синтаксис с классами совместим с прототипами. Чтобы убедиться в этом перепишите TaskQueue с использованием class и без IIFE:
- Уберите самовызывающуюся функцию.
- Перенесите вверх функцию runNextTask, потому что это не метод TaskQueue.
- Перепишите TaskQueue на синтаксис с классами.
- export default поставьте сразу перед инструкцией class.
4. Создайте новые карты:
- Duck с именем «Мирная утка» и силой 2
- Dog с именем «Пес-бандит» и силой 3
После добавления новых типов замените карты в колоде шерифа на уток, а в колоде бандита - на собак.
Функция isDuck должна возвращать true для утки, а функция isDog — для собаки.
Если все сделано правильно, то внизу карты утки должен быть текст Duck➔ Card, а у собаки Dog➔ Card.
5. Метод getDescriptions в Card создан для того, чтобы на картах появлялась дополнительная информация. Его функционал хочется расширить. Причем так, чтобы это работало и для уток, и для собак, и для всех остальных существ, которые будут добавляться.
- Создай новый тип Creature и унаследуй его от Card.
- Duck и Dog должны наследоваться от Creature.
- Переопредели в классе Creature реализацию getDescriptions на новую. Теперь в ней должны возвращаться две строки описания в виде массива: одна из getDescriptions в Card, вторая из функции getCreatureDescription, из index.js.
Используя те же колоды убедись, что у уток появилась надпись «Утка» над строкой с цепочкой наследования, а у собак надпись «Собака» над цепочкой наследования.
6. Добавьте новую карту "Браток" (Lad). Сила карты 2, наследуется от Dog. Замените в колоде бандита собак на двух братков. Добавьте в описание карты «Чем их больше, тем они сильнее».
Чем больше братков находится в игре, тем больше урона без потерь поглощается и больше урона по картам наносится каждым из них:
Защита от урона = количество * (количество + 1) / 2
Дополнительный урон = количество * (количество + 1) / 2
Чтобы следить за количеством братков, удобно использовать статические методы класса Lad. Добавьте классу методы:
static getInGameCount() { return this.inGameCount || 0; }
static setInGameCount(value) { this.inGameCount = value; }
Хоть inGameCount явно не объявляется, при первом вызове setInGameCount, оно будет создано со значением value.
- чтобы обновлять количество братков в игре переопределите методы doAfterComingIntoPlay, doBeforeRemoving
- чтобы рассчитывать бонус к урону и защите стоит завести статический метод getBonus в классе Lad.
Чтобы в getBonus обращаться к другим статическим методам можно использовать this, а не имя класса Lad.
- переопределите методы modifyDealedDamageToCreature и modifyTakenDamage, чтобы они использовали бонус.
7. Добавьте новую карту Изгой (Rogue). Сила 2, наследуется от Creature. Её особенность в том, что перед атакой на карту забирает у нее все способности к увеличению наносимого урона или уменьшению получаемого урона. Одновременно эти способности забираются у всех карт того же типа, но не у других типов карт. Изгой получает эти способности, но не передает их другим Изгоям. Для проверки:
const seriffStartDeck = [
new Duck(),
new Duck(),
new Duck(),
new Rogue(),
];
const banditStartDeck = [
new Lad(),
new Lad(),
new Lad(),
];
- Изгой похищает эти способности: modifyDealedDamageToCreature, modifyDealedDamageToPlayer, modifyTakenDamage
- Чтобы похитить способности у всех карт некоторого типа, надо взять их из прототипа
- Получить доступ к прототипу некоторой карты можно так: Object.getPrototypeOf(card)
- Чтобы не похищать способности у других типов, нельзя задевать прототип прототипа
- Object.getOwnPropertyNames и obj.hasOwnProperty позволяют получать только собственные свойства объекта
- Удалить свойство из объекта можно с помощью оператора delete так: delete obj[propName]
Это не то же самое, что obj[propName] = undefined
- После похищения стоит обновить вид всех объектов игры. updateView из gameContext поможет это сделать.
Практика 14
By frontschool-nsk
Практика 14
- 267