├── src
├── vite-env.d.ts
├── game
│ ├── assets
│ │ ├── bomb.png
│ │ ├── sky.png
│ │ └── thud.mp3
│ ├── scenes
│ │ ├── BootScene.ts
│ │ └── PlayScene.ts
│ └── game.ts
├── main.ts
├── App.vue
└── components
│ ├── Game.vue
│ └── PhaserContainer.vue
├── tsconfig.json
├── .gitignore
├── vite.config.ts
├── index.html
├── tsconfig.app.json
├── tsconfig.node.json
├── package.json
├── LICENSE
├── public
└── vite.svg
└── README.md
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/src/game/assets/bomb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sun0fABeach/vue-phaser-vite/HEAD/src/game/assets/bomb.png
--------------------------------------------------------------------------------
/src/game/assets/sky.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sun0fABeach/vue-phaser-vite/HEAD/src/game/assets/sky.png
--------------------------------------------------------------------------------
/src/game/assets/thud.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sun0fABeach/vue-phaser-vite/HEAD/src/game/assets/thud.mp3
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfig.app.json" },
5 | { "path": "./tsconfig.node.json" }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
18 |
--------------------------------------------------------------------------------
/.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 | .idea
18 | .DS_Store
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { fileURLToPath, URL } from 'node:url'
2 | import { defineConfig } from 'vite'
3 | import vue from '@vitejs/plugin-vue'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [vue()],
8 | resolve: {
9 | alias: {
10 | '@': fileURLToPath(new URL('./src', import.meta.url))
11 | }
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vue + Phaser + Vite
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/components/Game.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Downloading ...
12 |
13 |
14 |
15 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/src/components/PhaserContainer.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@vue/tsconfig/tsconfig.dom.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@/*": ["./src/*"],
6 | },
7 |
8 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
9 |
10 | /* Linting */
11 | "strict": true,
12 | "noUnusedLocals": true,
13 | "noUnusedParameters": true,
14 | "noFallthroughCasesInSwitch": true,
15 | "noUncheckedSideEffectImports": true
16 | },
17 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
18 | }
19 |
--------------------------------------------------------------------------------
/src/game/scenes/BootScene.ts:
--------------------------------------------------------------------------------
1 | import { Scene } from 'phaser'
2 | import sky from '@/game/assets/sky.png'
3 | import bomb from '@/game/assets/bomb.png'
4 | import thud from '@/game/assets/thud.mp3'
5 |
6 | export default class BootScene extends Scene {
7 | constructor () {
8 | super({ key: 'BootScene' })
9 | }
10 |
11 | preload () {
12 | this.load.image('sky', sky)
13 | this.load.image('bomb', bomb)
14 | this.load.audio('thud', thud)
15 | }
16 |
17 | create () {
18 | this.scene.start('PlayScene')
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/game/game.ts:
--------------------------------------------------------------------------------
1 | import Phaser from 'phaser'
2 | import BootScene from '@/game/scenes/BootScene'
3 | import PlayScene from '@/game/scenes/PlayScene'
4 |
5 | function launch(containerId: string) {
6 | return new Phaser.Game({
7 | type: Phaser.AUTO,
8 | width: 800,
9 | height: 600,
10 | parent: containerId,
11 | physics: {
12 | default: 'arcade',
13 | arcade: {
14 | gravity: { x: 0, y: 300 },
15 | debug: false
16 | }
17 | },
18 | scene: [BootScene, PlayScene]
19 | })
20 | }
21 |
22 | export default launch
23 | export { launch }
24 |
--------------------------------------------------------------------------------
/src/game/scenes/PlayScene.ts:
--------------------------------------------------------------------------------
1 | import { Scene } from 'phaser'
2 |
3 | export default class PlayScene extends Scene {
4 | constructor () {
5 | super({ key: 'PlayScene' })
6 | }
7 |
8 | create () {
9 | this.add.image(400, 300, 'sky')
10 |
11 | const bomb = this.physics.add.image(400, 200, 'bomb')
12 | bomb.setCollideWorldBounds(true)
13 | bomb.body.onWorldBounds = true // enable worldbounds collision event
14 | bomb.setBounce(1)
15 | bomb.setVelocity(200, 20)
16 |
17 | this.sound.add('thud')
18 | this.physics.world.on('worldbounds', () => {
19 | this.sound.play('thud', { volume: 0.75 })
20 | })
21 | }
22 |
23 | update () {
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4 | "target": "ES2022",
5 | "lib": ["ES2023"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 |
16 | /* Linting */
17 | "strict": true,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": true,
20 | "noFallthroughCasesInSwitch": true,
21 | "noUncheckedSideEffectImports": true
22 | },
23 | "include": ["vite.config.ts"]
24 | }
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-phaser-vite",
3 | "version": "1.1.0",
4 | "author": "Markus Appel ",
5 | "description": "Template for working with Phaser in a Vue project based on Vite",
6 | "keywords": [
7 | "vue",
8 | "phaser",
9 | "vite",
10 | "boilerplate",
11 | "template"
12 | ],
13 | "license": "MIT",
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/Sun0fABeach/vue-phaser-vite.git"
17 | },
18 | "type": "module",
19 | "scripts": {
20 | "dev": "vite",
21 | "build": "vue-tsc -b && vite build",
22 | "preview": "vite preview"
23 | },
24 | "dependencies": {
25 | "phaser": "^3.90.0",
26 | "vue": "^3.5.17"
27 | },
28 | "devDependencies": {
29 | "@types/node": "^24.1.0",
30 | "@vitejs/plugin-vue": "^6.0.0",
31 | "@vue/tsconfig": "^0.7.0",
32 | "typescript": "^5.8.3",
33 | "vite": "^7.0.5",
34 | "vue-tsc": "^3.0.3"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Markus Appel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-phaser-vite
2 |
3 | #### Vite boilerplate that integrates Phaser 3 into a Vue 3 project.
4 |
5 | This project template has been set up using **Vite** and includes:
6 | * *Typescript*
7 | * *Code Splitting*
8 | * *Source Minification*
9 | * *CSS Postprocessing*
10 |
11 | ## Build Setup
12 |
13 | ``` bash
14 | # install dependencies
15 | npm install
16 |
17 | # serve with live reloading on localhost
18 | npm run dev
19 |
20 | # build for production
21 | npm run build
22 |
23 | # serve your production build on localhost
24 | npm run preview
25 | ```
26 |
27 | ## Extending the project to your needs
28 |
29 | If you want to add more features like *linting*, *unit testing* or *SCSS* to
30 | your own project, you can do so quite easily with Vite. Read the
31 | documentation to get
32 | familiar with the tool. Also take a look at
33 |
34 | awesome-vite for plugins and more.
35 |
36 | ## Converting into your own repository
37 |
38 | If you want to maintain your own repo based on this boilerplate, you first need
39 | to detach it from this repo. Here is what you need to do:
40 |
41 | 1. edit these files and enter your own project info
42 | * *package.json*
43 | * *README.md*
44 | * *index.html*
45 |
46 | 2. delete *LICENSE* (and perhaps add your own)
47 |
48 | 3. reinitialize git
49 | rm -rf .git
50 | git init
51 | git add .
52 | git commit -m "Initial commit"
53 |
54 |
55 | ## Sharing data between Vue and Phaser
56 |
57 | You might want to expose some game state that lives inside of your Phaser code
58 | to your Vue components and vice versa, for example a highscore. Here are two
59 | ways you can achieve sharing state between the frameworks.
60 |
61 | * Import a Phaser EventEmitter instance in
62 | both your Vue components and Phaser modules. Both sides can then listen to and
63 | emit events on that emitter.
64 |
65 | * Have both sides share a
66 | Pinia store instance. It works like an event emitter, but can also hold
67 | state. The Pinia store is nicely integrated into your Vue components and is easily
68 | accessible on the Phaser side by applying the *useStore* hook.
69 |
--------------------------------------------------------------------------------