В этом курсе мы создадим игру в жанре tower defense с помощью PixiJS.
Дополнительные материалы
Перед началом разработки нужно выполнить два шага:
1️⃣ ( Скачайте наш шаблон проекта PIXI. Можно сразу начать работу над игрой или изучить руководство по созданию шаблона PIXI.
2️⃣ Скачайте игровые ресурсы:
- спрайты
- тайловую карту, созданную в редакторе Tiled
Мы скачали и распаковали шаблон проекта, в котором продолжим работу. Обычно я начинаю новую игру с фонового изображения. Здесь вместо него используем полную карту уровня, заранее подготовленную в Tiled в формате tilemap. Вся карта состоит из небольших тайлов. Данные уровня хранятся в двух файлах:
tilemap.jsontilemap.png
Разместим их в нужных папках проекта:
/src/json/tilemap.json/src/sprites/tilemap.png
Для создания карты на сцене сначала научимся разбирать изображение tilemap.png, чтобы рисовать только нужные тайлы.
Создадим класс Tile, отвечающий за отрисовку нужной части карты:
import { EventEmitter } from "events";
import * as PIXI from "pixi.js";
import { App } from "../system/App";
export class Tile extends EventEmitter {
constructor(id) {
super();
this.atlas = App.res("tilemap");
this.id = id;
this.createSprite();
}
createSprite() {
}
}
Tile будет наследоваться от EventEmitter, чтобы экземпляры могли отправлять нужные события. Например, башня — разновидность Tile. У неё могут быть события, которые в дальнейшем понадобится отслеживать.
В this.atlas получим текстуру загруженного ресурса tilemap. Пусть у каждого тайла будет свой ID в атласе, по которому можно определить его положение. Прежде чем рисовать нужную часть изображения, определим её позицию по ID.
Сначала вручную зададим число строк и столбцов изображения атласа tilemap.png в конфигурации игры и укажем размер тайлов:
import { Tools } from "../system/Tools";
import { GameScene } from "./GameScene";
export const Config = {
loader: Tools.massiveRequire(require["context"]('./../../sprites/', true, /\.(mp3|png|jpe?g)$/)),
scenes: {
"Game": GameScene
},
atlas: {
cols: 23,
rows: 13,
tileSize: 64
}
};
Зная число строк и столбцов атласа, вычислим, в какой строке и столбце находится тайл с заданным ID:
get position() {
let index = 0;
for (let row = 0; row < App.config.atlas.rows; row++) {
for (let col = 0; col < App.config.atlas.cols; col++) {
++index;
if (index === this.id) {
return {row, col};
}
}
}
return {row: 0, col: 0};
}
Определив строку и столбец тайла в сетке tilemap, наконец можем его нарисовать:
createSprite() {
const x = App.config.atlas.tileSize * this.position.col;
const y = App.config.atlas.tileSize * this.position.row;
const texture = new PIXI.Texture(this.atlas, new PIXI.Rectangle(x + 1, y + 1, App.config.atlas.tileSize - 2, App.config.atlas.tileSize - 2));
this.sprite = new PIXI.Sprite(texture);
this.sprite.anchor.set(0.5);
}
Находим координаты тайла по его месту в сетке с учётом размера. Здесь используем отступ 1px от каждого края: карта была сгенерирована с таким отступом для предотвращения наложения кадров.
Осталось проверить правильность создания тайлов:
import { Scene } from '../system/Scene';
import { Tile } from './Tile';
export class GameScene extends Scene {
create() {
const tile = new Tile(1);
this.container.addChild(tile.sprite);
}
}