├── src ├── react-app-env.d.ts ├── setupTests.ts ├── App.test.tsx ├── index.css ├── reportWebVitals.ts ├── PhaserGame.ts ├── index.tsx ├── App.css ├── scenes │ └── HelloWorldScene.ts ├── App.tsx └── logo.svg ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── .gitignore ├── tsconfig.json ├── LICENSE ├── package.json └── README.md /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinshen56714/create-react-phaser3-app/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinshen56714/create-react-phaser3-app/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinshen56714/create-react-phaser3-app/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom' 6 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render, screen } from '@testing-library/react' 3 | import App from './App' 4 | 5 | test('renders learn react link', () => { 6 | render() 7 | const linkElement = screen.getByText(/learn react/i) 8 | expect(linkElement).toBeInTheDocument() 9 | }) 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 11 | } 12 | 13 | canvas { 14 | display: block; 15 | } 16 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals' 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry) 7 | getFID(onPerfEntry) 8 | getFCP(onPerfEntry) 9 | getLCP(onPerfEntry) 10 | getTTFB(onPerfEntry) 11 | }) 12 | } 13 | } 14 | 15 | export default reportWebVitals 16 | -------------------------------------------------------------------------------- /src/PhaserGame.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser' 2 | 3 | import HelloWorldScene from './scenes/HelloWorldScene' 4 | 5 | const config: Phaser.Types.Core.GameConfig = { 6 | type: Phaser.AUTO, 7 | parent: 'phaser-container', 8 | backgroundColor: '#282c34', 9 | scale: { 10 | mode: Phaser.Scale.ScaleModes.RESIZE, 11 | width: window.innerWidth, 12 | height: window.innerHeight, 13 | }, 14 | physics: { 15 | default: 'arcade', 16 | arcade: { 17 | gravity: { y: 200 }, 18 | }, 19 | }, 20 | scene: [HelloWorldScene], 21 | } 22 | 23 | export default new Phaser.Game(config) 24 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import './index.css' 4 | import App from './App' 5 | import reportWebVitals from './reportWebVitals' 6 | 7 | import './PhaserGame' 8 | 9 | ReactDOM.render( 10 | 11 | 12 | , 13 | document.getElementById('root') 14 | ) 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals() 20 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | position: absolute; 4 | height: 100%; 5 | width: 100%; 6 | } 7 | 8 | .App-logo { 9 | height: 40vmin; 10 | pointer-events: none; 11 | } 12 | 13 | @media (prefers-reduced-motion: no-preference) { 14 | .App-logo { 15 | animation: App-logo-spin infinite 20s linear; 16 | } 17 | } 18 | 19 | .App-header { 20 | background-color: #282c3400; 21 | min-height: 100vh; 22 | display: flex; 23 | flex-direction: column; 24 | align-items: center; 25 | justify-content: center; 26 | font-size: calc(10px + 2vmin); 27 | color: white; 28 | } 29 | 30 | .App-link { 31 | color: #61dafb; 32 | } 33 | 34 | .App-button { 35 | font-size: calc(10px + 1vmin); 36 | cursor: pointer; 37 | margin-top: 20px; 38 | } 39 | 40 | @keyframes App-logo-spin { 41 | from { 42 | transform: rotate(0deg); 43 | } 44 | to { 45 | transform: rotate(360deg); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/scenes/HelloWorldScene.ts: -------------------------------------------------------------------------------- 1 | import Phaser from 'phaser' 2 | 3 | export default class HelloWorldScene extends Phaser.Scene { 4 | constructor() { 5 | super('helloworld') 6 | } 7 | 8 | preload() { 9 | this.load.setBaseURL('https://labs.phaser.io') 10 | 11 | this.load.image('logo', 'assets/sprites/phaser3-logo.png') 12 | this.load.image('red', 'assets/particles/red.png') 13 | } 14 | 15 | create() { 16 | this.createEmitter() 17 | } 18 | 19 | createEmitter() { 20 | const particles = this.add.particles('red') 21 | 22 | const emitter = particles.createEmitter({ 23 | speed: 100, 24 | scale: { start: 1, end: 0 }, 25 | blendMode: 'ADD', 26 | }) 27 | 28 | const logo = this.physics.add.image(400, 100, 'logo') 29 | 30 | logo.setVelocity(100, 200) 31 | logo.setBounce(1, 1) 32 | logo.setCollideWorldBounds(true) 33 | 34 | emitter.startFollow(logo) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import logo from './logo.svg' 3 | import './App.css' 4 | import phaserGame from './PhaserGame' 5 | import HelloWorldScene from './scenes/HelloWorldScene' 6 | 7 | const handleClick = () => { 8 | const scene = phaserGame.scene.keys.helloworld as HelloWorldScene 9 | scene.createEmitter() 10 | } 11 | 12 | function App() { 13 | return ( 14 |
15 |
16 | logo 17 |

Just a vanilla create-react-app overlaying a Phaser canvas :)

18 | 24 | View Source 25 | 26 | 29 |
30 |
31 | ) 32 | } 33 | 34 | export default App 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Kuan-Hsuan (Kevin) Shen 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. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-react-phaser3-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.14.1", 7 | "@testing-library/react": "^12.0.0", 8 | "@testing-library/user-event": "^13.2.1", 9 | "@types/jest": "^27.0.1", 10 | "@types/node": "^16.7.13", 11 | "@types/react": "^17.0.20", 12 | "@types/react-dom": "^17.0.9", 13 | "phaser": "^3.55.2", 14 | "react": "^17.0.2", 15 | "react-dom": "^17.0.2", 16 | "react-scripts": "5.0.0", 17 | "typescript": "^4.4.2", 18 | "web-vitals": "^2.1.0" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test", 24 | "eject": "react-scripts eject" 25 | }, 26 | "eslintConfig": { 27 | "extends": [ 28 | "react-app", 29 | "react-app/jest" 30 | ] 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phaser 3 + Create React App template 2 | ![image](https://user-images.githubusercontent.com/11501902/149049053-f46a9d1e-7075-4258-9102-cdbcbe7198ba.png) 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## What's included? - [Check the preview](https://create-react-phaser3-app.netlify.app/) 6 | 7 | - [Phaser 3](https://github.com/photonstorm/phaser) - overlaid canvas with the config in `src/PhaserGame.ts` and a scene in `src/scenes/` 8 | - [Create React App](https://github.com/facebook/create-react-app) - React, TSX, ES6, TypeScript, no need to install bundler, ...etc 9 | - An example button in `src/App.tsx` showing how to communicate with Phaser within a React component 10 | - That's it! 11 | ## Getting started 12 | 13 | Clone the project and in the project directory, you can run: 14 | 15 | ### `yarn install` or `npm install` 16 | 17 | Install all the packages in `create react app` + Phaser 3 18 | 19 | ### `yarn start` or `npm run start` 20 | 21 | Runs the app in the development mode.\ 22 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 23 | 24 | ### `yarn build` or `npm run build` 25 | 26 | Builds the app for production to the `build` folder.\ 27 | It correctly bundles React in production mode and optimizes the build for the best performance. 28 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 24 | React App 25 | 26 | 27 | 28 |
29 |
30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------