├── .gitignore ├── .prettierrc.json ├── .vscode └── settings.json ├── README.md ├── assets ├── assets.tps ├── disabled.png ├── down.png ├── hover.png ├── normal.png ├── small-down.png ├── small-hover.png ├── small-normal.png └── star-sprite.jpg ├── package.json ├── public ├── favicon.ico ├── images │ ├── assets.json │ ├── assets.png │ └── background.png ├── index.html ├── manifest.json └── robots.txt ├── src ├── App.scss ├── App.test.tsx ├── App.tsx ├── Theme │ ├── Button.ts │ ├── Theme.ts │ └── Typography.ts ├── Utils │ ├── History.ts │ ├── Particles.ts │ ├── PhaserConfig.ts │ ├── RotateOverlay.ts │ ├── Store.ts │ ├── UIUtils.ts │ └── constants.ts ├── actions │ └── index.ts ├── components │ ├── Business │ │ ├── BusinessScene.ts │ │ └── UpgradeBusiness.ts │ ├── Managers │ │ └── ManagerScene.ts │ ├── game │ │ ├── Button.ts │ │ ├── GameScene.ts │ │ ├── GameView.tsx │ │ ├── PreloaderScene.ts │ │ └── index.ts │ └── ui │ │ └── CurrentScore │ │ ├── CurrentScoreView.tsx │ │ └── index.tsx ├── index.scss ├── index.tsx ├── logo.svg ├── react-app-env.d.ts ├── reducers │ ├── Business.ts │ ├── CurrentScore.ts │ ├── Managers.ts │ └── index.ts └── serviceWorker.ts ├── tsconfig.json └── yarn.lock /.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 | 25 | .yarn/* 26 | !.yarn/releases 27 | !.yarn/plugins 28 | .pnp.* -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5" 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "javascript", 4 | "javascriptreact", 5 | { "language": "typescript", "autoFix": true }, 6 | { "language": "typescriptreact", "autoFix": true } 7 | ], 8 | "editor.defaultFormatter": "esbenp.prettier-vscode", 9 | "editor.formatOnSave": true, 10 | "javascript.format.enable": false, 11 | "editor.renderWhitespace": "all" 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `yarn install` 8 | 9 | Installs all dependencies required to run the project and populates a node_modules folder. Packages used can be found in package.json 10 | 11 | ### `yarn start` 12 | 13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 15 | 16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console. 18 | 19 | ### `yarn build` 20 | 21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance. 23 | 24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed! 26 | 27 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 28 | 29 | ## Learn More 30 | 31 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 32 | 33 | ## The Problem 34 | 35 | This project aims to emulate the successful game Adventure Capatalist. The game itself is a simulation of running multiple businesses, and can be played on many devices. 36 | 37 | Adventure Capatalist allows players to purchase businesses, earn capital and hire managers. On top of this, players can continue to earn money while away from the game which will automatically be applied to their account. 38 | 39 | This game follows many of the concepts mentioned in, yet does omit some of them due to time constraints. However, the core concepts have been explored. 40 | 41 | ## The Solution 42 | 43 | The game provided here has several functions that mimic what can be found in Adventure Capatalist. This project only focuses on the front end development however there have been considerations for the backend. These features are mentioned below: 44 | 45 | ### Buying a business 46 | 47 | Users are able to purchase a business using the funds they have availible. The businesses they buy earn a set amount of money each week, deposited on Fridays. A business can also be upgraded for a fee, which increases the amount of money generated each week. Up to 6 businesses can be purchased. 48 | 49 | ### Buying a Manager 50 | 51 | Players are also able to purchase a manager to help run their business empire. Unfortunatly there was not enough time to fully implement this feature. Users will have to purchase at least 1 business before they can purchase a manager, which should increase the output of the selected business. Due to time constraints this feature was not implemented fully and users can only purchase a manager, their output is not implemented and they cannot be applied to a business. 52 | 53 | ### Earning Money 54 | 55 | As previously stated, players earn money over time due to the amount of businesses they own. Money is deposited every Friday into the players account. Upgrading a business will increase the funds availible. 56 | 57 | ## Technical Considerations 58 | 59 | The project has been developed using Create React App, Phaser, and Redux. Redux was used as a central repository to track player progress, and reducers have been implemented to control the application of values and act on events created by the user. Redux was also chosen due to the ability for future integration with a server - it could easily be swapped out for many different options such as a NodeJS API with a Mongo backend, or Firebase storage. 60 | 61 | Phaser was chosen as it is a game development framework supported by Facebook and contains an extensive API making integration with Facebook easier. Scenes have been implemented to enable the display of screens the user needs to use, as well as other features such as particle physics. 62 | 63 | Create-React-App was chosen due to features such as code splitting, minifictation, and being able to bind values from Redux to the DOM. This is important to reduce draw calls, which can hamper performance. It is better to have things in the DOM, such as a score, rather then have them in canvas so they are not updated and drawn 60 times a second. Player information such as the current date and funds are rendered in the DOM to reduce the amount of work the GPU has to do each frame. 64 | 65 | In terms of scaling, the project only supports a landscape view. Custom scaling was implemented to ensure the project renders well on mobile, tablet and desktop and a rotate overlay was added to make sure the game is only played in this orientation. 66 | 67 | Texture Atlases have been used to improve GPU rendering speed and improve loading times by reducing HTTP requests for assets. The .tps file is included in the project. 68 | 69 | ## Code Guidelines 70 | 71 | To ensure a quality codebase, features such as Prettier have been added to ensure linting is done upon every save. This will be applied automatically if a developer uses the Prettier plugin with a IDE such as VSCode. 72 | 73 | ## Problems and Issues 74 | 75 | Due to time constraints focus was plased on the front end. Firebase was explored due to the ability to easily created timed functions to enable gameplay when the player was not at their computer, load balancing, real time database and API deployment. This could then be integrated with a Facebook release. 76 | 77 | Managers being assigned to a business was also omitted for time constraint reasons. 78 | 79 | Generally the code base is stable, managable and runs fast. The worst part would be the rotate overlay. This should have been written as a DOM element running above the game rather than being implemented on a scene by scene basis. It was an afterthought and should be done better. 80 | 81 | ## Future steps 82 | 83 | To improve this game in future, there are several opportunities. Apart from the previously mentioned issues, features such as natural disasters could be added, as well as balancing the values already included. Staff members could become unhappy and require higher wages, suppliers could become disgruntled and consumer opinion could be affected. Additionaly, instructions and advice popups as these events happen could guide the player to make good desicions to solve them. 84 | -------------------------------------------------------------------------------- /assets/assets.tps: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | fileFormatVersion 5 | 4 6 | texturePackerVersion 7 | 5.3.0 8 | autoSDSettings 9 | 10 | 11 | scale 12 | 1 13 | extension 14 | 15 | spriteFilter 16 | 17 | acceptFractionalValues 18 | 19 | maxTextureSize 20 | 21 | width 22 | -1 23 | height 24 | -1 25 | 26 | 27 | 28 | allowRotation 29 | 30 | shapeDebug 31 | 32 | dpi 33 | 72 34 | dataFormat 35 | phaser 36 | textureFileName 37 | 38 | flipPVR 39 | 40 | pvrCompressionQuality 41 | PVR_QUALITY_NORMAL 42 | atfCompressData 43 | 44 | mipMapMinSize 45 | 32768 46 | etc1CompressionQuality 47 | ETC1_QUALITY_LOW_PERCEPTUAL 48 | etc2CompressionQuality 49 | ETC2_QUALITY_LOW_PERCEPTUAL 50 | dxtCompressionMode 51 | DXT_PERCEPTUAL 52 | jxrColorFormat 53 | JXR_YUV444 54 | jxrTrimFlexBits 55 | 0 56 | jxrCompressionLevel 57 | 0 58 | ditherType 59 | NearestNeighbour 60 | backgroundColor 61 | 0 62 | libGdx 63 | 64 | filtering 65 | 66 | x 67 | Linear 68 | y 69 | Linear 70 | 71 | 72 | shapePadding 73 | 0 74 | jpgQuality 75 | 80 76 | pngOptimizationLevel 77 | 1 78 | webpQualityLevel 79 | 101 80 | textureSubPath 81 | 82 | atfFormats 83 | 84 | textureFormat 85 | png 86 | borderPadding 87 | 0 88 | maxTextureSize 89 | 90 | width 91 | 2048 92 | height 93 | 2048 94 | 95 | fixedTextureSize 96 | 97 | width 98 | -1 99 | height 100 | -1 101 | 102 | algorithmSettings 103 | 104 | algorithm 105 | MaxRects 106 | freeSizeMode 107 | Best 108 | sizeConstraints 109 | AnySize 110 | forceSquared 111 | 112 | maxRects 113 | 114 | heuristic 115 | Best 116 | 117 | basic 118 | 119 | sortBy 120 | Best 121 | order 122 | Ascending 123 | 124 | polygon 125 | 126 | alignToGrid 127 | 1 128 | 129 | 130 | dataFileNames 131 | 132 | json 133 | 134 | name 135 | ../public/images/assets.json 136 | 137 | 138 | multiPack 139 | 140 | forceIdenticalLayout 141 | 142 | outputFormat 143 | RGBA8888 144 | alphaHandling 145 | ClearTransparentPixels 146 | contentProtection 147 | 148 | key 149 | 150 | 151 | autoAliasEnabled 152 | 153 | trimSpriteNames 154 | 155 | prependSmartFolderName 156 | 157 | autodetectAnimations 158 | 159 | globalSpriteSettings 160 | 161 | scale 162 | 1 163 | scaleMode 164 | Smooth 165 | extrude 166 | 1 167 | trimThreshold 168 | 1 169 | trimMargin 170 | 1 171 | trimMode 172 | Trim 173 | tracerTolerance 174 | 200 175 | heuristicMask 176 | 177 | defaultPivotPoint 178 | 0,0 179 | writePivotPoints 180 | 181 | 182 | individualSpriteSettings 183 | 184 | disabled.png 185 | normal.png 186 | 187 | pivotPoint 188 | 0,0 189 | spriteScale 190 | 1 191 | scale9Enabled 192 | 193 | scale9Borders 194 | 79,35,157,70 195 | scale9Paddings 196 | 79,35,157,70 197 | scale9FromFile 198 | 199 | 200 | down.png 201 | hover.png 202 | 203 | pivotPoint 204 | 0,0 205 | spriteScale 206 | 1 207 | scale9Enabled 208 | 209 | scale9Borders 210 | 79,35,158,70 211 | scale9Paddings 212 | 79,35,158,70 213 | scale9FromFile 214 | 215 | 216 | small-down.png 217 | small-hover.png 218 | small-normal.png 219 | 220 | pivotPoint 221 | 0,0 222 | spriteScale 223 | 1 224 | scale9Enabled 225 | 226 | scale9Borders 227 | 43,43,85,87 228 | scale9Paddings 229 | 43,43,85,87 230 | scale9FromFile 231 | 232 | 233 | star-sprite.jpg 234 | 235 | pivotPoint 236 | 0,0 237 | spriteScale 238 | 1 239 | scale9Enabled 240 | 241 | scale9Borders 242 | 18,18,35,35 243 | scale9Paddings 244 | 18,18,35,35 245 | scale9FromFile 246 | 247 | 248 | 249 | fileList 250 | 251 | . 252 | 253 | ignoreFileList 254 | 255 | replaceList 256 | 257 | ignoredWarnings 258 | 259 | commonDivisorX 260 | 1 261 | commonDivisorY 262 | 1 263 | packNormalMaps 264 | 265 | autodetectNormalMaps 266 | 267 | normalMapFilter 268 | 269 | normalMapSuffix 270 | 271 | normalMapSheetFileName 272 | 273 | exporterProperties 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /assets/disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/disabled.png -------------------------------------------------------------------------------- /assets/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/down.png -------------------------------------------------------------------------------- /assets/hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/hover.png -------------------------------------------------------------------------------- /assets/normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/normal.png -------------------------------------------------------------------------------- /assets/small-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/small-down.png -------------------------------------------------------------------------------- /assets/small-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/small-hover.png -------------------------------------------------------------------------------- /assets/small-normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/small-normal.png -------------------------------------------------------------------------------- /assets/star-sprite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/assets/star-sprite.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "^4.6.1", 7 | "@material-ui/icons": "^4.9.1", 8 | "history": "^4.10.1", 9 | "howler": "^2.1.2", 10 | "husky": "^3.0.9", 11 | "lint-staged": "^9.4.2", 12 | "node-sass": "^4.13.0", 13 | "phaser": "^3.20.1", 14 | "prettier": "^1.19.1", 15 | "react": "^16.11.0", 16 | "react-dom": "^16.11.0", 17 | "react-redux": "^7.1.3", 18 | "react-router-dom": "^5.1.2", 19 | "react-scripts": "3.4.0", 20 | "redux": "^4.0.4", 21 | "redux-logger": "^3.0.6", 22 | "typeface-roboto": "^0.0.75", 23 | "typescript": "3.7.2" 24 | }, 25 | "devDependencies": { 26 | "@types/jest": "24.0.23", 27 | "@types/node": "12.12.7", 28 | "@types/react": "16.9.11", 29 | "@types/react-dom": "16.9.4", 30 | "@types/react-redux": "^7.1.5", 31 | "@types/react-router-dom": "^5.1.3" 32 | }, 33 | "lint-staged": { 34 | "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [ 35 | "prettier --write", 36 | "git add" 37 | ] 38 | }, 39 | "husky": { 40 | "hooks": { 41 | "pre-commit": "lint-staged" 42 | } 43 | }, 44 | "scripts": { 45 | "start": "react-scripts start", 46 | "build": "react-scripts build", 47 | "test": "react-scripts test", 48 | "eject": "react-scripts eject" 49 | }, 50 | "eslintConfig": { 51 | "extends": "react-app" 52 | }, 53 | "browserslist": { 54 | "production": [ 55 | ">0.2%", 56 | "not dead", 57 | "not op_mini all" 58 | ], 59 | "development": [ 60 | "last 1 chrome version", 61 | "last 1 firefox version", 62 | "last 1 safari version" 63 | ] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/public/favicon.ico -------------------------------------------------------------------------------- /public/images/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "textures": [ 3 | { 4 | "image": "assets.png", 5 | "format": "RGBA8888", 6 | "size": { 7 | "w": 491, 8 | "h": 597 9 | }, 10 | "scale": 1, 11 | "frames": [ 12 | { 13 | "filename": "down.png", 14 | "rotated": false, 15 | "trimmed": false, 16 | "sourceSize": { 17 | "w": 316, 18 | "h": 140 19 | }, 20 | "spriteSourceSize": { 21 | "x": 0, 22 | "y": 0, 23 | "w": 316, 24 | "h": 140 25 | }, 26 | "frame": { 27 | "x": 1, 28 | "y": 1, 29 | "w": 316, 30 | "h": 140 31 | } 32 | }, 33 | { 34 | "filename": "small-down.png", 35 | "rotated": false, 36 | "trimmed": false, 37 | "sourceSize": { 38 | "w": 171, 39 | "h": 173 40 | }, 41 | "spriteSourceSize": { 42 | "x": 0, 43 | "y": 0, 44 | "w": 171, 45 | "h": 173 46 | }, 47 | "frame": { 48 | "x": 319, 49 | "y": 1, 50 | "w": 171, 51 | "h": 173 52 | } 53 | }, 54 | { 55 | "filename": "hover.png", 56 | "rotated": false, 57 | "trimmed": false, 58 | "sourceSize": { 59 | "w": 316, 60 | "h": 140 61 | }, 62 | "spriteSourceSize": { 63 | "x": 0, 64 | "y": 0, 65 | "w": 316, 66 | "h": 140 67 | }, 68 | "frame": { 69 | "x": 1, 70 | "y": 143, 71 | "w": 316, 72 | "h": 140 73 | } 74 | }, 75 | { 76 | "filename": "small-hover.png", 77 | "rotated": false, 78 | "trimmed": false, 79 | "sourceSize": { 80 | "w": 171, 81 | "h": 173 82 | }, 83 | "spriteSourceSize": { 84 | "x": 0, 85 | "y": 0, 86 | "w": 171, 87 | "h": 173 88 | }, 89 | "frame": { 90 | "x": 319, 91 | "y": 176, 92 | "w": 171, 93 | "h": 173 94 | } 95 | }, 96 | { 97 | "filename": "disabled.png", 98 | "rotated": false, 99 | "trimmed": false, 100 | "sourceSize": { 101 | "w": 315, 102 | "h": 140 103 | }, 104 | "spriteSourceSize": { 105 | "x": 0, 106 | "y": 0, 107 | "w": 315, 108 | "h": 140 109 | }, 110 | "frame": { 111 | "x": 1, 112 | "y": 285, 113 | "w": 315, 114 | "h": 140 115 | } 116 | }, 117 | { 118 | "filename": "small-normal.png", 119 | "rotated": false, 120 | "trimmed": false, 121 | "sourceSize": { 122 | "w": 171, 123 | "h": 173 124 | }, 125 | "spriteSourceSize": { 126 | "x": 0, 127 | "y": 0, 128 | "w": 171, 129 | "h": 173 130 | }, 131 | "frame": { 132 | "x": 318, 133 | "y": 351, 134 | "w": 171, 135 | "h": 173 136 | } 137 | }, 138 | { 139 | "filename": "normal.png", 140 | "rotated": false, 141 | "trimmed": false, 142 | "sourceSize": { 143 | "w": 314, 144 | "h": 140 145 | }, 146 | "spriteSourceSize": { 147 | "x": 0, 148 | "y": 0, 149 | "w": 314, 150 | "h": 140 151 | }, 152 | "frame": { 153 | "x": 1, 154 | "y": 427, 155 | "w": 314, 156 | "h": 140 157 | } 158 | }, 159 | { 160 | "filename": "star-sprite.jpg", 161 | "rotated": false, 162 | "trimmed": false, 163 | "sourceSize": { 164 | "w": 70, 165 | "h": 70 166 | }, 167 | "spriteSourceSize": { 168 | "x": 0, 169 | "y": 0, 170 | "w": 70, 171 | "h": 70 172 | }, 173 | "frame": { 174 | "x": 317, 175 | "y": 526, 176 | "w": 70, 177 | "h": 70 178 | } 179 | } 180 | ] 181 | } 182 | ], 183 | "meta": { 184 | "app": "https://www.codeandweb.com/texturepacker", 185 | "version": "3.0", 186 | "smartupdate": "$TexturePacker:SmartUpdate:e167c9d2de7b8266cc818281b2cd12d7:ca741596969f9b74a58795045143257b:a759b6bbc8381ac9c472b28f589ad0d6$" 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /public/images/assets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/public/images/assets.png -------------------------------------------------------------------------------- /public/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraigBeswetherick/Typescript-phaser3-react-redux-boilerplate/35f97620fe5cec6618d288482d378a271f559198/public/images/background.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 31 | The Sim Game 32 | 33 | 34 | 35 |
36 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /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": "images/veg.png", 12 | "type": "image/png", 13 | "sizes": "256×208" 14 | } 15 | ], 16 | "start_url": ".", 17 | "display": "standalone", 18 | "theme_color": "#000000", 19 | "background_color": "#ffffff" 20 | } 21 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /src/App.scss: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | background-color: #282c34; 4 | } 5 | -------------------------------------------------------------------------------- /src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { GameContainer } from './Components/Game'; 3 | import './App.scss'; 4 | import { Router, Switch, Route } from 'react-router-dom'; 5 | import history from './Utils/History'; 6 | import Theme from './Theme/Theme'; 7 | import { MuiThemeProvider } from '@material-ui/core'; 8 | 9 | const App: React.FC = () => { 10 | return ( 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | ); 23 | }; 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /src/Theme/Button.ts: -------------------------------------------------------------------------------- 1 | 'use-strict'; 2 | 3 | const Button = { 4 | root: { 5 | backgroundColor: 'blue', 6 | }, 7 | textPrimary: { 8 | color: 'white', 9 | '&:hover': { 10 | color: 'white', 11 | backgroundColor: 'red', 12 | }, 13 | }, 14 | }; 15 | 16 | export default Button; 17 | -------------------------------------------------------------------------------- /src/Theme/Theme.ts: -------------------------------------------------------------------------------- 1 | 'use-strict'; 2 | 3 | import { createMuiTheme } from '@material-ui/core/styles'; 4 | import Typography from './Typography'; 5 | import Button from './Button'; 6 | 7 | const Theme = createMuiTheme({ 8 | overrides: { 9 | MuiTypography: Typography, 10 | MuiButton: Button, 11 | }, 12 | }); 13 | 14 | export default Theme; 15 | -------------------------------------------------------------------------------- /src/Theme/Typography.ts: -------------------------------------------------------------------------------- 1 | 'use-strict'; 2 | 3 | const Typography = { 4 | body1: { 5 | 'font-size': '1.5rem', 6 | 'line-height': '10vh', 7 | color: 'white', 8 | }, 9 | 10 | h1: { 11 | 'font-size': '4rem', 12 | 'text-align': 'center', 13 | padding: '10%', 14 | background: 'red', 15 | color: 'white', 16 | }, 17 | subtitle1: { 18 | 'font-size': '2rem', 19 | 'text-align': 'center', 20 | padding: '1%', 21 | color: 'white', 22 | background: 'grey', 23 | }, 24 | 25 | subtitle2: { 26 | 'font-size': '1rem', 27 | 'text-align': 'center', 28 | padding: '1%', 29 | color: 'white', 30 | background: 'grey', 31 | display: 'block', 32 | width: '50vw', 33 | }, 34 | }; 35 | 36 | export default Typography; 37 | -------------------------------------------------------------------------------- /src/Utils/History.ts: -------------------------------------------------------------------------------- 1 | import { createBrowserHistory } from 'history'; 2 | 3 | export default createBrowserHistory(); 4 | -------------------------------------------------------------------------------- /src/Utils/Particles.ts: -------------------------------------------------------------------------------- 1 | export const createEmitter = (scene: Phaser.Scene) => { 2 | const emitter = scene.add.particles('star-sprite.jpg').createEmitter({ 3 | x: 0, 4 | y: 0, 5 | speed: { min: -800, max: 800 }, 6 | angle: { min: 0, max: 360 }, 7 | scale: { start: 0.5, end: 0 }, 8 | //active: false, 9 | lifespan: 600, 10 | gravityY: 800, 11 | }); 12 | 13 | emitter.stop(); 14 | 15 | return emitter; 16 | }; 17 | -------------------------------------------------------------------------------- /src/Utils/PhaserConfig.ts: -------------------------------------------------------------------------------- 1 | export interface GameOptions { 2 | type: number; 3 | width: number; 4 | height: number; 5 | parent: string; 6 | } 7 | 8 | export function getPhaserConfig(): GameOptions { 9 | return { 10 | type: Phaser.CANVAS, 11 | width: window.innerWidth, 12 | height: window.innerHeight * 0.9, 13 | parent: 'game', 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /src/Utils/RotateOverlay.ts: -------------------------------------------------------------------------------- 1 | import { addText } from './UIUtils'; 2 | 3 | let rotateDeviceContainerList: Array = []; 4 | 5 | export const initRotateOverlay = (scene: Phaser.Scene, sceneId: number) => { 6 | scene.scale.addListener(Phaser.Scale.Events.ORIENTATION_CHANGE, () => { 7 | checkOrientation(scene, sceneId); 8 | }); 9 | }; 10 | 11 | export const removeRotateOverlay = (scene: Phaser.Scene, sceneId: number) => { 12 | scene.scale.removeListener(Phaser.Scale.Events.ORIENTATION_CHANGE, () => { 13 | checkOrientation(scene, sceneId); 14 | }); 15 | }; 16 | 17 | const checkOrientation = (scene: Phaser.Scene, sceneId: number) => { 18 | if (scene.game.scale.isPortrait) { 19 | createRotateScreen(scene, sceneId); 20 | } else { 21 | rotateDeviceContainerList[sceneId].visible = false; 22 | } 23 | }; 24 | 25 | const createRotateScreen = (scene: Phaser.Scene, sceneId: number) => { 26 | if (rotateDeviceContainerList[sceneId]) { 27 | rotateDeviceContainerList[sceneId].visible = true; 28 | return; 29 | } 30 | 31 | let rotateDeviceContainer = scene.add.container(0, 0); 32 | 33 | const { width, height } = scene.sys.game.canvas; 34 | let rotateDeviceText: Phaser.GameObjects.Text = addText( 35 | width / 2, 36 | height * 0.6, 37 | 'Please rotate your device', 38 | scene, 39 | '#FFF', 40 | 28 41 | ); 42 | 43 | rotateDeviceText.x -= rotateDeviceText.width / 2; 44 | 45 | let background: Phaser.GameObjects.Graphics = scene.add.graphics(); 46 | background.fillStyle(0x000, 1); 47 | background.fillRect(0, 0, width, height); 48 | 49 | rotateDeviceContainer.add(background); 50 | rotateDeviceContainer.add(rotateDeviceText); 51 | 52 | rotateDeviceContainerList[sceneId] = rotateDeviceContainer; 53 | }; 54 | -------------------------------------------------------------------------------- /src/Utils/Store.ts: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import { reducers } from '../Reducers/index'; 3 | 4 | let state = {}; 5 | const store = createStore(reducers, state, applyMiddleware()); 6 | 7 | export default store; 8 | -------------------------------------------------------------------------------- /src/Utils/UIUtils.ts: -------------------------------------------------------------------------------- 1 | import { Button } from '../Components/Game/Button'; 2 | import { 3 | GAME_SCALE, 4 | GAME_SCENE, 5 | UPGRADE_BUSINESS_SCENE, 6 | BUSINESS_SCENE, 7 | } from './Constants'; 8 | import store from './Store'; 9 | 10 | export const addHeader = (scene: Phaser.Scene, text: string) => { 11 | const fontSize: number = 40 * GAME_SCALE; 12 | scene.add.text(50 * GAME_SCALE, 45 * GAME_SCALE, text, { 13 | fontFamily: 'Roboto', 14 | fontSize: fontSize, 15 | color: '#fff', 16 | }); 17 | }; 18 | 19 | export const checkButtons = (buttons: Array