├── .gitignore
├── License.txt
├── art
├── CapturFiles-20170729_102112.png
├── CapturFiles-20170729_102158.png
├── CapturFiles-20170729_102215.png
└── CapturFiles-20170729_102242.png
├── assets
├── images
│ ├── 041.png
│ ├── UI_WINDOW_1.png
│ ├── UI_WINDOW_2.png
│ ├── UI_WINDOW_3.png
│ ├── UI_WINDOW_4.png
│ ├── UI_WINDOW_5.png
│ ├── UI_WINDOW_6.png
│ ├── UI_WINDOW_7.png
│ ├── UI_WINDOW_8.png
│ ├── UI_WINDOW_9.png
│ ├── arrowLeft.png
│ ├── arrowRight.png
│ ├── blackSmoke21.png
│ ├── buttonStart.png
│ ├── checkmark.png
│ ├── cloud.png
│ ├── crate_01.png
│ ├── crate_07.png
│ ├── crate_08.png
│ ├── crate_09.png
│ ├── crate_10.png
│ ├── crate_11.png
│ ├── crate_17.png
│ ├── crate_18.png
│ ├── crate_19.png
│ ├── crate_20.png
│ ├── crate_21.png
│ ├── crate_42.png
│ ├── crate_43.png
│ ├── crate_44.png
│ ├── crate_45.png
│ ├── cross.png
│ ├── exp2_0.png
│ ├── flatDark03.png
│ ├── flatDark48.png
│ ├── flatDark49.png
│ ├── gear.png
│ ├── grass2_64.png
│ ├── grass_64.png
│ ├── greenRobotMoving.png
│ ├── greyRobotMoving.png
│ ├── information.png
│ ├── jet_pack.png
│ ├── longCloud.png
│ ├── lucifer_cannon.png
│ ├── medical_pack.png
│ ├── menuList.png
│ ├── meteorGrey_big1.png
│ ├── meteorGrey_big2.png
│ ├── meteorGrey_big3.png
│ ├── meteorGrey_big4.png
│ ├── meteorGrey_med1.png
│ ├── meteorGrey_med2.png
│ ├── meteorGrey_small1.png
│ ├── meteorGrey_small2.png
│ ├── meteorGrey_tiny1.png
│ ├── meteorGrey_tiny2.png
│ ├── mountain2_64.png
│ ├── mountain_64.png
│ ├── musicOff.png
│ ├── musicOn.png
│ ├── oil.png
│ ├── pause.png
│ ├── redRobotMoving.png
│ ├── robot_3Dblue.png
│ ├── robot_3Dgreen.png
│ ├── robot_3Dred.png
│ ├── robot_3Dyellow.png
│ ├── robot_greenJump.png
│ ├── robot_redJump.png
│ ├── sand_64.png
│ ├── sandstone_64.png
│ ├── share1.png
│ ├── shield.png
│ ├── stone_64.png
│ ├── tank_bullet3.png
│ ├── tank_bulletFly2.png
│ ├── tank_bulletFly3.png
│ ├── tiled_64.png
│ ├── tracksLarge.png
│ ├── warning.png
│ └── yellowRobotMoving.png
├── json
│ ├── credits.json
│ ├── level.json
│ └── menu.json
└── sounds
│ ├── click.mp3
│ ├── explosion.mp3
│ ├── pling.mp3
│ └── shot.mp3
├── deliver.sh
├── gulpfile.js
├── index.html
├── js
├── config.js
├── main.js
├── prefabs
│ ├── animatedSprite.js
│ ├── bossRobot.js
│ ├── bossRobotSpawner.js
│ ├── button.js
│ ├── chest.js
│ ├── chestSpawner.js
│ ├── control.js
│ ├── creditsItem.js
│ ├── creditsItemSpawner.js
│ ├── dpad.js
│ ├── droppable.js
│ ├── droppableRobot.js
│ ├── dust.js
│ ├── dustSpawner.js
│ ├── earthQuakeSpawner.js
│ ├── enemyRobot.js
│ ├── enemyRobotSpawner.js
│ ├── explosion.js
│ ├── explosionSpawner.js
│ ├── loot.js
│ ├── lootSpawner.js
│ ├── menuBackgroundChooser.js
│ ├── menuRobot.js
│ ├── menuRobotChooser.js
│ ├── menuRobotSpawner.js
│ ├── messagePrefab.js
│ ├── messageSpawner.js
│ ├── meteorit.js
│ ├── meteoritSpawner.js
│ ├── minimap.js
│ ├── oil.js
│ ├── oilSpawner.js
│ ├── pauseDialog.js
│ ├── pauseDialogSpawner.js
│ ├── prefab.js
│ ├── robot.js
│ ├── robotSpawner.js
│ ├── selectableSprite.js
│ ├── smoke.js
│ ├── smokeSpawner.js
│ ├── soundPrefab.js
│ ├── soundSpawner.js
│ ├── spawner.js
│ ├── statisticsPanel.js
│ ├── textPrefab.js
│ ├── textSpawner.js
│ ├── tileSprite.js
│ ├── track.js
│ └── trackSpawner.js
├── states
│ ├── boot.js
│ ├── credits.js
│ ├── level.js
│ ├── loading.js
│ └── menu.js
└── utilities
│ ├── arrayUtilities.js
│ ├── groupUtilities.js
│ ├── mathUtilities.js
│ └── nameUtilities.js
├── libs
└── phaser.js
├── package.json
├── readme.md
└── watch.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea/
3 | #gulpfile.js
4 | dist
5 | #watch.sh
6 | #deliver.sh
7 | node_modules
8 | sketch
--------------------------------------------------------------------------------
/License.txt:
--------------------------------------------------------------------------------
1 | Copyright 2017 Stefan Neidig
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/art/CapturFiles-20170729_102112.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/art/CapturFiles-20170729_102112.png
--------------------------------------------------------------------------------
/art/CapturFiles-20170729_102158.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/art/CapturFiles-20170729_102158.png
--------------------------------------------------------------------------------
/art/CapturFiles-20170729_102215.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/art/CapturFiles-20170729_102215.png
--------------------------------------------------------------------------------
/art/CapturFiles-20170729_102242.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/art/CapturFiles-20170729_102242.png
--------------------------------------------------------------------------------
/assets/images/041.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/041.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_1.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_2.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_3.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_4.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_5.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_6.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_7.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_8.png
--------------------------------------------------------------------------------
/assets/images/UI_WINDOW_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/UI_WINDOW_9.png
--------------------------------------------------------------------------------
/assets/images/arrowLeft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/arrowLeft.png
--------------------------------------------------------------------------------
/assets/images/arrowRight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/arrowRight.png
--------------------------------------------------------------------------------
/assets/images/blackSmoke21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/blackSmoke21.png
--------------------------------------------------------------------------------
/assets/images/buttonStart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/buttonStart.png
--------------------------------------------------------------------------------
/assets/images/checkmark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/checkmark.png
--------------------------------------------------------------------------------
/assets/images/cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/cloud.png
--------------------------------------------------------------------------------
/assets/images/crate_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_01.png
--------------------------------------------------------------------------------
/assets/images/crate_07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_07.png
--------------------------------------------------------------------------------
/assets/images/crate_08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_08.png
--------------------------------------------------------------------------------
/assets/images/crate_09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_09.png
--------------------------------------------------------------------------------
/assets/images/crate_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_10.png
--------------------------------------------------------------------------------
/assets/images/crate_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_11.png
--------------------------------------------------------------------------------
/assets/images/crate_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_17.png
--------------------------------------------------------------------------------
/assets/images/crate_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_18.png
--------------------------------------------------------------------------------
/assets/images/crate_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_19.png
--------------------------------------------------------------------------------
/assets/images/crate_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_20.png
--------------------------------------------------------------------------------
/assets/images/crate_21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_21.png
--------------------------------------------------------------------------------
/assets/images/crate_42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_42.png
--------------------------------------------------------------------------------
/assets/images/crate_43.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_43.png
--------------------------------------------------------------------------------
/assets/images/crate_44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_44.png
--------------------------------------------------------------------------------
/assets/images/crate_45.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/crate_45.png
--------------------------------------------------------------------------------
/assets/images/cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/cross.png
--------------------------------------------------------------------------------
/assets/images/exp2_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/exp2_0.png
--------------------------------------------------------------------------------
/assets/images/flatDark03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/flatDark03.png
--------------------------------------------------------------------------------
/assets/images/flatDark48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/flatDark48.png
--------------------------------------------------------------------------------
/assets/images/flatDark49.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/flatDark49.png
--------------------------------------------------------------------------------
/assets/images/gear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/gear.png
--------------------------------------------------------------------------------
/assets/images/grass2_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/grass2_64.png
--------------------------------------------------------------------------------
/assets/images/grass_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/grass_64.png
--------------------------------------------------------------------------------
/assets/images/greenRobotMoving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/greenRobotMoving.png
--------------------------------------------------------------------------------
/assets/images/greyRobotMoving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/greyRobotMoving.png
--------------------------------------------------------------------------------
/assets/images/information.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/information.png
--------------------------------------------------------------------------------
/assets/images/jet_pack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/jet_pack.png
--------------------------------------------------------------------------------
/assets/images/longCloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/longCloud.png
--------------------------------------------------------------------------------
/assets/images/lucifer_cannon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/lucifer_cannon.png
--------------------------------------------------------------------------------
/assets/images/medical_pack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/medical_pack.png
--------------------------------------------------------------------------------
/assets/images/menuList.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/menuList.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_big1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_big1.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_big2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_big2.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_big3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_big3.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_big4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_big4.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_med1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_med1.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_med2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_med2.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_small1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_small1.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_small2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_small2.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_tiny1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_tiny1.png
--------------------------------------------------------------------------------
/assets/images/meteorGrey_tiny2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/meteorGrey_tiny2.png
--------------------------------------------------------------------------------
/assets/images/mountain2_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/mountain2_64.png
--------------------------------------------------------------------------------
/assets/images/mountain_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/mountain_64.png
--------------------------------------------------------------------------------
/assets/images/musicOff.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/musicOff.png
--------------------------------------------------------------------------------
/assets/images/musicOn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/musicOn.png
--------------------------------------------------------------------------------
/assets/images/oil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/oil.png
--------------------------------------------------------------------------------
/assets/images/pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/pause.png
--------------------------------------------------------------------------------
/assets/images/redRobotMoving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/redRobotMoving.png
--------------------------------------------------------------------------------
/assets/images/robot_3Dblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/robot_3Dblue.png
--------------------------------------------------------------------------------
/assets/images/robot_3Dgreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/robot_3Dgreen.png
--------------------------------------------------------------------------------
/assets/images/robot_3Dred.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/robot_3Dred.png
--------------------------------------------------------------------------------
/assets/images/robot_3Dyellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/robot_3Dyellow.png
--------------------------------------------------------------------------------
/assets/images/robot_greenJump.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/robot_greenJump.png
--------------------------------------------------------------------------------
/assets/images/robot_redJump.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/robot_redJump.png
--------------------------------------------------------------------------------
/assets/images/sand_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/sand_64.png
--------------------------------------------------------------------------------
/assets/images/sandstone_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/sandstone_64.png
--------------------------------------------------------------------------------
/assets/images/share1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/share1.png
--------------------------------------------------------------------------------
/assets/images/shield.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/shield.png
--------------------------------------------------------------------------------
/assets/images/stone_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/stone_64.png
--------------------------------------------------------------------------------
/assets/images/tank_bullet3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/tank_bullet3.png
--------------------------------------------------------------------------------
/assets/images/tank_bulletFly2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/tank_bulletFly2.png
--------------------------------------------------------------------------------
/assets/images/tank_bulletFly3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/tank_bulletFly3.png
--------------------------------------------------------------------------------
/assets/images/tiled_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/tiled_64.png
--------------------------------------------------------------------------------
/assets/images/tracksLarge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/tracksLarge.png
--------------------------------------------------------------------------------
/assets/images/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/warning.png
--------------------------------------------------------------------------------
/assets/images/yellowRobotMoving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/images/yellowRobotMoving.png
--------------------------------------------------------------------------------
/assets/json/credits.json:
--------------------------------------------------------------------------------
1 | {
2 | "assets": {
3 | "uiArrowRight": {
4 | "type": "image",
5 | "source": "assets/images/arrowRight.png"
6 | },
7 | "uiArrowLeft": {
8 | "type": "image",
9 | "source": "assets/images/arrowLeft.png"
10 | },
11 | "clickSound": {
12 | "type": "sound",
13 | "source": "assets/sounds/click.mp3"
14 | },
15 | "uiSettings": {
16 | "type": "image",
17 | "source": "assets/images/gear.png"
18 | },
19 | "uiInformation": {
20 | "type": "image",
21 | "source": "assets/images/information.png"
22 | },
23 | "uiStart": {
24 | "type": "image",
25 | "source": "assets/images/buttonStart.png"
26 | },
27 | "cloud1": {
28 | "type": "image",
29 | "source": "assets/images/longCloud.png"
30 | },
31 | "cloud2": {
32 | "type": "image",
33 | "source": "assets/images/cloud.png"
34 | },
35 | "logoRobotRed": {
36 | "type": "image",
37 | "source": "assets/images/robot_redJump.png"
38 | },
39 | "logoRobotGreen": {
40 | "type": "image",
41 | "source": "assets/images/robot_greenJump.png"
42 | },
43 | "logoBulletLeft": {
44 | "type": "image",
45 | "source": "assets/images/tank_bulletFly2.png"
46 | },
47 | "redRobotMoving": {
48 | "type": "spritesheet",
49 | "source": "assets/images/redRobotMoving.png",
50 | "frameWidth": 90,
51 | "frameHeight": 75,
52 | "frames": 2
53 | },
54 | "yellowRobotMoving": {
55 | "type": "spritesheet",
56 | "source": "assets/images/yellowRobotMoving.png",
57 | "frameWidth": 92,
58 | "frameHeight": 76,
59 | "frames": 2
60 | },
61 | "greenRobotMoving": {
62 | "type": "spritesheet",
63 | "source": "assets/images/greenRobotMoving.png",
64 | "frameWidth": 79,
65 | "frameHeight": 60,
66 | "frames": 2
67 | },
68 | "greyRobotMoving": {
69 | "type": "spritesheet",
70 | "source": "assets/images/greyRobotMoving.png",
71 | "frameWidth": 79,
72 | "frameHeight": 75,
73 | "frames": 2
74 | },
75 | "uiLink": {
76 | "type": "image",
77 | "source": "assets/images/share1.png"
78 | },
79 | "groundStone": {
80 | "type": "image",
81 | "source": "assets/images/sandstone_64.png"
82 | },
83 | "groundMountain": {
84 | "type": "image",
85 | "source": "assets/images/mountain_64.png"
86 | },
87 | "groundMountain2": {
88 | "type": "image",
89 | "source": "assets/images/mountain2_64.png"
90 | },
91 | "groundDirt": {
92 | "type": "image",
93 | "source": "assets/images/041.png"
94 | },
95 | "grass2": {
96 | "type": "image",
97 | "source": "assets/images/grass2_64.png"
98 | },
99 | "stone": {
100 | "type": "image",
101 | "source": "assets/images/stone_64.png"
102 | },
103 | "groundSand": {
104 | "type": "image",
105 | "source": "assets/images/sand_64.png"
106 | },
107 | "logoBulletRight": {
108 | "type": "image",
109 | "source": "assets/images/tank_bulletFly3.png"
110 | },
111 | "groundGrass": {
112 | "type": "image",
113 | "source": "assets/images/grass_64.png"
114 | },
115 | "groundTiled": {
116 | "type": "image",
117 | "source": "assets/images/tiled_64.png"
118 | },
119 | "robot3Dblue": {
120 | "type": "image",
121 | "source": "assets/images/robot_3Dblue.png"
122 | },
123 | "robot3Dgreen": {
124 | "type": "image",
125 | "source": "assets/images/robot_3Dgreen.png"
126 | },
127 | "robot3Dred": {
128 | "type": "image",
129 | "source": "assets/images/robot_3Dred.png"
130 | },
131 | "robot3Dyellow": {
132 | "type": "image",
133 | "source": "assets/images/robot_3Dyellow.png"
134 | },
135 | "bullet": {
136 | "type": "image",
137 | "source": "assets/images/tank_bullet3.png"
138 | },
139 | "jet_pack": {
140 | "type": "image",
141 | "source": "assets/images/jet_pack.png"
142 | },
143 | "lucifer_cannon": {
144 | "type": "image",
145 | "source": "assets/images/lucifer_cannon.png"
146 | },
147 | "medical_pack": {
148 | "type": "image",
149 | "source": "assets/images/medical_pack.png"
150 | },
151 | "shield": {
152 | "type": "image",
153 | "source": "assets/images/shield.png"
154 | },
155 | "blackSmoke": {
156 | "type": "image",
157 | "source": "assets/images/blackSmoke21.png"
158 | },
159 | "tracks": {
160 | "type": "image",
161 | "source": "assets/images/tracksLarge.png"
162 | },
163 | "explosion2": {
164 | "type": "spritesheet",
165 | "source": "assets/images/exp2_0.png",
166 | "frameWidth": 64,
167 | "frameHeight": 64,
168 | "frames": 16
169 | },
170 | "uiMenu": {
171 | "type": "image",
172 | "source": "assets/images/menuList.png"
173 | },
174 | "uiPause": {
175 | "type": "image",
176 | "source": "assets/images/pause.png"
177 | },
178 | "uiDPad": {
179 | "type": "image",
180 | "source": "assets/images/flatDark03.png"
181 | },
182 | "uiShootButton": {
183 | "type": "image",
184 | "source": "assets/images/flatDark48.png"
185 | },
186 | "crate_01": {
187 | "type": "image",
188 | "source": "assets/images/crate_01.png"
189 | },
190 | "crate_07": {
191 | "type": "image",
192 | "source": "assets/images/crate_07.png"
193 | },
194 | "crate_08": {
195 | "type": "image",
196 | "source": "assets/images/crate_08.png"
197 | },
198 | "crate_09": {
199 | "type": "image",
200 | "source": "assets/images/crate_09.png"
201 | },
202 | "crate_10": {
203 | "type": "image",
204 | "source": "assets/images/crate_10.png"
205 | },
206 | "crate_11": {
207 | "type": "image",
208 | "source": "assets/images/crate_11.png"
209 | },
210 | "crate_17": {
211 | "type": "image",
212 | "source": "assets/images/crate_17.png"
213 | },
214 | "crate_18": {
215 | "type": "image",
216 | "source": "assets/images/crate_18.png"
217 | },
218 | "crate_19": {
219 | "type": "image",
220 | "source": "assets/images/crate_19.png"
221 | },
222 | "crate_20": {
223 | "type": "image",
224 | "source": "assets/images/crate_20.png"
225 | },
226 | "crate_21": {
227 | "type": "image",
228 | "source": "assets/images/crate_21.png"
229 | },
230 | "crate_42": {
231 | "type": "image",
232 | "source": "assets/images/crate_42.png"
233 | },
234 | "crate_43": {
235 | "type": "image",
236 | "source": "assets/images/crate_43.png"
237 | },
238 | "crate_44": {
239 | "type": "image",
240 | "source": "assets/images/crate_44.png"
241 | },
242 | "crate_45": {
243 | "type": "image",
244 | "source": "assets/images/crate_45.png"
245 | },
246 | "oil": {
247 | "type": "image",
248 | "source": "assets/images/oil.png"
249 | },
250 | "meteorGrey_big1": {
251 | "type": "image",
252 | "source": "assets/images/meteorGrey_big1.png"
253 | },
254 | "meteorGrey_big2": {
255 | "type": "image",
256 | "source": "assets/images/meteorGrey_big2.png"
257 | },
258 | "meteorGrey_big3": {
259 | "type": "image",
260 | "source": "assets/images/meteorGrey_big3.png"
261 | },
262 | "meteorGrey_big4": {
263 | "type": "image",
264 | "source": "assets/images/meteorGrey_big4.png"
265 | },
266 | "meteorGrey_med1": {
267 | "type": "image",
268 | "source": "assets/images/meteorGrey_med1.png"
269 | },
270 | "meteorGrey_med2": {
271 | "type": "image",
272 | "source": "assets/images/meteorGrey_med2.png"
273 | },
274 | "meteorGrey_small1": {
275 | "type": "image",
276 | "source": "assets/images/meteorGrey_small1.png"
277 | },
278 | "meteorGrey_small2": {
279 | "type": "image",
280 | "source": "assets/images/meteorGrey_small2.png"
281 | },
282 | "meteorGrey_tiny1": {
283 | "type": "image",
284 | "source": "assets/images/meteorGrey_tiny1.png"
285 | },
286 | "meteorGrey_tiny2": {
287 | "type": "image",
288 | "source": "assets/images/meteorGrey_tiny2.png"
289 | },
290 | "uiWindow": {
291 | "type": "image",
292 | "source": "assets/images/UI_WINDOW_1.png"
293 | },
294 | "uiWindowBL": {
295 | "type": "image",
296 | "source": "assets/images/UI_WINDOW_2.png"
297 | },
298 | "uiWindowB": {
299 | "type": "image",
300 | "source": "assets/images/UI_WINDOW_3.png"
301 | },
302 | "uiWindowBR": {
303 | "type": "image",
304 | "source": "assets/images/UI_WINDOW_4.png"
305 | },
306 | "uiWindowR": {
307 | "type": "image",
308 | "source": "assets/images/UI_WINDOW_5.png"
309 | },
310 | "uiWindowL": {
311 | "type": "image",
312 | "source": "assets/images/UI_WINDOW_6.png"
313 | },
314 | "uiWindowTR": {
315 | "type": "image",
316 | "source": "assets/images/UI_WINDOW_7.png"
317 | },
318 | "uiWindowTL": {
319 | "type": "image",
320 | "source": "assets/images/UI_WINDOW_8.png"
321 | },
322 | "uiWindowT": {
323 | "type": "image",
324 | "source": "assets/images/UI_WINDOW_9.png"
325 | },
326 | "uiCross": {
327 | "type": "image",
328 | "source": "assets/images/cross.png"
329 | },
330 | "uiCheckmark": {
331 | "type": "image",
332 | "source": "assets/images/checkmark.png"
333 | }
334 | },
335 | "groups": [
336 | "background",
337 | "spawners",
338 | "credits",
339 | "hud"
340 | ],
341 | "prefabs": {
342 | "background": {
343 | "type": "tileSprite",
344 | "position": {
345 | "x": 0,
346 | "y": 0
347 | },
348 | "properties": {
349 | "group": "background",
350 | "key": "groundGrass",
351 | "size": {
352 | "width": 640,
353 | "height": 360
354 | },
355 | "fixedToCamera": true
356 | }
357 | },
358 | "menuButton": {
359 | "type": "button",
360 | "position": {
361 | "x": 24,
362 | "y": 24
363 | },
364 | "properties": {
365 | "group": "hud",
366 | "key": "uiMenu",
367 | "anchor": {
368 | "x": 0.5,
369 | "y": 0.5
370 | }
371 | }
372 | },
373 | "caption": {
374 | "type": "text",
375 | "position": {
376 | "x": 320,
377 | "y": 24
378 | },
379 | "properties": {
380 | "text": "Credits",
381 | "group": "credits",
382 | "fixedToCamera": true,
383 | "style": {
384 | "font": "25pt Arial",
385 | "fill": "#ffffff",
386 | "align": "center"
387 | },
388 | "anchor": {
389 | "x": 0.5,
390 | "y": 0.5
391 | },
392 | "shadow": true
393 | }
394 | },
395 | "text": {
396 | "type": "text",
397 | "position": {
398 | "x": 48,
399 | "y": 48
400 | },
401 | "properties": {
402 | "text": "This is my contribution for the 2017 Phaser hackathon hosted by Zenva. The objective was to create a fun game using only the Phaserjs game engine and a predefined set of assets. Furthermore you only had 500 KB of space for the whole game.\n\nMy take was a game heavily inspired by Slither.io and is called Bots. You are a robot driving in a huge world packed with other robots with the same goal - killing each other. Dive into the vivid world of Bots and claim your place!\n\nAnyway, this challenge was real fun! I want to thank Zenva for hosting such a hackathon to begin with. Furthermore I want to thank all people I took the assets from. Those are listed below with the respective assets I used from them. And finally I want to thank my wife, who immensely supported me in my endeavour by not only actively playing and testing the game but also by understanding and maintaining her patience. I love you!",
403 | "group": "credits",
404 | "fixedToCamera": true,
405 | "lineSpacing": -5,
406 | "style": {
407 | "font": "10pt Arial",
408 | "fill": "#ffffff",
409 | "align": "left",
410 | "wordWrap": true,
411 | "wordWrapWidth": 544
412 | },
413 | "anchor": {
414 | "x": 0,
415 | "y": 0
416 | },
417 | "shadow": true
418 | }
419 | },
420 | "thankYouText": {
421 | "type": "text",
422 | "position": {
423 | "x": 320,
424 | "y": 1165
425 | },
426 | "properties": {
427 | "text": "Thanks for playing!",
428 | "group": "credits",
429 | "fixedToCamera": true,
430 | "lineSpacing": -5,
431 | "style": {
432 | "font": "24pt Arial",
433 | "fill": "#ffffff",
434 | "align": "center",
435 | "wordWrap": true,
436 | "wordWrapWidth": 544
437 | },
438 | "anchor": {
439 | "x": 0.5,
440 | "y": 0
441 | },
442 | "shadow": true
443 | }
444 | },
445 | "creditsItemSpawner": {
446 | "type": "creditsItemSpawner",
447 | "position": {
448 | "x": 0,
449 | "y": 280
450 | },
451 | "properties": {
452 | "group": "spawners",
453 | "pool": "credits",
454 | "key": "",
455 | "spacing": 16,
456 | "margin": 48,
457 | "columnCount": 3,
458 | "mode": "once",
459 | "spawnTimeInSeconds": {
460 | "min": 0,
461 | "max": 0
462 | },
463 | "items": [
464 | {
465 | "key": "logoRobotRed",
466 | "title": "Robot pack",
467 | "link": "http://kenney.nl/assets/robot-pack",
468 | "author": "Kenney"
469 | },
470 | {
471 | "key": "bullet",
472 | "title": "Tanks",
473 | "link": "http://kenney.nl/assets/tanks",
474 | "author": "Kenney"
475 | },
476 | {
477 | "key": "groundTiled",
478 | "title": "Stone blocks",
479 | "link": "https://opengameart.org/content/stoneblocks",
480 | "author": "SpriteAttack"
481 | },
482 | {
483 | "key": "lucifer_cannon",
484 | "title": "Powers Icons",
485 | "link": "https://opengameart.org/content/powers-icons",
486 | "author": "Clint Bellanger"
487 | },
488 | {
489 | "key": "explosion2",
490 | "title": "Explosion",
491 | "link": "https://opengameart.org/content/explosion",
492 | "author": "Cuzco"
493 | },
494 | {
495 | "key": "blackSmoke",
496 | "title": "Smoke Particle Assets",
497 | "link": "https://opengameart.org/content/smoke-particle-assets",
498 | "author": "Kenney"
499 | },
500 | {
501 | "key": "groundGrass",
502 | "title": "Topdown Tanks",
503 | "link": "https://kenney.nl/assets/topdown-tanks",
504 | "author": "Kenney"
505 | },
506 | {
507 | "key": "uiStart",
508 | "title": "Game icons",
509 | "link": "https://opengameart.org/content/game-icons",
510 | "author": "Kenney"
511 | },
512 | {
513 | "key": "cloud2",
514 | "title": "Cloud set",
515 | "link": "https://opengameart.org/content/cloud-set",
516 | "author": "Sam"
517 | },
518 | {
519 | "key": "uiDPad",
520 | "title": "Onscreen - Controls",
521 | "link": "http://kenney.nl/assets/onscreen-controls",
522 | "author": "Kenney"
523 | },
524 | {
525 | "key": "crate_10",
526 | "title": "Sokoban (100+ Tiles)",
527 | "link": "https://opengameart.org/content/sokoban-100-tiles",
528 | "author": "Kenney"
529 | },
530 | {
531 | "key": "meteorGrey_big1",
532 | "title": "Space Shooter Redux",
533 | "link": "https://opengameart.org/content/space-shooter-redux",
534 | "author": "Kenney"
535 | },
536 | {
537 | "key": "groundDirt",
538 | "title": "50 free textures 5 - with normalmaps",
539 | "link": "https://opengameart.org/content/50-free-textures-5-with-normalmaps",
540 | "author": "rubberduck"
541 | }
542 | ]
543 | }
544 | },
545 | "clickSound": {
546 | "type": "sound",
547 | "position": {
548 | "x": 0,
549 | "y": 0
550 | },
551 | "properties": {
552 | "key": "clickSound"
553 | }
554 | }
555 | }
556 | }
--------------------------------------------------------------------------------
/assets/json/menu.json:
--------------------------------------------------------------------------------
1 | {
2 | "assets": {
3 | "groundStone": {
4 | "type": "image",
5 | "source": "assets/images/sandstone_64.png"
6 | },
7 | "groundMountain": {
8 | "type": "image",
9 | "source": "assets/images/mountain_64.png"
10 | },
11 | "groundMountain2": {
12 | "type": "image",
13 | "source": "assets/images/mountain2_64.png"
14 | },
15 | "grass2": {
16 | "type": "image",
17 | "source": "assets/images/grass2_64.png"
18 | },
19 | "groundDirt": {
20 | "type": "image",
21 | "source": "assets/images/041.png"
22 | },
23 | "stone": {
24 | "type": "image",
25 | "source": "assets/images/stone_64.png"
26 | },
27 | "groundSand": {
28 | "type": "image",
29 | "source": "assets/images/sand_64.png"
30 | },
31 | "groundGrass": {
32 | "type": "image",
33 | "source": "assets/images/grass_64.png"
34 | },
35 | "clickSound": {
36 | "type": "sound",
37 | "source": "assets/sounds/click.mp3"
38 | },
39 | "groundTiled": {
40 | "type": "image",
41 | "source": "assets/images/tiled_64.png"
42 | },
43 | "uiArrowRight": {
44 | "type": "image",
45 | "source": "assets/images/arrowRight.png"
46 | },
47 | "uiArrowLeft": {
48 | "type": "image",
49 | "source": "assets/images/arrowLeft.png"
50 | },
51 | "uiSettings": {
52 | "type": "image",
53 | "source": "assets/images/gear.png"
54 | },
55 | "uiInformation": {
56 | "type": "image",
57 | "source": "assets/images/information.png"
58 | },
59 | "uiMusicOn": {
60 | "type": "image",
61 | "source": "assets/images/musicOn.png"
62 | },
63 | "uiMusicOff": {
64 | "type": "image",
65 | "source": "assets/images/musicOff.png"
66 | },
67 | "uiStart": {
68 | "type": "image",
69 | "source": "assets/images/buttonStart.png"
70 | },
71 | "cloud1": {
72 | "type": "image",
73 | "source": "assets/images/longCloud.png"
74 | },
75 | "cloud2": {
76 | "type": "image",
77 | "source": "assets/images/cloud.png"
78 | },
79 | "logoRobotRed": {
80 | "type": "image",
81 | "source": "assets/images/robot_redJump.png"
82 | },
83 | "logoRobotGreen": {
84 | "type": "image",
85 | "source": "assets/images/robot_greenJump.png"
86 | },
87 | "logoBulletLeft": {
88 | "type": "image",
89 | "source": "assets/images/tank_bulletFly2.png"
90 | },
91 | "robot3Dblue": {
92 | "type": "image",
93 | "source": "assets/images/robot_3Dblue.png"
94 | },
95 | "robot3Dgreen": {
96 | "type": "image",
97 | "source": "assets/images/robot_3Dgreen.png"
98 | },
99 | "robot3Dred": {
100 | "type": "image",
101 | "source": "assets/images/robot_3Dred.png"
102 | },
103 | "robot3Dyellow": {
104 | "type": "image",
105 | "source": "assets/images/robot_3Dyellow.png"
106 | },
107 | "logoBulletRight": {
108 | "type": "image",
109 | "source": "assets/images/tank_bulletFly3.png"
110 | },
111 | "redRobotMoving": {
112 | "type": "spritesheet",
113 | "source": "assets/images/redRobotMoving.png",
114 | "frameWidth": 90,
115 | "frameHeight": 75,
116 | "frames": 2
117 | },
118 | "yellowRobotMoving": {
119 | "type": "spritesheet",
120 | "source": "assets/images/yellowRobotMoving.png",
121 | "frameWidth": 92,
122 | "frameHeight": 76,
123 | "frames": 2
124 | },
125 | "greenRobotMoving": {
126 | "type": "spritesheet",
127 | "source": "assets/images/greenRobotMoving.png",
128 | "frameWidth": 79,
129 | "frameHeight": 60,
130 | "frames": 2
131 | },
132 | "greyRobotMoving": {
133 | "type": "spritesheet",
134 | "source": "assets/images/greyRobotMoving.png",
135 | "frameWidth": 79,
136 | "frameHeight": 75,
137 | "frames": 2
138 | },
139 | "uiWindow": {
140 | "type": "image",
141 | "source": "assets/images/UI_WINDOW_1.png"
142 | },
143 | "uiWindowBL": {
144 | "type": "image",
145 | "source": "assets/images/UI_WINDOW_2.png"
146 | },
147 | "uiWindowB": {
148 | "type": "image",
149 | "source": "assets/images/UI_WINDOW_3.png"
150 | },
151 | "uiWindowBR": {
152 | "type": "image",
153 | "source": "assets/images/UI_WINDOW_4.png"
154 | },
155 | "uiWindowR": {
156 | "type": "image",
157 | "source": "assets/images/UI_WINDOW_5.png"
158 | },
159 | "uiWindowL": {
160 | "type": "image",
161 | "source": "assets/images/UI_WINDOW_6.png"
162 | },
163 | "uiWindowTR": {
164 | "type": "image",
165 | "source": "assets/images/UI_WINDOW_7.png"
166 | },
167 | "uiWindowTL": {
168 | "type": "image",
169 | "source": "assets/images/UI_WINDOW_8.png"
170 | },
171 | "uiWindowT": {
172 | "type": "image",
173 | "source": "assets/images/UI_WINDOW_9.png"
174 | },
175 | "uiCross": {
176 | "type": "image",
177 | "source": "assets/images/cross.png"
178 | }
179 | },
180 | "groups": [
181 | "background",
182 | "spawners",
183 | "shadows",
184 | "robots",
185 | "robotTexts",
186 | "logo",
187 | "chooser",
188 | "selectables",
189 | "hud"
190 | ],
191 | "prefabs": {
192 | "background": {
193 | "type": "tileSprite",
194 | "position": {
195 | "x": 0,
196 | "y": 0
197 | },
198 | "properties": {
199 | "group": "background",
200 | "key": "groundGrass",
201 | "size": {
202 | "width": 640,
203 | "height": 360
204 | },
205 | "fixedToCamera": true
206 | }
207 | },
208 | "redRobotMovingText": {
209 | "type": "text",
210 | "position": {
211 | "x": 0,
212 | "y": -92
213 | },
214 | "properties": {
215 | "text": "Easy",
216 | "group": "robotTexts",
217 | "fixedToCamera": true,
218 | "style": {
219 | "font": "18pt Arial",
220 | "fill": "#ffffff",
221 | "align": "center"
222 | },
223 | "anchor": {
224 | "x": 0.5,
225 | "y": 0.5
226 | },
227 | "shadow": true
228 | }
229 | },
230 | "greenRobotMovingText": {
231 | "type": "text",
232 | "position": {
233 | "x": 0,
234 | "y": -92
235 | },
236 | "properties": {
237 | "text": "Medium",
238 | "group": "robotTexts",
239 | "fixedToCamera": true,
240 | "style": {
241 | "font": "18pt Arial",
242 | "fill": "#ffffff",
243 | "align": "center"
244 | },
245 | "anchor": {
246 | "x": 0.5,
247 | "y": 0.5
248 | },
249 | "shadow": true
250 | }
251 | },
252 | "yellowRobotMovingText": {
253 | "type": "text",
254 | "position": {
255 | "x": 0,
256 | "y": -92
257 | },
258 | "properties": {
259 | "text": "Hard",
260 | "group": "robotTexts",
261 | "fixedToCamera": true,
262 | "style": {
263 | "font": "18pt Arial",
264 | "fill": "#ffffff",
265 | "align": "center"
266 | },
267 | "anchor": {
268 | "x": 0.5,
269 | "y": 0.5
270 | },
271 | "shadow": true
272 | }
273 | },
274 | "greyRobotMovingText": {
275 | "type": "text",
276 | "position": {
277 | "x": 0,
278 | "y": -92
279 | },
280 | "properties": {
281 | "text": "Very hard",
282 | "group": "robotTexts",
283 | "fixedToCamera": true,
284 | "style": {
285 | "font": "18pt Arial",
286 | "fill": "#ffffff",
287 | "align": "center"
288 | },
289 | "anchor": {
290 | "x": 0.5,
291 | "y": 0.5
292 | },
293 | "shadow": true
294 | }
295 | },
296 | "logoBulletLeft": {
297 | "type": "sprite",
298 | "position": {
299 | "x": 374,
300 | "y": 62
301 | },
302 | "properties": {
303 | "group": "logo",
304 | "key": "logoBulletLeft",
305 | "anchor": {
306 | "x": 0.5,
307 | "y": 0.5
308 | },
309 | "angle": 8,
310 | "mirror": {
311 | "x": true
312 | },
313 | "alpha": 0
314 | }
315 | },
316 | "logoBulletRight": {
317 | "type": "sprite",
318 | "position": {
319 | "x": 342,
320 | "y": 80
321 | },
322 | "properties": {
323 | "group": "logo",
324 | "key": "logoBulletRight",
325 | "anchor": {
326 | "x": 0.5,
327 | "y": 0.5
328 | },
329 | "angle": 343,
330 | "scale": {
331 | "x": 0.7,
332 | "y": 0.7
333 | },
334 | "alpha": 0
335 | }
336 | },
337 | "logoRobotRed": {
338 | "type": "sprite",
339 | "position": {
340 | "x": 374,
341 | "y": 62
342 | },
343 | "properties": {
344 | "group": "logo",
345 | "key": "logoRobotRed",
346 | "anchor": {
347 | "x": 0.5,
348 | "y": 0.5
349 | },
350 | "angle": 8,
351 | "mirror": {
352 | "x": true
353 | },
354 | "alpha": 0
355 | }
356 | },
357 | "logoRobotGreen": {
358 | "type": "sprite",
359 | "position": {
360 | "x": 342,
361 | "y": 80
362 | },
363 | "properties": {
364 | "group": "logo",
365 | "key": "logoRobotGreen",
366 | "anchor": {
367 | "x": 0.5,
368 | "y": 0.5
369 | },
370 | "angle": 343,
371 | "scale": {
372 | "x": 0.9,
373 | "y": 0.9
374 | },
375 | "alpha": 0
376 | }
377 | },
378 | "middleCloud": {
379 | "type": "sprite",
380 | "position": {
381 | "x": 320,
382 | "y": 100
383 | },
384 | "properties": {
385 | "group": "logo",
386 | "key": "cloud1",
387 | "anchor": {
388 | "x": 0.5,
389 | "y": 0.5
390 | },
391 | "alpha": 0
392 | }
393 | },
394 | "leftCloud": {
395 | "type": "sprite",
396 | "position": {
397 | "x": -211,
398 | "y": 122
399 | },
400 | "properties": {
401 | "group": "logo",
402 | "key": "cloud2",
403 | "anchor": {
404 | "x": 0,
405 | "y": 0.5
406 | }
407 | }
408 | },
409 | "rightCloud": {
410 | "type": "sprite",
411 | "position": {
412 | "x": 706,
413 | "y": 122
414 | },
415 | "properties": {
416 | "group": "logo",
417 | "key": "cloud2",
418 | "anchor": {
419 | "x": 0.5,
420 | "y": 0.5
421 | },
422 | "scale": {
423 | "x": 0.63,
424 | "y": 0.63
425 | },
426 | "angle": 180
427 | }
428 | },
429 | "redRobotMoving": {
430 | "type": "animatedSprite",
431 | "position": {
432 | "x": 320,
433 | "y": 180
434 | },
435 | "properties": {
436 | "group": "chooser",
437 | "key": "redRobotMoving",
438 | "secondKey": "robot3Dred",
439 | "anchor": {
440 | "x": 0.5,
441 | "y": 1
442 | },
443 | "animations": [
444 | {
445 | "name": "driving",
446 | "frameRate": 10,
447 | "frames": [
448 | 0,
449 | 1
450 | ],
451 | "loop": true,
452 | "killOnComplete": false
453 | }
454 | ]
455 | }
456 | },
457 | "yellowRobotMoving": {
458 | "type": "animatedSprite",
459 | "position": {
460 | "x": 180,
461 | "y": 180
462 | },
463 | "properties": {
464 | "group": "chooser",
465 | "key": "yellowRobotMoving",
466 | "secondKey": "robot3Dyellow",
467 | "anchor": {
468 | "x": 0.5,
469 | "y": 1
470 | },
471 | "animations": [
472 | {
473 | "name": "driving",
474 | "frameRate": 10,
475 | "frames": [
476 | 0,
477 | 1
478 | ],
479 | "loop": true,
480 | "killOnComplete": false
481 | }
482 | ]
483 | }
484 | },
485 | "greenRobotMoving": {
486 | "type": "animatedSprite",
487 | "position": {
488 | "x": 420,
489 | "y": 180
490 | },
491 | "properties": {
492 | "group": "chooser",
493 | "key": "greenRobotMoving",
494 | "secondKey": "robot3Dgreen",
495 | "anchor": {
496 | "x": 0.5,
497 | "y": 1
498 | },
499 | "animations": [
500 | {
501 | "name": "driving",
502 | "frameRate": 10,
503 | "frames": [
504 | 0,
505 | 1
506 | ],
507 | "loop": true,
508 | "killOnComplete": false
509 | }
510 | ]
511 | }
512 | },
513 | "greyRobotMoving": {
514 | "type": "animatedSprite",
515 | "position": {
516 | "x": 550,
517 | "y": 180
518 | },
519 | "properties": {
520 | "group": "chooser",
521 | "key": "greyRobotMoving",
522 | "secondKey": "robot3Dblue",
523 | "anchor": {
524 | "x": 0.5,
525 | "y": 1
526 | },
527 | "animations": [
528 | {
529 | "name": "driving",
530 | "frameRate": 10,
531 | "frames": [
532 | 0,
533 | 1
534 | ],
535 | "loop": true,
536 | "killOnComplete": false
537 | }
538 | ]
539 | }
540 | },
541 | "menuChooser": {
542 | "type": "menuRobotChooser",
543 | "position": {
544 | "x": 320,
545 | "y": 290
546 | },
547 | "properties": {
548 | "group": "spawners",
549 | "pool": "chooser",
550 | "robots": [
551 | "redRobotMoving",
552 | "greenRobotMoving",
553 | "yellowRobotMoving",
554 | "greyRobotMoving"
555 | ]
556 | }
557 | },
558 | "menuRobotSpawner": {
559 | "type": "menuRobotSpawner",
560 | "position": {
561 | "x": 0,
562 | "y": 0
563 | },
564 | "properties": {
565 | "key": "",
566 | "group": "spawners",
567 | "pool": "robots",
568 | "mode": "limited",
569 | "limit": 3,
570 | "spawnTimeInSeconds": {
571 | "min": 0,
572 | "max": 1
573 | }
574 | }
575 | },
576 | "informationButton": {
577 | "type": "button",
578 | "position": {
579 | "x": 616,
580 | "y": 24
581 | },
582 | "properties": {
583 | "group": "hud",
584 | "key": "uiInformation",
585 | "anchor": {
586 | "x": 0.5,
587 | "y": 0.5
588 | }
589 | }
590 | },
591 | "soundButton": {
592 | "type": "button",
593 | "position": {
594 | "x": 616,
595 | "y": 72
596 | },
597 | "properties": {
598 | "group": "hud",
599 | "key": "uiMusicOn",
600 | "anchor": {
601 | "x": 0.5,
602 | "y": 0.5
603 | }
604 | }
605 | },
606 | "leftButton": {
607 | "type": "button",
608 | "position": {
609 | "x": 240,
610 | "y": 250
611 | },
612 | "properties": {
613 | "group": "hud",
614 | "key": "uiArrowLeft",
615 | "anchor": {
616 | "x": 0.5,
617 | "y": 0.5
618 | }
619 | }
620 | },
621 | "rightButton": {
622 | "type": "button",
623 | "position": {
624 | "x": 400,
625 | "y": 250
626 | },
627 | "properties": {
628 | "group": "hud",
629 | "key": "uiArrowRight",
630 | "anchor": {
631 | "x": 0.5,
632 | "y": 0.5
633 | }
634 | }
635 | },
636 | "startButton": {
637 | "type": "button",
638 | "position": {
639 | "x": 320,
640 | "y": 328
641 | },
642 | "properties": {
643 | "group": "hud",
644 | "key": "uiStart",
645 | "anchor": {
646 | "x": 0.5,
647 | "y": 0.5
648 | }
649 | }
650 | },
651 | "menuBackgroundChooser": {
652 | "type": "menuBackgroundChooser",
653 | "position": {
654 | "x": 32,
655 | "y": 328
656 | },
657 | "properties": {
658 | "group": "spawners",
659 | "pool": "selectables",
660 | "columns": 4,
661 | "anchor": {
662 | "x": 0.5,
663 | "y": 0.5
664 | },
665 | "scale": {
666 | "x": 0.5,
667 | "y": 0.5
668 | },
669 | "shadow": true,
670 | "spacing": 16,
671 | "backgrounds": [
672 | "stone",
673 | "grass2",
674 | "groundDirt",
675 | "groundStone",
676 | "groundMountain",
677 | "groundSand",
678 | "groundGrass",
679 | "groundTiled",
680 | "groundMountain2"
681 | ]
682 | }
683 | },
684 | "pauseDialogSpawner": {
685 | "type": "pauseDialogSpawner",
686 | "position": {
687 | "x": 0,
688 | "y": 0
689 | },
690 | "properties": {
691 | "key": "",
692 | "group": "spawners",
693 | "pool": "hud",
694 | "mode": "never",
695 | "size": {
696 | "x": 200,
697 | "y": 80
698 | }
699 | }
700 | },
701 | "clickSound": {
702 | "type": "sound",
703 | "position": {
704 | "x": 0,
705 | "y": 0
706 | },
707 | "properties": {
708 | "key": "clickSound"
709 | }
710 | },
711 | "hintText": {
712 | "type": "text",
713 | "position": {
714 | "x": 632,
715 | "y": 360
716 | },
717 | "properties": {
718 | "group": "hud",
719 | "text": "Tip: Press shift in game to open the HUD!",
720 | "style": {
721 | "font": "10pt Arial",
722 | "fill": "#ffffff",
723 | "align": "right"
724 | },
725 | "anchor": {
726 | "x": 1,
727 | "y": 1
728 | },
729 | "shadow": true
730 | }
731 | }
732 | }
733 | }
--------------------------------------------------------------------------------
/assets/sounds/click.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/sounds/click.mp3
--------------------------------------------------------------------------------
/assets/sounds/explosion.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/sounds/explosion.mp3
--------------------------------------------------------------------------------
/assets/sounds/pling.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/sounds/pling.mp3
--------------------------------------------------------------------------------
/assets/sounds/shot.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dasheck0/robots/4767138d127cb6209d685a99fd7acb8e68483366/assets/sounds/shot.mp3
--------------------------------------------------------------------------------
/deliver.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | gulp transpile minify linkPhaser calculateSize copy
4 | #gulp transpile minifyAssets minify linkPhaser calculateSize copy
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 | const gulp = require('gulp');
6 | const fs = require('fs');
7 | const path = require('path');
8 | const opn = require('opn');
9 | const minify = require('gulp-minify');
10 | const babel = require('gulp-babel');
11 | const getFolderSize = require('get-folder-size');
12 | const imagemin = require('gulp-imagemin');
13 |
14 | gulp.task('minifyAssets', () =>
15 | gulp.src('assets/images/*')
16 | .pipe(imagemin())
17 | .pipe(gulp.dest('assets2'))
18 | );
19 |
20 | gulp.task('copy', ['minify', 'transpile', 'linkPhaser', 'calculateSize'], () => {
21 | const destination = '/Applications/MAMP/htdocs/dasheck-hackathon-phaser';
22 | const sources = ['dist', 'assets'].reverse();
23 |
24 | sources.forEach(source => copyFolderRecursiveSync(path.join(process.cwd(), source), destination));
25 | copyFileSync(path.join(process.cwd(), 'index.html'), destination);
26 | });
27 |
28 | gulp.task('open', () => {
29 | opn('http://localhost:8888/dasheck-hackathon-phaser');
30 | });
31 |
32 | gulp.task('minify', ['transpile'], (done) => {
33 | gulp.src('dist/**/*.js')
34 | .pipe(minify({
35 | ext: {
36 | min: '.js'
37 | },
38 | noSource: true,
39 | preserveComments: () => false,
40 | ignoreFiles: ['phaser.js']
41 | }))
42 | .pipe(gulp.dest('dist'))
43 | .on('end', done);
44 | });
45 |
46 | gulp.task('calculateSize', ['minify', 'transpile'], (done) => {
47 | getFolderSize(path.join(process.cwd(), 'dist'), /phaser.js/g, (error, distSize) => {
48 | getFolderSize(path.join(process.cwd(), 'assets'), (error, assetsSize) => {
49 | console.log('Size:', ((distSize + assetsSize) / 1024.0).toFixed(2), 'KB');
50 | done();
51 | });
52 | });
53 | });
54 |
55 | gulp.task('transpile', () => {
56 | deleteFolderRecursive(path.join(process.cwd(), 'dist'));
57 | return gulp.src('js/**/*.js')
58 | .pipe(babel({
59 | presets: ['es2015']
60 | }))
61 | .pipe(gulp.dest('dist'));
62 | });
63 |
64 | gulp.task('linkPhaser', ['minify'], () => {
65 | fs.mkdirSync(path.join(process.cwd(), 'dist/libs'));
66 | copyFileSync(path.join(process.cwd(), 'libs/phaser.js'), path.join(process.cwd(), 'dist/libs/phaser.js'));
67 | });
68 |
69 | function copyFileSync(source, target) {
70 |
71 | var targetFile = target;
72 |
73 | //if target is a directory a new file with the same name will be created
74 | if (fs.existsSync(target)) {
75 | if (fs.lstatSync(target).isDirectory()) {
76 | targetFile = path.join(target, path.basename(source));
77 | }
78 | }
79 |
80 | fs.writeFileSync(targetFile, fs.readFileSync(source));
81 | }
82 |
83 | function copyFolderRecursiveSync(source, target) {
84 | var files = [];
85 |
86 | //check if folder needs to be created or integrated
87 | var targetFolder = path.join(target, path.basename(source));
88 | if (!fs.existsSync(targetFolder)) {
89 | fs.mkdirSync(targetFolder);
90 | }
91 |
92 | //copy
93 | if (fs.lstatSync(source).isDirectory()) {
94 | files = fs.readdirSync(source);
95 | files.forEach(function (file) {
96 | var curSource = path.join(source, file);
97 | if (fs.lstatSync(curSource).isDirectory()) {
98 | copyFolderRecursiveSync(curSource, targetFolder);
99 | } else {
100 | copyFileSync(curSource, targetFolder);
101 | }
102 | });
103 | }
104 | }
105 |
106 | function deleteFolderRecursive(path) {
107 | if (fs.existsSync(path)) {
108 | fs.readdirSync(path).forEach(function (file, index) {
109 | var curPath = path + "/" + file;
110 | if (fs.lstatSync(curPath).isDirectory()) { // recurse
111 | deleteFolderRecursive(curPath);
112 | } else { // delete file
113 | fs.unlinkSync(curPath);
114 | }
115 | });
116 | fs.rmdirSync(path);
117 | }
118 | };
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 | Bots
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/js/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 16/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.debug = true;
8 | Bots.scale = 0.3;
9 | Bots.worldSize = new Phaser.Point(3000, 3000);
10 | Bots.screenSize = new Phaser.Point(640, 360);
11 | Bots.cameraPadding = 100;
12 | Bots.minimapWidth = Bots.screenSize.x * 0.25;
13 | Bots.minimapHeight = (Bots.minimapWidth * Bots.worldSize.y) / Bots.worldSize.x;
14 | Bots.minimapPadding = new Phaser.Point(16, 16);
15 | Bots.killCount = 0;
16 | Bots.deathCount = 0;
17 | Bots.soundsEnabled = true;
18 | Bots.background = '';
--------------------------------------------------------------------------------
/js/main.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | window.onload = function () {
9 | var game = new Phaser.Game(640, 360, Phaser.CANVAS);
10 |
11 | game.state.add('boot', new Bots.Boot());
12 | game.state.add('loading', new Bots.Loading());
13 | game.state.add('level', new Bots.Level());
14 | game.state.add('menu', new Bots.Menu());
15 | game.state.add('credits', new Bots.Credits());
16 |
17 | game.state.start('boot', true, false, {
18 | menu: 'assets/json/menu.json',
19 | level: 'assets/json/level.json',
20 | credits: 'assets/json/credits.json'
21 | });
22 | };
--------------------------------------------------------------------------------
/js/prefabs/animatedSprite.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 22/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.AnimatedSprite = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | (properties.animations || []).forEach((animation) => {
11 | this.animations.add(animation.name, properties.frames, properties.frameRate, properties.loop, properties.killOnComplete);
12 | })
13 | };
14 |
15 | Bots.AnimatedSprite.prototype = Object.create(Bots.Prefab.prototype);
16 | Bots.AnimatedSprite.prototype.constructor = Bots.AnimatedSprite;
17 |
18 | Bots.AnimatedSprite.prototype.play = function (name) {
19 | const animation = this.properties.animations.filter(animation => animation.name === name)[0];
20 | if (animation) {
21 | this.animations.play(animation.name, animation.frameRate, animation.loop, animation.killOnComplete);
22 | }
23 | }
--------------------------------------------------------------------------------
/js/prefabs/bossRobot.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 16/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.BossRobot = function (state, name, position, properties) {
8 | Bots.DroppableRobot.call(this, state, name, position, properties);
9 |
10 | this.boss = true;
11 | this.currentDestination = null;
12 | this.body.mass = 100;
13 | };
14 |
15 | Bots.BossRobot.prototype = Object.create(Bots.DroppableRobot.prototype);
16 | Bots.BossRobot.prototype.constructor = Bots.BossRobot;
17 |
18 | Bots.BossRobot.prototype.initializeObject = function () {
19 | Bots.DroppableRobot.prototype.initializeObject(this);
20 |
21 | this.properties.rotationSpeed = this.properties.speed / 17;
22 | this.properties.maxSpeed = this.properties.speed * 2;
23 | this.body.maxVelocity.setTo(this.properties.maxSpeed);
24 |
25 | this.smokeTimer = this.game.time.events.loop(500, ()=> getMemberByName(this.state.groups.spawners, 'smokeSpawner').spawn(this), this);
26 | this.checkSurroundingsTimer = this.game.time.events.loop(1000, this.attackSurrounding, this);
27 | this.jumpTimer = this.game.time.events.add(11284, this.jump, this);
28 | this.meteoritTimer = this.game.time.events.add(17420, this.initiateMeteoritHail, this);
29 | }
30 |
31 | Bots.BossRobot.prototype.getClosestMemberOfGroup = function (group) {
32 | let closestMember = null;
33 | let closestDistance = Number.MAX_VALUE;
34 |
35 | group.forEachAlive((member) => {
36 | if (member.name !== this.name) {
37 | const distance = this.game.physics.arcade.distanceBetween(this, member);
38 | if (distance < closestDistance) {
39 | closestDistance = distance;
40 | closestMember = member;
41 | }
42 | }
43 | });
44 |
45 | return {
46 | member: closestMember,
47 | distance: closestDistance,
48 | present: closestMember !== null
49 | };
50 | }
51 |
52 | Bots.BossRobot.prototype.update = function () {
53 | Bots.DroppableRobot.prototype.update(this);
54 |
55 | if (!this.isDead) {
56 | if (!this.currentDestination || this.game.physics.arcade.distanceToXY(this, this.currentDestination.x, this.currentDestination.y) <= 50) {
57 | this.currentDestination = new Phaser.Point(randomInteger(Bots.worldSize.x) - Bots.worldSize.x / 2, randomInteger(Bots.worldSize.y) - Bots.worldSize.y / 2);
58 | const offset = -60 * this.game.rnd.realInRange(this.properties.accuracy, 1) + 60;
59 | }
60 |
61 | if (this.currentDestination) {
62 | this.rotation = this.game.physics.arcade.angleToXY(this, this.currentDestination.x, this.currentDestination.y, true);
63 | this.game.physics.arcade.moveToObject(this, this.currentDestination, this.properties.maxSpeed);
64 | }
65 | //
66 | // if (!this.checkSurroundingsTimer) {
67 | // this.checkSurroundingsTimer = this.game.time.events.loop(1000, this.attackSurrounding, this);
68 | // }
69 | }
70 | }
71 |
72 | Bots.BossRobot.prototype.attackNearbyObjects = function (group) {
73 | if (!this.attackedNearbyObjectInTurn) {
74 | group.forEachAlive((object) => {
75 | if (this.game.physics.arcade.distanceBetween(this, object) < this.properties.shootRange && this.game.rnd.frac() < this.properties.sloppiness) {
76 | this.rotation = this.game.physics.arcade.angleBetween(this, object);
77 | Bots.DroppableRobot.prototype.fire.call(this);
78 | this.attackedNearbyObjectInTurn = true;
79 | return;
80 | }
81 | }, this);
82 | }
83 | }
84 |
85 | Bots.BossRobot.prototype.attackSurrounding = function () {
86 | this.attackedNearbyObjectInTurn = false;
87 | this.attackNearbyObjects(this.state.groups.robots);
88 | this.attackNearbyObjects(this.state.groups.chests);
89 | }
90 |
91 | Bots.BossRobot.prototype.jump = function () {
92 | this.game.add.tween(this.scale).to({
93 | x: Bots.scale * this.properties.scaleMultiplier * 2,
94 | y: Bots.scale * this.properties.scaleMultiplier * 2
95 | }, 300, Phaser.Easing.Linear.None, true)
96 | .onComplete.add(() => {
97 | this.scale.x = Bots.scale * this.properties.scaleMultiplier * 2;
98 | this.scale.y = Bots.scale * this.properties.scaleMultiplier * 2;
99 |
100 | this.isJumping = false;
101 | this.game.add.tween(this.scale).to({
102 | x: Bots.scale * this.properties.scaleMultiplier,
103 | y: Bots.scale * this.properties.scaleMultiplier
104 | }, 300, Phaser.Easing.Linear.None, true)
105 | .onComplete.add(() => {
106 | this.scale.x = Bots.scale * this.properties.scaleMultiplier;
107 | this.scale.y = Bots.scale * this.properties.scaleMultiplier;
108 |
109 | getMemberByName(this.state.groups.spawners, 'earthQuakeSpawner').spawn(this, 10);
110 | }, this);
111 | }, this);
112 | }
113 |
114 | Bots.BossRobot.prototype.initiateMeteoritHail = function () {
115 | this.state.groups.robots.forEachAlive((robot) => {
116 | if (!robot.isDead && !robot.boss && this.game.physics.arcade.distanceBetween(this, robot) < this.properties.shootRange) {
117 | const position = new Phaser.Point(robot.x, robot.y);
118 | getMemberByName(this.state.groups.spawners, 'meteoritSpawner').forceSpawn(position);
119 | }
120 | })
121 |
122 | const count = this.game.rnd.integerInRange(5, 10);
123 | for (let i = 0; i < count; i++) {
124 | this.game.time.events.add(this.game.rnd.integerInRange(50, 500), () => {
125 | const position = new Phaser.Point(this.x + this.game.rnd.integerInRange(0, 200) * (randomBoolean() ? 1 : -1), this.y + this.game.rnd.integerInRange(0, 200) * (randomBoolean() ? 1 : -1));
126 | getMemberByName(this.state.groups.spawners, 'meteoritSpawner').forceSpawn(position);
127 | }, this);
128 | }
129 | }
--------------------------------------------------------------------------------
/js/prefabs/bossRobotSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.BossRobotSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.BossRobotSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.BossRobotSpawner.prototype.constructor = Bots.BossRobotSpawner;
13 |
14 | Bots.BossRobotSpawner.prototype.spawn = function (withDelay) {
15 | const time = this.game.rnd.integerInRange(this.properties.spawnTimeInSeconds.min, this.properties.spawnTimeInSeconds.max);
16 | this.game.time.events.add(withDelay ? time * 1000 : 0, () => {
17 | if (this.isAllowedToSpawn()) {
18 | const position = new Phaser.Point(this.game.rnd.between(-Bots.worldSize.x / 2, Bots.worldSize.x / 2), this.game.rnd.between(-Bots.worldSize.y / 2, Bots.worldSize.y / 2));
19 | const name = `object_${this.pool.countLiving()}`;
20 | const object = this.createObject(name, position);
21 | }
22 | }, this);
23 | }
24 |
25 | Bots.BossRobotSpawner.prototype.createObject = function (name, position) {
26 | const maxHealth = this.state.game.rnd.integerInRange(1000, 1500);
27 | const randomName = getRandomName();
28 |
29 | getMemberByName(this.state.groups.spawners, 'messageSpawner').spawn(`A new boss '${randomName}' has entered the stage`, 'warning');
30 |
31 | return new Bots.BossRobot(this.state, name, position, {
32 | group: "robots",
33 | key: sample(['robot3Dred', 'robot3Dblue', 'robot3Dgreen', 'robot3Dyellow']),
34 | friction: 10,
35 | rotationSpeed: 5,
36 | attack: this.state.game.rnd.integerInRange(60, 80),
37 | defense: this.state.game.rnd.integerInRange(130, 180),
38 | speed: this.state.game.rnd.integerInRange(20, 35),
39 | health: maxHealth,
40 | maxHealth: maxHealth,
41 | displayName: randomName,
42 | shootRange: this.state.game.rnd.integerInRange(300, 500),
43 | stopRange: this.state.game.rnd.integerInRange(150, 200),
44 | accuracy: this.state.game.rnd.realInRange(0.9, 1),
45 | scaleMultiplier: 3,
46 | sloppiness: this.state.game.rnd.realInRange(0.25, 0.6)
47 | });
48 | }
49 |
--------------------------------------------------------------------------------
/js/prefabs/button.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 22/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.Button = function (state, name, position, properties) {
10 | Bots.Prefab.call(this, state, name, position, properties);
11 |
12 | this.fixedToCamera = true;
13 |
14 | this.inputEnabled = true;
15 | this.input.priorityId = 999; // ui
16 | this.input.useHandCursor = true;
17 |
18 | this.events.onInputDown.add(this.onButtonPressed, this);
19 | this.events.onInputUp.add(this.onButtonReleased, this);
20 |
21 | this.shadow = this.game.add.sprite(this.x, this.y + 2, this.properties.key);
22 | this.shadow.tint = 0x000000;
23 | this.shadow.anchor.setTo(0.5);
24 | this.shadow.fixedToCamera = true;
25 |
26 | this.state.groups.hud.addAt(this.shadow, 0);
27 | };
28 |
29 | Bots.Button.prototype = Object.create(Bots.Prefab.prototype);
30 | Bots.Button.prototype.constructor = Bots.Button;
31 |
32 | Bots.Button.prototype.onButtonPressed = function () {
33 | if (!this.game.paused || this.properties.force) {
34 | this.scale.setTo(1.1);
35 | this.shadow.scale.setTo(1.1);
36 | }
37 | }
38 |
39 | Bots.Button.prototype.onButtonReleased = function () {
40 | if (!this.game.paused || this.properties.force) {
41 | this.scale.setTo(1);
42 | this.shadow.scale.setTo(1);
43 |
44 | if (Bots.soundsEnabled) {
45 | this.state.prefabs.clickSound.safelyPlay();
46 | }
47 |
48 | this.state.onButtonPressed(this);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/js/prefabs/chest.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.Chest = function (state, name, position, properties) {
10 | Bots.Droppable.call(this, state, name, position, properties);
11 |
12 | this.scale.setTo(Bots.scale);
13 | this.anchor.setTo(0.5);
14 | this.angle = this.game.rnd.integerInRange(0, 360);
15 |
16 | this.shadow = this.game.add.sprite(this.x, this.y, properties.key);
17 | this.shadow.scale.x = this.scale.x * 1.3;
18 | this.shadow.scale.y = this.scale.y * 1.3;
19 | this.shadow.alpha = 0.25;
20 | this.shadow.anchor.setTo(0.5);
21 | this.shadow.tint = 0x000000;
22 | this.shadow.name = `${name}_shadow`;
23 | this.shadow.angle = this.angle;
24 | this.state.groups.shadows.add(this.shadow);
25 | };
26 |
27 | Bots.Chest.prototype = Object.create(Bots.Droppable.prototype);
28 | Bots.Chest.prototype.constructor = Bots.Chest;
29 |
30 | Bots.Chest.prototype.initializeObject = function () {
31 | this.game.physics.enable(this, Phaser.Physics.ARCADE);
32 | this.body.immovable = true;
33 | }
34 |
35 | Bots.Chest.prototype.hit = function () {
36 | this.properties.lifePoints -= 1;
37 | return this.properties.lifePoints <= 0;
38 | }
--------------------------------------------------------------------------------
/js/prefabs/chestSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.ChestSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.ChestSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.ChestSpawner.prototype.constructor = Bots.ChestSpawner;
13 |
14 | Bots.ChestSpawner.prototype.createObject = function (name, position) {
15 | const key = sample(this.properties.keys);
16 |
17 | return new Bots.Chest(this.state, name, position, {
18 | key,
19 | group: 'chests',
20 | scale: {
21 | x: 0.75,
22 | y: 0.75
23 | },
24 | lifePoints: this.game.rnd.integerInRange(1, 5)
25 | });
26 | }
--------------------------------------------------------------------------------
/js/prefabs/control.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 21/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Control = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | this.isPressed = false;
11 |
12 | this.inputEnabled = true;
13 | this.events.onInputDown.add(() => (this.isPressed = true), this);
14 | this.events.onInputUp.add(() => {
15 | this.isPressed = false;
16 | }, this);
17 | };
18 |
19 | Bots.Control.prototype = Object.create(Bots.Prefab.prototype);
20 | Bots.Control.prototype.constructor = Bots.Control;
--------------------------------------------------------------------------------
/js/prefabs/creditsItem.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.CreditsItem = function (state, name, position, properties) {
10 | Bots.Prefab.call(this, state, name, position, properties);
11 |
12 | const factor = 0.4;
13 |
14 | this.graphics = this.game.add.graphics(0, 0);
15 | this.addChild(this.graphics);
16 |
17 | this.sprite = this.game.add.sprite(0, 0, properties.dummyKey);
18 | this.sprite.anchor.setTo(0.5);
19 |
20 | const scaleX = (factor * this.properties.size.width) / this.sprite.width;
21 | const scaleY = (factor * this.properties.size.height) / this.sprite.height;
22 |
23 | this.sprite.scale.setTo((scaleX < scaleY) ? scaleX : scaleY);
24 | this.sprite.x = -this.properties.size.width / 2 + this.sprite.width / 2 + 8;
25 | this.addChild(this.sprite);
26 |
27 | this.caption = this.game.add.text(this.sprite.x + this.sprite.width / 2 + 8, this.sprite.y - this.sprite.height / 2, shortenName(properties.title, 15), this.captionTextStyle());
28 | this.addChild(this.caption);
29 |
30 | this.author = this.game.add.text(this.sprite.x + this.sprite.width / 2 + 8, this.sprite.y - this.sprite.height / 2 + 16, `by ${shortenName(properties.author, 12)}`, this.regularTextStyle());
31 | this.addChild(this.author);
32 |
33 | this.linkIcon = this.game.add.sprite(this.properties.size.width / 2 - 8, this.properties.size.height / 2 - 8, 'uiLink');
34 | this.linkIcon.anchor.setTo(1);
35 | this.addChild(this.linkIcon);
36 |
37 | this.linkIcon.inputEnabled = true;
38 | this.linkIcon.events.onInputUp.add(() => {
39 | if (this.game.device.iPad) {
40 | location.href = properties.link;
41 | } else {
42 | var newWindow = window.open(properties.link, '_blank');
43 | if (newWindow) {
44 | newWindow.focus();
45 | } else {
46 | location.href = properties.link;
47 | }
48 | }
49 | }, this);
50 | };
51 |
52 | Bots.CreditsItem.prototype = Object.create(Bots.Prefab.prototype);
53 | Bots.CreditsItem.prototype.constructor = Bots.CreditsItem;
54 |
55 | Bots.CreditsItem.prototype.update = function () {
56 | this.graphics.clear();
57 | this.graphics.beginFill(0x000000, 0.5);
58 | this.graphics.drawRect(-this.properties.size.width / 2, -this.properties.size.height / 2, this.properties.size.width, this.properties.size.height);
59 | this.graphics.endFill();
60 | }
61 |
62 | Bots.CreditsItem.prototype.captionTextStyle = function () {
63 | return {
64 | font: '10pt bold Helvetica, sans-serif',
65 | fill: '#ffffff',
66 | align: 'left'
67 | }
68 | }
69 |
70 | Bots.CreditsItem.prototype.regularTextStyle = function (fontSize = 8) {
71 | return {
72 | font: `${fontSize}pt Helvetica, sans-serif`,
73 | fill: '#ffffff',
74 | align: 'left'
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/js/prefabs/creditsItemSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.CreditsItemSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 |
10 | this.currentRow = 0;
11 | };
12 |
13 | Bots.CreditsItemSpawner.prototype = Object.create(Bots.Spawner.prototype);
14 | Bots.CreditsItemSpawner.prototype.constructor = Bots.CreditsItemSpawner;
15 |
16 | Bots.CreditsItemSpawner.prototype.spawn = function () {
17 | this.properties.items.forEach((item, index) => {
18 | const name = `object_${this.pool.countLiving()}`;
19 | const object = this.createObject(name, item, index);
20 | });
21 | }
22 |
23 | Bots.CreditsItemSpawner.prototype.createObject = function (name, properties, index) {
24 | const modIndex = mod(index, this.properties.columnCount);
25 | if (modIndex === 0 && index !== 0) {
26 | this.currentRow += 1;
27 | }
28 |
29 | const width = (Bots.screenSize.x - (this.properties.columnCount - 1 ) * this.properties.spacing - 2 * this.properties.margin) / this.properties.columnCount
30 | const height = width / 1.61803398875;
31 |
32 | const position = new Phaser.Point(this.properties.margin + modIndex * (width + this.properties.spacing) + width / 2, this.y + this.currentRow * (height + this.properties.spacing) + height / 2);
33 | return new Bots.CreditsItem(this.state, name, position, {
34 | dummyKey: properties.key,
35 | title: properties.title,
36 | author: properties.author,
37 | link: properties.link,
38 | group: this.properties.pool,
39 | size: { width, height },
40 | anchor: {
41 | x: 0.5,
42 | y: 0.5
43 | },
44 | fixedToCamera: true
45 | });
46 | }
--------------------------------------------------------------------------------
/js/prefabs/dpad.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.DPad = function (state, name, position, properties) {
9 | Bots.Prefab.call(this, state, name, position, properties);
10 |
11 | this.isPressed = false;
12 | this.pointer = null;
13 |
14 | this.inputEnabled = true;
15 | this.events.onInputDown.add(function (dpad, pointer) {
16 | this.isPressed = true;
17 | this.pointer = pointer;
18 | }, this);
19 | this.events.onInputUp.add(function () {
20 | this.isPressed = false;
21 | this.pointer = null;
22 | }, this);
23 | };
24 |
25 | Bots.DPad.prototype = Object.create(Bots.Prefab.prototype);
26 | Bots.DPad.prototype.constructor = Bots.DPad;
27 |
28 | Bots.DPad.prototype.dpadAngle = function () {
29 | if (this.pointer) {
30 | return this.game.physics.arcade.angleToPointer(this, this.pointer) * 180 / 3.141592654;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/js/prefabs/droppable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.Droppable = function (state, name, position, properties) {
10 | Bots.Prefab.call(this, state, name, position, properties);
11 |
12 | this.dropped = false;
13 | this.dropObject();
14 | };
15 |
16 | Bots.Droppable.prototype = Object.create(Phaser.Sprite.prototype);
17 | Bots.Droppable.prototype.constructor = Bots.Droppable;
18 |
19 | Bots.Droppable.prototype.dropObject = function () {
20 | const easing = this.properties.avoidBounce ? Phaser.Easing.Quintic.In : Phaser.Easing.Bounce.Out;
21 |
22 | this.scale.setTo(Bots.scale * 8);
23 | const tween = this.game.add.tween(this.scale).to({
24 | x: Bots.scale * (this.properties.scaleMultiplier || 1),
25 | y: Bots.scale * (this.properties.scaleMultiplier || 1)
26 | }, 750, easing, true);
27 | tween.onComplete.add(function () {
28 | this.dropped = true;
29 | this.initializeObject();
30 | }, this);
31 | }
32 |
33 | Bots.Droppable.prototype.reset = function (x, y) {
34 | Phaser.Sprite.prototype.reset.call(this, x, y);
35 |
36 | this.dropped = false;
37 | this.dropObject();
38 | }
--------------------------------------------------------------------------------
/js/prefabs/droppableRobot.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 16/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.DroppableRobot = function (state, name, position, properties) {
10 | Bots.Droppable.call(this, state, name, position, properties);
11 | this.anchor.setTo(0.5);
12 | this.human = false;
13 | this.isDead = false;
14 | this.isJumping = false;
15 | this.kills = 0;
16 | this.deaths = 0;
17 |
18 | this.scale.setTo(Bots.scale);
19 | this.game.physics.enable(this, Phaser.Physics.ARCADE);
20 | this.currentSpeed = 0;
21 | this.body.maxVelocity.setTo(this.properties.speed);
22 | this.body.mass = 1;
23 | this.body.collideWorldBounds = true;
24 | this.speedMultiplier = 1;
25 |
26 | this.weapon = this.game.add.weapon(10 + this.game.rnd.integerInRange(-2, 2), 'bullet', 0, this.state.groups.bullets);
27 | this.weapon.bullets.forEach((bullet) => {
28 | bullet.scale.setTo(Bots.scale);
29 | }, this);
30 | this.weapon.bulletKillType = Phaser.Weapon.KILL_DISTANCE;
31 | this.weapon.bulletKillDistance = 1000;
32 | this.weapon.bulletSpeed = 600 + this.game.rnd.integerInRange(-50, 50);
33 | this.weapon.fireRate = 300 + this.game.rnd.integerInRange(-30, 30); // 1 per 60 ms
34 | this.weapon.bulletAngleVariance = 5 + this.game.rnd.integerInRange(-5, 5);
35 | this.weapon.trackSprite(this, 0, 0, true);
36 | this.weapon.onFire.add(() => {
37 | getMemberByName(this.state.groups.spawners, 'soundSpawner').spawn(this, 'shotSound');
38 | }, this);
39 |
40 | this.killCounter = this.game.add.text(0, 0, '1', { font: '10pt Arial', fill: '#ffffff', align: 'right' })
41 | this.killCounter.anchor.setTo(1, 0);
42 | this.state.groups.hud.add(this.killCounter);
43 |
44 | this.nameText = this.game.add.text(0, 0, properties.displayName || 'Player', {
45 | font: '10pt Arial',
46 | fill: '#ffffff',
47 | align: 'center'
48 | });
49 | this.nameText.anchor.setTo(0.5);
50 | this.state.groups.hud.add(this.nameText);
51 |
52 | this.healthBar = this.game.add.graphics(0, 0, state.groups.hud);
53 |
54 | this.shadow = this.game.add.sprite(this.x, this.y, properties.key);
55 | this.shadow.scale.x = this.scale.x * 1.2;
56 | this.shadow.scale.y = this.scale.y * 1.2;
57 | this.shadow.alpha = 0.25;
58 | this.shadow.anchor.setTo(0.5);
59 | this.shadow.tint = 0x000000;
60 | this.shadow.name = `${name}_shadow`;
61 | this.state.groups.shadows.add(this.shadow);
62 |
63 | this.spawnProtect = true;
64 | };
65 |
66 | Bots.DroppableRobot.prototype = Object.create(Bots.Droppable.prototype);
67 | Bots.DroppableRobot.prototype.constructor = Bots.DroppableRobot;
68 |
69 | Bots.DroppableRobot.prototype.initializeObject = function (instance) {
70 | instance.alpha = 0.5;
71 | instance.spawnProtect = true;
72 | instance.game.time.events.add(2000, () => {
73 | instance.alpha = 1;
74 | instance.spawnProtect = false;
75 | }, instance);
76 | }
77 |
78 | Bots.DroppableRobot.prototype.reset = function (x, y) {
79 | Bots.Droppable.prototype.reset.call(this, x, y);
80 | }
81 |
82 | Bots.DroppableRobot.prototype.dealDamage = function (damage) {
83 | if (this.spawnProtect) {
84 | return false;
85 | }
86 |
87 | if (this.boss && damage < 0) {
88 | damage = 0;
89 | }
90 |
91 | this.properties.health = Math.ceil(this.properties.health - damage);
92 |
93 | if (this.properties.health > this.properties.maxHealth) {
94 | this.properties.health = this.properties.maxHealth;
95 | }
96 |
97 | if (this.human) {
98 | getMemberByName(this.state.groups.hud, 'healthText').text = this.properties.health < 0 ? 0 : this.properties.health;
99 | }
100 |
101 | if (this.properties.health < 0) {
102 | this.animateDeath();
103 | return true;
104 | }
105 |
106 | return false;
107 | }
108 |
109 | Bots.DroppableRobot.prototype.killedOtherRobot = function (deadRobot) {
110 | this.dealDamage(-this.properties.maxHealth);
111 |
112 | if (this.human) {
113 | Bots.killCount += 1;
114 | }
115 |
116 | if (deadRobot.human) {
117 | Bots.deathCount += 1;
118 | }
119 |
120 | this.killCounter.text = parseInt(this.killCounter.text) + parseInt(deadRobot.killCounter.text);
121 | this.game.time.events.repeat(50, parseInt(deadRobot.killCounter.text), function () {
122 | getMemberByName(this.state.groups.spawners, 'lootSpawner').spawn(deadRobot, this);
123 | }, this);
124 | }
125 |
126 | Bots.DroppableRobot.prototype.animateDeath = function () {
127 | this.isDead = true;
128 |
129 | const deathTween = this.game.add.tween(this).to({ x: this.x - 10 }, 25, Phaser.Easing.Quadratic.InOut, true, 0, 5, true);
130 | deathTween.onComplete.add(function () {
131 | getMemberByName(this.state.groups.spawners, 'dustSpawner').spawn(this);
132 | getMemberByName(this.state.groups.spawners, 'explosionSpawner').spawn(this);
133 | getMemberByName(this.state.groups.spawners, 'earthQuakeSpawner').spawn(this, 4);
134 |
135 | killFromGroup(this.shadow, this.state.groups.shadows);
136 |
137 | this.game.add.tween(this.scale).to({ x: 4, y: 4 }, 500, Phaser.Easing.Quadratic.Out, true);
138 | this.game.add.tween(this).to({ alpha: 0 }, 500, Phaser.Easing.Quadratic.Out, true).onComplete.add(function () {
139 | if (this.trackTimer) {
140 | this.game.time.events.remove(this.trackTimer);
141 | this.trackTimer = null;
142 | }
143 |
144 | if (this.checkSurroundingsTimer) {
145 | this.game.time.events.remove(this.checkSurroundingsTimer);
146 | this.checkSurroundingsTimer = null;
147 | }
148 |
149 | if (this.jumpTimer) {
150 | this.game.time.events.remove(this.jumpTimer);
151 | this.jumpTimer = null;
152 | }
153 |
154 | if (this.meteoritTimer) {
155 | this.game.time.events.remove(this.meteoritTimer);
156 | this.meteoritTimer = null;
157 | }
158 |
159 | if (this.smokeTimer) {
160 | this.game.time.events.remove(this.smokeTimer);
161 | this.smokeTimer = null;
162 | }
163 |
164 | killFromGroup(this.killCounter, this.state.groups.hud);
165 | killFromGroup(this.healthBar, this.state.groups.hud);
166 | killFromGroup(this.nameText, this.state.groups.hud);
167 | killFromGroup(this, this.state.groups.hud);
168 |
169 | if (this.human) {
170 | getMemberByName(this.state.groups.spawners, 'robotSpawner').spawn('robot');
171 | } else if (this.boss) {
172 | getMemberByName(this.state.groups.spawners, 'bossRobotSpawner').spawn(true);
173 | }
174 | }, this);
175 | }, this);
176 | }
177 |
178 | Bots.DroppableRobot.prototype.update = function (instance) {
179 | instance.speedMultiplier = 1;
180 |
181 | if (instance.body) {
182 | instance.game.physics.arcade.overlap(instance.weapon.bullets, instance.state.groups.chests, this.onBulletChestCollide, null, instance);
183 | instance.game.physics.arcade.overlap(instance.weapon.bullets, instance.state.groups.robots, this.onBulletRobotCollide, this.onBulletRobotCollideProcess, instance);
184 | instance.game.physics.arcade.overlap(instance.state.groups.oil, instance.state.groups.robots, this.onOilRobotOverlap, null, instance);
185 | }
186 |
187 | if (instance.healthBar) {
188 | instance.healthBar.clear();
189 |
190 | if (instance.properties.health > 0) {
191 | let color = 0x00ff00;
192 | if (instance.properties.health < 0.5 * instance.properties.maxHealth) {
193 | color = 0xffae00;
194 | }
195 |
196 | if (instance.properties.health < 0.25 * instance.properties.maxHealth) {
197 | color = 0xff0000;
198 | }
199 |
200 | instance.healthBar.beginFill(color);
201 | instance.healthBar.lineStyle(0);
202 | instance.healthBar.drawRect(instance.x - instance.width / 2 + 16, instance.y + instance.height / 2 + 4, (instance.width - 16) * (instance.properties.health / instance.properties.maxHealth), 4);
203 | instance.healthBar.endFill();
204 |
205 | instance.healthBar.lineStyle(1, 0x000000, 0.8)
206 | instance.healthBar.drawRect(instance.x - instance.width / 2 + 16, instance.y + instance.height / 2 + 4, instance.width - 16, 4);
207 | }
208 | }
209 |
210 | if (instance.killCounter) {
211 | instance.killCounter.x = instance.x - instance.width / 2 + 12;
212 | instance.killCounter.y = instance.y + instance.height / 2 - 2;
213 | }
214 |
215 | if (instance.nameText) {
216 | instance.nameText.x = instance.x;
217 | instance.nameText.y = instance.y - instance.height / 2 - 4;
218 | }
219 |
220 | instance.shadow.x = instance.x;
221 | instance.shadow.y = instance.y;
222 | instance.shadow.angle = instance.angle;
223 | }
224 |
225 | Bots.DroppableRobot.prototype.onBulletChestCollide = function (bullet, chest) {
226 | bullet.kill();
227 | getMemberByName(this.state.groups.spawners, 'soundSpawner').spawn(chest, 'plingSound');
228 |
229 | if (chest.hit()) {
230 | killFromGroup(chest.shadow, this.state.groups.shadows);
231 | killFromGroup(chest, this.state.groups.chests);
232 |
233 | getMemberByName(this.state.groups.spawners, 'explosionSpawner').spawn(chest);
234 | getMemberByName(this.state.groups.spawners, 'dustSpawner').spawn(chest);
235 | getMemberByName(this.state.groups.spawners, 'earthQuakeSpawner').spawn(this, 2);
236 | getMemberByName(this.state.groups.spawners, 'lootSpawner').spawn(chest, this);
237 | }
238 | }
239 |
240 | Bots.DroppableRobot.prototype.onBulletRobotCollide = function (bullet, robot) {
241 | if (robot !== this && !robot.isDead) {
242 | bullet.kill();
243 |
244 | if (robot.dealDamage(calculateDamage2(this.properties.attack, robot.properties.defense))) {
245 | getMemberByName(this.state.groups.spawners, 'textSpawner').spawn(`${this.properties.displayName} (${this.killCounter.text}) killed ${robot.properties.displayName} (${robot.killCounter.text})`);
246 |
247 | this.killedOtherRobot(robot);
248 | }
249 | }
250 | }
251 |
252 | Bots.DroppableRobot.prototype.onOilRobotOverlap = function (oil, robot) {
253 | robot.speedMultiplier = 0.5;
254 | }
255 |
256 | Bots.DroppableRobot.prototype.onBulletRobotCollideProcess = function (bullet, robot) {
257 | return robot !== this;
258 | }
259 |
260 | Bots.DroppableRobot.prototype.fire = function () {
261 | if (!this.isDead && !this.spawnProtect) {
262 | this.weapon.fire();
263 | }
264 | }
265 |
266 | Bots.DroppableRobot.prototype.applySpeedIncrease = function () {
267 | this.properties.rotationSpeed = this.properties.speed / 17;
268 | this.properties.maxSpeed = this.properties.speed * 2.5;
269 |
270 | if (this.body) {
271 | this.body.maxVelocity.setTo(this.boss ? 100 : this.properties.maxSpeed);
272 | }
273 | }
--------------------------------------------------------------------------------
/js/prefabs/dust.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 21/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Dust = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | this.game.add.tween(this).to({ alpha: 0 }, 5000, Phaser.Easing.Quartic.In, true).onComplete.add(function () {
11 | this.kill();
12 | this.destroy();
13 | this.state.groups[this.properties.group].remove(this);
14 | }, this);
15 | //
16 | // const explosion = this.animations.add('explosion');
17 | // this.animations.play('explosion', 25, false);
18 | // this.animations.currentAnim.onComplete.add(function () {
19 | // console.log("Rxploded");
20 | //
21 | // this.loadTexture('blackSmoke', 0);
22 | // this.alpha = 0.8;
23 | //
24 | // this.game.add.tween(this).to({ alpha: 0 }, 1000, Phaser.Easing.Quartic.In, true).onComplete.add(function () {
25 | // this.kill();
26 | // this.destroy();
27 | // this.state.groups[this.properties.group].remove(this);
28 | // }, this);
29 | // }, this)
30 | };
31 |
32 | Bots.Dust.prototype = Object.create(Bots.Prefab.prototype);
33 | Bots.Dust.prototype.constructor = Bots.Dust;
--------------------------------------------------------------------------------
/js/prefabs/dustSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.DustSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.DustSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.DustSpawner.prototype.constructor = Bots.DustSpawner;
13 |
14 | Bots.DustSpawner.prototype.spawn = function (object) {
15 | const position = new Phaser.Point(object.x, object.y);
16 |
17 | let dust = this.pool.getFirstDead();
18 | if (dust) {
19 | dust.reset(position.x, position.y);
20 | } else {
21 | const name = `dust_${this.pool.countLiving()}`;
22 | const dustOrNull = this.createObject(name, position, object);
23 |
24 | if (dustOrNull) {
25 | dust = dustOrNull;
26 | }
27 | }
28 | }
29 |
30 | Bots.DustSpawner.prototype.createObject = function (name, position, object) {
31 | if (object) {
32 | const properties = {
33 | key: 'blackSmoke',
34 | group: 'ground',
35 | alpha: this.game.rnd.realInRange(0.4, 0.6),
36 | scale: {
37 | x: this.game.rnd.realInRange(0.9, 1.1),
38 | y: this.game.rnd.realInRange(0.9, 1.1)
39 | },
40 | angle: this.game.rnd.integerInRange(0, 360),
41 | anchor: {
42 | x: 0.5,
43 | y: 0.5
44 | }
45 | }
46 |
47 | return new Bots.Dust(this.state, name, position, properties);
48 | }
49 |
50 | return null;
51 | }
--------------------------------------------------------------------------------
/js/prefabs/earthQuakeSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.EarthQuakeSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.EarthQuakeSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.EarthQuakeSpawner.prototype.constructor = Bots.EarthQuakeSpawner;
13 |
14 | Bots.EarthQuakeSpawner.prototype.spawn = function (object, magnitude = 1) {
15 | if (this.game.physics.arcade.distanceBetween(object, getHumanRobot(this.state.groups.robots)) < 400) {
16 | const position = new Phaser.Point(object.x, object.y);
17 | this.game.camera.shake(0.001 * magnitude, 150 * magnitude);
18 | }
19 |
20 | if (magnitude >= 5) {
21 | this.state.groups.robots.forEach((robot) => {
22 | if (this.game.physics.arcade.distanceBetween(object, robot) < 400 && !robot.boss) {
23 | robot.stunned = true;
24 | this.game.time.events.add(150 * magnitude / 2, () => {
25 | robot.stunned = false;
26 | }, this);
27 | }
28 | });
29 | }
30 | }
--------------------------------------------------------------------------------
/js/prefabs/enemyRobot.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 16/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.EnemyRobot = function (state, name, position, properties) {
8 | Bots.DroppableRobot.call(this, state, name, position, properties);
9 | };
10 |
11 |
12 | Bots.EnemyRobot.prototype = Object.create(Bots.DroppableRobot.prototype);
13 | Bots.EnemyRobot.prototype.constructor = Bots.EnemyRobot;
14 |
15 | Bots.EnemyRobot.prototype.initializeObject = function () {
16 | Bots.DroppableRobot.prototype.initializeObject(this);
17 |
18 | this.properties.rotationSpeed = this.properties.speed / 17;
19 | this.properties.maxSpeed = this.properties.speed * 2.5;
20 | this.body.maxVelocity.setTo(this.properties.maxSpeed);
21 |
22 | this.trackTimer = this.game.time.events.loop(100, function () {
23 | if (!this.isDead) {
24 | getMemberByName(this.state.groups.spawners, 'trackSpawner').spawn(this);
25 | }
26 | }, this);
27 | }
28 |
29 | Bots.EnemyRobot.prototype.getClosestMemberOfGroup = function (group, isRobot) {
30 | let closestMember = null;
31 | let closestDistance = Number.MAX_VALUE;
32 |
33 | group.forEachAlive((member) => {
34 | if (member.name !== this.name) {
35 | const distance = this.game.physics.arcade.distanceBetween(this, member);
36 | if (distance < closestDistance) {
37 | if (isRobot && !member.isDead && !member.spawnProtect) {
38 | closestDistance = distance;
39 | closestMember = member;
40 | }
41 | }
42 | }
43 | });
44 |
45 | return {
46 | member: closestMember,
47 | distance: closestDistance,
48 | present: closestMember !== null
49 | };
50 | }
51 |
52 | Bots.EnemyRobot.prototype.update = function () {
53 | Bots.DroppableRobot.prototype.update(this);
54 |
55 | if (!this.stunned) {
56 | if (this.dropped && !this.isDead) {
57 | const closestRobot = this.getClosestMemberOfGroup(this.state.groups.robots, true);
58 | const closestChest = this.getClosestMemberOfGroup(this.state.groups.chests);
59 |
60 | const member = (closestRobot.present && closestRobot.distance < closestChest.distance) ? closestRobot : closestChest;
61 |
62 | if (member.member) {
63 | if (member.distance < this.properties.shootRange) {
64 | if (member.distance < this.properties.stopRange) {
65 | this.body.velocity.x = 0;
66 | this.body.velocity.y = 0;
67 | } else {
68 | }
69 |
70 | Bots.DroppableRobot.prototype.fire.call(this);
71 | }
72 |
73 | const offset = -60 * this.game.rnd.realInRange(this.properties.accuracy, 1) + 60;
74 | const destinationPosition = new Phaser.Point(member.member.x + offset * (randomBoolean() ? 1 : -1), member.member.y + offset * (randomBoolean() ? 1 : -1));
75 |
76 | this.rotation = this.game.physics.arcade.angleBetween(this, member.member);// + (offset * (randomBoolean() ? 1 : -1)) * 3.141592563 / 180;
77 | this.game.physics.arcade.moveToObject(this, destinationPosition, this.properties.maxSpeed);
78 | }
79 | }
80 | } else {
81 | this.body.velocity.x = 0;
82 | this.body.velocity.y = 0;
83 | }
84 | }
--------------------------------------------------------------------------------
/js/prefabs/enemyRobotSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.EnemyRobotSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.EnemyRobotSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.EnemyRobotSpawner.prototype.constructor = Bots.EnemyRobotSpawner;
13 |
14 | Bots.EnemyRobotSpawner.prototype.createObject = function (name, position) {
15 | const maxHealth = this.state.game.rnd.integerInRange(90, 120);
16 |
17 | return new Bots.EnemyRobot(this.state, name, position, {
18 | "group": "robots",
19 | "key": sample(['robot3Dred', 'robot3Dblue', 'robot3Dgreen', 'robot3Dyellow']),
20 | "friction": 10,
21 | "rotationSpeed": 10,
22 | "attack": this.state.game.rnd.integerInRange(30, 38),
23 | "defense": this.state.game.rnd.integerInRange(40, 48),
24 | "speed": this.state.game.rnd.integerInRange(40, 60),
25 | "health": maxHealth,
26 | "maxHealth": maxHealth,
27 | "displayName": getRandomName(),
28 | shootRange: this.state.game.rnd.integerInRange(200, 300),
29 | stopRange: this.state.game.rnd.integerInRange(150, 200),
30 | accuracy: this.state.game.rnd.realInRange(0.75, 0.98),
31 | scaleMultiplier: 1
32 | });
33 | }
34 |
--------------------------------------------------------------------------------
/js/prefabs/explosion.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 21/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Explosion = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | const explosion = this.animations.add('explosion');
11 | this.animations.play('explosion', 25, false, true);
12 |
13 | getMemberByName(this.state.groups.spawners, 'soundSpawner').spawn(this, 'explosionSound');
14 | };
15 |
16 | Bots.Explosion.prototype = Object.create(Bots.Prefab.prototype);
17 | Bots.Explosion.prototype.constructor = Bots.Explosion;
--------------------------------------------------------------------------------
/js/prefabs/explosionSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.ExplosionSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.ExplosionSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.ExplosionSpawner.prototype.constructor = Bots.ExplosionSpawner;
13 |
14 | Bots.ExplosionSpawner.prototype.spawn = function (object) {
15 | const position = new Phaser.Point(object.x, object.y);
16 |
17 | let explosion = this.pool.getFirstDead();
18 | if (explosion) {
19 | explosion.reset(position.x, position.y);
20 | } else {
21 | const name = `explosion_${this.pool.countLiving()}`;
22 | const explosionOrNull = this.createObject(name, position, object);
23 |
24 | if (explosionOrNull) {
25 | explosion = explosionOrNull;
26 | }
27 | }
28 | }
29 |
30 | Bots.ExplosionSpawner.prototype.createObject = function (name, position, object) {
31 | if (object) {
32 | const properties = {
33 | key: 'explosion2',
34 | group: 'explosions',
35 | anchor: {
36 | x: 0.5,
37 | y: 0.5
38 | }
39 | }
40 |
41 | return new Bots.Explosion(this.state, name, position, properties);
42 | }
43 |
44 | return null;
45 | }
--------------------------------------------------------------------------------
/js/prefabs/loot.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.Loot = function (state, name, position, properties) {
9 | Bots.Prefab.call(this, state, name, position, properties);
10 |
11 | this.properties.robot.properties[this.properties.type] += this.properties.amount;
12 | if (this.properties.robot.properties[this.properties.type] > this.properties.maxValue) {
13 | this.properties.robot.properties[this.properties.type] = this.properties.maxValue;
14 | }
15 |
16 | if (this.properties.type === 'speed') {
17 | this.properties.robot.applySpeedIncrease();
18 | }
19 |
20 | if (this.properties.robot.human) {
21 | // update hud
22 | const tweenColor = this.properties.amount >= 0 ? '#00ff00' : '#ff0000';
23 | this.game.time.events.add(0, function () {
24 | const text = getMemberByName(this.state.groups.hud, this.properties.hudTextName);
25 | text.addColor(tweenColor, 0);
26 |
27 | this.game.time.events.add(250, function () {
28 | const text = getMemberByName(this.state.groups.hud, this.properties.hudTextName);
29 | text.addColor('#ffffff', 0);
30 | }, this)
31 | }, this);
32 |
33 | getMemberByName(this.state.groups.hud, this.properties.hudTextName).text = this.properties.robot.properties[this.properties.type]
34 | }
35 |
36 | this.game.add.tween(this).to({ y: position.y - 150, alpha: 0 }, 1000, Phaser.Easing.Quadratic.Out, true);
37 | this.game.add.tween(this.scale).to({
38 | x: 4,
39 | y: 4
40 | }, 1000, Phaser.Easing.Quadratic.Out, true).onComplete.add(function () {
41 | this.kill();
42 | this.destroy();
43 | this.state.groups.loot.remove(this);
44 | }, this);
45 | };
46 |
47 | Bots.Loot.prototype = Object.create(Bots.Prefab.prototype);
48 | Bots.Loot.prototype.constructor = Bots.Loot;
49 |
--------------------------------------------------------------------------------
/js/prefabs/lootSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.LootSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.LootSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.LootSpawner.prototype.constructor = Bots.LootSpawner;
13 |
14 | Bots.LootSpawner.prototype.spawn = function (chest, robot) {
15 | const position = new Phaser.Point(chest.x, chest.y);
16 |
17 | let loot = this.pool.getFirstDead();
18 | if (loot) {
19 | loot.reset(position.x, position.y);
20 | } else {
21 | const name = `loot_${this.pool.countLiving()}`;
22 | const lootOrNull = this.createObject(name, position, robot);
23 |
24 | if (lootOrNull) {
25 | loot = lootOrNull;
26 | }
27 | }
28 | }
29 |
30 | Bots.LootSpawner.prototype.createObject = function (name, position, robot) {
31 | const properties = this.generateLootProperties(robot);
32 | if (properties) {
33 | properties.robot = robot;
34 | properties.alpha = 0.5;
35 | properties.group = 'loot';
36 | properties.anchor = { x: 0.5, y: 0.5 };
37 |
38 | return new Bots.Loot(this.state, name, position, properties);
39 | }
40 |
41 | return null;
42 | }
43 |
44 | Bots.LootSpawner.prototype.generateLootProperties = function (robot) {
45 | if (robot) {
46 | const properties = [{
47 | type: 'attack',
48 | amount: this.game.rnd.integerInRange(3, 6),
49 | key: 'lucifer_cannon',
50 | hudTextName: 'atkText',
51 | maxValue: 255
52 | }, {
53 | type: 'defense',
54 | amount: this.game.rnd.integerInRange(5, 10),
55 | key: 'shield',
56 | hudTextName: 'defText',
57 | maxValue: 255
58 | }, {
59 | type: 'maxHealth',
60 | amount: this.game.rnd.integerInRange(20, 35),
61 | key: 'medical_pack',
62 | hudTextName: 'healthText',
63 | maxValue: 999
64 | }, {
65 | type: 'speed',
66 | amount: this.game.rnd.integerInRange(2, 4),
67 | key: 'jet_pack',
68 | hudTextName: 'speedText',
69 | maxValue: 255
70 | }];
71 |
72 | return sample(properties);
73 | }
74 |
75 | return null;
76 | }
--------------------------------------------------------------------------------
/js/prefabs/menuBackgroundChooser.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 22/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.MenuBackgroundChooser = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | this.selectedTile = null;
11 | this.backgrounds = [];
12 | let selectedTile = null;
13 |
14 | properties.backgrounds.forEach((key, index) => {
15 | const spriteProperties = {
16 | key,
17 | group: properties.pool,
18 | anchor: properties.anchor,
19 | scale: properties.scale,
20 | parent: this,
21 | shadow: properties.shadow,
22 | index: index
23 | };
24 |
25 |
26 | const selectableSprite = new Bots.SelectableSprite(state, key, position, spriteProperties);
27 | this.backgrounds.push(selectableSprite);
28 |
29 | if (Bots.background === key) {
30 | selectedTile = selectableSprite;
31 | }
32 | });
33 |
34 | this.backgrounds.forEach((background, index) => {
35 | const length = this.backgrounds.length;
36 | background.x += (background.width + properties.spacing) * mod(index, properties.columns);// - (length * background.width + (length - 1) * properties.spacing) / 2 + background.width / 2;
37 | background.y -= Math.trunc(index / properties.columns) * (background.width + properties.spacing);
38 | });
39 |
40 | this.onTileSelected(selectedTile === null ? this.backgrounds[0] : selectedTile);
41 | }
42 |
43 | Bots.MenuBackgroundChooser.prototype = Object.create(Bots.Prefab.prototype);
44 | Bots.MenuBackgroundChooser.prototype.constructor = Bots.MenuBackgroundChooser;
45 |
46 | Bots.MenuBackgroundChooser.prototype.onTileSelected = function (selectedTile) {
47 | this.selectedTile = selectedTile;
48 | this.backgrounds.forEach((tile) => (tile.isSelected = false));
49 | selectedTile.isSelected = true;
50 | getMemberByName(this.state.groups.background, 'background').loadTexture(selectedTile.properties.key);
51 | }
--------------------------------------------------------------------------------
/js/prefabs/menuRobot.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 16/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.MenuRobot = function (state, name, position, properties) {
10 | Bots.Prefab.call(this, state, name, position, properties);
11 | this.anchor.setTo(0.5);
12 | this.scale.setTo(Bots.scale);
13 | this.currentDestination = null;
14 |
15 | this.game.physics.enable(this, Phaser.Physics.ARCADE);
16 | this.body.maxVelocity.setTo(100);
17 | this.currentSpeed = this.game.rnd.integerInRange(50, 100);
18 | this.body.mass = 1;
19 | this.speedMultiplier = 1;
20 |
21 | this.shadow = this.game.add.sprite(this.x, this.y, properties.key);
22 | this.shadow.scale.x = this.scale.x * 1.2;
23 | this.shadow.scale.y = this.scale.y * 1.2;
24 | this.shadow.alpha = 0.25;
25 | this.shadow.anchor.setTo(0.5);
26 | this.shadow.tint = 0x000000;
27 | this.shadow.name = `${name}_shadow`;
28 | this.state.groups.shadows.add(this.shadow);
29 | };
30 |
31 | Bots.MenuRobot.prototype = Object.create(Bots.Prefab.prototype);
32 | Bots.MenuRobot.prototype.constructor = Bots.MenuRobot;
33 |
34 | Bots.MenuRobot.prototype.reset = function (x, y) {
35 | Bots.Prefab.prototype.reset.call(this, x, y);
36 | }
37 |
38 | Bots.MenuRobot.prototype.update = function () {
39 | this.speedMultiplier = 1;
40 |
41 | this.shadow.x = this.x;
42 | this.shadow.y = this.y;
43 | this.shadow.angle = this.angle;
44 |
45 | if (!this.currentDestination || this.game.physics.arcade.distanceToXY(this, this.currentDestination.x, this.currentDestination.y) <= 50) {
46 | this.currentDestination = new Phaser.Point(randomInteger(2 * Bots.screenSize.x) - Bots.screenSize.x / 2, randomInteger(2 * Bots.screenSize.y) - Bots.screenSize.y / 2);
47 | }
48 |
49 | if (this.currentDestination) {
50 | this.rotation = this.game.physics.arcade.angleToXY(this, this.currentDestination.x, this.currentDestination.y, true);
51 | this.game.physics.arcade.moveToObject(this, this.currentDestination, this.currentSpeed);
52 | }
53 | }
--------------------------------------------------------------------------------
/js/prefabs/menuRobotChooser.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 22/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.MenuRobotChooser = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | this.index = 0;
11 | this.robots = [];
12 | properties.robots.forEach((name, index) => {
13 | const robot = getMemberByName(this.state.groups[properties.pool], name)
14 | if (robot) {
15 | this.robots.push(robot);
16 |
17 | robot.alpha = 0;
18 | robot.x = position.x;
19 | robot.y = position.y;
20 |
21 | const text = getMemberByName(this.state.groups.robotTexts, `${name}Text`);
22 | if (text) {
23 | robot.addChild(text);
24 | }
25 | }
26 | });
27 | }
28 |
29 | Bots.MenuRobotChooser.prototype = Object.create(Bots.Prefab.prototype);
30 | Bots.MenuRobotChooser.prototype.constructor = Bots.MenuRobotChooser;
31 |
32 | Bots.MenuRobotChooser.prototype.showNext = function () {
33 | this.index = mod(this.index + 1, this.robots.length)
34 | this.showRobot(this.index, true);
35 | }
36 |
37 | Bots.MenuRobotChooser.prototype.showPrevious = function () {
38 | this.index = mod(this.index - 1, this.robots.length)
39 | this.showRobot(this.index, false);
40 | }
41 |
42 | Bots.MenuRobotChooser.prototype.showRobot = function (index, forward) {
43 | const currentIndex = mod(index, this.robots.length);
44 | const lastIndex = mod(index + (forward ? -1 : 1), this.robots.length);
45 |
46 | this.robots[lastIndex].x = Bots.screenSize.x / 2;
47 | this.robots[lastIndex].alpha = 1;
48 | this.game.add.tween(this.robots[lastIndex])
49 | .to({ alpha: 0, x: this.robots[lastIndex].x + (forward ? 100 : -100 ) }, 500, Phaser.Easing.Quintic.Out, true);
50 |
51 | this.robots[currentIndex].x = Bots.screenSize.x / 2 + (forward ? -100 : 100);
52 | this.robots[currentIndex].alpha = 0;
53 | this.game.add.tween(this.robots[currentIndex])
54 | .to({
55 | alpha: 1,
56 | x: this.robots[currentIndex].x + (forward ? 100 : -100 )
57 | }, 500, Phaser.Easing.Quintic.Out, true);
58 | }
59 |
60 | Bots.MenuRobotChooser.prototype.chooseRobot = function (animationDuration) {
61 | this.game.add.tween(this.robots[this.index])
62 | .to({ alpha: 0.5, x: Bots.screenSize.x * 1.5 }, animationDuration, Phaser.Easing.Quintic.Out, true);
63 | }
64 |
65 | Bots.MenuRobotChooser.prototype.getChosenRobot = function () {
66 | return this.robots[this.index];
67 | }
--------------------------------------------------------------------------------
/js/prefabs/menuRobotSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.MenuRobotSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.MenuRobotSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.MenuRobotSpawner.prototype.constructor = Bots.MenuRobotSpawner;
13 |
14 | Bots.MenuRobotSpawner.prototype.createObject = function (name, position) {
15 | position = new Phaser.Point(randomInteger(2 * Bots.screenSize.x) - Bots.screenSize.x / 2, randomInteger(2 * Bots.screenSize.y) - Bots.screenSize.y / 2);
16 |
17 | return new Bots.MenuRobot(this.state, name, position, {
18 | "group": "robots",
19 | "key": sample(['robot3Dred', 'robot3Dblue', 'robot3Dgreen', 'robot3Dyellow']),
20 | "friction": 10,
21 | "rotationSpeed": 10
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/js/prefabs/messagePrefab.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.MessagePrefab = function (state, name, position, properties) {
9 | this.messageHeight = 36;
10 | Phaser.Graphics.call(this, state.game, Bots.screenSize.x / 2, 100, properties.text, properties.style);
11 |
12 | this.state = state;
13 | this.name = name;
14 | this.properties = properties;
15 | this.state.prefabs[name] = this;
16 | this.game = state.game;
17 | this.anchor.setTo(0.5);
18 | this.fixedToCamera = true;
19 |
20 | if (properties.group) {
21 | this.state.groups[properties.group].add(this);
22 | }
23 |
24 | this.beginFill(0x000000, 0.75);
25 | this.drawRect(-Bots.screenSize.x / 2, -this.messageHeight / 2, Bots.screenSize.x, this.messageHeight);
26 | this.endFill();
27 |
28 | this.text = this.game.add.text(0, 2, properties.text, properties.style);
29 | this.text.anchor.setTo(0.5);
30 | this.addChild(this.text);
31 |
32 | this.sprite = this.game.add.sprite(0, 0, properties.key);
33 | this.sprite.anchor.setTo(0.5)
34 | this.sprite.scale.setTo(properties.imageScale.x, properties.imageScale.y);
35 | this.addChild(this.sprite);
36 |
37 | this.sprite.x = -this.text.width / 2 - this.sprite.width / 2 - 8;
38 |
39 |
40 | this.game.time.events.add(2000, () => {
41 | this.game.add.tween(this).to({ alpha: 0 }, 3000, Phaser.Easing.Quadratic.Out, true)
42 | .onComplete.add(() => {
43 | killFromGroup(this, this.state.groups[properties.group]);
44 | }, this);
45 | }, this);
46 | };
47 |
48 | Bots.MessagePrefab.prototype = Object.create(Phaser.Graphics.prototype);
49 | Bots.MessagePrefab.prototype.constructor = Bots.MessagePrefab;
50 |
51 | Bots.MessagePrefab.prototype.autoSize = function (width, height) {
52 | if (!this.defaultFontSize) {
53 | this.defaultFontSize = this.fontSize;
54 | }
55 |
56 | if (width > 0 && height > 0) {
57 | this.fontSize = 64;
58 | let size = this.fontSize;
59 | while (this.fontSize > 4) {
60 | if (this.width < width && this.height < height) {
61 | return size;
62 | }
63 |
64 | this.fontSize = --size;
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/js/prefabs/messageSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.MessageSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.MessageSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.MessageSpawner.prototype.constructor = Bots.MessageSpawner;
13 |
14 | Bots.MessageSpawner.prototype.spawn = function (text, key) {
15 | const name = `textPrefab_${this.pool.countLiving()}`;
16 | const textPrefabOrNull = this.createObject(name, text, key);
17 | }
18 |
19 | Bots.MessageSpawner.prototype.createObject = function (name, text, key) {
20 | const result = new Bots.MessagePrefab(this.state, name, new Phaser.Point(0, 0), {
21 | group: this.properties.pool,
22 | text: text,
23 | key: key,
24 | style: {
25 | font: `12pt Arial`,
26 | fill: '#ffffff',
27 | align: 'left'
28 | },
29 | imageScale: {
30 | x: 0.75,
31 | y: 0.75
32 | }
33 | });
34 |
35 | return result;
36 | }
--------------------------------------------------------------------------------
/js/prefabs/meteorit.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.Meteorit = function (state, name, position, properties) {
10 | Bots.Droppable.call(this, state, name, position, properties);
11 |
12 | this.scale.setTo(Bots.scale);
13 | this.anchor.setTo(0.5);
14 | this.angle = this.game.rnd.integerInRange(0, 360);
15 | };
16 |
17 | Bots.Meteorit.prototype = Object.create(Bots.Droppable.prototype);
18 | Bots.Meteorit.prototype.constructor = Bots.Meteorit;
19 |
20 | Bots.Meteorit.prototype.initializeObject = function () {
21 | this.game.physics.enable(this, Phaser.Physics.ARCADE);
22 | this.body.immovable = true;
23 |
24 | getMemberByName(this.state.groups.spawners, 'explosionSpawner').spawn(this);
25 | getMemberByName(this.state.groups.spawners, 'dustSpawner').spawn(this);
26 | getMemberByName(this.state.groups.spawners, 'earthQuakeSpawner').spawn(this, this.game.rnd.integerInRange(0, 10));
27 |
28 | const bounds = this.getBounds();
29 | this.state.groups.robots.forEachAlive((robot) => {
30 | if (!robot.isDead && !robot.boss && Phaser.Rectangle.intersects(bounds, robot.getBounds())) {
31 | if (robot.dealDamage(calculateDamage2(this.properties.attack, robot.properties.defense))) {
32 | getMemberByName(this.state.groups.spawners, 'textSpawner').spawn(`${robot.properties.displayName} (${robot.killCounter.text}) was killed by a comet`);
33 | }
34 | }
35 | });
36 |
37 | killFromGroup(this, this.state.groups[this.properties.group]);
38 | }
--------------------------------------------------------------------------------
/js/prefabs/meteoritSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.MeteoritSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.MeteoritSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.MeteoritSpawner.prototype.constructor = Bots.MeteoritSpawner;
13 |
14 | Bots.MeteoritSpawner.prototype.forceSpawn = function (position) {
15 | let object = this.pool.getFirstDead();
16 | if (object) {
17 | object.reset(position.x, position.y);
18 | } else {
19 | const name = `object_${this.pool.countLiving()}`;
20 | object = this.createObject(name, position);
21 | }
22 | }
23 |
24 | Bots.MeteoritSpawner.prototype.createObject = function (name, position) {
25 | const key = sample(this.properties.keys);
26 |
27 | return new Bots.Meteorit(this.state, name, position, {
28 | key,
29 | group: this.properties.pool,
30 | scale: {
31 | x: 0.75,
32 | y: 0.75
33 | },
34 | avoidBounce: this.properties.avoidBounce,
35 | attack: this.game.rnd.integerInRange(100, 200)
36 | });
37 | }
--------------------------------------------------------------------------------
/js/prefabs/minimap.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 16/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.Minimap = function (state, name, position, properties) {
10 | const x = state.game.width - Bots.minimapPadding.x - Bots.minimapWidth;
11 | const y = Bots.minimapPadding.y;
12 |
13 | Phaser.Graphics.call(this, state.game, x, y);
14 |
15 | this.state = state;
16 | this.name = name;
17 | this.alpha = properties.alpha;
18 | this.fixedToCamera = true;
19 | this.properties = properties;
20 | this.state.prefabs[name] = this;
21 |
22 | if (properties.group) {
23 | this.state.groups[properties.group].add(this);
24 | }
25 | };
26 |
27 | Bots.Minimap.prototype = Object.create(Phaser.Graphics.prototype);
28 | Bots.Minimap.prototype.constructor = Bots.Minimap;
29 |
30 | Bots.Minimap.prototype.update = function () {
31 | this.clear();
32 |
33 | this.drawRectangle(0, 0, Bots.minimapWidth, Bots.minimapHeight);
34 |
35 | this.state.groups.robots.forEachAlive((robot) => this.drawMinimapObject(robot, this.getRobotMinimapColor(robot), robot.boss ? 5 : 3));
36 | this.state.groups.chests.forEachAlive((chest) => this.drawMinimapObject(chest, 0x00ff00));
37 | this.state.groups.oil.forEachAlive((oil) => this.drawMinimapObject(oil, 0xff00ff));
38 | }
39 |
40 | Bots.Minimap.prototype.drawRectangle = function (x, y, w, h, color = 0x000000) {
41 | this.beginFill(color);
42 | this.drawRect(x, y, w, h);
43 | this.endFill();
44 | }
45 |
46 | Bots.Minimap.prototype.drawMinimapObject = function (object, color = 0xffffff, size = 3) {
47 | const x = object.world.x + Bots.worldSize.x / 2;
48 | const y = object.world.y + Bots.worldSize.y / 2;
49 |
50 | const mapX = (x / (1.0 * Bots.worldSize.x)) * Bots.minimapWidth;
51 | const mapY = (y / (1.0 * Bots.worldSize.y)) * Bots.minimapHeight;
52 |
53 | this.drawRectangle(mapX - (size - 1) / 2, mapY - (size - 1) / 2, size, size, color);
54 | }
55 |
56 | Bots.Minimap.prototype.getRobotMinimapColor = function (robot) {
57 | if (robot) {
58 | if (robot.human) {
59 | return 0x0000ff;
60 | }
61 |
62 | if (robot.boss) {
63 | return 0xff0000;
64 | }
65 |
66 | return 0xffffff;
67 | }
68 | }
--------------------------------------------------------------------------------
/js/prefabs/oil.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 21/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Oil = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | this.game.physics.enable(this, Phaser.Physics.ARCADE);
11 | this.game.add.tween(this).to({ alpha: 0 }, 20000, Phaser.Easing.Quartic.In, true)
12 | .onComplete.add(() => killFromGroup(this, this.state.groups[this.properties.group]), this);
13 | };
14 |
15 | Bots.Oil.prototype = Object.create(Bots.Prefab.prototype);
16 | Bots.Oil.prototype.constructor = Bots.Oil;
--------------------------------------------------------------------------------
/js/prefabs/oilSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.OilSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.OilSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.OilSpawner.prototype.constructor = Bots.OilSpawner;
13 |
14 | Bots.OilSpawner.prototype.createObject = function (name, position) {
15 | const scale = this.game.rnd.realInRange(0.5, 1.3);
16 |
17 | const properties = {
18 | key: 'oil',
19 | group: 'oil',
20 | alpha: this.game.rnd.realInRange(0.6, 0.75),
21 | scale: {
22 | x: scale,
23 | y: scale
24 | },
25 | angle: this.game.rnd.integerInRange(0, 360),
26 | anchor: {
27 | x: 0.5,
28 | y: 0.5
29 | }
30 | }
31 |
32 | return new Bots.Oil(this.state, name, position, properties);
33 | }
--------------------------------------------------------------------------------
/js/prefabs/pauseDialog.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 21/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.PauseDialog = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | // this.fixedToCamera = true;
11 |
12 | this.tl = this.game.add.sprite(-this.properties.size.x / 2, -this.properties.size.y / 2, 'uiWindowTL');
13 | this.tl.anchor.setTo(0, 0);
14 | this.tr = this.game.add.sprite(this.properties.size.x / 2, -this.properties.size.y / 2, 'uiWindowTR');
15 | this.tr.anchor.setTo(1, 0);
16 | this.t = this.game.add.sprite(0, -this.properties.size.y / 2, 'uiWindowT');
17 | this.t.anchor.setTo(0.5, 0);
18 | this.t.scale.x = (this.properties.size.x - this.tl.width - this.tr.width) / (this.t.width - 5);
19 |
20 | this.bl = this.game.add.sprite(-this.properties.size.x / 2, this.properties.size.y / 2, 'uiWindowBL');
21 | this.bl.anchor.setTo(0, 1);
22 | this.br = this.game.add.sprite(this.properties.size.x / 2, this.properties.size.y / 2, 'uiWindowBR');
23 | this.br.anchor.setTo(1, 1);
24 | this.b = this.game.add.sprite(0, this.properties.size.y / 2, 'uiWindowB');
25 | this.b.anchor.setTo(0.5, 1);
26 | this.b.scale.x = (this.properties.size.x - this.bl.width - this.br.width) / (this.b.width - 5);
27 |
28 | this.ml = this.game.add.sprite(-this.properties.size.x / 2, 0, 'uiWindowL');
29 | this.ml.anchor.setTo(0, 0.5);
30 | this.ml.scale.y = (this.properties.size.y - this.bl.height - this.bl.height) / (this.ml.height - 5);
31 |
32 | this.mr = this.game.add.sprite(this.properties.size.x / 2, 0, 'uiWindowR');
33 | this.mr.anchor.setTo(1, 0.5);
34 | this.mr.scale.y = (this.properties.size.y - this.br.height - this.br.height) / (this.mr.height - 5);
35 |
36 | this.m = this.game.add.sprite(0, 0, 'uiWindow');
37 | this.m.anchor.setTo(0.5, 0.5);
38 | this.m.scale.x = (this.properties.size.x - this.ml.width - this.mr.width) / (this.m.width - 5);
39 | this.m.scale.y = (this.properties.size.y - this.br.height - this.br.height) / (this.m.height - 5);
40 |
41 | this.graphics = this.game.add.graphics(0, 0);
42 | this.graphics.beginFill(0x000000, 0.5);
43 | this.graphics.drawRect(-Bots.screenSize.x / 2, -Bots.screenSize.y / 2, Bots.screenSize.x, Bots.screenSize.y);
44 | this.graphics.endFill();
45 |
46 | this.cross = new Bots.Button(this.state, 'crossButton', new Phaser.Point(properties.size.x / 2 - 24, -properties.size.y / 2 + 24), {
47 | anchor: {
48 | x: 0.5,
49 | y: 0.5
50 | },
51 | scale: {
52 | x: 0.5,
53 | y: 0.5
54 | },
55 | key: 'uiCross',
56 | group: properties.group,
57 | force: true
58 | });
59 |
60 | this.caption = new Bots.TextPrefab(this.state, 'pauseDialogCaption', new Phaser.Point(0, -properties.size.y / 2 + 24), {
61 | text: 'Pause',
62 | group: properties.group,
63 | style: {
64 | font: "20pt Arial",
65 | fill: "#ffffff",
66 | align: "center"
67 | },
68 | anchor: {
69 | x: 0.5,
70 | y: 0.5
71 | }
72 | });
73 |
74 | this.addChild(this.graphics);
75 | this.addChild(this.ml);
76 | this.addChild(this.mr);
77 | this.addChild(this.tr);
78 | this.addChild(this.br);
79 | this.addChild(this.tl);
80 | this.addChild(this.bl);
81 | this.addChild(this.b);
82 | this.addChild(this.t);
83 | this.addChild(this.m);
84 | this.addChild(this.caption);
85 | this.addChild(this.cross);
86 |
87 | this.game.paused = true;
88 | };
89 |
90 | Bots.PauseDialog.prototype = Object.create(Bots.Prefab.prototype);
91 | Bots.PauseDialog.prototype.constructor = Bots.PauseDialog;
--------------------------------------------------------------------------------
/js/prefabs/pauseDialogSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.PauseDialogSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.PauseDialogSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.PauseDialogSpawner.prototype.constructor = Bots.PauseDialogSpawner;
13 |
14 | Bots.PauseDialogSpawner.prototype.spawn = function (offset = new Phaser.Point(0, 0)) {
15 | if (!getMemberByName(this.state.groups[this.properties.pool], 'pauseDialog')) {
16 | return new Bots.PauseDialog(this.state, 'pauseDialog', new Phaser.Point(Bots.screenSize.x / 2 + offset.x, Bots.screenSize.y / 2 + offset.y), {
17 | group: this.properties.pool,
18 | size: this.properties.size,
19 | anchor: {
20 | x: 0.5,
21 | y: 0.5
22 | }
23 | });
24 | }
25 | }
--------------------------------------------------------------------------------
/js/prefabs/prefab.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.Prefab = function (state, name, position, properties) {
9 | Phaser.Sprite.call(this, state.game, position.x, position.y, properties.key);
10 |
11 | this.state = state;
12 | this.name = name;
13 | this.properties = properties;
14 | this.state.prefabs[name] = this;
15 | this.game = state.game;
16 |
17 | if (properties.group) {
18 | this.state.groups[properties.group].add(this);
19 | }
20 |
21 | if (properties.frame) {
22 | this.frame = properties.frame;
23 | }
24 |
25 | if (properties.anchor) {
26 | this.anchor.setTo(properties.anchor.x, properties.anchor.y);
27 | }
28 |
29 | if (properties.scale) {
30 | this.scale.setTo(properties.scale.x, properties.scale.y);
31 | }
32 |
33 | if (properties.alpha !== undefined) {
34 | this.alpha = properties.alpha;
35 | }
36 |
37 | if (properties.angle) {
38 | this.angle = properties.angle;
39 | }
40 |
41 | if (properties.mirror) {
42 | if (properties.mirror.x) {
43 | this.scale.x *= -1;
44 | }
45 |
46 | if (properties.mirror.y) {
47 | this.scale.y *= -1;
48 | }
49 | }
50 |
51 | this.fixedToCamera = properties.fixedToCamera;
52 | };
53 |
54 | Bots.Prefab.prototype = Object.create(Phaser.Sprite.prototype);
55 | Bots.Prefab.prototype.constructor = Bots.Prefab;
56 |
57 | Bots.Prefab.prototype.render = function () {
58 | this.game.debug.spriteInfo(this, 32, 32);
59 | }
--------------------------------------------------------------------------------
/js/prefabs/robot.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Robot = function (state, name, position, properties) {
8 | Bots.DroppableRobot.call(this, state, name, position, properties);
9 |
10 | this.human = true;
11 | this.deaths = 0;
12 | this.kills = 0;
13 |
14 | this.game.camera.follow(this);
15 | this.game.camera.deadzone = new Phaser.Rectangle(Bots.cameraPadding, Bots.cameraPadding, Bots.screenSize.x - 4 * Bots.minimapPadding.x - Bots.minimapWidth - Bots.cameraPadding, Bots.screenSize.y - 2 * Bots.cameraPadding);
16 | this.game.camera.focusOnXY(position.x, position.y);
17 |
18 | this.trackTimer = null;
19 |
20 | this.dpad = getMemberByName(this.state.groups.hud, 'uiDPad');
21 | this.shootButton = getMemberByName(this.state.groups.hud, 'uiShootButton');
22 | this.menuButton = getMemberByName(this.state.groups.hud, 'uiMenuButton');
23 |
24 | if (this.game.device.desktop) {
25 | killFromGroup(this.dpad, this.state.groups.hud);
26 | killFromGroup(this.shootButton, this.state.groups.hud);
27 | killFromGroup(this.menuButton, this.state.groups.hud);
28 |
29 | this.dpad = null;
30 | this.shootButton = null;
31 | this.menuButton = null;
32 | }
33 | };
34 |
35 | Bots.Robot.prototype = Object.create(Bots.DroppableRobot.prototype);
36 | Bots.Robot.prototype.constructor = Bots.Robot;
37 |
38 | Bots.Robot.prototype.initializeObject = function () {
39 | Bots.DroppableRobot.prototype.initializeObject(this);
40 |
41 | getMemberByName(this.state.groups.hud, 'atkText').text = this.properties.attack;
42 | getMemberByName(this.state.groups.hud, 'defText').text = this.properties.defense;
43 | getMemberByName(this.state.groups.hud, 'healthText').text = this.properties.health;
44 | getMemberByName(this.state.groups.hud, 'speedText').text = this.properties.speed;
45 |
46 | this.properties.rotationSpeed = this.properties.speed / 17;
47 | this.properties.maxSpeed = this.properties.speed * 2.5;
48 | this.body.maxVelocity.setTo(this.properties.maxSpeed);
49 | }
50 |
51 | Bots.Robot.prototype.update = function () {
52 | Bots.DroppableRobot.prototype.update(this);
53 |
54 | if (this.body) {
55 | this.body.angularAcceleration = 0;
56 | this.body.velocity.x = 0;
57 | this.body.velocity.y = 0;
58 | this.body.angularVelocity = 0;
59 |
60 | if (!this.stunned) {
61 | if (this.dropped && !this.isDead) {
62 | if (this.game.device.desktop) {
63 | if (this.game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
64 | this.angle -= this.properties.rotationSpeed;
65 | } else if (this.game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
66 | this.angle += this.properties.rotationSpeed;
67 | }
68 |
69 | if (this.game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
70 | this.currentSpeed = this.properties.maxSpeed * this.speedMultiplier;
71 | } else if (this.game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
72 | this.currentSpeed = -this.properties.maxSpeed * this.speedMultiplier;
73 | }
74 |
75 | if (this.game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)) {
76 | Bots.DroppableRobot.prototype.fire.call(this);
77 | }
78 | } else {
79 | if (this.dpad && this.dpad.isPressed) {
80 | const angle = this.dpad.dpadAngle();
81 | if (angle) {
82 | this.angle = angle;
83 | this.currentSpeed = this.properties.maxSpeed * this.speedMultiplier;
84 | }
85 | }
86 |
87 | if (this.shootButton && this.shootButton.isPressed) {
88 | Bots.DroppableRobot.prototype.fire.call(this);
89 | }
90 |
91 | if (this.menuButton) {
92 | const panel = getMemberByName(this.state.groups.panel, 'statisticsPanel');
93 | panel.show(this.menuButton.isPressed);
94 | panel.update();
95 | }
96 | }
97 |
98 | if (this.currentSpeed > 0) {
99 | this.currentSpeed -= this.properties.friction;
100 | } else {
101 | this.currentSpeed += this.properties.friction;
102 | }
103 |
104 | if (Math.abs(this.currentSpeed) <= this.properties.friction) {
105 | this.currentSpeed = 0;
106 | }
107 |
108 | if (this.currentSpeed !== 0) {
109 | this.game.physics.arcade.velocityFromRotation(this.rotation, this.currentSpeed, this.body.velocity);
110 |
111 | if (!this.trackTimer) {
112 | this.trackTimer = this.game.time.events.loop(100, function () {
113 | getMemberByName(this.state.groups.spawners, 'trackSpawner').spawn(this);
114 | }, this);
115 | }
116 | } else {
117 | this.game.time.events.remove(this.trackTimer);
118 | this.trackTimer = 0;
119 | }
120 | }
121 | }
122 | }
123 | }
124 |
125 | Bots.Robot.prototype.onBulletChestCollide = function (bullet, chest) {
126 | bullet.kill();
127 | chest.kill();
128 | }
129 |
130 | Bots.Robot.prototype.onBulletRobotCollide = function (bullet, robot) {
131 | if (robot !== this) {
132 | bullet.kill();
133 | robot.animateDeath();
134 | }
135 | }
136 |
137 | Bots.Robot.prototype.onBulletRobotCollideProcess = function (bullet, robot) {
138 | return robot !== this;
139 | }
--------------------------------------------------------------------------------
/js/prefabs/robotSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.RobotSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.RobotSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.RobotSpawner.prototype.constructor = Bots.RobotSpawner;
13 |
14 | Bots.RobotSpawner.prototype.createObject = function (name, position) {
15 | const properties = this.robotStats();
16 |
17 | return new Bots.Robot(this.state, name, position, {
18 | group: "robots",
19 | key: this.properties.spawnKey,
20 | friction: 10,
21 | attack: properties.attack,
22 | defense: properties.defense,
23 | speed: properties.speed,
24 | health: properties.health,
25 | maxHealth: properties.maxHealth,
26 | displayName: "Player",
27 | scaleMultiplier: 1
28 | });
29 | }
30 |
31 | Bots.RobotSpawner.prototype.robotStats = function () {
32 | switch (this.properties.spawnKey) {
33 | case 'robot3Dred':
34 | return {
35 | attack: 70,
36 | defense: 70,
37 | speed: 90,
38 | health: 200,
39 | maxHealth: 200
40 | };
41 |
42 | case 'robot3Dgreen':
43 | return {
44 | attack: 50,
45 | defense: 50,
46 | speed: 80,
47 | health: 150,
48 | maxHealth: 150
49 | };
50 |
51 | case 'robot3Dyellow':
52 | return {
53 | attack: 40,
54 | defense: 45,
55 | speed: 70,
56 | health: 120,
57 | maxHealth: 120
58 | };
59 |
60 | case 'robot3Dblue':
61 | return {
62 | attack: 40,
63 | defense: 40,
64 | speed: 65,
65 | health: 110,
66 | maxHealth: 110
67 | };
68 |
69 | default:
70 | return {
71 | attack: 34,
72 | defense: 48,
73 | speed: 70,
74 | health: 100,
75 | maxHealth: 100
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/js/prefabs/selectableSprite.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.SelectableSprite = function (state, name, position, properties) {
9 | Bots.Prefab.call(this, state, name, position, properties);
10 |
11 | this.isSelected = false;
12 | this.frameGraphic = this.game.add.graphics(0, 0);
13 | this.addChild(this.frameGraphic);
14 |
15 | this.inputEnabled = true;
16 | this.events.onInputUp.add(() => {
17 | if (!this.game.paused || this.properties.force) {
18 | if (Bots.soundsEnabled) {
19 | this.state.prefabs.clickSound.safelyPlay();
20 | }
21 |
22 | this.isSelected = true;
23 | properties.parent.onTileSelected(this);
24 | }
25 | }, this);
26 |
27 | this.game.physics.enable(this, Phaser.Physics.ARCADE);
28 |
29 | if (this.properties.shadow) {
30 | this.shadowGraphic = this.game.add.graphics(0, 0);
31 | this.state.groups[properties.group].addAt(this.shadowGraphic, 0);
32 | }
33 | };
34 |
35 | Bots.SelectableSprite.prototype = Object.create(Bots.Prefab.prototype);
36 | Bots.SelectableSprite.prototype.constructor = Bots.SelectableSprite;
37 |
38 | Bots.SelectableSprite.prototype.update = function () {
39 | this.frameGraphic.clear();
40 |
41 | if (this.properties.shadow) {
42 | this.shadowGraphic.clear();
43 | this.shadowGraphic.beginFill(0x000000);
44 | this.shadowGraphic.drawRect(this.x - this.width * this.scale.x + 2, this.y - this.height * this.scale.y + 2, this.width, this.height);
45 | this.shadowGraphic.endFill();
46 | }
47 |
48 | this.frameGraphic.lineStyle(1, 0x000000, 1);
49 | this.frameGraphic.beginFill(0x000000, this.isSelected ? 0 : 0.25);
50 | this.frameGraphic.drawRect(-this.width / 2 / this.scale.x, -this.height / 2 / this.scale.y, this.width / this.scale.x, this.height / this.scale.y);
51 | this.frameGraphic.endFill();
52 | }
--------------------------------------------------------------------------------
/js/prefabs/smoke.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 21/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Smoke = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | const initialScale = this.scale;
11 |
12 | this.game.physics.enable(this, Phaser.Physics.ARCADE);
13 | this.game.add.tween(this.scale).to({
14 | x: initialScale.x * 3,
15 | y: initialScale.y * 3
16 | }, 5000, Phaser.Easing.Quartic.In, true)
17 | this.game.add.tween(this).to({ alpha: 0 }, 3000, Phaser.Easing.Quartic.In, true)
18 | .onComplete.add(() => killFromGroup(this, this.state.groups[this.properties.group]), this);
19 | };
20 |
21 | Bots.Smoke.prototype = Object.create(Bots.Prefab.prototype);
22 | Bots.Smoke.prototype.constructor = Bots.Smoke;
--------------------------------------------------------------------------------
/js/prefabs/smokeSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.SmokeSpwaner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.SmokeSpwaner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.SmokeSpwaner.prototype.constructor = Bots.SmokeSpwaner;
13 |
14 | Bots.SmokeSpwaner.prototype.spawn = function (object) {
15 | let probability = 0;
16 |
17 | if (object.properties.health <= object.properties.maxHealth * 0.5) {
18 | probability = 0.4;
19 | }
20 |
21 | if (object.properties.health <= object.properties.maxHealth * 0.25) {
22 | probability = 1;
23 | }
24 |
25 | if (this.game.rnd.frac() <= probability) {
26 | return this.createObject('randomName', object)
27 | }
28 | }
29 |
30 | Bots.SmokeSpwaner.prototype.createObject = function (name, position) {
31 | const scale = this.game.rnd.realInRange(0.5, 2);
32 | const maxOffset = 30;
33 | const offset = new Phaser.Point(this.game.rnd.integerInRange(-maxOffset, maxOffset), this.game.rnd.integerInRange(-maxOffset, maxOffset));
34 |
35 | const properties = {
36 | key: 'blackSmoke',
37 | group: this.properties.pool,
38 | alpha: this.game.rnd.realInRange(0.7, 1),
39 | scale: {
40 | x: scale,
41 | y: scale
42 | },
43 | angle: this.game.rnd.integerInRange(0, 360),
44 | anchor: {
45 | x: 0.5,
46 | y: 0.5
47 | }
48 | }
49 |
50 | return new Bots.Smoke(this.state, name, new Phaser.Point(position.x + offset.x, position.y + offset.y), properties);
51 | }
--------------------------------------------------------------------------------
/js/prefabs/soundPrefab.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.SoundPrefab = function (state, name, position, properties) {
9 | Phaser.Sound.call(this, state.game, properties.key);
10 |
11 | this.name = name;
12 | this.properties = properties;
13 | this.game = state.game;
14 | this.isPrepared = false;
15 | this.isKilled = false;
16 |
17 | this.game.sound.setDecodedCallback([this], () => {
18 | this.isPrepared = true;
19 | if (properties.playAfterDecode) {
20 | this.safelyPlay();
21 | }
22 | }, this);
23 | };
24 |
25 | Bots.SoundPrefab.prototype = Object.create(Phaser.Sound.prototype);
26 | Bots.SoundPrefab.prototype.constructor = Bots.SoundPrefab;
27 |
28 | Bots.SoundPrefab.prototype.safelyPlay = function () {
29 | if (!this.isKilled && this.isPrepared) {
30 | this.play('', 0, 1, false, false);
31 | }
32 | }
--------------------------------------------------------------------------------
/js/prefabs/soundSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.SoundSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.SoundSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.SoundSpawner.prototype.constructor = Bots.SoundSpawner;
13 |
14 | Bots.SoundSpawner.prototype.spawn = function (source, key) {
15 | if (Bots.soundsEnabled) {
16 | const humanRobot = getHumanRobot(this.state.groups.robots);
17 |
18 | if (humanRobot) {
19 | const distance = this.game.physics.arcade.distanceBetween(source, humanRobot);
20 | if (distance < 300) {
21 | const sound = this.createObject(`sound_${key}`, key);
22 | }
23 | }
24 | }
25 | }
26 |
27 | Bots.SoundSpawner.prototype.createObject = function (name, key) {
28 | const properties = {
29 | key,
30 | playAfterDecode: true,
31 | killAfterPlay: true
32 | };
33 |
34 | return new Bots.SoundPrefab(this.state, name, new Phaser.Point(0, 0), properties);
35 | };
--------------------------------------------------------------------------------
/js/prefabs/spawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Spawner = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | this.pool = this.state.groups[properties.pool];
11 |
12 | this.spawnTime = properties.spawnTimeInSeconds;
13 | this.spawnTimer = this.game.time.create();
14 |
15 | this.scheduleSpawn();
16 | }
17 |
18 | Bots.Spawner.prototype = Object.create(Bots.Prefab.prototype);
19 | Bots.Spawner.prototype.constructor = Bots.Spawner;
20 |
21 | Bots.Spawner.prototype.scheduleSpawn = function () {
22 | if (this.properties.mode !== 'never') {
23 | const time = this.game.rnd.between(this.spawnTime.min, this.spawnTime.max);
24 |
25 | this.spawnTimer.add(Phaser.Timer.SECOND * time, this.spawn, this);
26 | this.spawnTimer.start();
27 | }
28 | }
29 |
30 | Bots.Spawner.prototype.spawn = function () {
31 | if (this.isAllowedToSpawn()) {
32 | const position = new Phaser.Point(this.game.rnd.between(-Bots.worldSize.x / 2, Bots.worldSize.x / 2), this.game.rnd.between(-Bots.worldSize.y / 2, Bots.worldSize.y / 2));
33 |
34 | let object = this.pool.getFirstDead();
35 | if (object) {
36 | object.reset(position.x, position.y);
37 | } else {
38 | const name = `object_${this.pool.countLiving()}`;
39 | object = this.createObject(name, position);
40 | }
41 | }
42 |
43 | if (this.properties.mode === 'infinite' || this.properties.mode === 'limited') {
44 | this.scheduleSpawn();
45 | }
46 | }
47 |
48 | Bots.Spawner.prototype.isAllowedToSpawn = function () {
49 | return this.properties.mode === 'once' ||
50 | this.properties.mode === 'infinite' ||
51 | (this.properties.mode === 'limited' && this.pool.countLiving() < this.properties.limit);
52 | }
--------------------------------------------------------------------------------
/js/prefabs/statisticsPanel.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 24/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.StatisticsPanel = function (state, name, position, properties) {
10 | Bots.Prefab.call(this, state, name, position, properties);
11 |
12 | this.fixedToCamera = true;
13 | this.alpha = 0;
14 |
15 | this.topLeft = new Phaser.Point(50, 50);
16 | this.bottomRight = new Phaser.Point(Bots.screenSize.x - 50, Bots.screenSize.y - 50);
17 | this.panelSize = new Phaser.Point(this.bottomRight.x - this.topLeft.x, this.bottomRight.y - this.topLeft.y);
18 |
19 | this.graphics = this.game.add.graphics(0, 0);
20 | this.graphics.beginFill(0x000000, 0.75);
21 | this.graphics.drawRect(this.topLeft.x, this.topLeft.y, this.panelSize.x, this.panelSize.y);
22 | this.graphics.endFill();
23 | this.addChild(this.graphics);
24 |
25 | this.rankText = this.game.add.text(this.topLeft.x + 16, this.topLeft.y + 16, 'Rank', this.captionTextStyle());
26 | this.addChild(this.rankText);
27 |
28 | this.rankTexts = [];
29 | for (let i = 0; i < 12; i++) {
30 | const rankText = this.game.add.text(this.topLeft.x + 16, this.topLeft.y + 48 + i * 16, '', this.regularTextStyle());
31 | this.addChild(rankText);
32 |
33 | this.rankTexts.push(rankText);
34 | }
35 |
36 | this.playerText = this.game.add.text(this.topLeft.x + 16 + 100, this.topLeft.y + 16, 'Player', this.captionTextStyle());
37 | this.addChild(this.playerText);
38 |
39 | this.player = this.game.add.sprite(this.topLeft.x + 100 + 40, this.topLeft.y + 48 + 40, Bots.humanRobotKey);
40 | this.player.anchor.setTo(0.5);
41 | this.player.scale.x = Bots.scale * 0.9;
42 | this.player.scale.y = Bots.scale * 0.9;
43 | this.game.add.tween(this.player).to({ angle: 360 }, 30000, Phaser.Easing.Linear.None, true, 0, -1);
44 | this.addChild(this.player);
45 |
46 | this.attackText = this.game.add.text(this.topLeft.x + 16 + 100, this.topLeft.y + 48 + 64 + 32, 'Atl\t120', this.regularTextStyleWithTabs(48));
47 | this.addChild(this.attackText);
48 |
49 | this.defenseText = this.game.add.text(this.topLeft.x + 16 + 100, this.topLeft.y + 48 + 64 + 48, 'Def\t120', this.regularTextStyleWithTabs(48));
50 | this.addChild(this.defenseText);
51 |
52 | this.healthText = this.game.add.text(this.topLeft.x + 16 + 100, this.topLeft.y + 48 + 64 + 64, 'HP\t4800', this.regularTextStyleWithTabs(48));
53 | this.addChild(this.healthText);
54 |
55 | this.speedText = this.game.add.text(this.topLeft.x + 16 + 100, this.topLeft.y + 48 + 64 + 80, 'Spd\t120', this.regularTextStyleWithTabs(48));
56 | this.addChild(this.speedText);
57 |
58 | this.killsText = this.game.add.text(this.topLeft.x + 16 + 100, this.topLeft.y + 48 + 64 + 96, 'Kills\t120', this.regularTextStyleWithTabs(48));
59 | this.addChild(this.killsText);
60 |
61 | this.deathsText = this.game.add.text(this.topLeft.x + 16 + 100, this.topLeft.y + 48 + 64 + 112, 'Deaths\t120', this.regularTextStyleWithTabs(48));
62 | this.addChild(this.deathsText);
63 |
64 | this.helpText = this.game.add.text(this.topLeft.x + 200, this.topLeft.y + 16, 'Help', this.captionTextStyle());
65 | this.addChild(this.helpText);
66 |
67 | [
68 | 'Up\tMove forwards',
69 | 'Down\tMove backwards',
70 | 'Left\tTurn left',
71 | 'Right\tTurn right',
72 | 'Space\tShoot',
73 | 'Shift\tShow info dialog',
74 | '',
75 | 'Minimap:',
76 | 'Blue\tYou',
77 | 'White\tEnemies',
78 | 'Red\tBoss',
79 | 'Green\tChests'
80 | ].forEach((item, index) => {
81 | const text = this.game.add.text(this.topLeft.x + 200, this.topLeft.y + 48 + index * 16, item, this.regularTextStyleWithTabs(52));
82 | this.addChild(text);
83 | });
84 |
85 | this.objectiveText = this.game.add.text(this.topLeft.x + 360, this.topLeft.y + 16, 'Objective', this.captionTextStyle());
86 | this.addChild(this.objectiveText);
87 |
88 | this.player1 = this.game.add.sprite(this.topLeft.x + 16 + 400, this.topLeft.y + 64, Bots.humanRobotKey);
89 | this.player1.anchor.setTo(0.5);
90 | this.player1.scale.setTo(Bots.scale * 0.7);
91 | this.player1.angle = 355;
92 | this.addChild(this.player1);
93 |
94 | this.player2 = this.game.add.sprite(this.topLeft.x + 16 + 484, this.topLeft.y + 64, sample(['robot3Dgreen', 'robot3Dred', 'robot3Dyellow', 'robot3Dblue'], Bots.humanRobotKey));
95 | this.player2.anchor.setTo(0.5);
96 | this.player2.scale.setTo(Bots.scale * 0.7);
97 | this.player2.angle = 95;
98 | this.addChild(this.player2);
99 |
100 | this.rocket1 = this.game.add.sprite(this.topLeft.x + 16 + 442, this.topLeft.y + 64, 'logoBulletRight');
101 | this.rocket1.anchor.setTo(0.5);
102 | this.rocket1.scale.setTo(Bots.scale);
103 | this.rocket1.angle = 355;
104 | this.addChild(this.rocket1);
105 |
106 | this.player3 = this.game.add.sprite(this.topLeft.x + 16 + 400, this.topLeft.y + 128, Bots.humanRobotKey);
107 | this.player3.anchor.setTo(0.5);
108 | this.player3.scale.setTo(Bots.scale * 0.7);
109 | this.player3.angle = 350;
110 | this.addChild(this.player3);
111 |
112 | this.chest = this.game.add.sprite(this.topLeft.x + 16 + 484, this.topLeft.y + 118, 'crate_45');
113 | this.chest.anchor.setTo(0.5);
114 | this.chest.scale.setTo(Bots.scale * 0.7);
115 | this.chest.angle = 95;
116 | this.addChild(this.chest);
117 |
118 | this.rocket2 = this.game.add.sprite(this.topLeft.x + 16 + 442, this.topLeft.y + 128, 'logoBulletRight');
119 | this.rocket2.anchor.setTo(0.5);
120 | this.rocket2.scale.setTo(Bots.scale);
121 | this.rocket2.angle = 350;
122 | this.addChild(this.rocket2);
123 |
124 | this.player4 = this.game.add.sprite(this.topLeft.x + 16 + 400, this.topLeft.y + 192, Bots.humanRobotKey);
125 | this.player4.anchor.setTo(0.5);
126 | this.player4.scale.setTo(Bots.scale * 0.7);
127 | this.player4.angle = 190;
128 | this.addChild(this.player4);
129 |
130 | this.player5 = this.game.add.sprite(this.topLeft.x + 16 + 484, this.topLeft.y + 192, sample(['robot3Dgreen', 'robot3Dred', 'robot3Dyellow', 'robot3Dblue'], Bots.humanRobotKey));
131 | this.player5.anchor.setTo(0.5);
132 | this.player5.scale.setTo(Bots.scale * 0.7);
133 | this.player5.angle = 170;
134 | this.addChild(this.player5);
135 |
136 | this.rocket3 = this.game.add.sprite(this.topLeft.x + 16 + 442, this.topLeft.y + 192, 'logoBulletRight');
137 | this.rocket3.anchor.setTo(0.5);
138 | this.rocket3.scale.setTo(Bots.scale);
139 | this.rocket3.angle = 170;
140 | this.addChild(this.rocket3);
141 |
142 | this.checkmark1 = this.game.add.sprite(this.topLeft.x + 16 + 360, this.topLeft.y + 64, 'uiCheckmark');
143 | this.checkmark1.anchor.setTo(0.5);
144 | this.checkmark1.scale.setTo(0.5);
145 | this.checkmark1.tint = 0x00ff00;
146 | this.addChild(this.checkmark1);
147 |
148 | this.checkmark2 = this.game.add.sprite(this.topLeft.x + 16 + 360, this.topLeft.y + 128, 'uiCheckmark');
149 | this.checkmark2.anchor.setTo(0.5);
150 | this.checkmark2.scale.setTo(0.5);
151 | this.checkmark2.tint = 0x00ff00;
152 | this.addChild(this.checkmark2);
153 |
154 | this.cross1 = this.game.add.sprite(this.topLeft.x + 16 + 360, this.topLeft.y + 192, 'uiCross');
155 | this.cross1.anchor.setTo(0.5);
156 | this.cross1.scale.setTo(0.5);
157 | this.cross1.tint = 0xff0000;
158 | this.addChild(this.cross1);
159 | };
160 |
161 | Bots.StatisticsPanel.prototype = Object.create(Bots.Prefab.prototype);
162 | Bots.StatisticsPanel.prototype.constructor = Bots.StatisticsPanel;
163 |
164 | Bots.StatisticsPanel.prototype.captionTextStyle = function () {
165 | return {
166 | font: '12pt bold Helvetica, sans-serif',
167 | fill: '#ffffff',
168 | align: 'left'
169 | }
170 | }
171 |
172 | Bots.StatisticsPanel.prototype.regularTextStyle = function (fontSize = 10) {
173 | return {
174 | font: `${fontSize}pt Helvetica, sans-serif`,
175 | fill: '#ffffff',
176 | align: 'left'
177 | }
178 | }
179 |
180 | Bots.StatisticsPanel.prototype.regularTextStyleWithTabs = function (tabWidth, fontsize) {
181 | const style = Object.assign({}, this.regularTextStyle());
182 | style.tabs = tabWidth;
183 |
184 | return style;
185 | }
186 |
187 | Bots.StatisticsPanel.prototype.show = function (show) {
188 | this.alpha = show ? 1 : 0;
189 | }
190 |
191 | Bots.StatisticsPanel.prototype.update = function () {
192 | if (this.alpha === 1) {
193 | const robotNamesWithLevel = [];
194 | this.state.groups.robots.forEachAlive((robot) => {
195 | robotNamesWithLevel.push({
196 | name: robot.properties.displayName,
197 | level: parseInt(robot.killCounter.text)
198 | });
199 | });
200 |
201 | robotNamesWithLevel
202 | .sort((l, r) => r.level - l.level)
203 | .slice(0, this.rankTexts.length)
204 | .forEach((robot, index) => {
205 | this.rankTexts[index].text = `${robot.level} ${shortenName(robot.name, 8)}`;
206 | });
207 |
208 | this.attackText.text = `Atk\t${getMemberByName(this.state.groups.hud, 'atkText').text}`;
209 | this.defenseText.text = `Def\t${getMemberByName(this.state.groups.hud, 'defText').text}`;
210 | this.healthText.text = `HP\t${getMemberByName(this.state.groups.hud, 'healthText').text}`;
211 | this.speedText.text = `Spd\t${getMemberByName(this.state.groups.hud, 'speedText').text}`;
212 | this.killsText.text = `Kills\t${Bots.killCount}`;
213 | this.deathsText.text = `Deaths\t${Bots.deathCount}`;
214 | }
215 | }
--------------------------------------------------------------------------------
/js/prefabs/textPrefab.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.TextPrefab = function (state, name, position, properties) {
9 | Phaser.Text.call(this, state.game, position.x, position.y, properties.text, properties.style);
10 |
11 | this.state = state;
12 | this.name = name;
13 | this.properties = properties;
14 | this.state.prefabs[name] = this;
15 | this.game = state.game;
16 |
17 | if (properties.group) {
18 | this.state.groups[properties.group].add(this);
19 | }
20 |
21 | if (properties.anchor) {
22 | this.anchor.setTo(properties.anchor.x, properties.anchor.y);
23 | }
24 |
25 | if (properties.scale) {
26 | this.scale.setTo(properties.scale.x, properties.scale.y);
27 | }
28 |
29 | if (properties.alpha) {
30 | this.alpha = properties.alpha;
31 | }
32 |
33 | this.fixedToCamera = properties.fixedToCamera;
34 |
35 | if (properties.size) {
36 | this.autoSize(properties.size.width, properties.size.height);
37 | }
38 |
39 | if (properties.lineSpacing) {
40 | this.lineSpacing = properties.lineSpacing;
41 | }
42 |
43 | if (properties.shadow) {
44 | this.setShadow(2, 2, 'rgba(0,0,0,0.5)', 0);
45 | }
46 | };
47 |
48 | Bots.TextPrefab.prototype = Object.create(Phaser.Text.prototype);
49 | Bots.TextPrefab.prototype.constructor = Bots.TextPrefab;
50 |
51 | Bots.TextPrefab.prototype.autoSize = function (width, height) {
52 | if (!this.defaultFontSize) {
53 | this.defaultFontSize = this.fontSize;
54 | }
55 |
56 | if (width > 0 && height > 0) {
57 | this.fontSize = 64;
58 | let size = this.fontSize;
59 | while (this.fontSize > 4) {
60 | if (this.width < width && this.height < height) {
61 | return size;
62 | }
63 |
64 | this.fontSize = --size;
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/js/prefabs/textSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.TextSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 |
10 | this.texts = [];
11 | this.maximumRows = this.properties.maximumRows || 5;
12 | this.fontSize = this.properties.fontSize || 8;
13 | };
14 |
15 | Bots.TextSpawner.prototype = Object.create(Bots.Spawner.prototype);
16 | Bots.TextSpawner.prototype.constructor = Bots.TextSpawner;
17 |
18 | Bots.TextSpawner.prototype.spawn = function (text) {
19 | const position = new Phaser.Point(Bots.screenSize.x / 2, 100);
20 |
21 | let textPrefab = this.pool.getFirstDead();
22 | if (textPrefab) {
23 | textPrefab.reset(position.x, position.y);
24 | } else {
25 | const name = `textPrefab_${this.pool.countLiving()}`;
26 | const textPrefabOrNull = this.createObject(name, position, text);
27 |
28 | if (textPrefabOrNull) {
29 | textPrefab = textPrefabOrNull;
30 | }
31 | }
32 | }
33 |
34 | Bots.TextSpawner.prototype.createObject = function (name, position, text) {
35 | position = this.nextPosition();
36 |
37 | const result = new Bots.TextPrefab(this.state, name, position, {
38 | group: 'hud',
39 | text: text,
40 | fixedToCamera: true,
41 | style: {
42 | font: `${this.fontSize}pt Arial`,
43 | fill: '#ffffff',
44 | align: 'left'
45 | },
46 | anchor: {
47 | x: 0,
48 | y: 0.5
49 | }
50 | });
51 |
52 | const indexOfPlayer = text.indexOf('Player');
53 |
54 | if (indexOfPlayer >= 0) {
55 | result.addColor('#0000ff', indexOfPlayer);
56 | result.addColor('#ffffff', indexOfPlayer + 6);
57 | }
58 |
59 | this.texts.push(result);
60 | return result;
61 | }
62 |
63 | Bots.TextSpawner.prototype.nextPosition = function () {
64 | if (this.texts.length >= this.maximumRows) {
65 | this.texts.forEach(text => {
66 | text.cameraOffset.y -= this.fontSize * 1.6;
67 |
68 | });
69 | killFromGroup(this.texts[0], this.state.groups.hud);
70 | this.texts.shift();
71 | }
72 |
73 | return new Phaser.Point(48, 18 + this.texts.length * this.fontSize * 1.6);
74 | }
--------------------------------------------------------------------------------
/js/prefabs/tileSprite.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 16/07/17.
3 | */
4 |
5 | "use strict";
6 |
7 | var Bots = Bots || {};
8 |
9 | Bots.TileSprite = function (state, name, position, properties) {
10 | Phaser.TileSprite.call(this, state.game, position.x, position.y, properties.size.width, properties.size.height, properties.key);
11 |
12 | this.state = state;
13 | this.name = name;
14 | this.properties = properties;
15 | this.state.prefabs[name] = this;
16 | this.fixedToCamera = !!properties.fixedToCamera;
17 |
18 | if (properties.group) {
19 | this.state.groups[properties.group].add(this);
20 | }
21 |
22 | if (properties.frame) {
23 | this.frame = properties.frame;
24 | }
25 |
26 | if (properties.anchor) {
27 | this.anchor.setTo(properties.anchor.x, properties.anchor.y);
28 | }
29 | };
30 |
31 | Bots.TileSprite.prototype = Object.create(Phaser.TileSprite.prototype);
32 | Bots.TileSprite.prototype.constructor = Bots.TileSprite;
33 |
34 | Bots.TileSprite.prototype.update = function () {
35 | if (this.properties.fixedToCamera) {
36 | this.tilePosition.x = -this.game.camera.x;
37 | this.tilePosition.y = -this.game.camera.y;
38 | }
39 | }
--------------------------------------------------------------------------------
/js/prefabs/track.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 21/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 |
7 | Bots.Track = function (state, name, position, properties) {
8 | Bots.Prefab.call(this, state, name, position, properties);
9 |
10 | this.game.add.tween(this).to({ alpha: 0 }, 1000, Phaser.Easing.Quartic.In, true).onComplete.add(function () {
11 | this.kill();
12 | this.destroy();
13 | this.state.groups[this.properties.group].remove(this);
14 | }, this);
15 | };
16 |
17 | Bots.Track.prototype = Object.create(Bots.Prefab.prototype);
18 | Bots.Track.prototype.constructor = Bots.Track;
--------------------------------------------------------------------------------
/js/prefabs/trackSpawner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 15/07/17.
3 | */
4 |
5 | var Bots = Bots || {};
6 |
7 | Bots.TrackSpawner = function (state, name, position, properties) {
8 | Bots.Spawner.call(this, state, name, position, properties);
9 | };
10 |
11 | Bots.TrackSpawner.prototype = Object.create(Bots.Spawner.prototype);
12 | Bots.TrackSpawner.prototype.constructor = Bots.TrackSpawner;
13 |
14 | Bots.TrackSpawner.prototype.spawn = function (robot) {
15 | const position = new Phaser.Point(robot.x, robot.y);
16 |
17 | let track = this.pool.getFirstDead();
18 | if (track) {
19 | track.reset(position.x, position.y);
20 | } else {
21 | const name = `track_${this.pool.countLiving()}`;
22 | const trackOrNull = this.createObject(name, position, robot);
23 |
24 | if (trackOrNull) {
25 | track = trackOrNull;
26 | }
27 | }
28 | }
29 |
30 | Bots.TrackSpawner.prototype.createObject = function (name, position, robot) {
31 | if (robot) {
32 | const properties = {
33 | key: 'tracks',
34 | group: 'ground',
35 | angle: robot.angle,
36 | alpha: 0.5,
37 | anchor: {
38 | x: 0.5,
39 | y: 0.5
40 | }
41 | }
42 |
43 | return new Bots.Track(this.state, name, position, properties);
44 | }
45 |
46 | return null;
47 | }
--------------------------------------------------------------------------------
/js/states/boot.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.Boot = function () {
9 | Phaser.State.call(this);
10 | };
11 |
12 | Bots.Boot.prototype = Object.create(Phaser.State.prototype);
13 | Bots.Boot.prototype.constructor = Bots.Boot;
14 |
15 | Bots.Boot.prototype.init = function (data) {
16 | this.data = data;
17 | };
18 |
19 | Bots.Boot.prototype.preload = function () {
20 | for (const name in this.data) {
21 | if (this.data.hasOwnProperty(name)) {
22 | this.load.text(name, this.data[name]);
23 | }
24 | }
25 |
26 | };
27 |
28 | Bots.Boot.prototype.create = function () {
29 | var content = this.game.cache.getText('menu');
30 | var payload = JSON.parse(content);
31 |
32 | this.prepareScreenForScaling();
33 | this.game.state.start('loading', true, false, payload, 'menu');
34 | };
35 |
36 | Bots.Boot.prototype.prepareScreenForScaling = function () {
37 | this.game.stage.disableVisibilityChange = true;
38 |
39 | this.game.scale.maxWidth = window.innerWidth * window.devicePixelRatio;
40 | this.game.scale.maxHeight = window.innerHeight * window.devicePixelRatio;
41 | this.game.scale.pageAlignVertically = true;
42 | this.game.scale.pageAlignHorizontally = true;
43 | this.game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
44 | this.game.scale.windowConstraints.bottom = 'visual';
45 | }
--------------------------------------------------------------------------------
/js/states/credits.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 22/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 | Bots.Credits = function () {
7 | Phaser.State.call(this);
8 |
9 | this.prefabClasses = {
10 | 'sprite': Bots.Prefab.prototype.constructor,
11 | 'tileSprite': Bots.TileSprite.prototype.constructor,
12 | 'button': Bots.Button.prototype.constructor,
13 | 'creditsItem': Bots.CreditsItem.prototype.constructor,
14 | 'creditsItemSpawner': Bots.CreditsItemSpawner.prototype.constructor,
15 | 'text': Bots.TextPrefab.prototype.constructor,
16 | 'sound': Bots.SoundPrefab.prototype.constructor
17 | }
18 | };
19 |
20 | Bots.Credits.prototype = Object.create(Phaser.State.prototype);
21 | Bots.Credits.prototype.constructor = Bots.Credits;
22 |
23 | Bots.Credits.prototype.create = function () {
24 | this.game.time.advancedTiming = true;
25 | }
26 |
27 | Bots.Credits.prototype.init = function (data) {
28 | this.data = data;
29 | this.game.physics.startSystem(Phaser.Physics.ARCADE);
30 | }
31 |
32 | Bots.Credits.prototype.create = function () {
33 | this.game.time.advancedTiming = true
34 |
35 | this.game.stage.backgroundColor = '#212A31';
36 | this.groups = {};
37 | this.prefabs = {};
38 |
39 | this.data.groups.forEach(groupName => (this.groups[groupName] = this.game.add.group()), this);
40 | for (var prefabName in this.data.prefabs) {
41 | if (this.data.prefabs.hasOwnProperty(prefabName)) {
42 | this.createPrefab(prefabName, this.data.prefabs[prefabName]);
43 | }
44 | }
45 |
46 | this.game.add.tween(this.groups.credits).to({ y: -1000 }, 120000, Phaser.Easing.Linear.None, true, 5000);
47 | };
48 |
49 | Bots.Credits.prototype.createPrefab = function (prefabName, properties) {
50 | if (this.prefabClasses.hasOwnProperty(properties.type)) {
51 | const position = new Phaser.Point(properties.position.x, properties.position.y);
52 | const prefab = new this.prefabClasses[properties.type](this, prefabName, position, properties.properties);
53 |
54 | this.prefabs[prefabName] = prefab;
55 | }
56 | };
57 |
58 | Bots.Credits.prototype.onButtonPressed = function (button) {
59 | if (button.name === 'menuButton') {
60 | const content = this.game.cache.getText('menu');
61 | const payload = JSON.parse(content);
62 | payload.prefabs.background.properties.key = Bots.background;
63 | this.game.state.start('loading', true, false, payload, 'menu');
64 | }
65 | }
--------------------------------------------------------------------------------
/js/states/level.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 | Bots.Level = function () {
8 | Phaser.State.call(this);
9 |
10 | this.prefabClasses = {
11 | 'sprite': Bots.Prefab.prototype.constructor,
12 | 'tileSprite': Bots.TileSprite.prototype.constructor,
13 | 'robot': Bots.Robot.prototype.constructor,
14 | 'enemyRobot': Bots.EnemyRobot.prototype.constructor,
15 | 'spawner': Bots.Spawner.prototype.constructor,
16 | 'robotSpawner': Bots.RobotSpawner.prototype.constructor,
17 | 'enemyRobotSpawner': Bots.EnemyRobotSpawner.prototype.constructor,
18 | 'bossRobotSpawner': Bots.BossRobotSpawner.prototype.constructor,
19 | 'chestSpawner': Bots.ChestSpawner.prototype.constructor,
20 | 'chest': Bots.Chest.prototype.constructor,
21 | 'meteoritSpawner': Bots.MeteoritSpawner.prototype.constructor,
22 | 'meteorit': Bots.Meteorit.prototype.constructor,
23 | 'minimap': Bots.Minimap.prototype.constructor,
24 | 'text': Bots.TextPrefab.prototype.constructor,
25 | 'lootSpawner': Bots.LootSpawner.prototype.constructor,
26 | 'loot': Bots.Loot.prototype.constructor,
27 | 'explosionSpawner': Bots.ExplosionSpawner.prototype.constructor,
28 | 'smokeSpawner': Bots.SmokeSpwaner.prototype.constructor,
29 | 'earthQuakeSpawner': Bots.EarthQuakeSpawner.prototype.constructor,
30 | 'textSpawner': Bots.TextSpawner.prototype.constructor,
31 | 'soundSpawner': Bots.SoundSpawner.prototype.constructor,
32 | 'explosion': Bots.Explosion.prototype.constructor,
33 | 'dust': Bots.Dust.prototype.constructor,
34 | 'dustSpawner': Bots.DustSpawner.prototype.constructor,
35 | 'statisticsPanel': Bots.StatisticsPanel.prototype.constructor,
36 | 'oilSpawner': Bots.OilSpawner.prototype.constructor,
37 | 'track': Bots.Track.prototype.constructor,
38 | 'trackSpawner': Bots.TrackSpawner.prototype.constructor,
39 | 'button': Bots.Button.prototype.constructor,
40 | 'dpad': Bots.DPad.prototype.constructor,
41 | 'control': Bots.Control.prototype.constructor,
42 | 'pauseDialogSpawner': Bots.PauseDialogSpawner.prototype.constructor,
43 | 'messageSpawner': Bots.MessageSpawner.prototype.constructor,
44 | 'sound': Bots.SoundPrefab.prototype.constructor
45 | }
46 | };
47 |
48 | Bots.Level.prototype = Object.create(Phaser.State.prototype);
49 | Bots.Level.prototype.constructor = Bots.Level;
50 |
51 | Bots.Level.prototype.init = function (data) {
52 | this.data = data;
53 | this.game.physics.startSystem(Phaser.Physics.ARCADE);
54 | };
55 |
56 | Bots.Level.prototype.create = function () {
57 | this.game.time.advancedTiming = true
58 |
59 | this.game.stage.backgroundColor = '#212A31';
60 | this.groups = {};
61 | this.prefabs = {};
62 |
63 | this.data.groups.forEach(groupName => (this.groups[groupName] = this.game.add.group()), this);
64 | for (var prefabName in this.data.prefabs) {
65 | if (this.data.prefabs.hasOwnProperty(prefabName)) {
66 | this.createPrefab(prefabName, this.data.prefabs[prefabName]);
67 | }
68 | }
69 |
70 | this.game.world.setBounds(-Bots.worldSize.x / 2, -Bots.worldSize.y / 2, Bots.worldSize.x, Bots.worldSize.y);
71 | Bots.killCount = 0;
72 | Bots.deathCount = 0;
73 | };
74 |
75 | Bots.Level.prototype.createPrefab = function (prefabName, properties) {
76 | if (this.prefabClasses.hasOwnProperty(properties.type)) {
77 | const position = new Phaser.Point(properties.position.x, properties.position.y);
78 | const prefab = new this.prefabClasses[properties.type](this, prefabName, position, properties.properties);
79 |
80 | this.prefabs[prefabName] = prefab;
81 | }
82 | };
83 |
84 | Bots.Level.prototype.update = function () {
85 | this.game.physics.arcade.collide(this.groups.chests, this.groups.robots);
86 | this.game.physics.arcade.collide(this.groups.robots, this.groups.robots, function (robot1, robot2) {
87 | if (robot1.boss && !robot2.isDead && !robot1.isDead) {
88 | robot1.killedOtherRobot(robot2);
89 | robot2.animateDeath();
90 | }
91 |
92 | if (robot2.boss && !robot1.isDead && !robot2.isDead) {
93 | robot2.killedOtherRobot(robot1);
94 | robot1.animateDeath();
95 | }
96 | }, null, this);
97 |
98 | const panel = getMemberByName(this.groups.panel, 'statisticsPanel');
99 | if (panel) {
100 | panel.show(this.game.input.keyboard.isDown(Phaser.Keyboard.SHIFT));
101 | }
102 | }
103 |
104 | Bots.Level.prototype.onButtonPressed = function (button) {
105 | if (button.name === 'menuButton') {
106 | const content = this.game.cache.getText('menu');
107 | const payload = JSON.parse(content);
108 | payload.prefabs.background.properties.key = Bots.background;
109 | this.game.state.start('loading', true, false, payload, 'menu');
110 | }
111 | }
--------------------------------------------------------------------------------
/js/states/loading.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 11/07/17.
3 | */
4 |
5 |
6 | let Bots = Bots || {};
7 |
8 | Bots.Loading = function () {
9 | Phaser.State.call(this);
10 | };
11 |
12 | Bots.prototype = Object.create(Phaser.State.prototype);
13 | Bots.prototype.constructor = Bots.Loading;
14 |
15 | Bots.Loading.prototype.init = function (data, nextState) {
16 | this.data = data;
17 | this.nextState = nextState;
18 | };
19 |
20 | Bots.Loading.prototype.preload = function () {
21 | var assets = this.data.assets;
22 |
23 | for (var assetKey in assets) {
24 | if (assets.hasOwnProperty(assetKey)) {
25 | var asset = assets[assetKey];
26 |
27 | switch (asset.type) {
28 | case "image":
29 | this.load.image(assetKey, asset.source);
30 | break;
31 | case "spritesheet":
32 | this.load.spritesheet(assetKey, asset.source, asset.frameWidth, asset.frameHeight, asset.frames, asset.margin || 0, asset.spacing || 0);
33 | break;
34 | case "sound":
35 | this.load.audio(assetKey, asset.source);
36 | break;
37 | }
38 | }
39 | }
40 | };
41 |
42 | Bots.Loading.prototype.create = function () {
43 | this.game.state.start(this.nextState, true, false, this.data);
44 | };
--------------------------------------------------------------------------------
/js/states/menu.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 22/07/17.
3 | */
4 |
5 | let Bots = Bots || {};
6 | Bots.Menu = function () {
7 | Phaser.State.call(this);
8 |
9 | this.prefabClasses = {
10 | 'sprite': Bots.Prefab.prototype.constructor,
11 | 'text': Bots.TextPrefab.prototype.constructor,
12 | 'animatedSprite': Bots.AnimatedSprite.prototype.constructor,
13 | 'tileSprite': Bots.TileSprite.prototype.constructor,
14 | 'button': Bots.Button.prototype.constructor,
15 | 'menuRobotChooser': Bots.MenuRobotChooser.prototype.constructor,
16 | 'menuBackgroundChooser': Bots.MenuBackgroundChooser.prototype.constructor,
17 | 'pauseDialogSpawner': Bots.PauseDialogSpawner.prototype.constructor,
18 | 'selectableSprite': Bots.SelectableSprite.prototype.constructor,
19 | 'sound': Bots.SoundPrefab.prototype.constructor,
20 | 'menuRobotSpawner': Bots.MenuRobotSpawner.prototype.constructor,
21 | 'sound': Bots.SoundPrefab.prototype.constructor
22 | }
23 | };
24 |
25 | Bots.Menu.prototype = Object.create(Phaser.State.prototype);
26 | Bots.Menu.prototype.constructor = Bots.Menu;
27 |
28 | Bots.Menu.prototype.create = function () {
29 | this.game.time.advancedTiming = true;
30 | }
31 |
32 | Bots.Menu.prototype.init = function (data) {
33 | this.data = data;
34 | this.game.physics.startSystem(Phaser.Physics.ARCADE);
35 | }
36 |
37 | Bots.Menu.prototype.create = function () {
38 | this.game.time.advancedTiming = true
39 |
40 | this.game.stage.backgroundColor = '#212A31';
41 | this.groups = {};
42 | this.prefabs = {};
43 |
44 | this.data.groups.forEach(groupName => (this.groups[groupName] = this.game.add.group()), this);
45 | for (var prefabName in this.data.prefabs) {
46 | if (this.data.prefabs.hasOwnProperty(prefabName)) {
47 | this.createPrefab(prefabName, this.data.prefabs[prefabName]);
48 | }
49 | }
50 |
51 | /* Animations */
52 |
53 | /* Clouds */
54 | this.game.add.tween(getMemberByName(this.groups.logo, 'middleCloud'))
55 | .to({ alpha: 1 }, 500, Phaser.Easing.Circular.InOut, true);
56 | this.game.add.tween(getMemberByName(this.groups.logo, 'leftCloud'))
57 | .to({ x: 35 }, 550, Phaser.Easing.Circular.InOut, true, 500)
58 | .onComplete.add(() => {
59 | getMemberByName(this.groups.logo, 'leftCloud').x = 35;
60 | this.game.add.tween(getMemberByName(this.groups.logo, 'leftCloud'))
61 | .to({ x: getMemberByName(this.groups.logo, 'leftCloud').x + 10 }, 5000, Phaser.Easing.Linear.None, true, 25, -1, true);
62 | this.game.add.tween(getMemberByName(this.groups.logo, 'leftCloud'))
63 | .to({ y: getMemberByName(this.groups.logo, 'leftCloud').y + 8 }, 7200, Phaser.Easing.Linear.None, true, 75, -1, true);
64 | }, this);
65 | this.game.add.tween(getMemberByName(this.groups.logo, 'rightCloud'))
66 | .to({ x: 500 }, 550, Phaser.Easing.Circular.InOut, true, 500)
67 | .onComplete.add(() => {
68 | getMemberByName(this.groups.logo, 'rightCloud').x = 500;
69 | this.game.add.tween(getMemberByName(this.groups.logo, 'rightCloud'))
70 | .to({ x: getMemberByName(this.groups.logo, 'rightCloud').x - 8 }, 4500, Phaser.Easing.Linear.None, true, 50, -1, true);
71 | this.game.add.tween(getMemberByName(this.groups.logo, 'rightCloud'))
72 | .to({ y: getMemberByName(this.groups.logo, 'rightCloud').y + 4 }, 9000, Phaser.Easing.Linear.None, true, 82, -1, true);
73 | }, this);
74 |
75 | /* robots */
76 | this.game.add.tween(getMemberByName(this.groups.logo, 'logoRobotGreen'))
77 | .to({ alpha: 1, x: 442 }, 500, Phaser.Easing.Circular.InOut, true, 500);
78 | this.game.add.tween(getMemberByName(this.groups.logo, 'logoRobotRed'))
79 | .to({ alpha: 1, x: 274 }, 500, Phaser.Easing.Circular.InOut, true, 500);
80 | this.game.add.tween(getMemberByName(this.groups.logo, 'logoBulletRight'))
81 | .to({ alpha: 1, x: 510, y: 42 }, 500, Phaser.Easing.Circular.InOut, true, 500);
82 | this.game.add.tween(getMemberByName(this.groups.logo, 'logoBulletLeft'))
83 | .to({ alpha: 1, x: 194, y: 36 }, 500, Phaser.Easing.Circular.InOut, true, 500);
84 |
85 | /* chooser */
86 |
87 | getMemberByName(this.groups.chooser, 'redRobotMoving').play('driving');
88 | getMemberByName(this.groups.chooser, 'greenRobotMoving').play('driving');
89 | getMemberByName(this.groups.chooser, 'greyRobotMoving').play('driving');
90 | getMemberByName(this.groups.chooser, 'yellowRobotMoving').play('driving');
91 |
92 | this.chooser = getMemberByName(this.groups.spawners, 'menuChooser');
93 | this.chooser.showRobot(0, true);
94 |
95 | this.backgroundChooser = getMemberByName(this.groups.spawners, 'menuBackgroundChooser');
96 | getMemberByName(this.groups.hud, 'soundButton').loadTexture(Bots.soundsEnabled ? 'uiMusicOn' : 'uiMusicOff');
97 | };
98 |
99 | Bots.Menu.prototype.createPrefab = function (prefabName, properties) {
100 | if (this.prefabClasses.hasOwnProperty(properties.type)) {
101 | const position = new Phaser.Point(properties.position.x, properties.position.y);
102 | const prefab = new this.prefabClasses[properties.type](this, prefabName, position, properties.properties);
103 |
104 | this.prefabs[prefabName] = prefab;
105 | }
106 | };
107 |
108 | Bots.Menu.prototype.update = function () {
109 | this.game.physics.arcade.collide(this.groups.robots);
110 | }
111 |
112 | Bots.Menu.prototype.onButtonPressed = function (button) {
113 | if (button.name === 'leftButton') {
114 | this.chooser.showPrevious();
115 | }
116 |
117 | if (button.name === 'rightButton') {
118 | this.chooser.showNext();
119 | }
120 |
121 | if (button.name === 'startButton') {
122 | const content = this.game.cache.getText('level');
123 | const payload = JSON.parse(content);
124 | Bots.background = this.backgroundChooser.selectedTile.properties.key;
125 | payload.prefabs.robotSpawner.properties.spawnKey = this.chooser.getChosenRobot().properties.secondKey;
126 | payload.prefabs.background.properties.key = this.backgroundChooser.selectedTile.properties.key;
127 |
128 | Bots.humanRobotKey = this.chooser.getChosenRobot().properties.secondKey;
129 | this.chooser.chooseRobot(500);
130 | this.fadeOutUI('level', payload);
131 | }
132 |
133 | if (button.name === 'informationButton') {
134 | const content = this.game.cache.getText('credits');
135 | const payload = JSON.parse(content);
136 | Bots.background = this.backgroundChooser.selectedTile.properties.key;
137 | payload.prefabs.background.properties.key = this.backgroundChooser.selectedTile.properties.key;
138 |
139 | Bots.humanRobotKey = this.chooser.getChosenRobot().properties.secondKey;
140 | this.fadeOutUI('credits', payload);
141 | }
142 |
143 | if (button.name === 'soundButton') {
144 | Bots.soundsEnabled = !Bots.soundsEnabled;
145 | button.loadTexture(Bots.soundsEnabled ? 'uiMusicOn' : 'uiMusicOff');
146 | }
147 | }
148 |
149 | Bots.Menu.prototype.fadeOutUI = function (nextState, payload) {
150 | this.game.add.tween(this.groups.logo).to({ y: -200 }, 500, Phaser.Easing.Elastic.In, true);
151 | this.game.add.tween(this.groups.hud).to({ alpha: 0 }, 500, Phaser.Easing.Quintic.Out, true)
152 | .onComplete.add(function () {
153 | this.game.state.start('loading', true, false, payload, nextState);
154 | }, this);
155 | }
--------------------------------------------------------------------------------
/js/utilities/arrayUtilities.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 19/07/17.
3 | */
4 |
5 | const sample = (array, exception) => {
6 | const temp = Object.assign([], array).filter(item => item !== exception);
7 | return temp[Math.floor(Math.random() * temp.length)];
8 | }
--------------------------------------------------------------------------------
/js/utilities/groupUtilities.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 19/07/17.
3 | */
4 |
5 | const getMemberByName = (group, name) => {
6 | if (!!group && !!name) {
7 | return group.filter(item => item.name === name).list[0];
8 | }
9 | }
10 |
11 | const getHumanRobot = (robotsGroup) => {
12 | return robotsGroup.filter(item => item.human).list[0];
13 | }
14 |
15 | const killFromGroup = (item, group) => {
16 | if (item) {
17 | item.kill();
18 | item.destroy();
19 | group.remove(item);
20 | }
21 | }
--------------------------------------------------------------------------------
/js/utilities/mathUtilities.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 19/07/17.
3 | */
4 |
5 | const calculateDamage = (attack, defense) => {
6 | const baseDamage = Math.pow(attack, 3) / 32 + 32;
7 | const damageReduction = Math.pow(defense - 280.4, 2) / 110 + 16;
8 | const baseDamage2 = baseDamage * damageReduction / 730;
9 |
10 | return baseDamage2 * (730 - (defense * 51 - Math.pow(defense, 2) / 11) / 10) / 7300;
11 | }
12 |
13 | const calculateDamage2 = (attack, defense) => {
14 | return attack * attack / (attack + defense);
15 | }
16 |
17 | const mod = (number, mod) => ((number % mod) + mod) % mod;
18 |
19 | const randomBoolean = () => randomInteger(10) < 5;
--------------------------------------------------------------------------------
/js/utilities/nameUtilities.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by s.neidig on 22/07/17.
3 | */
4 |
5 | const parseRule = (rule) => {
6 | return rule.substr(1).split('$');
7 | }
8 |
9 | const structure = () => {
10 | return {
11 | vowel: ['a', 'e', 'i', 'o', 'u', 'y'],
12 | start: ['Aer', 'Al', 'Am', 'An', 'Ar', 'Arm', 'Arth', 'B', 'Bal', 'Bar', 'Be', 'Bel', 'Ber', 'Bok', 'Bor', 'Bran', 'Breg', 'Bren', 'Brod', 'Cam', 'Chal', 'Cham', 'Ch', 'Cuth', 'Dag', 'Daim', 'Dair', 'Del', 'Dr', 'Dur', 'Duv', 'Ear', 'Elen', 'Er', 'Erel', 'Erem', 'Fal', 'Ful', 'Gal', 'G', 'Get', 'Gil', 'Gor', 'Grin', 'Gun', 'H', 'Hal', 'Han', 'Har', 'Hath', 'Hett', 'Hur', 'Iss', 'Khel', 'K', 'Kor', 'Lel', 'Lor', 'M', 'Mal', 'Man', 'Mard', 'N', 'Ol', 'Radh', 'Rag', 'Relg', 'Rh', 'Run', 'Sam', 'Tarr', 'T', 'Tor', 'Tul', 'Tur', 'Ul', 'Ulf', 'Unr', 'Ur', 'Urth', 'Yar', 'Z', 'Zan', 'Zer'],
13 | middle: ['de', 'do', 'dra', 'du', 'duna', 'ga', 'go', 'hara', 'kaltho', 'la', 'latha', 'le', 'ma', 'nari', 'ra', 're', 'rego', 'ro', 'rodda', 'romi', 'rui', 'sa', 'to', 'ya', 'zila'],
14 | end: ['bar', 'bers', 'blek', 'chak', 'chik', 'dan', 'dar', 'das', 'dig', 'dil', 'din', 'dir', 'dor', 'dur', 'fang', 'fast', 'gar', 'gas', 'gen', 'gorn', 'grim', 'gund', 'had', 'hek', 'hell', 'hir', 'hor', 'kan', 'kath', 'khad', 'kor', 'lach', 'lar', 'ldil', 'ldir', 'leg', 'len', 'lin', 'mas', 'mnir', 'ndil', 'ndur', 'neg', 'nik', 'ntir', 'rab', 'rach', 'rain', 'rak', 'ran', 'rand', 'rath', 'rek', 'rig', 'rim', 'rin', 'rion', 'sin', 'sta', 'stir', 'sus', 'tar', 'thad', 'thel', 'tir', 'von', 'vor', 'yon', 'zor'],
15 | rule: '$start$vowel$35$middle$10$middle$end'
16 | };
17 | }
18 |
19 | const randomInteger = (max) => {
20 | return Math.floor(Math.random() * max);
21 | }
22 |
23 | const isNameValid = (name)
24 |
25 | const shortenName = (name, length = 10) => {
26 | if (name.length > length) {
27 | return name.substring(0, length) + '...';
28 | } else {
29 | return name;
30 | }
31 | };
32 |
33 | const getRandomName = () => {
34 | const rule = parseRule(structure().rule);
35 | const ruleCount = rule.length;
36 | let name = '';
37 |
38 | for (let i = 0; i < ruleCount; i++) {
39 | const percent = parseInt(rule[i]);
40 | if (isNaN(percent)) {
41 | if (rule[i] === '_') {
42 | name += ' ';
43 | } else {
44 | const segCount = structure()[rule[i]].length;
45 | name += structure()[rule[i]][randomInteger(segCount)];
46 | }
47 | } else if (randomInteger(100) > percent && i < (ruleCount - 1)) {
48 | i += 1;
49 | }
50 | }
51 |
52 | return name.replace(/^\s+|\s+$/g, "");
53 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dasheck-hackathon-phaser",
3 | "version": "1.0.0",
4 | "description": "This is my entry for the 2017 phaser hackathon",
5 | "main": " ",
6 | "dependencies": {
7 | "textversionjs": "^1.0.2"
8 | },
9 | "devDependencies": {
10 | "babel-cli": "^6.24.1",
11 | "babel-preset-es2015": "^6.24.1",
12 | "get-folder-size": "^1.0.0",
13 | "gulp": "^3.9.1",
14 | "gulp-babel": "^6.1.2",
15 | "gulp-imagemin": "^3.3.0",
16 | "gulp-minify": "^1.0.0",
17 | "opn": "^5.1.0"
18 | },
19 | "scripts": {
20 | "test": "echo \"Error: no test specified\" && exit 1"
21 | },
22 | "keywords": [
23 | "phaser",
24 | "hackathon",
25 | "nodejs"
26 | ],
27 | "author": "Stefan Neidig (http://appcom-interactive.de)",
28 | "license": "MIT"
29 | }
30 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Robots
2 |
3 | This is my contribution to the [2017 Zenva Phaser Hackathon](https://gamedevacademy.org/first-zenva-phaser-hackathon/?a=13).
4 | The competion is held from July 6th to July 30th 2017 with the goal to create
5 | a game only by using phaser. However there were some rules each contestant
6 | had to respect. The most notably onews were that only predefined assets
7 | could be used and that the complete game must not exceed 500 KB of disk space.
8 |
9 | ## Game
10 |
11 | ### Installation
12 |
13 | To create the games dist folder you have to setup the build
14 | pipeline. This is as easy as running `npm install` on the projects
15 | directory. This will install required dependencies (i.e. gulp). Then
16 | run `gulp transpile minify` to create the `dist` directory, which will
17 | contain the games sources. You can verify that the required space does not
18 | exceed 500 KB by running `gulp calculateSize`. Then open the `index.html`
19 | and the game should start.
20 |
21 | ### Objective
22 |
23 | Robots is a game where you control a robot and try to survive as long as
24 | you can. Other robots will spawn and attack you. But fear not! Dodge
25 | their bullets and fire your own to destroy them and gain loot and other
26 | goodies. These will help to upgrade your robot.
27 |
28 | ### Features
29 |
30 | #### Comprehensive battle system
31 |
32 | Your robot has 4 main states, namely attack, defense, speed and health.
33 | Attack and defense are used for damage calculation once your robot is hit.
34 | The formula is quite complex and tweaked, such that you last at least a few
35 | hits before you die. Speed controls not only your translation speed but
36 | also how fast you can rotate. And health is the most important stat you
37 | need to focus on. Once it drops below zero you are dead. Don't worry!
38 | Your health is replenished after killing an enemy robot.
39 |
40 | ### Loots
41 |
42 | There are several possibilities to gain loot within the game. The most
43 | obvious one is to open chests by destroying them. Once they are opened
44 | you get a persistent boost of one of your main stats. So do not focus
45 | that much on killing robots and get some chests too!
46 |
47 | ### Bosses
48 |
49 | Every once in a while there spawns a boss robot. There will be a special
50 | notification for this event. The boss will be displayed as a red dot on
51 | the minimap. But be careful the boss has way better stats than any other
52 | robot including yourself (probably). Also the boss has special attacks
53 | like the stun jump and a periodic meteor hail. Each robot will explode
54 | instantaneously upon boss collision. Boss fights are only for the best
55 | of the best. But believe me it is worth it. According to the legend one
56 | will receive its power when a boss dies!
57 |
58 | ### Environment
59 |
60 | The world of Bots is dangerous by itself. But pay attention to your
61 | surroundings. There are random events, which you should avoid. This can
62 | randomly placed oil on the road, which will slow you down or even
63 | meteors dropping from the sky, which will likely kill you instantly.
64 | Sometimes the earth shatters for no reason, stunning each robot nearby
65 | for a certain time.
66 |
67 | ### HUD
68 |
69 | Keep everything in sight by using your hud. Simply press shift (or tap
70 | the button when you are on mobile) and show your HUD. This contains
71 | information about yourself, the current robots ranking based on their level
72 | and a basic help as well as a "how to". Never get lost with your HUD!
73 |
74 | ## Screenshots
75 |
76 |
77 |
78 |
79 |
80 |
81 | ## Road map
82 |
83 | ### Crucial
84 |
85 | * Check licenses
86 |
87 | ### Important
88 |
89 | ### Nice to have
90 |
91 | ### Not for hackathon
92 |
93 | * Add more robot ai types (timid, circeling, random)
94 | * Add consumables - invisible, mirror, stun enemies,
95 | * Add randomly placed obstacles (destroyable and not destroyable)
96 | * Add mines as secondary weapons and add camera shake for explosion
97 | * Scrolling message window (like a ticker)
98 | * Add more weapon graphics
99 | * Increase size of robot for the minimap based on kill counter
100 | * Add temp stat boosts for special actions
101 | * Add task systems, which give medals and stat boosts
102 | * Add stats for controlling weapon system
103 | * Add randomly placed structures (like a maze/labyrinth)
104 | * Add pause mode in game
105 |
106 | ### Done
107 |
108 | * ~~Minify assets~~
109 | * ~~Tweaking game parameters~~
110 | * ~~Add help for minimap!~~
111 | * ~~Show hud in the first game or a hint so that the player knows how to show it~~
112 | * ~~Do not spawn boss continuously and place warning when he appears (with warning symbol, flashing screen and shaking)~~
113 | * ~~Revamp damage calculation~~
114 | * ~~Atk, Def, Spd, Health fixed values based on chosen robot (yellow -> good def)~~
115 | * ~~Add sounds~~
116 | * ~~Spawn protect~~
117 | * ~~Robot should emit smoke when on low health (only bosses)~~
118 | * ~~Add randomly driving robots for menu (just to make it more dynamic)~~
119 | * ~~Add oil on street again~~
120 | * ~~Draw healthbar in different colors based on HP~~
121 | * ~~Add menu, settings, credits, options~~
122 | * ~~Animate gaining loots and stat boosts~~
123 | * ~~Drop loot after killing another robot~~
124 | * ~~Statistics per TAB Button (With points, ranks, history, etc)~~
125 | * ~~Add start button in menu~~
126 | * ~~Add bosses (Can jump and stun robots within distance, can drop missiles, yield medals uopn defeat)~~
127 | * ~~Add more crate graphics~~
128 | * ~~Add robot shadows~~
129 | * ~~Kill notification like in CS:GO~~
130 | * ~~Funny names for bots~~
131 | * ~~Draw human robot in another color for the minimap~~
132 | * ~~Respawn player after death~~
133 | * ~~Add support for mobile~~
134 | * ~~Add explosion tweens and scorch marks after killing a robot~~
135 | * ~~Add tracks to robot for the last 100 meters~~
136 |
137 | ## Considerations
138 |
139 | This game was developed as part of a hackathon. Keep that in mind. The code
140 | and its structure does not need to apply to the highest quality standards
141 | and this game might contain bugs. If you have feedback to both see the about me
142 | section to find out how you can get in contact with me to actually tell me
143 | your feedback.
144 |
145 | While the game runs on 60 fps on my machine it does not need to do so on
146 | yours (especially when your device is a mobile device). There are many
147 | objects, which need to be rendered and calculated. There can be many
148 | optimizations done, but again, this was a hackathon. So bear with me!
149 |
150 | ## Used assets
151 |
152 | ### Images
153 |
154 | * [Robot pack](http://kenney.nl/assets/robot-pack)
155 | * [Tanks](http://kenney.nl/assets/tanks)
156 | * [Smoke Particle Assets](https://opengameart.org/content/smoke-particle-assets)
157 | * [Topdown Tanks](https://kenney.nl/assets/topdown-tanks)
158 | * [Game icons](https://opengameart.org/content/game-icons)
159 | * [Cloud set](https://opengameart.org/content/cloud-set)
160 | * [Onscreen - Controls](http://kenney.nl/assets/onscreen-controls)
161 | * [Sokoban (100+ Tiles)](https://opengameart.org/content/sokoban-100-tiles)
162 | * [Space Shooter Redux](https://opengameart.org/content/space-shooter-redux)
163 | * [FREE UI ASSET PACK 1](https://opengameart.org/content/free-ui-asset-pack-1)
164 | * [Stone blocks](https://opengameart.org/content/stoneblocks)
165 | * [50 free textures 5 - with normalmaps](https://opengameart.org/content/50-free-textures-5-with-normalmaps)
166 | * [Explosion](https://opengameart.org/content/explosion)
167 | * [Powers Icons](https://opengameart.org/content/powers-icons)
168 |
169 | ### Sounds
170 |
171 | * [droplet4](http://freesound.org/people/willy_ineedthatapp_com/sounds/167329/) by willy_ineedthatapp
172 | * [whack01](http://freesound.org/people/Qat/sounds/114682/) by Qat
173 | * [LightBulletPing](http://freesound.org/people/wilhellboy/sounds/351369/) by wilhellby
174 | * [PVC Rocket Cannon_2](http://freesound.org/people/bowlingballout/sounds/151714/) by bowlingballout
175 | * [MoCa abstract kick](http://freesound.org/people/moca/sounds/49030/) by moca
176 |
177 | ## Assets removed due to insufficient licenses
178 |
179 | * [Hand Painted Texture - Sandstone](https://opengameart.org/content/hand-painted-texture-sandstone)
180 | * [Hand Painted Texture - Floor Tile](https://opengameart.org/content/hand-painted-texture-floor-tile)
181 | * [95 Game icons](https://opengameart.org/content/95-game-icons)
182 | * [Bomb Explosion Animation](https://opengameart.org/content/bomb-explosion-animation)
183 | * [LCP Terrain Pack](https://opengameart.org/content/lpc-terrain-repack)
184 | * [2d Lost Garden Zelda style tiles resized to 32x32 with additions](https://opengameart.org/content/2d-lost-garden-zelda-style-tiles-resized-to-32x32-with-additions)
185 |
186 | ## About me
187 |
188 | I am from Germany and involved with programming for almost 15 years. I
189 | actually started with developing games back in the days with C++ and OpenGL,
190 | before switching to Irrlicht 3D, Unity 3D and finally PhaserJS. So far
191 | PhaserJS gave me the best experience, since it is easy to understand
192 | and extremly powerful letting me completely focus on the actual game.
193 | Projects with the previously mentioned engines were never completed, since
194 | I got stuck in patching the engine or building missing parts
195 | (i.e. gamestates, object pooling, ...).
196 |
197 | This is the first bigger game I finished. You can play it on [itch.io](https://dasheck.itch.io/bots).
198 | Any feedback is appreciated. You can contact my via twitter, email or provide the feedback directly via itch.io.
199 | Thanks for reading, playing and feedbacking!
200 |
201 | ## License
202 |
203 | This game is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT)
204 |
--------------------------------------------------------------------------------
/watch.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | fswatch -o -r ./assets ./js index.html | xargs -n1 bash ./deliver.sh
--------------------------------------------------------------------------------