├── src
├── api
│ └── index.ts
├── plugins
│ ├── storage
│ │ └── index.ts
│ └── engine
│ │ └── index.ts
├── ui
│ ├── sprites
│ │ ├── ts-logo.sprite.ts
│ │ ├── vite-logo.sprite.ts
│ │ └── pixi-logo.sprite.ts
│ ├── textures
│ │ ├── ts-logo.texture.ts
│ │ ├── vite-logo.sprite.ts
│ │ └── pixi-logo.texture.ts
│ ├── containers
│ │ ├── locaing-box.container.ts
│ │ └── loading-bar.container.ts
│ └── scenes
│ │ ├── loader.scene.ts
│ │ └── game.scene.ts
├── shared
│ ├── constant
│ │ └── constants.ts
│ └── config
│ │ └── manifest.ts
├── app
│ ├── index.ts
│ └── app.impl.ts
├── entities
│ ├── loader
│ │ ├── index.ts
│ │ ├── interfaces
│ │ │ ├── assets.interface.ts
│ │ │ └── loader.interface.ts
│ │ └── loader.impl.ts
│ └── manager
│ │ ├── index.ts
│ │ ├── interfaces
│ │ ├── manager.interface.ts
│ │ ├── scene.interface.ts
│ │ └── application.interface.ts
│ │ └── manager.impl.ts
├── main.ts
└── style.css
├── public
├── logo
│ ├── pixi-logo.png
│ ├── ts-logo.png
│ └── vite-logo.png
└── sound
│ ├── sound-gif.gif
│ └── forklift-effect.wav
├── Dockerfile
├── .gitignore
├── index.html
├── package.json
├── tsconfig.json
└── README.md
/src/api/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/plugins/storage/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/ui/sprites/ts-logo.sprite.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/ui/sprites/vite-logo.sprite.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/ui/textures/ts-logo.texture.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/ui/textures/vite-logo.sprite.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/shared/constant/constants.ts:
--------------------------------------------------------------------------------
1 | export const FILL_COLOR = 0xffffff;
--------------------------------------------------------------------------------
/src/app/index.ts:
--------------------------------------------------------------------------------
1 | /** App-wide settings, styles and providers.
2 | *
3 | */
4 | export * from './app.impl';
--------------------------------------------------------------------------------
/public/logo/pixi-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbokirichenko/pixijs-typescript-vite-template/HEAD/public/logo/pixi-logo.png
--------------------------------------------------------------------------------
/public/logo/ts-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbokirichenko/pixijs-typescript-vite-template/HEAD/public/logo/ts-logo.png
--------------------------------------------------------------------------------
/public/logo/vite-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbokirichenko/pixijs-typescript-vite-template/HEAD/public/logo/vite-logo.png
--------------------------------------------------------------------------------
/public/sound/sound-gif.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbokirichenko/pixijs-typescript-vite-template/HEAD/public/sound/sound-gif.gif
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18
2 |
3 | WORKDIR /app
4 |
5 | COPY . /app
6 |
7 | RUN npm install
8 |
9 | ENTRYPOINT ["npm", "run", "dev", "--", "--host"]
--------------------------------------------------------------------------------
/public/sound/forklift-effect.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/turbokirichenko/pixijs-typescript-vite-template/HEAD/public/sound/forklift-effect.wav
--------------------------------------------------------------------------------
/src/entities/loader/index.ts:
--------------------------------------------------------------------------------
1 | export { LoaderImpl as Loader } from './loader.impl';
2 | export * from './interfaces/assets.interface';
3 | export * from './interfaces/loader.interface';
--------------------------------------------------------------------------------
/src/entities/manager/index.ts:
--------------------------------------------------------------------------------
1 | export { ManagerImpl as Manager }from './manager.impl';
2 | export * from './interfaces/application.interface';
3 | export * from './interfaces/scene.interface';
4 | export * from './interfaces/manager.interface';
--------------------------------------------------------------------------------
/src/ui/textures/pixi-logo.texture.ts:
--------------------------------------------------------------------------------
1 | import { PixiTexture } from "../../plugins/engine";
2 |
3 | export class PixiLogoTexture extends PixiTexture {
4 | constructor(source: string) {
5 | const baseTexture = PixiTexture.from(source);
6 | super(baseTexture);
7 | }
8 | }
--------------------------------------------------------------------------------
/src/ui/sprites/pixi-logo.sprite.ts:
--------------------------------------------------------------------------------
1 | import { PixiTexture, PixiSprite } from "../../plugins/engine";
2 |
3 | export class PixiLogoSprite extends PixiSprite {
4 | constructor(source: string) {
5 | const pixiTexture = PixiTexture.from(source);
6 | super(pixiTexture);
7 | }
8 | }
--------------------------------------------------------------------------------
/src/ui/containers/locaing-box.container.ts:
--------------------------------------------------------------------------------
1 | import { PixiContainer } from "../../plugins/engine";
2 |
3 | export class LoadingBoxContainer extends PixiContainer {
4 | constructor(parentWidth: number, parentHeight: number) {
5 | super();
6 |
7 | this.width = parentWidth;
8 | this.height = parentHeight;
9 | }
10 | }
--------------------------------------------------------------------------------
/src/entities/manager/interfaces/manager.interface.ts:
--------------------------------------------------------------------------------
1 | import { ApplicationInterface, StageInterface } from "./application.interface";
2 | import { SceneInterface } from "./scene.interface";
3 |
4 | export interface ManagerInterface {
5 | init(app: ApplicationInterface, stage: StageInterface): void;
6 | changeScene(newScene: SceneInterface): void;
7 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/src/entities/manager/interfaces/scene.interface.ts:
--------------------------------------------------------------------------------
1 | export interface SceneInterface {
2 | /** update scene
3 | *
4 | * @param framesPassed
5 | */
6 | update(framesPassed: number): void;
7 |
8 | /** resize scene
9 | *
10 | * @param screenWidth
11 | * @param screenHeight
12 | */
13 | resize(screenWidth: number, screenHeight: number): void;
14 |
15 | /**
16 | *
17 | */
18 | destroy(): void;
19 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pixijs-typescript-vite-template",
3 | "private": true,
4 | "version": "0.1.4",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "preview": "vite preview"
10 | },
11 | "devDependencies": {
12 | "typescript": "5.9.2",
13 | "vite": "6.3.6"
14 | },
15 | "dependencies": {
16 | "@pixi/gif": "3.0.1",
17 | "@pixi/sound": "6.0.1",
18 | "pixi.js": "8.13.2"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": ["ESNext", "DOM"],
7 | "moduleResolution": "Node",
8 | "strict": true,
9 | "resolveJsonModule": true,
10 | "isolatedModules": true,
11 | "esModuleInterop": true,
12 | "noEmit": true,
13 | "noUnusedLocals": true,
14 | "noUnusedParameters": true,
15 | "noImplicitReturns": true,
16 | "skipLibCheck": true
17 | },
18 | "include": ["src"]
19 | }
20 |
--------------------------------------------------------------------------------
/src/plugins/engine/index.ts:
--------------------------------------------------------------------------------
1 | import { Container, Sprite, Application, Texture, ApplicationOptions, Assets, BasisTexture, Graphics, Text } from 'pixi.js';
2 | import { SoundLibrary, Options } from '@pixi/sound';
3 |
4 | export { Container as PixiContainer };
5 | export { Sprite as PixiSprite };
6 | export { Application as PixiApplication };
7 | export { Texture as PixiTexture };
8 | export { Graphics as PixiGraphics };
9 | export type { BasisTexture as PixiBaseTexture };
10 | export type { ApplicationOptions as IPixiApplicationOptions };
11 | export { Assets as PixiAssets };
12 | export { Text as PixiText };
13 |
14 | export { SoundLibrary as PixiSoundLibrary };
15 | export type { Options as PixiSoundOptions };
--------------------------------------------------------------------------------
/src/shared/config/manifest.ts:
--------------------------------------------------------------------------------
1 | import type { LoaderOptions } from "../../entities/loader";
2 |
3 | export const options: LoaderOptions = {
4 | manifest: {
5 | bundles: [
6 | {
7 | name: "logo",
8 | assets: {
9 | "vite-logo": "logo/vite-logo.png",
10 | "ts-logo": "logo/ts-logo.png",
11 | "pixi-logo": "logo/pixi-logo.png"
12 | }
13 | },
14 | {
15 | name: "sound",
16 | assets: {
17 | "forklift-effect": "sound/forklift-effect.wav",
18 | "sound-gif": "sound/sound-gif.gif"
19 | }
20 | }
21 | ]
22 | }
23 | }
--------------------------------------------------------------------------------
/src/entities/loader/interfaces/assets.interface.ts:
--------------------------------------------------------------------------------
1 | import { LoaderOptions } from "./loader.interface";
2 | /** Callback function, take the number of the loading progress between 0 and 1;
3 | *
4 | */
5 | export type AssetsProgressCallback = (progress: number) => void
6 | /** Assets is static source of the project
7 | *
8 | */
9 | export interface AssetsInterface {
10 | /** assets inizialization
11 | *
12 | * @param options - assets parameters
13 | */
14 | init(options?: LoaderOptions | undefined): Promise;
15 |
16 | /** load bundle file
17 | *
18 | * @param data - deserialized assets names
19 | * @param onProgress - callback function to check the progress of the loading
20 | */
21 | loadBundle(data: string | string[], onProgress: AssetsProgressCallback): Promise;
22 | }
--------------------------------------------------------------------------------
/src/entities/loader/interfaces/loader.interface.ts:
--------------------------------------------------------------------------------
1 | /** loading callback, take the number between 0 and 1
2 | *
3 | */
4 | export type LoadingCallback = (progress: number) => void;
5 | /** a bundle object
6 | *
7 | */
8 | export interface LoaderBundle {
9 | name: string;
10 | assets: any;
11 | }
12 | /** the object contains bunldle sources
13 | *
14 | */
15 | export interface LoaderManifest {
16 | bundles: LoaderBundle[];
17 | }
18 | /** manifest options
19 | *
20 | */
21 | export interface LoaderOptions {
22 | manifest: LoaderManifest | undefined;
23 | };
24 | /** the entity allows to download bundle-assets for the project
25 | *
26 | */
27 | export interface LoaderInterface {
28 | /** downloading assets
29 | *
30 | * @param data - manifest file
31 | * @param onLoading - loading callback, take the number between 0 and 1
32 | */
33 | download(data: LoaderOptions, onLoading: LoadingCallback): Promise;
34 | }
--------------------------------------------------------------------------------
/src/app/app.impl.ts:
--------------------------------------------------------------------------------
1 | import { PixiApplication, IPixiApplicationOptions } from '../plugins/engine';
2 | import { ApplicationInterface, StageInterface, PanelInterface, TickerInterface } from '../entities/manager';
3 |
4 | export class App implements ApplicationInterface {
5 | private _app: PixiApplication;
6 | ticker?: TickerInterface;
7 | stage?: StageInterface;
8 | panel: PanelInterface;
9 |
10 | constructor() {
11 | // create application
12 | this._app = new PixiApplication();
13 |
14 | // set pixi panel
15 | const pixiPanel: PanelInterface = {
16 | resize: (fn: () => void) => {
17 | window.addEventListener("resize", fn);
18 | }
19 | }
20 | this.panel = pixiPanel;
21 | };
22 |
23 | public async init>(options: T): Promise {
24 | await this._app.init(options!);
25 |
26 | // set stage and ticker
27 | this.ticker = this._app.ticker;
28 | this.stage = this._app.stage;
29 | };
30 | }
--------------------------------------------------------------------------------
/src/entities/loader/loader.impl.ts:
--------------------------------------------------------------------------------
1 | import { AssetsInterface } from "./interfaces/assets.interface";
2 | import { LoaderInterface, LoaderOptions, LoadingCallback } from "./interfaces/loader.interface";
3 |
4 | /** Loader entity, to load assets for gameplay
5 | *
6 | */
7 | export class LoaderImpl implements LoaderInterface {
8 | private readonly _assets: AssetsInterface;
9 |
10 | private _isLoaded: boolean;
11 | get isLoaded() {
12 | return this._isLoaded;
13 | }
14 |
15 | constructor(assets: AssetsInterface) {
16 | this._assets = assets;
17 | this._isLoaded = false;
18 | }
19 |
20 | async download(data: LoaderOptions, onLoading: LoadingCallback): Promise {
21 | if (this._isLoaded) {
22 | return;
23 | }
24 | if (!data.manifest) {
25 | return;
26 | }
27 | await this._assets.init(data);
28 | const ids = data.manifest.bundles.map(bundle => bundle.name);
29 | await this._assets.loadBundle(ids, onLoading);
30 | this._isLoaded = true;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/ui/scenes/loader.scene.ts:
--------------------------------------------------------------------------------
1 | import { PixiContainer } from "../../plugins/engine";
2 | import { Manager, SceneInterface } from "../../entities/manager";
3 | import { LoadingBarContainer } from "../containers/loading-bar.container";
4 |
5 | export class LoaderScene extends PixiContainer implements SceneInterface {
6 |
7 | private _loadingBar: LoadingBarContainer;
8 | constructor() {
9 | super();
10 | const parentWidth = Manager.width;
11 | const parentHeight = Manager.height;
12 |
13 | const loaderBarWidth = 280;
14 | this._loadingBar = new LoadingBarContainer(loaderBarWidth, parentWidth, parentHeight);
15 | this.addChild(this._loadingBar);
16 | }
17 |
18 | progressCallback(progress: number): void {
19 | this._loadingBar.scaleProgress(progress);
20 | }
21 |
22 | update(_framesPassed: number): void {}
23 | resize(screenWidth: number, screenHeight: number): void {
24 | this.width = screenWidth;
25 | this.height = screenHeight;
26 | this._loadingBar.resize(screenWidth, screenHeight);
27 | }
28 | }
--------------------------------------------------------------------------------
/src/entities/manager/interfaces/application.interface.ts:
--------------------------------------------------------------------------------
1 | export interface StageInterface {
2 | /** add one or several children
3 | *
4 | * @param children
5 | */
6 | addChild(...children: T): T[0];
7 |
8 | /** remove one or several children
9 | *
10 | * @param children
11 | */
12 | removeChild(...children: T): T[0];
13 | }
14 |
15 | export interface TickerInterface {
16 | /** add update function to the ticker
17 | *
18 | * @param fn
19 | * @param context
20 | */
21 | add(fn: (framesPassed: any) => void, context?: any): TickerInterface
22 | }
23 |
24 | export type ResizeCallback = () => void;
25 | export interface PanelInterface {
26 | /** function that up the resize callback
27 | *
28 | */
29 | resize: (fn: ResizeCallback) => void
30 | }
31 |
32 | export interface ApplicationInterface {
33 | /** time ticker
34 | *
35 | */
36 | ticker?: TickerInterface;
37 |
38 | /** stage of scene
39 | *
40 | */
41 | stage?: StageInterface;
42 |
43 | /** panel with emitter
44 | *
45 | */
46 | panel: PanelInterface;
47 |
48 | /** set initial state of the application
49 | *
50 | * @returns
51 | */
52 | init: (options: T) => Promise
53 | }
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import './style.css';
2 | import '@pixi/gif';
3 | import { App } from './app';
4 | import { FILL_COLOR } from './shared/constant/constants';
5 | import { Manager } from './entities/manager';
6 | import { IPixiApplicationOptions, PixiAssets } from './plugins/engine';
7 | import { Loader } from './entities/loader';
8 | import { options } from './shared/config/manifest';
9 | import { LoaderScene } from './ui/scenes/loader.scene';
10 | import { GameScene } from './ui/scenes/game.scene';
11 |
12 | const boostsrap = async () => {
13 | const canvas = document.getElementById("pixi-screen") as HTMLCanvasElement;
14 | const resizeTo = window;
15 | const resolution = window.devicePixelRatio || 1;
16 | const autoDensity = true;
17 | const backgroundColor = FILL_COLOR;
18 | const appOptions: Partial = {
19 | canvas,
20 | resizeTo,
21 | resolution,
22 | autoDensity,
23 | backgroundColor
24 | }
25 |
26 | const application = new App();
27 | await application.init(appOptions);
28 |
29 | Manager.init(application);
30 | const loader = new Loader(PixiAssets);
31 | const loaderScene = new LoaderScene();
32 | Manager.changeScene(loaderScene);
33 | loader.download(options, loaderScene.progressCallback.bind(loaderScene)).then(() => {
34 | Manager.changeScene(new GameScene());
35 | });
36 | }
37 |
38 | boostsrap();
39 |
--------------------------------------------------------------------------------
/src/entities/manager/manager.impl.ts:
--------------------------------------------------------------------------------
1 | import { ApplicationInterface } from "./interfaces/application.interface";
2 | import { SceneInterface } from "./interfaces/scene.interface";
3 |
4 | export class ManagerImpl {
5 | constructor() {};
6 | private static _app?: ApplicationInterface = undefined;
7 | private static _currentScene?: SceneInterface = undefined;
8 |
9 | public static get width() {
10 | return Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
11 | }
12 |
13 | public static get height() {
14 | return Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
15 | }
16 |
17 | static init(app: ApplicationInterface): void {
18 | ManagerImpl._app = app;
19 | ManagerImpl._app.panel.resize(ManagerImpl.resize);
20 | ManagerImpl._app.ticker?.add(ManagerImpl.update);
21 | }
22 |
23 | static changeScene(newScene: SceneInterface): void {
24 | if (ManagerImpl._currentScene) {
25 | ManagerImpl._app?.stage?.removeChild(ManagerImpl._currentScene);
26 | ManagerImpl._currentScene.destroy();
27 | }
28 |
29 | // Add the new one
30 | ManagerImpl._currentScene = newScene;
31 | ManagerImpl._app?.stage?.addChild(ManagerImpl._currentScene);
32 | }
33 |
34 | private static update(framesPassed: number): void {
35 | if (ManagerImpl._currentScene) {
36 | ManagerImpl._currentScene.update(framesPassed);
37 | }
38 | }
39 |
40 | private static resize(): void {
41 | // if we have a scene, we let it know that a resize happened!
42 | if (ManagerImpl._currentScene) {
43 | ManagerImpl._currentScene.resize(ManagerImpl.width, ManagerImpl.height);
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3 | line-height: 1.5;
4 | font-weight: 400;
5 |
6 | color-scheme: light dark;
7 | color: rgba(255, 255, 255, 0.87);
8 | background-color: #242424;
9 |
10 | font-synthesis: none;
11 | text-rendering: optimizeLegibility;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | -webkit-text-size-adjust: 100%;
15 | }
16 |
17 | a {
18 | font-weight: 500;
19 | color: #646cff;
20 | text-decoration: inherit;
21 | }
22 | a:hover {
23 | color: #535bf2;
24 | }
25 |
26 | body {
27 | margin: 0;
28 | display: flex;
29 | place-items: center;
30 | min-width: 320px;
31 | min-height: 100vh;
32 | }
33 |
34 | h1 {
35 | font-size: 3.2em;
36 | line-height: 1.1;
37 | }
38 |
39 | #app {
40 | max-width: 100%;
41 | margin: 0 auto;
42 | text-align: center;
43 | min-height: 100vh;
44 | }
45 |
46 | #pixi-screen {
47 | position: fixed;
48 | top:0;
49 | left:0;
50 | bottom: 0;
51 | right: 0;
52 | width: 100%;
53 | height: 100%;
54 | }
55 |
56 | .logo {
57 | height: 6em;
58 | padding: 1.5em;
59 | will-change: filter;
60 | transition: filter 300ms;
61 | }
62 | .logo:hover {
63 | filter: drop-shadow(0 0 2em #646cffaa);
64 | }
65 | .logo.vanilla:hover {
66 | filter: drop-shadow(0 0 2em #3178c6aa);
67 | }
68 |
69 | .card {
70 | padding: 2em;
71 | }
72 |
73 | .read-the-docs {
74 | color: #888;
75 | }
76 |
77 | button {
78 | border-radius: 8px;
79 | border: 1px solid transparent;
80 | padding: 0.6em 1.2em;
81 | font-size: 1em;
82 | font-weight: 500;
83 | font-family: inherit;
84 | background-color: #1a1a1a;
85 | cursor: pointer;
86 | transition: border-color 0.25s;
87 | }
88 | button:hover {
89 | border-color: #646cff;
90 | }
91 | button:focus,
92 | button:focus-visible {
93 | outline: 4px auto -webkit-focus-ring-color;
94 | }
95 |
96 | @media (prefers-color-scheme: light) {
97 | :root {
98 | color: #213547;
99 | background-color: #ffffff;
100 | }
101 | a:hover {
102 | color: #747bff;
103 | }
104 | button {
105 | background-color: #f9f9f9;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/ui/containers/loading-bar.container.ts:
--------------------------------------------------------------------------------
1 | import { Graphics, Container } from "pixi.js";
2 | // import { PixiContainer } from "../../plugins/engine";
3 |
4 | export class LoadingBarContainer extends Container {
5 | private _loaderBar: Container;
6 | private _loaderBarBorder: Graphics;
7 | private _loaderProgress?: Graphics;
8 | private _barWidth: number;
9 | private _barHeight: number;
10 |
11 | constructor(barWidth: number, parentWidth: number, parentHeight: number) {
12 | super();
13 | this._barWidth = barWidth;
14 | this._barHeight = 48;
15 |
16 | this._loaderBarBorder = new Graphics();
17 |
18 | const lineWidth = 4;
19 | const lineColor = 0x000000;
20 | const barPosX = 0;
21 | const barPosY = 0;
22 | this._loaderBarBorder
23 | .rect(barPosX, barPosY, this._barWidth + 6, this._barHeight)
24 | .stroke({ width: lineWidth, color: lineColor })
25 |
26 | this._loaderBar = new Container();
27 | this._loaderBar.addChild(this._loaderBarBorder);
28 | this._loaderBar.position.x = (parentWidth - this._loaderBar.width) / 2;
29 | this._loaderBar.position.y = (parentHeight - this._loaderBar.height) / 2;
30 | this.addChild(this._loaderBar);
31 | }
32 |
33 | public scaleProgress(progress: number) {
34 | if (this._loaderProgress) {
35 | this._loaderBar.removeChild(this._loaderProgress);
36 | this._loaderProgress.destroy();
37 | }
38 | this._loaderProgress = this.makeRect(progress);
39 | this._loaderBar.addChild(this._loaderProgress);
40 | }
41 |
42 | resize(width: number, height: number) {
43 | this._loaderBar.position.x = (width - this._loaderBar.width) / 2;
44 | this._loaderBar.position.y = (height - this._loaderBar.height) / 2;
45 | }
46 |
47 | /**
48 | *
49 | * @param progress:number - line of loading the progress from 0.0 to 1.0
50 | * @returns rect:Graphics - drawing objects of pixi that fill the bar
51 | */
52 | private makeRect(progress: number): Graphics {
53 | const percentLines = Math.floor((progress*100)/10);
54 | const padding = 6;
55 | const pieceWidth = this._barWidth/10 - padding;
56 | const rect = new Graphics();
57 |
58 | //rect dimentions
59 | const rectPositionX = (i:number) => padding*(i+1) + pieceWidth*i;
60 | const rectPositionY = padding;
61 | const rectWidth = pieceWidth;
62 | const rectHeight = this._barHeight - 2*padding;
63 |
64 | // fill loading bar
65 | for (let i = 0; i < percentLines; ++i) {
66 | rect
67 | .rect(
68 | rectPositionX(i),
69 | rectPositionY,
70 | rectWidth,
71 | rectHeight
72 | )
73 | .fill(0xffff00 - i*0x001100);
74 | }
75 | return rect;
76 | }
77 | }
--------------------------------------------------------------------------------
/src/ui/scenes/game.scene.ts:
--------------------------------------------------------------------------------
1 | import { PixiContainer, PixiSprite, PixiSoundLibrary, PixiText } from "../../plugins/engine";
2 | import { Manager, SceneInterface } from "../../entities/manager";
3 | import { Assets } from "pixi.js";
4 |
5 | export class GameScene extends PixiContainer implements SceneInterface {
6 | // you may remove all of these variables
7 | private _viteLogo: PixiSprite;
8 | private _tsLogo: PixiSprite;
9 | private _pixiLogo: PixiSprite;
10 | private _sound: PixiSoundLibrary;
11 | private _soundLogo: PixiSprite;
12 | private _pixiText: PixiText;
13 |
14 | constructor() {
15 | super();
16 | this.interactive = true;
17 | this.position.x = 0;
18 | this.position.y = 0;
19 | const parentWidth = Manager.width;
20 | const parentHeight = Manager.height;
21 |
22 | // you may remove all of these
23 | this._viteLogo = PixiSprite.from("vite-logo");
24 | this._viteLogo.anchor.set(0.5);
25 | this._viteLogo.width = 50;
26 | this._viteLogo.height = 50;
27 | this._viteLogo.position.x = parentWidth/2 - 120;
28 | this._viteLogo.position.y = parentHeight/2;
29 |
30 | this._pixiLogo = PixiSprite.from("pixi-logo");
31 | this._pixiLogo.anchor.set(0.5);
32 | this._pixiLogo.width = 128;
33 | this._pixiLogo.height = 50;
34 | this._pixiLogo.position.x = parentWidth/2;
35 | this._pixiLogo.position.y = parentHeight/2;
36 |
37 | this._tsLogo = PixiSprite.from("ts-logo");
38 | this._tsLogo.anchor.set(0.5);
39 | this._tsLogo.width = 50;
40 | this._tsLogo.height = 50;
41 | this._tsLogo.position.x = parentWidth/2 + 120;
42 | this._tsLogo.position.y = parentHeight/2;
43 |
44 | this._pixiText = new PixiText({
45 | text: 'Click on icon!',
46 | style: {
47 | fontFamily: 'Arial',
48 | fontSize: 24,
49 | fill: 0xff1010,
50 | align: 'center',
51 | }
52 | })
53 | this._pixiText.anchor.set(0.5);
54 | this._pixiText.position.x = parentWidth/2;
55 | this._pixiText.position.y = parentHeight/2 + 60;
56 |
57 | this._soundLogo = PixiSprite.from("sound-gif");
58 | this._soundLogo.anchor.set(0.5);
59 | this._soundLogo.position.x = 80;
60 | this._soundLogo.position.y = 60;
61 |
62 | this._sound = new PixiSoundLibrary();
63 | this._sound.add("forklift-effect", Assets.get("forklift-effect"));
64 | this._sound.disableAutoPause = true;
65 | this.on("pointerdown", () => {
66 | this._sound.play("forklift-effect");
67 | })
68 | this.addChild(this._viteLogo, this._tsLogo, this._pixiLogo, this._pixiText, this._soundLogo);
69 | }
70 |
71 | update(_framesPassed: number): void {
72 | this._soundLogo.visible = this._sound.isPlaying() ? true : false;
73 | }
74 |
75 | resize(parentWidth: number, parentHeight: number): void {
76 | this._viteLogo.position.x = parentWidth/2 - 120;
77 | this._viteLogo.position.y = parentHeight/2;
78 |
79 | this._pixiLogo.position.x = parentWidth/2;
80 | this._pixiLogo.position.y = parentHeight/2;
81 |
82 | this._tsLogo.position.x = parentWidth/2 + 120;
83 | this._tsLogo.position.y = parentHeight/2;
84 |
85 | this._pixiText.position.x = parentWidth/2;
86 | this._pixiText.position.y = parentHeight/2 + 60;
87 | }
88 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Pixi JS + Typescript + Vite template
2 |
3 | ### A template that combines the power of typescript and efficiency of pixi.js!
4 |
5 | **For clean code dvelopment**
6 |
7 | :white_check_mark: pixi `version 8` \
8 | :white_check_mark: vanilla typescript \
9 | :white_check_mark: for game development
10 |
11 | ### Tags
12 |
13 | #### `0.1.x`
14 |
15 | **Compatible with pixi.js `v8.x`**
16 |
17 | > template is uses modern version of pixi.js \
18 | > this template is **not** compatible with old pixi libs as pixi/layers and pixi/lights
19 |
20 | #### `0.0.x`
21 |
22 | **Compatible with pixi.js `v7.x`**
23 |
24 | > if you prefer to using old pixi libs as @pixi/layers or @pixi/lights \
25 | > I recommended you use this template with version `0.0.x`
26 |
27 | `0.0.x` tags are also compatible with libraries:
28 |
29 | - pixi/layers
30 | - pixi/lights
31 |
32 | ### Branches
33 |
34 | - `main` or `template-pixi8/stable` is stable version of pixi8 template
35 |
36 | - `template-pixi8/dev` is branch of pixi v8.x template development
37 |
38 | - `template-pixi7/stable` is stable version of pixi v7.x template
39 |
40 | - `template-pixi7/dev` is branch of pixi7 template development
41 |
42 | ### Folder Structure
43 |
44 | ```sh
45 | \public # for static content
46 | \src # source code
47 | \api # for external api
48 | \app # app bootstrap
49 | \entities # logical entities (user, admin, ...)
50 | \plugins # used plugins (store, pixi, axios, ...)
51 | \engine # pixi.js classes
52 | \storage # game internal storage
53 | \web # browser api
54 | \shared # shared libs (configs, global constants, utils, ...)
55 | \configs
56 | manifest.ts # pixi.js manifest config
57 | \constants
58 | \utils
59 | \ui # pixi.js user interfaces
60 | \animations
61 | \containers
62 | \scenes
63 | \sprites
64 | \textures
65 | main.ts # entrypoint
66 | ```
67 |
68 | ### Architecture
69 |
70 | > The solution uses the **MVP** design \
71 | > This means that the logic of the application must **be independent** of the user interface
72 |
73 | 1. **Entities** \
74 | main logic of app
75 | 2. **Plugins** \
76 | core modules that used entities
77 | 3. **Shared** \
78 | libs, config, utils, ...
79 | 4. **UI** \
80 | views
81 |
82 | ```
83 |
84 | (Entities) <-- (Plugins) <-- (Shared) <-- (UI) <-- (Shared | AppBootstrap)
85 |
86 | ```
87 |
88 | ### Quick start
89 |
90 | **intsllation**
91 |
92 | ```bash
93 | $ cd pixijs-typescript-vite-template
94 | $ npm install
95 | $ npm run dev -- --host
96 | ```
97 |
98 | **build**
99 |
100 | ```
101 | $ npm run build
102 | ```
103 |
104 | ### Docker
105 |
106 | ```bash
107 | $ cd pixijs-typescript-vite-template
108 | $ docker build -t pixi-template .
109 | $ docker run --name pixi-container -p 5173:5173 pixi-template
110 | ```
111 |
112 | ### Installed deps
113 |
114 | **dependencies**
115 |
116 | - pixi.js
117 | - @pixi/sound
118 | - @pixi/gif
119 |
120 | **dev-dependencies**
121 |
122 | - typescript
123 | - vite
124 |
125 | ### Requirements
126 |
127 | :white_check_mark: **OS** `Linux`, `win32`, `macOS` \
128 | :white_check_mark: **NodeJS** `^18.x`
129 |
130 | #### Source
131 |
132 | [pixi elementals](https://www.pixijselementals.com/#before-we-even-start) \
133 | [pixi js official website](https://pixijs.com/) \
134 | [vite guide](https://vitejs.dev/guide/) \
135 | [typescript handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
136 |
--------------------------------------------------------------------------------