diff --git a/content/posts/pixijs/assets-and-parallax.md b/content/posts/pixijs/assets-and-parallax.md
new file mode 100644
index 0000000..e08354f
--- /dev/null
+++ b/content/posts/pixijs/assets-and-parallax.md
@@ -0,0 +1,286 @@
+---
+title: "Pixi.js: Пример эффекта параллакс и использование ассетов"
+date: 2022-10-29T00:24:59+03:00
+draft: false
+tags: [pixijs, gamedev, tutorial, javascript]
+---
+
+## Pixi.js 7.0.0
+
+4 часа назад вышла [7–я версия](https://github.com/pixijs/pixijs/releases/tag/v7.0.0)
+библиотеки [Pixi.js](https://pixijs.com).
+
+Для тех, кто уже использует Pixi.js подготовлен
+[документ](https://github.com/pixijs/pixijs/wiki/v7-Migration-Guide)
+по миграции на новую версию.
+
+В данном примере будем использовать загрузчик ассетов [PIXI.Assets](https://pixijs.download/release/docs/PIXI.Assets.html),
+который потеснил [PIXI.Loader](https://pixijs.download/release/docs/PIXI.Loader.html).
+Подробнее написано здесь: [v7-Migration-Guide#-replaces-loader-with-assets](https://github.com/pixijs/pixijs/wiki/v7-Migration-Guide#-replaces-loader-with-assets).
+
+## PIXI.Assets
+
+> PIXI.Assets — это универсальный инструмент для управления ресурсами в Pixi!
+> Суперсовременный и простой в использовании, с достаточной гибкостью,
+> чтобы настраивать и делать то, что вам нужно!
+
+### Загрузка ассетов
+Не бойся загружать данные несколько раз —
+Pixi.Assets **НИКОГДА** ничего не загрузит больше одного раза.
+
+Например:
+
+```javascript
+promise1 = PIXI.Assets.load('bunny.png')
+promise2 = PIXI.Assets.load('bunny.png')
+
+// promise1 === promise2
+```
+
+Вот несколько примеров загрузки ассетов:
+
+```javascript
+// простой пример
+PIXI.Assets.add('bunnyBooBoo', 'bunny.png');
+const bunny = await PIXI.Assets.load('bunnyBooBoo');
+
+// несколько значений
+PIXI.Assets.add(['burger', 'chicken'], 'bunny.png');
+
+const bunny = await PIXI.Assets.load('burger');
+const bunny2 = await PIXI.Assets.load('chicken');
+
+// передача параметров объекту
+PIXI.Assets.add(
+ 'bunnyBooBooSmooth',
+ 'bunny{png,webp}',
+ {scaleMode:SCALE_MODES.NEAREST},
+);
+```
+
+## Каркас приложения
+
+HTML документ `index.html`:
+
+```html
+
+
+
+
+
+ pixi.js - assets & parallax
+
+
+
+
+
+
+```
+
+Код приложения `app.js`
+
+```javascript
+let app;
+let backgroundTextures;
+let background = {
+ sky: null,
+ back: null,
+ middle: null,
+ front: null,
+ x: 0,
+ speed: 1,
+};
+
+/** Инициализация PIXI и настройка PIXI.Assets */
+window.onload = function() {
+ app = new PIXI.Application({
+ width: 640,
+ height: 360,
+ backgroundColor: 0x2a2a3a,
+ });
+ document.body.appendChild(app.view);
+}
+
+/** Функция инициализации уровня */
+function initLevel() {
+ app.ticker.add(gameLoop);
+}
+
+/** Игровой цикл */
+function gameLoop(delta) {
+ //
+}
+```
+
+В переменной `app` я буду хранить объект `PIXI.Application`,
+чтобы можно было получать доступ к нему из других функций.
+
+В переменную `backgroundTextures` будет загружать текстуры.
+
+Переменная `background` отвечает за необходимые параметры,
+такие как скорость эффекта параллакса и положение тайлов изображений
+**sky**, **back**, **middle**, **front**.
+
+В этом примере я буду использовать ассет
+[Desert Parallax Background](https://styloo.itch.io/desert-parallax-background)
+за авторством **styloo**.
+
+В этом ассете есть фон, и три изображения с частями пустыни.
+
+## Добавление ассетов
+
+Я распаковал ассет **Desert Parallax Background** в директорию `assets`,
+а также переименовал изображения.
+
+Теперь в функцию `window.onload = function() {}` указываем ресурсы,
+которые я буду загружать и вызываем их загрузку.
+
+```javascript
+PIXI.Assets.add('bg_back', '/assets/3.png');
+PIXI.Assets.add('desert_2', '/assets/2.png');
+PIXI.Assets.add('desert_1', '/assets/1.png');
+PIXI.Assets.add('desert_0', '/assets/0.png');
+
+let promise = PIXI.Assets.load(
+ ['bg_back', 'desert_2', 'desert_1', 'desert_0'],
+ (progress) => {
+ console.log(`Assets loading progress: ${progress * 100}%`);
+});
+```
+
+Функция `PIXI.Assets.load` принимает в качестве аргумента имя ассета, который
+необходимо загрузить, либо список ассетов.
+
+Второй необязательный аргумент, это callback функция,
+которая вызывается во время загрузки Ассетов.
+Функции передается параметр `progress`,
+который представляет процент (0.0 - 1.0) загруженных ассетов.
+
+Функция возвращает **Promise** ассетов, которые были загружены.
+
+По окончании загрузки ассетов, я вызываю функцию `initLevel()`,
+а также передаю в переменную `backgroundTextures` список загруженых ассетов,
+в данном случае это текстуры.
+
+```javascript
+promise.then((value) => {
+ backgroundTextures = value;
+ initLevel();
+});
+```
+
+## Инициализация тайлов
+
+Для создания тайлов, я написал функцию `createBg()`, которая создаёт объект
+[PIXI.TilingSprite](https://pixijs.download/release/docs/PIXI.TilingSprite.html)
+и устанавливает позицию на экране.
+
+```javascript
+function createBg(texture) {
+ let tiling = new PIXI.TilingSprite(texture, 640, 360);
+ tiling.position.set(0, 0);
+ app.stage.addChild(tiling);
+
+ return tiling;
+}
+```
+
+Создаёт тайлы:
+
+```javascript
+function initLevel() {
+ background.sky = createBg(backgroundTextures.bg_back);
+ background.back = createBg(backgroundTextures.desert_2);
+ background.middle = createBg(backgroundTextures.desert_1);
+ background.front = createBg(backgroundTextures.desert_0);
+
+ app.ticker.add(gameLoop);
+}
+```
+
+## Создаём эффект параллакса
+
+Этот этап самый простой.
+
+В игровом цикле я изменяю значение переменной `background.x` и
+смещаю позицию тайлов.
+
+```javascript
+function gameLoop(delta) {
+ background.x = (background.x - background.speed);
+ background.front.tilePosition.x = background.x;
+ background.middle.tilePosition.x = background.x / 2;
+ background.back.tilePosition.x = background.x / 4;
+}
+```
+
+## Исходный код
+
+```javascript
+const DEBUG = true;
+
+let app;
+let backgroundTextures;
+let background = {
+ sky: null,
+ back: null,
+ middle: null,
+ front: null,
+ x: 0,
+ speed: 1,
+};
+
+/** PIXI and PIXI.Assets init */
+window.onload = function() {
+ app = new PIXI.Application({
+ width: 640,
+ height: 360,
+ backgroundColor: 0x2a2a3a,
+ });
+ document.body.appendChild(app.view);
+
+ PIXI.Assets.add('bg_back', '/assets/3.png');
+ PIXI.Assets.add('desert_2', '/assets/2.png');
+ PIXI.Assets.add('desert_1', '/assets/1.png');
+ PIXI.Assets.add('desert_0', '/assets/0.png');
+
+let promise = PIXI.Assets.load(
+ ['bg_back', 'desert_2', 'desert_1', 'desert_0'],
+ (progress) => {
+ if (DEBUG)
+ console.log(`Assets loading progress: ${progress * 100}%`);
+ });
+
+ promise.then((value) => {
+ backgroundTextures = value;
+ initLevel();
+ });
+}
+
+/** Level init */
+function initLevel() {
+ background.sky = createBg(backgroundTextures.bg_back);
+ background.back = createBg(backgroundTextures.desert_2);
+ background.middle = createBg(backgroundTextures.desert_1);
+ background.front = createBg(backgroundTextures.desert_0);
+
+ app.ticker.add(gameLoop);
+}
+
+/** Game loop */
+function gameLoop(delta) {
+ background.x = (background.x - background.speed);
+ background.front.tilePosition.x = background.x;
+ background.middle.tilePosition.x = background.x / 2;
+ background.back.tilePosition.x = background.x / 4;
+}
+
+/** Create background sprite */
+function createBg(texture) {
+ let tiling = new PIXI.TilingSprite(texture, 640, 360);
+ tiling.position.set(0, 0);
+ app.stage.addChild(tiling);
+
+ return tiling;
+}
+```