├── 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 | --------------------------------------------------------------------------------