pixi assets & parallax guide
This commit is contained in:
parent
8f429afc77
commit
4438b6ce74
286
content/posts/pixijs/assets-and-parallax.md
Normal file
286
content/posts/pixijs/assets-and-parallax.md
Normal file
@ -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
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>pixi.js - assets & parallax</title>
|
||||
<script type="text/javascript" src="pixi.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Код приложения `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;
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue
Block a user