├── .gitignore ├── .vscode ├── commandbar.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── art ├── AG-hero.png ├── AG-hero.psd ├── AG-letterbox.png ├── AG-letterbox.psd ├── AG-thumbnail.png ├── AG-thumbnail.psd ├── banner.png ├── fontStyle.psd ├── itchBanner.png ├── itchBg.png ├── itchCover.png ├── ldCover.png ├── ldCover.psd ├── thumbnail.png ├── thumbnail.psd ├── tiles.psd ├── tiles.tps ├── title.psd └── youtube.png ├── base.hxml ├── hl.debug.hxml ├── hl.hxml ├── iframeTest.html ├── jam ├── client.js └── sabotage.win.zip ├── js.html ├── js.hxml ├── langParser.hxml ├── redist ├── js │ ├── client.js │ └── index.html └── opengl_win │ └── Sabotage │ ├── OpenAL32.dll │ ├── SDL2.dll │ ├── Sabotage.exe │ ├── fmt.hdll │ ├── hlboot.dat │ ├── libhl.dll │ ├── msvcp120.dll │ ├── msvcr120.dll │ ├── openal.hdll │ ├── sdl.hdll │ ├── ssl.hdll │ ├── ui.hdll │ └── uv.hdll ├── res ├── atlas │ ├── tiles.atlas │ └── tiles.png ├── data.cdb ├── fonts │ ├── barlow_condensed_medium_regular_11.fnt │ ├── barlow_condensed_medium_regular_11.png │ ├── barlow_condensed_medium_regular_17.fnt │ ├── barlow_condensed_medium_regular_17.png │ ├── barlow_condensed_medium_regular_32.fnt │ ├── barlow_condensed_medium_regular_32.png │ ├── barlow_condensed_medium_regular_9.fnt │ ├── barlow_condensed_medium_regular_9.png │ ├── minecraftiaOutline.fnt │ └── minecraftiaOutline.png ├── lang │ ├── en.mo │ ├── en.po │ └── sourceTexts.pot ├── map │ ├── intro.json │ ├── itch.json │ ├── lab.json │ ├── ld45.ldtk │ ├── ld45.ogmo │ ├── level0.json │ ├── level1.json │ ├── level2.json │ ├── level3.json │ ├── level4.json │ ├── level5.json │ ├── level6.json │ ├── test.json │ └── tilesets │ │ ├── markers.png │ │ └── tileset.png ├── music │ └── leatherneck.mp3 ├── sfx │ ├── explode0.lch │ ├── explode0.wav │ ├── explode1.lch │ ├── explode1.wav │ ├── explode2.lch │ ├── explode2.wav │ ├── grab0.lch │ ├── grab0.wav │ ├── grab1.lch │ ├── grab1.wav │ ├── grab2.lch │ ├── grab2.wav │ ├── grab3.lch │ ├── grab3.wav │ ├── grab4.lch │ ├── grab4.wav │ ├── hero0.lch │ ├── hero0.wav │ ├── hero1.lch │ ├── hero1.wav │ ├── hero2.lch │ ├── hero2.wav │ ├── hit0.lch │ ├── hit0.wav │ ├── hit1.lch │ ├── hit1.wav │ ├── hit2.lch │ ├── hit2.wav │ ├── hit3.lch │ ├── hit3.wav │ ├── hit4.lch │ ├── hit4.wav │ ├── hit5.lch │ ├── hit5.wav │ ├── hit6.lch │ ├── hit6.wav │ ├── item0.lch │ ├── item0.wav │ ├── item1.lch │ ├── item1.wav │ ├── item2.lch │ ├── item2.wav │ ├── item3.lch │ ├── item3.wav │ ├── item4.lch │ ├── item4.wav │ ├── item5.lch │ ├── item5.wav │ ├── mob0.lch │ ├── mob0.wav │ ├── mob1.lch │ ├── mob1.wav │ ├── mob2.lch │ ├── mob2.wav │ ├── mob3.lch │ ├── mob3.wav │ ├── mob4.lch │ ├── mob4.wav │ ├── surprise0.lch │ ├── surprise0.wav │ ├── surprise1.lch │ ├── surprise1.wav │ ├── surprise2.lch │ ├── surprise2.wav │ ├── throw0.lch │ ├── throw0.wav │ ├── throw1.lch │ ├── throw1.wav │ ├── throw2.lch │ ├── throw2.wav │ ├── throw3.lch │ └── throw3.wav └── title.png ├── screenshots ├── 01.png ├── 02.png ├── 03.gif ├── 04.png ├── 05.png ├── 06.png ├── 07.gif ├── 08.png └── itch.io.gif ├── src.langParser └── LangParser.hx └── src ├── Assets.hx ├── Boot.hx ├── Camera.hx ├── Const.hx ├── Data.hx ├── Entity.hx ├── Fx.hx ├── Game.hx ├── Lang.hx ├── LdtkWorld.hx ├── Level.hx ├── Main.hx ├── Title.hx ├── Types.hx ├── en ├── Bullet.hx ├── Cadaver.hx ├── Door.hx ├── Exit.hx ├── Hero.hx ├── Item.hx ├── Mob.hx ├── Spike.hx └── mob │ ├── Guard.hx │ └── Turret.hx ├── import.hx ├── tools └── CPoint.hx └── ui ├── Console.hx ├── Hud.hx ├── Modal.hx └── Window.hx /.gitignore: -------------------------------------------------------------------------------- 1 | .tmp 2 | art/export* 3 | bin/*.* 4 | *.zip -------------------------------------------------------------------------------- /.vscode/commandbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "skipTerminateQuickPick": true, 3 | "skipSwitchToOutput": false, 4 | "skipErrorMessage": true, 5 | "commands": [ 6 | { 7 | "text": "🍊 Build HL", 8 | "color": "orange", 9 | "commandType":"palette", 10 | "command": "workbench.action.tasks.runTask|HL release", 11 | "alignment": "right", 12 | "skipTerminateQuickPick": false, 13 | "priority": -10 14 | }, 15 | { 16 | "text": "Run HL", 17 | "color": "orange", 18 | "command": "hl bin/client.hl", 19 | "alignment": "right", 20 | "skipTerminateQuickPick": false, 21 | "priority": -11 22 | }, 23 | { 24 | "text": "☕ Build JS", 25 | "color": "yellow", 26 | "commandType":"palette", 27 | "command": "workbench.action.tasks.runTask|JS release", 28 | "alignment": "right", 29 | "skipTerminateQuickPick": false, 30 | "priority": -20 31 | }, 32 | { 33 | "text": "Run JS", 34 | "color": "yellow", 35 | "command": "start js.html", 36 | "alignment": "right", 37 | "skipTerminateQuickPick": false, 38 | "priority": -21 39 | }, 40 | { 41 | "text": "🅰️ Build POT", 42 | "color": "white", 43 | "commandType":"palette", 44 | "command": "workbench.action.tasks.runTask|Lang", 45 | "alignment": "right", 46 | "skipTerminateQuickPick": false, 47 | "priority": -40 48 | }, 49 | { 50 | "text": "📦 Redist JS only", 51 | "color": "lightgreen", 52 | "command": "haxelib run redistHelper js.hxml -p sabotage", 53 | "alignment": "right", 54 | "skipTerminateQuickPick": false, 55 | "priority": -49 56 | }, 57 | { 58 | "text": "📦 Redist", 59 | "color": "lightgreen", 60 | "command": "haxelib run redistHelper hl.hxml js.hxml -p Sabotage -zip", 61 | "alignment": "right", 62 | "skipTerminateQuickPick": false, 63 | "priority": -50 64 | } 65 | ] 66 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "HL debug", 9 | "request": "launch", 10 | "type": "hl", 11 | "hxml": "hl.debug.hxml", 12 | "cwd": "${workspaceRoot}", 13 | "preLaunchTask": "HL debug" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "titleBar.inactiveBackground": "#412727", 4 | "titleBar.activeBackground": "#a94319", 5 | "titleBar.activeForeground": "#ffffff" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "HL debug", 8 | "type": "hxml", 9 | "file": "hl.debug.hxml", 10 | "presentation": { 11 | "reveal": "never", 12 | "panel": "dedicated", 13 | "clear": true 14 | }, 15 | "problemMatcher": ["$haxe"], 16 | "group": { 17 | "kind": "build", 18 | "isDefault": true 19 | } 20 | }, 21 | 22 | { 23 | "label": "HL release", 24 | "type": "hxml", 25 | "file": "hl.hxml", 26 | "presentation": { 27 | "reveal": "never", 28 | "panel": "dedicated", 29 | "clear": true 30 | }, 31 | "problemMatcher": ["$haxe"], 32 | }, 33 | { 34 | "label": "JS release", 35 | "type": "hxml", 36 | "file": "js.hxml", 37 | "presentation": { 38 | "reveal": "never", 39 | "panel": "dedicated", 40 | "clear": true 41 | }, 42 | "problemMatcher": ["$haxe"], 43 | }, 44 | { 45 | "label": "Lang", 46 | "type": "hxml", 47 | "file": "langParser.hxml", 48 | "presentation": { 49 | "reveal": "always", 50 | "panel": "shared", 51 | "clear": true 52 | }, 53 | "problemMatcher": ["$haxe"], 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sébastien Bénard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | _You are Colonel Jean-François Hubert from the French army. As the most badass colonel ever, you take on your missions naked, without any weapon._ 4 | _Improvise, adapt, overcome._ 5 | 6 | _Sabotage_ is my **Ludum Dare 45** entry. It was created in about 72h using Haxe language. The theme was _“Start with nothing”_. 7 | 8 | You can play/download it here: https://deepnight.net/games/sabotage/ -------------------------------------------------------------------------------- /art/AG-hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/AG-hero.png -------------------------------------------------------------------------------- /art/AG-hero.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/AG-hero.psd -------------------------------------------------------------------------------- /art/AG-letterbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/AG-letterbox.png -------------------------------------------------------------------------------- /art/AG-letterbox.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/AG-letterbox.psd -------------------------------------------------------------------------------- /art/AG-thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/AG-thumbnail.png -------------------------------------------------------------------------------- /art/AG-thumbnail.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/AG-thumbnail.psd -------------------------------------------------------------------------------- /art/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/banner.png -------------------------------------------------------------------------------- /art/fontStyle.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/fontStyle.psd -------------------------------------------------------------------------------- /art/itchBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/itchBanner.png -------------------------------------------------------------------------------- /art/itchBg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/itchBg.png -------------------------------------------------------------------------------- /art/itchCover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/itchCover.png -------------------------------------------------------------------------------- /art/ldCover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/ldCover.png -------------------------------------------------------------------------------- /art/ldCover.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/ldCover.psd -------------------------------------------------------------------------------- /art/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/thumbnail.png -------------------------------------------------------------------------------- /art/thumbnail.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/thumbnail.psd -------------------------------------------------------------------------------- /art/tiles.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/tiles.psd -------------------------------------------------------------------------------- /art/title.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/title.psd -------------------------------------------------------------------------------- /art/youtube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/art/youtube.png -------------------------------------------------------------------------------- /base.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib castle 3 | -lib heaps 4 | -lib deepnightLibs 5 | -lib heapsOgmo 6 | -main Boot 7 | -dce full -------------------------------------------------------------------------------- /hl.debug.hxml: -------------------------------------------------------------------------------- 1 | hl.hxml 2 | -debug -------------------------------------------------------------------------------- /hl.hxml: -------------------------------------------------------------------------------- 1 | base.hxml 2 | -D windowSize=1280x720 3 | -D heaps_enable_hl_mp3 4 | -hl bin/client.hl 5 | -lib hlsdl -------------------------------------------------------------------------------- /iframeTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sabotage 6 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin dictum risus lorem, vel efficitur mi sodales vitae. Etiam mollis finibus sapien, vel posuere velit iaculis id. Quisque laoreet tristique auctor. Cras et hendrerit orci. Proin metus ante, ultrices eget justo a, iaculis ultrices augue. Nullam lorem sem, imperdiet a varius in, fringilla et ex. Aenean porttitor nec risus vitae vehicula. In aliquam volutpat sapien vitae gravida. Sed ullamcorper, sem eu tincidunt luctus, erat urna posuere ipsum, ut dictum mi erat at quam. Curabitur et vestibulum orci, non cursus augue. Proin semper, ante sed gravida volutpat, ex nunc condimentum dolor, a egestas augue magna eu massa. Ut ultricies ante eu lorem feugiat ullamcorper. Praesent scelerisque feugiat lectus vel egestas.

32 |

Nulla elementum est nec est semper pellentesque. Fusce accumsan enim non pretium cursus. Fusce eu sapien sit amet felis pharetra posuere. Aenean luctus sodales nisl, pellentesque fringilla nisl lobortis eu. In ligula lorem, sagittis eget nisl sed, pellentesque pretium nulla. Nullam at commodo tortor. Nulla malesuada quis elit nec rutrum. Phasellus vitae eleifend nunc. Donec non vehicula purus. Morbi tincidunt felis in neque dictum, ac scelerisque ipsum sodales. Cras ac purus mi.

33 |
34 | 35 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /jam/sabotage.win.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/jam/sabotage.win.zip -------------------------------------------------------------------------------- /js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | sabotage 6 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /js.hxml: -------------------------------------------------------------------------------- 1 | base.hxml 2 | -js bin/client.js 3 | -------------------------------------------------------------------------------- /langParser.hxml: -------------------------------------------------------------------------------- 1 | -cp src.langParser 2 | -main LangParser 3 | -lib castle 4 | -lib deepnightLibs 5 | -D potools 6 | -hl bin/langParser.hl 7 | 8 | --next 9 | -cmd hl bin/langParser.hl -------------------------------------------------------------------------------- /redist/js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sabotage 6 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/OpenAL32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/OpenAL32.dll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/SDL2.dll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/Sabotage.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/Sabotage.exe -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/fmt.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/fmt.hdll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/hlboot.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/hlboot.dat -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/libhl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/libhl.dll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/msvcp120.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/msvcp120.dll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/msvcr120.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/msvcr120.dll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/openal.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/openal.hdll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/sdl.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/sdl.hdll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/ssl.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/ssl.hdll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/ui.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/ui.hdll -------------------------------------------------------------------------------- /redist/opengl_win/Sabotage/uv.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/redist/opengl_win/Sabotage/uv.hdll -------------------------------------------------------------------------------- /res/atlas/tiles.atlas: -------------------------------------------------------------------------------- 1 | 2 | tiles.png 3 | size: 256,512 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | Barrel 8 | rotate: false 9 | xy: 169, 322 10 | size: 14, 15 11 | orig: 16, 16 12 | offset: 1, 0 13 | index: -1 14 | bird0 15 | rotate: false 16 | xy: 120, 235 17 | size: 5, 4 18 | orig: 5, 5 19 | offset: 0, 1 20 | index: -1 21 | bird1 22 | rotate: false 23 | xy: 81, 275 24 | size: 5, 4 25 | orig: 5, 5 26 | offset: 0, 1 27 | index: -1 28 | bird2 29 | rotate: false 30 | xy: 81, 281 31 | size: 5, 4 32 | orig: 5, 5 33 | offset: 0, 1 34 | index: -1 35 | bird3 36 | rotate: false 37 | xy: 81, 287 38 | size: 5, 4 39 | orig: 5, 5 40 | offset: 0, 0 41 | index: -1 42 | bird4 43 | rotate: false 44 | xy: 81, 293 45 | size: 5, 4 46 | orig: 5, 5 47 | offset: 0, 0 48 | index: -1 49 | bird5 50 | rotate: false 51 | xy: 81, 299 52 | size: 5, 4 53 | orig: 5, 5 54 | offset: 0, 0 55 | index: -1 56 | btA 57 | rotate: false 58 | xy: 33, 352 59 | size: 13, 14 60 | orig: 13, 16 61 | offset: 0, 0 62 | index: -1 63 | btB 64 | rotate: false 65 | xy: 48, 352 66 | size: 13, 14 67 | orig: 13, 16 68 | offset: 0, 0 69 | index: -1 70 | btX 71 | rotate: false 72 | xy: 16, 353 73 | size: 13, 14 74 | orig: 13, 16 75 | offset: 0, 0 76 | index: -1 77 | bulletMob0 78 | rotate: false 79 | xy: 220, 67 80 | size: 7, 7 81 | orig: 7, 7 82 | offset: 0, 0 83 | index: -1 84 | bulletMob1 85 | rotate: false 86 | xy: 37, 295 87 | size: 7, 7 88 | orig: 7, 7 89 | offset: 0, 0 90 | index: -1 91 | bulletMob2 92 | rotate: false 93 | xy: 102, 200 94 | size: 5, 5 95 | orig: 5, 5 96 | offset: 0, 0 97 | index: -1 98 | bulletSmallMob0 99 | rotate: false 100 | xy: 102, 207 101 | size: 5, 5 102 | orig: 5, 5 103 | offset: 0, 0 104 | index: -1 105 | bulletSmallMob1 106 | rotate: false 107 | xy: 102, 214 108 | size: 5, 5 109 | orig: 5, 5 110 | offset: 0, 0 111 | index: -1 112 | bulletSmallMob2 113 | rotate: false 114 | xy: 120, 221 115 | size: 5, 5 116 | orig: 5, 5 117 | offset: 0, 0 118 | index: -1 119 | bulletSmallMob3 120 | rotate: false 121 | xy: 120, 228 122 | size: 5, 5 123 | orig: 5, 5 124 | offset: 0, 0 125 | index: -1 126 | dirtFull0 127 | rotate: false 128 | xy: 185, 158 129 | size: 16, 16 130 | orig: 16, 16 131 | offset: 0, 0 132 | index: -1 133 | doorH 134 | rotate: false 135 | xy: 1, 301 136 | size: 16, 15 137 | orig: 16, 16 138 | offset: 0, 0 139 | index: -1 140 | doorSilverH 141 | rotate: false 142 | xy: 19, 301 143 | size: 16, 15 144 | orig: 16, 16 145 | offset: 0, 0 146 | index: -1 147 | doorSilverV 148 | rotate: false 149 | xy: 188, 241 150 | size: 12, 24 151 | orig: 16, 24 152 | offset: 2, 0 153 | index: -1 154 | doorV 155 | rotate: false 156 | xy: 188, 267 157 | size: 12, 24 158 | orig: 16, 24 159 | offset: 2, 0 160 | index: -1 161 | empty 162 | rotate: false 163 | xy: 252, 51 164 | size: 3, 3 165 | orig: 1, 1 166 | offset: 0, -2 167 | index: -1 168 | exit 169 | rotate: false 170 | xy: 185, 176 171 | size: 16, 16 172 | orig: 16, 16 173 | offset: 0, 0 174 | index: -1 175 | fxAlarm0 176 | rotate: false 177 | xy: 102, 185 178 | size: 5, 13 179 | orig: 5, 13 180 | offset: 0, 0 181 | index: -1 182 | fxCircle 183 | rotate: false 184 | xy: 185, 194 185 | size: 16, 16 186 | orig: 16, 16 187 | offset: 0, 0 188 | index: -1 189 | fxDot 190 | rotate: false 191 | xy: 252, 56 192 | size: 3, 3 193 | orig: 3, 3 194 | offset: 0, 0 195 | index: -1 196 | fxExplosion0 197 | rotate: false 198 | xy: 202, 238 199 | size: 37, 37 200 | orig: 39, 39 201 | offset: 1, 1 202 | index: -1 203 | fxExplosion1 204 | rotate: false 205 | xy: 1, 185 206 | size: 50, 50 207 | orig: 50, 50 208 | offset: 0, 0 209 | index: -1 210 | fxExplosion2 211 | rotate: false 212 | xy: 203, 76 213 | size: 52, 52 214 | orig: 55, 55 215 | offset: 2, 2 216 | index: -1 217 | fxExplosion3 218 | rotate: false 219 | xy: 203, 130 220 | size: 52, 52 221 | orig: 55, 55 222 | offset: 1, 2 223 | index: -1 224 | fxExplosion4 225 | rotate: false 226 | xy: 1, 131 227 | size: 52, 52 228 | orig: 55, 55 229 | offset: 1, 2 230 | index: -1 231 | fxExplosion5 232 | rotate: false 233 | xy: 55, 131 234 | size: 52, 52 235 | orig: 55, 55 236 | offset: 1, 2 237 | index: -1 238 | fxExplosion6 239 | rotate: false 240 | xy: 131, 158 241 | size: 52, 52 242 | orig: 55, 55 243 | offset: 1, 2 244 | index: -1 245 | fxExplosion7 246 | rotate: false 247 | xy: 203, 184 248 | size: 52, 52 249 | orig: 55, 55 250 | offset: 1, 2 251 | index: -1 252 | fxExplosion8 253 | rotate: false 254 | xy: 53, 185 255 | size: 47, 52 256 | orig: 55, 55 257 | offset: 1, 2 258 | index: -1 259 | fxExplosionSmoke0 260 | rotate: false 261 | xy: 88, 241 262 | size: 33, 31 263 | orig: 48, 47 264 | offset: 7, 5 265 | index: -1 266 | fxExplosionSmoke1 267 | rotate: false 268 | xy: 53, 239 269 | size: 33, 34 270 | orig: 48, 47 271 | offset: 7, 6 272 | index: -1 273 | fxExplosionSmoke2 274 | rotate: false 275 | xy: 202, 277 276 | size: 35, 41 277 | orig: 48, 47 278 | offset: 6, 1 279 | index: -1 280 | fxExplosionSmoke3 281 | rotate: false 282 | xy: 127, 232 283 | size: 41, 42 284 | orig: 48, 47 285 | offset: 4, 3 286 | index: -1 287 | fxFlame0 288 | rotate: false 289 | xy: 157, 294 290 | size: 10, 16 291 | orig: 10, 16 292 | offset: 0, 0 293 | index: -1 294 | fxFlame1 295 | rotate: false 296 | xy: 159, 276 297 | size: 9, 16 298 | orig: 9, 16 299 | offset: 0, 0 300 | index: -1 301 | fxFlame2 302 | rotate: false 303 | xy: 157, 312 304 | size: 10, 16 305 | orig: 10, 16 306 | offset: 0, 0 307 | index: -1 308 | fxFragment0 309 | rotate: false 310 | xy: 47, 243 311 | size: 4, 3 312 | orig: 4, 3 313 | offset: 0, 0 314 | index: -1 315 | fxFragment1 316 | rotate: false 317 | xy: 252, 61 318 | size: 3, 3 319 | orig: 3, 3 320 | offset: 0, 0 321 | index: -1 322 | fxFragment2 323 | rotate: false 324 | xy: 47, 237 325 | size: 4, 4 326 | orig: 4, 4 327 | offset: 0, 0 328 | index: -1 329 | fxLargeFlame0 330 | rotate: false 331 | xy: 109, 179 332 | size: 19, 22 333 | orig: 19, 23 334 | offset: 0, 0 335 | index: -1 336 | fxLargeFlame1 337 | rotate: false 338 | xy: 230, 51 339 | size: 20, 23 340 | orig: 20, 24 341 | offset: 0, 0 342 | index: -1 343 | fxLargeFlame2 344 | rotate: false 345 | xy: 109, 131 346 | size: 20, 18 347 | orig: 20, 18 348 | offset: 0, 0 349 | index: -1 350 | fxLine 351 | rotate: false 352 | xy: 88, 274 353 | size: 33, 3 354 | orig: 33, 3 355 | offset: 0, 0 356 | index: -1 357 | fxLineDir0 358 | rotate: false 359 | xy: 47, 275 360 | size: 32, 3 361 | orig: 33, 3 362 | offset: 1, 0 363 | index: -1 364 | fxNova0 365 | rotate: false 366 | xy: 1, 1 367 | size: 128, 128 368 | orig: 128, 128 369 | offset: 0, 0 370 | index: -1 371 | fxPick 372 | rotate: false 373 | xy: 81, 305 374 | size: 14, 15 375 | orig: 15, 15 376 | offset: 0, 0 377 | index: -1 378 | fxQuestion0 379 | rotate: false 380 | xy: 37, 283 381 | size: 7, 10 382 | orig: 7, 10 383 | offset: 0, 0 384 | index: -1 385 | fxSmallCircle 386 | rotate: false 387 | xy: 113, 314 388 | size: 6, 6 389 | orig: 6, 6 390 | offset: 0, 0 391 | index: -1 392 | fxSmoke0 393 | rotate: false 394 | xy: 1, 237 395 | size: 44, 44 396 | orig: 44, 44 397 | offset: 0, 0 398 | index: -1 399 | fxSweat0 400 | rotate: false 401 | xy: 1, 363 402 | size: 13, 11 403 | orig: 16, 16 404 | offset: 1, 2 405 | index: -1 406 | fxSweat1 407 | rotate: false 408 | xy: 188, 293 409 | size: 11, 11 410 | orig: 16, 16 411 | offset: 1, 2 412 | index: -1 413 | fxSweat2 414 | rotate: false 415 | xy: 36, 322 416 | size: 14, 10 417 | orig: 16, 16 418 | offset: 0, 2 419 | index: -1 420 | GoldKey 421 | rotate: false 422 | xy: 140, 308 423 | size: 15, 10 424 | orig: 16, 16 425 | offset: 1, 0 426 | index: -1 427 | Grenade 428 | rotate: false 429 | xy: 1, 318 430 | size: 16, 8 431 | orig: 16, 16 432 | offset: 0, 0 433 | index: -1 434 | guardDead0 435 | rotate: false 436 | xy: 109, 203 437 | size: 16, 16 438 | orig: 16, 16 439 | offset: 0, 0 440 | index: -1 441 | guardDead1 442 | rotate: false 443 | xy: 230, 42 444 | size: 23, 7 445 | orig: 23, 16 446 | offset: 0, 0 447 | index: -1 448 | guardGrabbed0 449 | rotate: false 450 | xy: 18, 336 451 | size: 13, 15 452 | orig: 16, 16 453 | offset: 1, 0 454 | index: -1 455 | guardGrabbed1 456 | rotate: false 457 | xy: 1, 346 458 | size: 13, 15 459 | orig: 16, 16 460 | offset: 1, 0 461 | index: -1 462 | guardHit0 463 | rotate: false 464 | xy: 102, 221 465 | size: 16, 16 466 | orig: 16, 16 467 | offset: 0, 0 468 | index: -1 469 | guardHit1 470 | rotate: false 471 | xy: 106, 279 472 | size: 15, 16 473 | orig: 16, 16 474 | offset: 1, 0 475 | index: -1 476 | guardHit2 477 | rotate: false 478 | xy: 64, 316 479 | size: 14, 15 480 | orig: 16, 16 481 | offset: 1, 0 482 | index: -1 483 | guardIdle0 484 | rotate: false 485 | xy: 241, 238 486 | size: 14, 16 487 | orig: 16, 16 488 | offset: 1, 0 489 | index: -1 490 | guardRun0 491 | rotate: false 492 | xy: 123, 276 493 | size: 16, 15 494 | orig: 16, 16 495 | offset: 0, 1 496 | index: -1 497 | guardRun1 498 | rotate: false 499 | xy: 241, 256 500 | size: 14, 16 501 | orig: 16, 16 502 | offset: 1, 0 503 | index: -1 504 | guardRun2 505 | rotate: false 506 | xy: 97, 314 507 | size: 14, 15 508 | orig: 16, 16 509 | offset: 0, 1 510 | index: -1 511 | guardShoot0 512 | rotate: false 513 | xy: 241, 274 514 | size: 14, 16 515 | orig: 16, 16 516 | offset: 0, 0 517 | index: -1 518 | guardShoot1 519 | rotate: false 520 | xy: 64, 298 521 | size: 15, 16 522 | orig: 16, 16 523 | offset: 1, 0 524 | index: -1 525 | guardShootDown0 526 | rotate: false 527 | xy: 36, 334 528 | size: 13, 16 529 | orig: 16, 16 530 | offset: 2, 0 531 | index: -1 532 | guardShootDown1 533 | rotate: false 534 | xy: 64, 333 535 | size: 13, 16 536 | orig: 16, 16 537 | offset: 2, 0 538 | index: -1 539 | guardWalk0 540 | rotate: false 541 | xy: 65, 280 542 | size: 14, 16 543 | orig: 16, 16 544 | offset: 1, 0 545 | index: -1 546 | guardWalk1 547 | rotate: false 548 | xy: 169, 304 549 | size: 14, 16 550 | orig: 16, 16 551 | offset: 1, 0 552 | index: -1 553 | guardWalk2 554 | rotate: false 555 | xy: 79, 339 556 | size: 13, 16 557 | orig: 16, 16 558 | offset: 0, 0 559 | index: -1 560 | Gun 561 | rotate: false 562 | xy: 170, 277 563 | size: 16, 12 564 | orig: 16, 16 565 | offset: 0, 0 566 | index: -1 567 | Heal 568 | rotate: false 569 | xy: 170, 291 570 | size: 16, 11 571 | orig: 16, 16 572 | offset: 0, 1 573 | index: -1 574 | heartLoss 575 | rotate: false 576 | xy: 37, 304 577 | size: 7, 7 578 | orig: 7, 7 579 | offset: 0, 0 580 | index: -1 581 | heartOff 582 | rotate: false 583 | xy: 37, 313 584 | size: 7, 7 585 | orig: 7, 7 586 | offset: 0, 0 587 | index: -1 588 | heartOn 589 | rotate: false 590 | xy: 97, 305 591 | size: 7, 7 592 | orig: 7, 7 593 | offset: 0, 0 594 | index: -1 595 | heroDead0 596 | rotate: false 597 | xy: 80, 322 598 | size: 14, 15 599 | orig: 16, 16 600 | offset: 1, 0 601 | index: -1 602 | heroDead1 603 | rotate: false 604 | xy: 109, 169 605 | size: 20, 8 606 | orig: 22, 16 607 | offset: 1, 0 608 | index: -1 609 | heroGlide0 610 | rotate: false 611 | xy: 19, 318 612 | size: 15, 16 613 | orig: 16, 16 614 | offset: 1, 0 615 | index: -1 616 | heroGlide1 617 | rotate: false 618 | xy: 1, 328 619 | size: 15, 16 620 | orig: 16, 16 621 | offset: 1, 0 622 | index: -1 623 | heroGlide2 624 | rotate: false 625 | xy: 123, 293 626 | size: 15, 16 627 | orig: 16, 16 628 | offset: 1, 0 629 | index: -1 630 | heroGrab0 631 | rotate: false 632 | xy: 121, 321 633 | size: 14, 15 634 | orig: 16, 16 635 | offset: 2, 0 636 | index: -1 637 | heroHit0 638 | rotate: false 639 | xy: 140, 293 640 | size: 15, 13 641 | orig: 16, 16 642 | offset: 1, 0 643 | index: -1 644 | heroIdle0 645 | rotate: false 646 | xy: 170, 241 647 | size: 16, 16 648 | orig: 16, 16 649 | offset: 0, 0 650 | index: -1 651 | heroIdle1 652 | rotate: false 653 | xy: 170, 259 654 | size: 16, 16 655 | orig: 16, 16 656 | offset: 0, 0 657 | index: -1 658 | heroIdle2 659 | rotate: false 660 | xy: 239, 292 661 | size: 16, 16 662 | orig: 16, 16 663 | offset: 0, 0 664 | index: -1 665 | heroIdleBack0 666 | rotate: false 667 | xy: 239, 310 668 | size: 16, 16 669 | orig: 16, 16 670 | offset: 0, 0 671 | index: -1 672 | heroPunch0 673 | rotate: false 674 | xy: 47, 280 675 | size: 16, 16 676 | orig: 16, 16 677 | offset: 0, 0 678 | index: -1 679 | heroPunch1 680 | rotate: false 681 | xy: 109, 151 682 | size: 20, 16 683 | orig: 24, 16 684 | offset: 4, 0 685 | index: -1 686 | heroPunch2 687 | rotate: false 688 | xy: 1, 283 689 | size: 16, 16 690 | orig: 16, 16 691 | offset: 0, 0 692 | index: -1 693 | heroPunch3 694 | rotate: false 695 | xy: 140, 320 696 | size: 14, 16 697 | orig: 16, 16 698 | offset: 0, 0 699 | index: -1 700 | heroRun0 701 | rotate: false 702 | xy: 19, 283 703 | size: 16, 16 704 | orig: 16, 16 705 | offset: 0, 0 706 | index: -1 707 | heroRun1 708 | rotate: false 709 | xy: 63, 351 710 | size: 13, 16 711 | orig: 16, 16 712 | offset: 2, 0 713 | index: -1 714 | heroRun2 715 | rotate: false 716 | xy: 141, 276 717 | size: 16, 15 718 | orig: 16, 16 719 | offset: 0, 1 720 | index: -1 721 | heroThrow0 722 | rotate: false 723 | xy: 185, 306 724 | size: 14, 16 725 | orig: 16, 16 726 | offset: 1, 0 727 | index: -1 728 | heroThrow1 729 | rotate: false 730 | xy: 96, 331 731 | size: 14, 15 732 | orig: 16, 16 733 | offset: 2, 0 734 | index: -1 735 | heroUseGun0 736 | rotate: false 737 | xy: 106, 297 738 | size: 15, 15 739 | orig: 16, 16 740 | offset: 1, 0 741 | index: -1 742 | ItchIo 743 | rotate: false 744 | xy: 230, 21 745 | size: 23, 19 746 | orig: 23, 19 747 | offset: 0, 0 748 | index: -1 749 | Knife 750 | rotate: false 751 | xy: 203, 67 752 | size: 15, 7 753 | orig: 16, 16 754 | offset: 1, 0 755 | index: -1 756 | longKey 757 | rotate: false 758 | xy: 127, 212 759 | size: 43, 18 760 | orig: 43, 18 761 | offset: 0, 0 762 | index: -1 763 | parachute 764 | rotate: false 765 | xy: 131, 67 766 | size: 70, 89 767 | orig: 80, 97 768 | offset: 3, 3 769 | index: -1 770 | pixel 771 | rotate: false 772 | xy: 252, 66 773 | size: 1, 1 774 | orig: 1, 1 775 | offset: 0, 0 776 | index: -1 777 | shortKey 778 | rotate: false 779 | xy: 230, 1 780 | size: 25, 18 781 | orig: 25, 18 782 | offset: 0, 0 783 | index: -1 784 | SilverKey 785 | rotate: false 786 | xy: 123, 311 787 | size: 15, 8 788 | orig: 16, 16 789 | offset: 1, 0 790 | index: -1 791 | spike 792 | rotate: false 793 | xy: 88, 279 794 | size: 16, 11 795 | orig: 16, 16 796 | offset: 0, 0 797 | index: -1 798 | spikeBlood 799 | rotate: false 800 | xy: 88, 292 801 | size: 16, 11 802 | orig: 16, 16 803 | offset: 0, 0 804 | index: -1 805 | spikeFragile 806 | rotate: false 807 | xy: 46, 298 808 | size: 16, 11 809 | orig: 16, 16 810 | offset: 0, 0 811 | index: -1 812 | spikeFragileBlood 813 | rotate: false 814 | xy: 46, 311 815 | size: 16, 9 816 | orig: 16, 16 817 | offset: 0, 0 818 | index: -1 819 | stun0 820 | rotate: false 821 | xy: 156, 330 822 | size: 10, 8 823 | orig: 10, 8 824 | offset: 0, 0 825 | index: -1 826 | stun1 827 | rotate: false 828 | xy: 52, 322 829 | size: 10, 8 830 | orig: 10, 8 831 | offset: 0, 0 832 | index: -1 833 | stun2 834 | rotate: false 835 | xy: 52, 332 836 | size: 10, 8 837 | orig: 10, 8 838 | offset: 0, 0 839 | index: -1 840 | stun3 841 | rotate: false 842 | xy: 51, 342 843 | size: 10, 8 844 | orig: 10, 8 845 | offset: 0, 0 846 | index: -1 847 | stun4 848 | rotate: false 849 | xy: 31, 368 850 | size: 10, 8 851 | orig: 10, 8 852 | offset: 0, 0 853 | index: -1 854 | turret0 855 | rotate: false 856 | xy: 172, 212 857 | size: 28, 27 858 | orig: 28, 27 859 | offset: 0, 0 860 | index: -1 861 | viewCone 862 | rotate: false 863 | xy: 131, 1 864 | size: 97, 64 865 | orig: 128, 66 866 | offset: 0, 1 867 | index: -1 868 | -------------------------------------------------------------------------------- /res/atlas/tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/atlas/tiles.png -------------------------------------------------------------------------------- /res/data.cdb: -------------------------------------------------------------------------------- 1 | { 2 | "sheets": [ 3 | { 4 | "name": "room", 5 | "columns": [ 6 | { 7 | "name": "id", 8 | "typeStr": "0" 9 | }, 10 | { 11 | "typeStr": "17", 12 | "name": "params" 13 | }, 14 | { 15 | "name": "width", 16 | "typeStr": "3" 17 | }, 18 | { 19 | "name": "height", 20 | "typeStr": "3" 21 | }, 22 | { 23 | "name": "props", 24 | "typeStr": "16" 25 | }, 26 | { 27 | "name": "tileProps", 28 | "typeStr": "8" 29 | }, 30 | { 31 | "name": "layers", 32 | "typeStr": "8" 33 | }, 34 | { 35 | "typeStr": "8", 36 | "name": "markers", 37 | "display": null 38 | } 39 | ], 40 | "lines": [], 41 | "separators": [], 42 | "props": { 43 | "level": { 44 | "tileSets": { 45 | "levelTiles.png": { 46 | "stride": 16, 47 | "sets": [], 48 | "props": [] 49 | } 50 | } 51 | }, 52 | "hasIndex": true 53 | } 54 | }, 55 | { 56 | "name": "room@tileProps", 57 | "props": { 58 | "hide": true 59 | }, 60 | "separators": [], 61 | "lines": [], 62 | "columns": [] 63 | }, 64 | { 65 | "name": "room@layers", 66 | "props": { 67 | "hide": true 68 | }, 69 | "separators": [], 70 | "lines": [], 71 | "columns": [ 72 | { 73 | "name": "name", 74 | "typeStr": "1" 75 | }, 76 | { 77 | "name": "data", 78 | "typeStr": "15" 79 | } 80 | ] 81 | }, 82 | { 83 | "name": "marker", 84 | "columns": [ 85 | { 86 | "typeStr": "11", 87 | "name": "color", 88 | "display": null 89 | }, 90 | { 91 | "typeStr": "14", 92 | "name": "icon" 93 | }, 94 | { 95 | "typeStr": "0", 96 | "name": "id" 97 | } 98 | ], 99 | "lines": [ 100 | { 101 | "color": 65287, 102 | "id": "Hero1", 103 | "icon": { 104 | "file": "levelTiles.png", 105 | "size": 16, 106 | "x": 0, 107 | "y": 30 108 | } 109 | }, 110 | { 111 | "color": 62719, 112 | "id": "Hero2", 113 | "icon": { 114 | "file": "levelTiles.png", 115 | "size": 16, 116 | "x": 2, 117 | "y": 30 118 | } 119 | }, 120 | { 121 | "color": 12779775, 122 | "id": "Hero3", 123 | "icon": { 124 | "file": "levelTiles.png", 125 | "size": 16, 126 | "x": 2, 127 | "y": 30 128 | } 129 | }, 130 | { 131 | "color": 16711680, 132 | "id": "Demon", 133 | "icon": { 134 | "file": "levelTiles.png", 135 | "size": 16, 136 | "x": 0, 137 | "y": 30 138 | } 139 | }, 140 | { 141 | "color": 16757760, 142 | "id": "Bomber", 143 | "icon": { 144 | "file": "levelTiles.png", 145 | "size": 16, 146 | "x": 4, 147 | "y": 30 148 | } 149 | }, 150 | { 151 | "color": 16713409, 152 | "id": "Peon", 153 | "icon": { 154 | "file": "levelTiles.png", 155 | "size": 16, 156 | "x": 1, 157 | "y": 30 158 | } 159 | }, 160 | { 161 | "color": 7573661, 162 | "id": "Touchplate", 163 | "icon": { 164 | "file": "levelTiles.png", 165 | "size": 16, 166 | "x": 2, 167 | "y": 30 168 | } 169 | }, 170 | { 171 | "color": 9983007, 172 | "id": "Door", 173 | "icon": { 174 | "file": "levelTiles.png", 175 | "size": 16, 176 | "x": 2, 177 | "y": 30 178 | } 179 | }, 180 | { 181 | "color": 16764956, 182 | "id": "Light", 183 | "icon": { 184 | "file": "levelTiles.png", 185 | "size": 16, 186 | "x": 2, 187 | "y": 31 188 | } 189 | }, 190 | { 191 | "color": 16711680, 192 | "id": "Spikes", 193 | "icon": { 194 | "file": "levelTiles.png", 195 | "size": 16, 196 | "x": 1, 197 | "y": 31 198 | } 199 | }, 200 | { 201 | "color": 16777215, 202 | "id": "Exit", 203 | "icon": { 204 | "file": "levelTiles.png", 205 | "size": 16, 206 | "x": 3, 207 | "y": 30 208 | } 209 | }, 210 | { 211 | "color": 6313029, 212 | "id": "Cinematic", 213 | "icon": { 214 | "file": "levelTiles.png", 215 | "size": 16, 216 | "x": 2, 217 | "y": 30 218 | } 219 | }, 220 | { 221 | "color": 65355, 222 | "id": "FreeMarker", 223 | "icon": { 224 | "file": "levelTiles.png", 225 | "size": 16, 226 | "x": 2, 227 | "y": 30 228 | } 229 | } 230 | ], 231 | "separators": [], 232 | "props": { 233 | "displayIcon": "icon" 234 | } 235 | }, 236 | { 237 | "name": "room@markers", 238 | "props": { 239 | "hide": true 240 | }, 241 | "separators": [], 242 | "lines": [], 243 | "columns": [ 244 | { 245 | "typeStr": "6:marker", 246 | "name": "marker", 247 | "display": null 248 | }, 249 | { 250 | "typeStr": "3", 251 | "name": "x" 252 | }, 253 | { 254 | "typeStr": "3", 255 | "name": "y", 256 | "display": null 257 | }, 258 | { 259 | "typeStr": "3", 260 | "name": "width", 261 | "display": null 262 | }, 263 | { 264 | "typeStr": "3", 265 | "name": "height", 266 | "display": null 267 | }, 268 | { 269 | "typeStr": "1", 270 | "name": "id", 271 | "opt": true 272 | } 273 | ] 274 | }, 275 | { 276 | "name": "room@collisionsOld", 277 | "props": { 278 | "hide": true 279 | }, 280 | "separators": [], 281 | "lines": [], 282 | "columns": [ 283 | { 284 | "typeStr": "3", 285 | "name": "x", 286 | "display": null 287 | }, 288 | { 289 | "typeStr": "3", 290 | "name": "y", 291 | "display": null 292 | }, 293 | { 294 | "typeStr": "3", 295 | "name": "width", 296 | "display": null 297 | }, 298 | { 299 | "typeStr": "3", 300 | "name": "height", 301 | "display": null 302 | } 303 | ] 304 | }, 305 | { 306 | "name": "room@params", 307 | "props": { 308 | "hide": true, 309 | "isProps": true 310 | }, 311 | "separators": [], 312 | "lines": [], 313 | "columns": [ 314 | { 315 | "typeStr": "2", 316 | "name": "fastPeons", 317 | "opt": true, 318 | "display": null 319 | } 320 | ] 321 | }, 322 | { 323 | "name": "sheet", 324 | "columns": [], 325 | "lines": [], 326 | "separators": [], 327 | "props": {} 328 | } 329 | ], 330 | "customTypes": [], 331 | "compress": false 332 | } -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/fonts/barlow_condensed_medium_regular_11.png -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/fonts/barlow_condensed_medium_regular_17.png -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/fonts/barlow_condensed_medium_regular_32.png -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_9.fnt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 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 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/fonts/barlow_condensed_medium_regular_9.png -------------------------------------------------------------------------------- /res/fonts/minecraftiaOutline.fnt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 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 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /res/fonts/minecraftiaOutline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/fonts/minecraftiaOutline.png -------------------------------------------------------------------------------- /res/lang/en.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/lang/en.mo -------------------------------------------------------------------------------- /res/lang/en.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "POT-Creation-Date: \n" 5 | "PO-Revision-Date: 2019-05-27 12:09+0200\n" 6 | "Last-Translator: \n" 7 | "Language-Team: \n" 8 | "Language: en\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Generator: Poedit 2.2.3\n" 13 | "X-Poedit-Basepath: .\n" 14 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 15 | 16 | #: src/Game.hx:19 17 | msgid "Game is ready." 18 | msgstr "" 19 | 20 | #: src/Game.hx:57 21 | msgid "Press ESCAPE again to exit." 22 | msgstr "" 23 | -------------------------------------------------------------------------------- /res/lang/sourceTexts.pot: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Content-Type: text/plain; charset=UTF-8\n" 4 | "Content-Transfer-Encoding: 8bit\n" 5 | "MIME-Version: 1.0\n" 6 | 7 | #: src/Game.hx:19 8 | msgid "Game is ready." 9 | msgstr "" 10 | 11 | #: src/Game.hx:57 12 | msgid "Press ESCAPE again to exit." 13 | msgstr "" 14 | 15 | 16 | -------------------------------------------------------------------------------- /res/map/tilesets/markers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/map/tilesets/markers.png -------------------------------------------------------------------------------- /res/map/tilesets/tileset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/map/tilesets/tileset.png -------------------------------------------------------------------------------- /res/music/leatherneck.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/music/leatherneck.mp3 -------------------------------------------------------------------------------- /res/sfx/explode0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/explode0.lch -------------------------------------------------------------------------------- /res/sfx/explode0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/explode0.wav -------------------------------------------------------------------------------- /res/sfx/explode1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/explode1.lch -------------------------------------------------------------------------------- /res/sfx/explode1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/explode1.wav -------------------------------------------------------------------------------- /res/sfx/explode2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/explode2.lch -------------------------------------------------------------------------------- /res/sfx/explode2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/explode2.wav -------------------------------------------------------------------------------- /res/sfx/grab0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab0.lch -------------------------------------------------------------------------------- /res/sfx/grab0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab0.wav -------------------------------------------------------------------------------- /res/sfx/grab1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab1.lch -------------------------------------------------------------------------------- /res/sfx/grab1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab1.wav -------------------------------------------------------------------------------- /res/sfx/grab2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab2.lch -------------------------------------------------------------------------------- /res/sfx/grab2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab2.wav -------------------------------------------------------------------------------- /res/sfx/grab3.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab3.lch -------------------------------------------------------------------------------- /res/sfx/grab3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab3.wav -------------------------------------------------------------------------------- /res/sfx/grab4.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab4.lch -------------------------------------------------------------------------------- /res/sfx/grab4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/grab4.wav -------------------------------------------------------------------------------- /res/sfx/hero0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hero0.lch -------------------------------------------------------------------------------- /res/sfx/hero0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hero0.wav -------------------------------------------------------------------------------- /res/sfx/hero1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hero1.lch -------------------------------------------------------------------------------- /res/sfx/hero1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hero1.wav -------------------------------------------------------------------------------- /res/sfx/hero2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hero2.lch -------------------------------------------------------------------------------- /res/sfx/hero2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hero2.wav -------------------------------------------------------------------------------- /res/sfx/hit0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit0.lch -------------------------------------------------------------------------------- /res/sfx/hit0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit0.wav -------------------------------------------------------------------------------- /res/sfx/hit1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit1.lch -------------------------------------------------------------------------------- /res/sfx/hit1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit1.wav -------------------------------------------------------------------------------- /res/sfx/hit2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit2.lch -------------------------------------------------------------------------------- /res/sfx/hit2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit2.wav -------------------------------------------------------------------------------- /res/sfx/hit3.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit3.lch -------------------------------------------------------------------------------- /res/sfx/hit3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit3.wav -------------------------------------------------------------------------------- /res/sfx/hit4.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit4.lch -------------------------------------------------------------------------------- /res/sfx/hit4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit4.wav -------------------------------------------------------------------------------- /res/sfx/hit5.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit5.lch -------------------------------------------------------------------------------- /res/sfx/hit5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit5.wav -------------------------------------------------------------------------------- /res/sfx/hit6.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit6.lch -------------------------------------------------------------------------------- /res/sfx/hit6.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/hit6.wav -------------------------------------------------------------------------------- /res/sfx/item0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item0.lch -------------------------------------------------------------------------------- /res/sfx/item0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item0.wav -------------------------------------------------------------------------------- /res/sfx/item1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item1.lch -------------------------------------------------------------------------------- /res/sfx/item1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item1.wav -------------------------------------------------------------------------------- /res/sfx/item2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item2.lch -------------------------------------------------------------------------------- /res/sfx/item2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item2.wav -------------------------------------------------------------------------------- /res/sfx/item3.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item3.lch -------------------------------------------------------------------------------- /res/sfx/item3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item3.wav -------------------------------------------------------------------------------- /res/sfx/item4.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item4.lch -------------------------------------------------------------------------------- /res/sfx/item4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item4.wav -------------------------------------------------------------------------------- /res/sfx/item5.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item5.lch -------------------------------------------------------------------------------- /res/sfx/item5.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/item5.wav -------------------------------------------------------------------------------- /res/sfx/mob0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob0.lch -------------------------------------------------------------------------------- /res/sfx/mob0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob0.wav -------------------------------------------------------------------------------- /res/sfx/mob1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob1.lch -------------------------------------------------------------------------------- /res/sfx/mob1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob1.wav -------------------------------------------------------------------------------- /res/sfx/mob2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob2.lch -------------------------------------------------------------------------------- /res/sfx/mob2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob2.wav -------------------------------------------------------------------------------- /res/sfx/mob3.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob3.lch -------------------------------------------------------------------------------- /res/sfx/mob3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob3.wav -------------------------------------------------------------------------------- /res/sfx/mob4.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob4.lch -------------------------------------------------------------------------------- /res/sfx/mob4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/mob4.wav -------------------------------------------------------------------------------- /res/sfx/surprise0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/surprise0.lch -------------------------------------------------------------------------------- /res/sfx/surprise0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/surprise0.wav -------------------------------------------------------------------------------- /res/sfx/surprise1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/surprise1.lch -------------------------------------------------------------------------------- /res/sfx/surprise1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/surprise1.wav -------------------------------------------------------------------------------- /res/sfx/surprise2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/surprise2.lch -------------------------------------------------------------------------------- /res/sfx/surprise2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/surprise2.wav -------------------------------------------------------------------------------- /res/sfx/throw0.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw0.lch -------------------------------------------------------------------------------- /res/sfx/throw0.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw0.wav -------------------------------------------------------------------------------- /res/sfx/throw1.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw1.lch -------------------------------------------------------------------------------- /res/sfx/throw1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw1.wav -------------------------------------------------------------------------------- /res/sfx/throw2.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw2.lch -------------------------------------------------------------------------------- /res/sfx/throw2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw2.wav -------------------------------------------------------------------------------- /res/sfx/throw3.lch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw3.lch -------------------------------------------------------------------------------- /res/sfx/throw3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/sfx/throw3.wav -------------------------------------------------------------------------------- /res/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/res/title.png -------------------------------------------------------------------------------- /screenshots/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/01.png -------------------------------------------------------------------------------- /screenshots/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/02.png -------------------------------------------------------------------------------- /screenshots/03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/03.gif -------------------------------------------------------------------------------- /screenshots/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/04.png -------------------------------------------------------------------------------- /screenshots/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/05.png -------------------------------------------------------------------------------- /screenshots/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/06.png -------------------------------------------------------------------------------- /screenshots/07.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/07.gif -------------------------------------------------------------------------------- /screenshots/08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/08.png -------------------------------------------------------------------------------- /screenshots/itch.io.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/ld45-Sabotage/57dfcc6c00a30df93c470e54e3e627a0513f40ac/screenshots/itch.io.gif -------------------------------------------------------------------------------- /src.langParser/LangParser.hx: -------------------------------------------------------------------------------- 1 | import dn.data.GetText; 2 | 3 | class LangParser { 4 | public static function main() { 5 | var name = "sourceTexts"; 6 | Sys.println("Building "+name+" file..."); 7 | var entries = []; 8 | entries = entries.concat( GetText.parseSourceCode("src") ); 9 | GetText.writePOT('res/lang/$name.pot', entries); 10 | Sys.println("Done."); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Assets.hx: -------------------------------------------------------------------------------- 1 | import dn.heaps.slib.*; 2 | 3 | class Assets { 4 | public static var SFX = dn.heaps.assets.SfxDirectory.load("sfx",true); 5 | 6 | public static var fontPixel : h2d.Font; 7 | public static var fontTiny : h2d.Font; 8 | public static var fontSmall : h2d.Font; 9 | public static var fontMedium : h2d.Font; 10 | public static var fontLarge : h2d.Font; 11 | public static var tiles : SpriteLib; 12 | static var music : dn.heaps.Sfx; 13 | 14 | static var initDone = false; 15 | public static function init() { 16 | if( initDone ) 17 | return; 18 | initDone = true; 19 | 20 | dn.heaps.Sfx.muteGroup(0); // HACK 21 | dn.heaps.Sfx.setGroupVolume(0,0.6); 22 | 23 | music = new dn.heaps.Sfx(hxd.Res.music.leatherneck); 24 | music.groupId = 1; 25 | 26 | fontPixel = hxd.Res.fonts.minecraftiaOutline.toFont(); 27 | fontTiny = hxd.Res.fonts.barlow_condensed_medium_regular_9.toFont(); 28 | fontSmall = hxd.Res.fonts.barlow_condensed_medium_regular_11.toFont(); 29 | fontMedium = hxd.Res.fonts.barlow_condensed_medium_regular_17.toFont(); 30 | fontLarge = hxd.Res.fonts.barlow_condensed_medium_regular_32.toFont(); 31 | 32 | tiles = dn.heaps.assets.Atlas.load("atlas/tiles.atlas"); 33 | tiles.defineAnim("heroRun", "0(2), 1(1), 2(2), 1(1)"); 34 | tiles.defineAnim("heroIdle", "0(10), 1(1), 2(8)"); 35 | tiles.defineAnim("heroThrow", "0(1), 1(999)"); 36 | tiles.defineAnim("heroPunch", "0(2), 1(1), 2(2), 3(3)"); 37 | tiles.defineAnim("heroGlide", "0-2, 1"); 38 | 39 | tiles.defineAnim("guardRun", "0(2), 1(1), 2(2), 1(1)"); 40 | tiles.defineAnim("guardWalk", "0(3), 1(1), 2(3), 1(1)"); 41 | tiles.defineAnim("guardShoot", "1(3), 0(1), 1(4)"); 42 | tiles.defineAnim("guardShootDown", "1(1), 0(2), 1(4)"); 43 | tiles.defineAnim("guardHit", "0(1), 1(2), 2(9999) "); 44 | 45 | tiles.defineAnim("stun", "0-3,3,2,1"); 46 | tiles.defineAnim("bird", "0(2), 1(2), 2(4), 4(2), 3(6), 5(1)"); 47 | } 48 | 49 | public static function playMusic() { 50 | music.play(true); 51 | } 52 | public static function toggleMusicPause() { 53 | music.togglePlayPause(); 54 | } 55 | } -------------------------------------------------------------------------------- /src/Boot.hx: -------------------------------------------------------------------------------- 1 | class Boot extends hxd.App { 2 | public static var ME : Boot; 3 | 4 | // Boot 5 | static function main() { 6 | new Boot(); 7 | } 8 | 9 | // Engine ready 10 | override function init() { 11 | ME = this; 12 | new Main(s2d); 13 | onResize(); 14 | } 15 | 16 | override function onResize() { 17 | super.onResize(); 18 | dn.Process.resizeAll(); 19 | } 20 | 21 | var speed = 1.0; 22 | override function update(deltaTime:Float) { 23 | super.update(deltaTime); 24 | 25 | // Bullet time 26 | #if debug 27 | if( hxd.Key.isPressed(hxd.Key.NUMPAD_SUB) ) 28 | speed = speed>=1 ? 0.33 : 1; 29 | #end 30 | 31 | var tmod = hxd.Timer.tmod * speed; 32 | #if debug 33 | tmod *= hxd.Key.isDown(hxd.Key.NUMPAD_ADD) ? 5 : 1; 34 | #end 35 | Controller.beforeUpdate(); 36 | dn.Process.updateAll(tmod); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/Camera.hx: -------------------------------------------------------------------------------- 1 | class Camera extends dn.Process { 2 | public var target : Null; 3 | public var x : Float; 4 | public var y : Float; 5 | public var dx : Float; 6 | public var dy : Float; 7 | public var wid(get,never) : Int; 8 | public var hei(get,never) : Int; 9 | 10 | public function new() { 11 | super(Game.ME); 12 | x = y = 0; 13 | dx = dy = 0; 14 | } 15 | 16 | function get_wid() { 17 | return M.ceil( Game.ME.w() / Const.SCALE ); 18 | } 19 | 20 | function get_hei() { 21 | return M.ceil( Game.ME.h() / Const.SCALE ); 22 | } 23 | 24 | public function recenter() { 25 | if( target!=null ) { 26 | x = target.centerX; 27 | y = target.centerY; 28 | } 29 | } 30 | 31 | public inline function scrollerToGlobalX(v:Float) return v*Const.SCALE + Game.ME.scroller.x; 32 | public inline function scrollerToGlobalY(v:Float) return v*Const.SCALE + Game.ME.scroller.y; 33 | 34 | var shakePower = 1.0; 35 | public function shakeS(t:Float, ?pow=1.0) { 36 | cd.setS("shaking", t, false); 37 | shakePower = pow; 38 | } 39 | 40 | override function update() { 41 | super.update(); 42 | 43 | // Follow target entity 44 | if( target!=null ) { 45 | var s = 0.006; 46 | var deadZone = 5; 47 | var tx = target.footX; 48 | var ty = target.footY; 49 | 50 | for(e in en.Mob.ALL) 51 | if( e.is(en.mob.Turret) && e.distCase(target)<=9 ) { 52 | tx = ( tx*3 + e.centerX*1 ) / 4; 53 | ty = ( ty*3 + e.centerY*1 ) / 4; 54 | } 55 | else if( e.isAlive() && e.hasAlarm() && e.distCase(target)<=9 ) { 56 | tx = ( tx*4 + e.centerX*1 ) / 5; 57 | ty = ( ty*4 + e.centerY*1 ) / 5; 58 | } 59 | 60 | var d = M.dist(x,y, tx, ty); 61 | if( d>=deadZone ) { 62 | var a = Math.atan2( ty-y, tx-x ); 63 | dx += Math.cos(a) * (d-deadZone) * s * tmod; 64 | dy += Math.sin(a) * (d-deadZone) * s * tmod; 65 | } 66 | } 67 | 68 | var frict = 0.89; 69 | x += dx*tmod; 70 | dx *= Math.pow(frict,tmod); 71 | 72 | y += dy*tmod; 73 | dy *= Math.pow(frict,tmod); 74 | } 75 | 76 | 77 | override function postUpdate() { 78 | super.postUpdate(); 79 | 80 | if( !ui.Console.ME.hasFlag("scroll") ) { 81 | var level = Game.ME.level; 82 | var scroller = Game.ME.scroller; 83 | 84 | // Update scroller 85 | if( wid; 2 | -------------------------------------------------------------------------------- /src/Entity.hx: -------------------------------------------------------------------------------- 1 | class Entity { 2 | public static var ALL : Array = []; 3 | public static var GC : Array = []; 4 | 5 | public var game(get,never) : Game; inline function get_game() return Game.ME; 6 | public var fx(get,never) : Fx; inline function get_fx() return Game.ME.fx; 7 | public var level(get,never) : Level; inline function get_level() return Game.ME.level; 8 | public var destroyed(default,null) = false; 9 | public var ftime(get,never) : Float; inline function get_ftime() return game.ftime; 10 | public var tmod(get,never) : Float; inline function get_tmod() return Game.ME.tmod; 11 | public var hero(get,never) : en.Hero; inline function get_hero() return Game.ME.hero; 12 | 13 | public var cd : dn.Cooldown; 14 | 15 | public var uid : Int; 16 | public var cx = 0; 17 | public var cy = 0; 18 | public var xr = 0.5; 19 | public var yr = 0.5; 20 | public var zr = 0.; 21 | 22 | public var dx = 0.; 23 | public var dy = 0.; 24 | public var dz = 0.; 25 | public var bdx = 0.; 26 | public var bdy = 0.; 27 | public var dxTotal(get,never) : Float; inline function get_dxTotal() return dx+bdx; 28 | public var dyTotal(get,never) : Float; inline function get_dyTotal() return dy+bdy; 29 | public var frict = 0.82; 30 | public var gravity = 0.02; 31 | public var hasCollisions = true; 32 | public var bumpFrict = 0.93; 33 | public var hei : Float = Const.GRID; 34 | public var radius = Const.GRID*0.5; 35 | public var zPriorityOffset = 0.; 36 | public var bumpReduction = 0.; 37 | 38 | public var life : Int; 39 | public var maxLife : Int; 40 | 41 | public var dir(default,set) = 1; 42 | public var sprScaleX = 1.0; 43 | public var sprScaleY = 1.0; 44 | public var sprOffX = 0.; 45 | public var sprOffY = 0.; 46 | 47 | public var spr : HSprite; 48 | public var colorAdd : h3d.Vector; 49 | public var shadow : Null; 50 | public var stunSpr : HSprite; 51 | var lifeBar : Null; 52 | var debugLabel : Null; 53 | var lastHitSource : Null; 54 | var lastHitAng(get,never) : Float; 55 | var lastHitDir(get,never) : Int; 56 | public var lastFootX : Float; 57 | public var lastFootY : Float; 58 | 59 | public var footX(get,never) : Float; inline function get_footX() return (cx+xr)*Const.GRID; 60 | public var footY(get,never) : Float; inline function get_footY() return (cy+yr)*Const.GRID; 61 | public var headX(get,never) : Float; inline function get_headX() return footX; 62 | public var headY(get,never) : Float; inline function get_headY() return footY-hei; 63 | public var centerX(get,never) : Float; inline function get_centerX() return footX; 64 | public var centerY(get,never) : Float; inline function get_centerY() return footY-hei*0.5; 65 | 66 | public function new(x:Int, y:Int) { 67 | uid = Const.NEXT_UNIQ; 68 | ALL.push(this); 69 | 70 | cd = new dn.Cooldown(Const.FPS); 71 | setPosCase(x,y); 72 | 73 | spr = new HSprite(Assets.tiles); 74 | Game.ME.scroller.add(spr, Const.DP_MAIN); 75 | spr.setCenterRatio(0.5,1); 76 | spr.colorAdd = colorAdd = new h3d.Vector(); 77 | enableShadow(); 78 | initLife(1); 79 | 80 | stunSpr = Assets.tiles.h_get("stun",0, 0.5,0.5); 81 | stunSpr.anim.playAndLoop("stun").setSpeed(0.3); 82 | stunSpr.alpha = 0.7; 83 | game.scroller.add(stunSpr, Const.DP_FX_TOP); 84 | } 85 | 86 | public function toString() { 87 | return Type.getClassName(Type.getClass(this)) + '($uid)@$cx,$cy'; 88 | } 89 | 90 | public function isGrabbed() return hero.isAlive() && hero.grabbedEnt==this; 91 | 92 | public function initLife(v) { 93 | life = maxLife = v; 94 | renderLife(); 95 | } 96 | 97 | public function renderLife(?loss=0) { 98 | if( lifeBar==null ) { 99 | lifeBar = new h2d.Flow(); 100 | game.scroller.add(lifeBar, Const.DP_UI); 101 | lifeBar.alpha = 0; 102 | lifeBar.verticalAlign = Middle; 103 | } 104 | 105 | lifeBar.removeChildren(); 106 | for(i in 0...maxLife) 107 | Assets.tiles.getBitmap(i+1<=life ? "heartOn" : i+1<=life+loss ? "heartLoss" : "heartOff", lifeBar); 108 | 109 | lifeBar.horizontalSpacing = maxLife>=7 ? -4 : 0; 110 | } 111 | 112 | public function heal(v) { 113 | life = M.iclamp(life+v, 0, maxLife); 114 | showLifeChange(); 115 | } 116 | 117 | function showLifeChange(?loss=0) { 118 | renderLife(loss); 119 | lifeBar.alpha = 1; 120 | cd.setS("showLifeBar", Const.INFINITE); 121 | cd.setS("showLifeChangeLock",0.2); 122 | cd.setS("showLifeChange",Const.INFINITE); 123 | } 124 | 125 | public function hit(?from:Entity, dmg) { 126 | if( !isAlive() || dmg<=0 ) 127 | return; 128 | 129 | lastHitSource = from; 130 | var oldLife = life; 131 | life = M.iclamp(life-dmg, 0, maxLife); 132 | showLifeChange(oldLife-life); 133 | onDamage(dmg); 134 | if( life<=0 ) 135 | onDie(); 136 | } 137 | 138 | function onDamage(dmg:Int) {} 139 | 140 | function onDie() { 141 | destroy(); 142 | } 143 | 144 | inline function get_lastHitAng() { 145 | return 146 | lastHitSource==null ? ( dir==1 ? M.PI : 0 ) 147 | : lastHitSource.is(en.Bullet) ? Math.atan2(lastHitSource.dy,lastHitSource.dx) : lastHitSource.angTo(this); 148 | } 149 | 150 | inline function get_lastHitDir() { 151 | return M.radDistance(lastHitAng,0)<=M.PIHALF ? 1 : -1; 152 | } 153 | 154 | public function disableShadow() { 155 | if( shadow!=null ) { 156 | shadow.remove(); 157 | shadow = null; 158 | } 159 | } 160 | 161 | public function enableShadow() { 162 | disableShadow(); 163 | shadow = new HSprite(spr.lib); 164 | game.scroller.add(shadow, Const.DP_BG); 165 | shadow.setCenterRatio(0.5,1); 166 | shadow.color.r = 0; 167 | shadow.color.g = 0; 168 | shadow.color.b = 0; 169 | shadow.alpha = 0.6; 170 | } 171 | 172 | inline function isMoving() return M.fabs(dxTotal)>=0.01 || M.fabs(dyTotal)>=0.01; 173 | 174 | public function zOver() { 175 | game.scroller.over(spr); 176 | } 177 | 178 | inline function set_dir(v) { 179 | return dir = v>0 ? 1 : v<0 ? -1 : dir; 180 | } 181 | 182 | public inline function isAlive() { 183 | return !destroyed && life>0; 184 | } 185 | 186 | public function kill(by:Null) { 187 | destroy(); 188 | } 189 | 190 | public function setPosCase(x:Int, y:Int, ?xr=0.5, ?yr=0.5) { 191 | cx = x; 192 | cy = y; 193 | this.xr = xr; 194 | this.yr = yr; 195 | lastFootX = footX; 196 | lastFootY = footY; 197 | } 198 | 199 | public function setPosPixel(x:Float, y:Float) { 200 | cx = Std.int(x/Const.GRID); 201 | cy = Std.int(y/Const.GRID); 202 | xr = (x-cx*Const.GRID)/Const.GRID; 203 | yr = (y-cy*Const.GRID)/Const.GRID; 204 | lastFootX = footX; 205 | lastFootY = footY; 206 | } 207 | 208 | public inline function bumpAwayFrom(e:Entity, spd:Float, ?spdZ=0., ?ignoreReduction=false) { 209 | var a = e.angTo(this); 210 | bump(Math.cos(a)*spd, Math.sin(a)*spd*0.5, spdZ, ignoreReduction); 211 | } 212 | public function bump(x:Float,y:Float,z:Float, ?ignoreReduction=false) { 213 | var f = ignoreReduction ? 1.0 : 1-bumpReduction; 214 | bdx+=x*f; 215 | bdy+=y*f; 216 | dz+=z*f; 217 | } 218 | 219 | public function cancelVelocities() { 220 | dx = bdx = 0; 221 | dy = bdy = 0; 222 | } 223 | 224 | public function canBeGrabbed() return false; 225 | 226 | public inline function mulVelocities(f:Float) { 227 | dx*=f; 228 | dy*=f; 229 | bdx*=f; 230 | bdy*=f; 231 | } 232 | 233 | public inline function at(x,y) return cx==x && cy==y; 234 | public function is(c:Class) return Std.isOfType(this, c); 235 | public function as(c:Class) : T return Std.downcast(this, c); 236 | 237 | public inline function rnd(min,max,?sign) return Lib.rnd(min,max,sign); 238 | public inline function irnd(min,max,?sign) return Lib.irnd(min,max,sign); 239 | public inline function pretty(v,?p=1) return M.pretty(v,p); 240 | 241 | public inline function sightCheckEnt(e:Entity) { 242 | return sightCheckCase(e.cx,e.cy); 243 | } 244 | 245 | public inline function sightCheckCase(tcx:Int, tcy:Int) { 246 | return dn.Bresenham.checkThinLine(cx,cy,tcx,tcy, function(x,y) return !level.hasCollision(x,y)); 247 | } 248 | 249 | public inline function dirTo(e:Entity) return e.centerX0 ) { 410 | xr+=step; 411 | if( hasCollisions && level.hasCollision(cx+1, cy) && xr>0.8 ) { 412 | xr = 0.8; 413 | if( yr<0.6 && !level.hasCollision(cx+1,cy-1) && dyTotal<=wallSlideTolerance ) dy-=wallSlide*tmod; 414 | if( yr>0.6 && !level.hasCollision(cx+1,cy+1) && dyTotal>=-wallSlideTolerance ) dy+=wallSlide*tmod; 415 | onTouchWall(1,0); 416 | 417 | } 418 | if( hasCollisions && level.hasCollision(cx-1, cy) && xr<0.2 ) { 419 | xr = 0.2; 420 | if( yr<0.6 && !level.hasCollision(cx-1,cy-1) && dyTotal<=wallSlideTolerance ) dy-=wallSlide*tmod; 421 | if( yr>0.6 && !level.hasCollision(cx-1,cy+1) && dyTotal>=-wallSlideTolerance ) dy+=wallSlide*tmod; 422 | onTouchWall(-1,0); 423 | } 424 | while( xr>1 ) { xr--; cx++; } 425 | while( xr<0 ) { xr++; cx--; } 426 | steps--; 427 | } 428 | dx*=Math.pow(frict,tmod); 429 | bdx*=Math.pow(bumpFrict,tmod); 430 | if( M.fabs(dx)<=0.0005*tmod ) dx = 0; 431 | if( M.fabs(bdx)<=0.0005*tmod ) bdx = 0; 432 | 433 | // Y 434 | var steps = M.ceil( M.fabs(dyTotal*tmod) ); 435 | var step = dyTotal*tmod / steps; 436 | while( steps>0 ) { 437 | yr+=step; 438 | if( hasCollisions && level.hasCollision(cx, cy+1) && yr>0.9 ) { 439 | yr = 0.9; 440 | if( xr<0.5 && !level.hasCollision(cx-1,cy+1) && dxTotal<=wallSlideTolerance ) dx-=wallSlide*tmod; 441 | if( xr>0.5 && !level.hasCollision(cx+1,cy+1) && dxTotal>=-wallSlideTolerance ) dx+=wallSlide*tmod; 442 | onTouchWall(0,1); 443 | } 444 | if( hasCollisions && level.hasCollision(cx, cy-1) && yr<0.5 ) { 445 | yr = 0.5; 446 | if( xr<0.5 && !level.hasCollision(cx-1,cy-1) && dxTotal<=wallSlideTolerance ) dx-=wallSlide*tmod; 447 | if( xr>0.5 && !level.hasCollision(cx+1,cy-1) && dxTotal>=-wallSlideTolerance ) dx+=wallSlide*tmod; 448 | onTouchWall(0,-1); 449 | } 450 | while( yr>1 ) { yr--; cy++; } 451 | while( yr<0 ) { yr++; cy--; } 452 | steps--; 453 | } 454 | dy*=Math.pow(frict,tmod); 455 | bdy*=Math.pow(bumpFrict,tmod); 456 | if( M.fabs(dy)<=0.0005*tmod ) dy = 0; 457 | if( M.fabs(bdy)<=0.0005*tmod ) bdy = 0; 458 | 459 | // Z 460 | zr+=dz*tmod; 461 | if( zr>0 ) 462 | dz-=gravity*tmod; 463 | if( zr<0 ) { 464 | zr = 0; 465 | dz = -dz*0.9; 466 | if( M.fabs(dz)<=0.06 ) 467 | dz = 0; 468 | onZLand(); 469 | } 470 | dz*=Math.pow(0.9,tmod); 471 | if( M.fabs(dz)<=0.0010*tmod ) dz = 0; 472 | } 473 | } -------------------------------------------------------------------------------- /src/Fx.hx: -------------------------------------------------------------------------------- 1 | import h2d.Sprite; 2 | import dn.heaps.HParticle; 3 | import dn.Tweenie; 4 | 5 | 6 | class Fx extends dn.Process { 7 | public var pool : ParticlePool; 8 | 9 | public var bgAddSb : h2d.SpriteBatch; 10 | public var bgNormalSb : h2d.SpriteBatch; 11 | public var topAddSb : h2d.SpriteBatch; 12 | public var topNormalSb : h2d.SpriteBatch; 13 | 14 | var game(get,never) : Game; inline function get_game() return Game.ME; 15 | 16 | public function new() { 17 | super(Game.ME); 18 | 19 | pool = new ParticlePool(Assets.tiles.tile, 2048, Const.FPS); 20 | 21 | bgAddSb = new h2d.SpriteBatch(Assets.tiles.tile); 22 | game.scroller.add(bgAddSb, Const.DP_FX_BG); 23 | bgAddSb.blendMode = Add; 24 | bgAddSb.hasRotationScale = true; 25 | 26 | bgNormalSb = new h2d.SpriteBatch(Assets.tiles.tile); 27 | game.scroller.add(bgNormalSb, Const.DP_FX_BG); 28 | bgNormalSb.hasRotationScale = true; 29 | 30 | topNormalSb = new h2d.SpriteBatch(Assets.tiles.tile); 31 | game.scroller.add(topNormalSb, Const.DP_FX_TOP); 32 | topNormalSb.hasRotationScale = true; 33 | 34 | topAddSb = new h2d.SpriteBatch(Assets.tiles.tile); 35 | game.scroller.add(topAddSb, Const.DP_FX_TOP); 36 | topAddSb.blendMode = Add; 37 | topAddSb.hasRotationScale = true; 38 | } 39 | 40 | override public function onDispose() { 41 | super.onDispose(); 42 | 43 | pool.dispose(); 44 | bgAddSb.remove(); 45 | bgNormalSb.remove(); 46 | topAddSb.remove(); 47 | topNormalSb.remove(); 48 | } 49 | 50 | public function clear() { 51 | pool.clear(); 52 | } 53 | 54 | public inline function allocTopAdd(t:h2d.Tile, x:Float, y:Float) : HParticle { 55 | return pool.alloc(topAddSb, t, x, y); 56 | } 57 | 58 | public inline function allocTopNormal(t:h2d.Tile, x:Float, y:Float) : HParticle { 59 | return pool.alloc(topNormalSb, t,x,y); 60 | } 61 | 62 | public inline function allocBgAdd(t:h2d.Tile, x:Float, y:Float) : HParticle { 63 | return pool.alloc(bgAddSb, t,x,y); 64 | } 65 | 66 | public inline function allocBgNormal(t:h2d.Tile, x:Float, y:Float) : HParticle { 67 | return pool.alloc(bgNormalSb, t,x,y); 68 | } 69 | 70 | public inline function getTile(id:String) : h2d.Tile { 71 | return Assets.tiles.getTileRandom(id); 72 | } 73 | 74 | public function killAll() { 75 | pool.clear(); 76 | } 77 | 78 | public function markerEntity(e:Entity, ?c=0xFF00FF, ?short=false) { 79 | #if debug 80 | if( e==null ) 81 | return; 82 | 83 | markerCase(e.cx, e.cy, short?0.03:3, c); 84 | #end 85 | } 86 | 87 | public function markerCase(cx:Int, cy:Int, ?sec=3.0, ?c=0xFF00FF) { 88 | #if debug 89 | var p = allocTopAdd(getTile("fxCircle"), (cx+0.5)*Const.GRID, (cy+0.5)*Const.GRID); 90 | p.setFadeS(1, 0, 0.06); 91 | p.colorize(c); 92 | p.lifeS = sec; 93 | 94 | var p = allocTopAdd(getTile("pixel"), (cx+0.5)*Const.GRID, (cy+0.5)*Const.GRID); 95 | p.setFadeS(1, 0, 0.06); 96 | p.colorize(c); 97 | p.setScale(2); 98 | p.lifeS = sec; 99 | #end 100 | } 101 | 102 | public function markerFree(x:Float, y:Float, ?sec=3.0, ?c=0xFF00FF) { 103 | #if debug 104 | var p = allocTopAdd(getTile("fxDot"), x,y); 105 | p.setCenterRatio(0.5,0.5); 106 | p.setFadeS(1, 0, 0.06); 107 | p.colorize(c); 108 | p.setScale(3); 109 | p.lifeS = sec; 110 | #end 111 | } 112 | 113 | public function markerText(cx:Int, cy:Int, txt:String, ?t=1.0) { 114 | #if debug 115 | var tf = new h2d.Text(Assets.fontTiny, topNormalSb); 116 | tf.text = txt; 117 | 118 | var p = allocTopAdd(getTile("fxCircle"), (cx+0.5)*Const.GRID, (cy+0.5)*Const.GRID); 119 | p.colorize(0x0080FF); 120 | p.alpha = 0.6; 121 | p.lifeS = 0.3; 122 | p.fadeOutSpeed = 0.4; 123 | p.onKill = tf.remove; 124 | 125 | tf.setPosition(p.x-tf.textWidth*0.5, p.y-tf.textHeight*0.5); 126 | #end 127 | } 128 | 129 | public function flashBangS(c:UInt, a:Float, ?t=0.1) { 130 | var e = new h2d.Bitmap(h2d.Tile.fromColor(c,1,1,a)); 131 | game.scroller.add(e, Const.DP_FX_TOP); 132 | e.scaleX = game.w(); 133 | e.scaleY = game.h(); 134 | e.blendMode = Add; 135 | game.tw.createS(e.alpha, 0, t).end( function() { 136 | e.remove(); 137 | }); 138 | } 139 | 140 | public function emitSound(x:Float, y:Float, ?c=0xffffff) { 141 | var n = 2; 142 | for(i in 0...n) { 143 | var p = allocTopAdd(getTile("fxNova"), x,y); 144 | p.setFadeS(0.3, 0, 0.2); 145 | p.colorize(c); 146 | p.setScale(0.03); 147 | p.ds = 0.03; 148 | p.dsFrict = 0.83; 149 | p.delayS = 0.4*(i+1)/n; 150 | p.lifeS = 0.1; 151 | } 152 | } 153 | 154 | public function alarm(e:Entity) { 155 | var p = allocTopNormal(getTile("fxAlarm"), e.headX, e.headY+5); 156 | p.setCenterRatio(0.5,1); 157 | p.dy = -3; 158 | p.frict = 0.8; 159 | p.lifeS = 1; 160 | } 161 | 162 | public function question(x:Float, y:Float) { 163 | var p = allocTopNormal(getTile("fxQuestion"), x,y); 164 | p.setCenterRatio(0.5,1); 165 | p.dy = -1; 166 | p.frict = 0.8; 167 | p.lifeS = 1; 168 | } 169 | 170 | public function wallImpact(x:Float, y:Float, a:Float, c:UInt) { 171 | for(i in 0...15) { 172 | var a = a + M.PI + rnd(0,M.PIHALF,true); 173 | var p = allocTopAdd(getTile("fxLineDir"), x+rnd(0,6,true), y+rnd(0,6,true)); 174 | p.setCenterRatio(1,0.5); 175 | p.colorAnimS(0xff9900, c, rnd(0.2,0.4)); 176 | p.moveAng(a, rnd(4,5)); 177 | p.rotation = p.getMoveAng(); 178 | p.scaleX = rnd(0.4,0.6); 179 | p.scaleXMul = rnd(0.92,0.97); 180 | p.frict = rnd(0.7,0.8); 181 | p.lifeS = rnd(0.2, 0.4); 182 | } 183 | } 184 | 185 | public function explosion(ox:Float, oy:Float, r:Float) { 186 | flashBangS(0xffcc00, 0.1, 0.7); 187 | // Bigs 188 | var n = 14; 189 | for(i in 0...n) { 190 | var dist = r*rnd(0.01,0.6); 191 | var a = rnd(0,6.28); 192 | var x = ox+Math.cos(a)*dist; 193 | var y = oy+Math.sin(a)*dist; 194 | var p = allocTopAdd(getTile("fxExplosion"), x,y); 195 | p.playAnimAndKill(Assets.tiles, "fxExplosion", rnd(0.7,0.8)); 196 | p.rotation = rnd(0,6.28); 197 | p.setScale(rnd(0.7,1.1,true)); 198 | p.delayS = i<=4 ? 0 : 0.25*i/n + rnd(0,0.03,true); 199 | } 200 | // Smokes 201 | var n = 20; 202 | for(i in 0...n) { 203 | var dist = r*rnd(0.2,0.7); 204 | var a = rnd(0,6.28); 205 | var x = ox+Math.cos(a)*dist; 206 | var y = oy+Math.sin(a)*dist; 207 | var p = allocBgNormal(getTile("fxExplosionSmoke"),x,y); 208 | p.alpha = rnd(0.6,0.8); 209 | p.playAnimAndKill(Assets.tiles, "fxExplosionSmoke", rnd(0.06,0.10)); 210 | p.colorAnimS(0x660000, 0x0, rnd(0.4,0.8)); 211 | p.rotation = rnd(0,6.28); 212 | p.setScale(rnd(0.8,1.1,true)); 213 | p.delayS = 0.2*i/n + rnd(0,0.1,true); 214 | } 215 | // Lines 216 | for(i in 0...30) { 217 | var p = allocTopAdd(getTile("fxLineDir"), ox+rnd(0,20,true), oy+rnd(0,20,true)); 218 | p.setCenterRatio(1,0.5); 219 | p.colorAnimS(0xffcc00, 0xff0000, rnd(0.2,0.4)); 220 | p.moveAwayFrom(ox,oy, rnd(10,13)); 221 | p.rotation = p.getMoveAng(); 222 | p.scaleXMul = rnd(0.92,0.97); 223 | p.frict = rnd(0.7,0.8); 224 | p.lifeS = rnd(0.2, 0.4); 225 | } 226 | } 227 | 228 | public function destroyItem(e:Entity) { 229 | var n = 20; 230 | for(i in 0...n) { 231 | var a = 6.28*i/n + rnd(0,0.3,true); 232 | var p = allocTopNormal(getTile("fxFragment"), e.centerX+rnd(0,4,true), e.centerY+rnd(0,4,true)); 233 | p.colorize(0x848ca5); 234 | p.moveAng(a, rnd(1.5,2)); 235 | p.setFadeS(rnd(0.4,0.9), 0, rnd(0.1,0.2) ); 236 | p.gy = rnd(0,0.02); 237 | p.frict = rnd(0.80,0.83); 238 | p.lifeS = rnd(1,1.5); 239 | } 240 | } 241 | 242 | public function pickPerma(e:Item, ?c=0x2b5997) { 243 | var n = 35; 244 | for(i in 0...n) { 245 | var a = 6.28*i/n + rnd(0,0.3,true); 246 | var p = allocTopAdd(getTile("pixel"), e.centerX+rnd(0,4,true), e.footY+rnd(0,4,true)); 247 | p.setFadeS(rnd(0.6,0.9), 0, rnd(0.3,0.7) ); 248 | p.colorize(c); 249 | p.alphaFlicker = 0.5; 250 | p.dy = -rnd(1,3); 251 | p.gy = rnd(0.001, 0.012); 252 | p.groundY = e.footY+rnd(0,3); 253 | // p.gy = -rnd(0.1,0.2); 254 | p.frict = rnd(0.87,0.91); 255 | p.lifeS = rnd(0.6,0.4); 256 | } 257 | var n = 30; 258 | for(i in 0...n) { 259 | var a = 6.28*i/n + rnd(0,0.3,true); 260 | var p = allocTopAdd(getTile("fxLineDir"), e.centerX+rnd(0,4,true), e.footY+rnd(0,4,true)); 261 | p.setCenterRatio(1,0.5); 262 | p.setFadeS(rnd(0.3,0.5), 0, rnd(0.5,0.7) ); 263 | p.colorize(c); 264 | // p.colorize(Color.interpolateInt(0xffcc00, 0x990000, rnd(0,1))); 265 | p.moveAwayFrom(e.footX, e.footY+5, 0.1); 266 | p.rotation = p.getMoveAng(); 267 | p.scaleX = -rnd(0.4,0.7); 268 | p.scaleY = rnd(2,3); 269 | p.scaleXMul = rnd(0.97,0.98); 270 | p.dr = rnd(0,0.01,true); 271 | p.frict = rnd(0.87,0.91); 272 | p.lifeS = rnd(0.3,0.4); 273 | } 274 | 275 | var n = 20; 276 | for(i in 0...n) { 277 | var a = 6.28*i/n + rnd(0,0.1,true); 278 | var p = allocTopAdd(getTile("fxSmoke"), e.footX+rnd(0,6,true), e.footY-3+rnd(0,3,true)); 279 | p.setFadeS(rnd(0.2,0.3), 0, rnd(0.5,0.7) ); 280 | p.colorize(c); 281 | p.rotation = rnd(0,6.28); 282 | p.moveAwayFrom(e.footX, e.footY-3, rnd(0.10,0.13)); 283 | e.dy*=0.5; 284 | p.frict = 0.98; 285 | p.setScale(rnd(0.1,0.2,true)); 286 | p.scaleXMul = rnd(1,1.01); 287 | p.dr = rnd(0,0.02,true); 288 | p.lifeS = rnd(1.3,1.4); 289 | } 290 | 291 | // Icon 292 | var p = allocBgAdd(getTile("fxPick"), e.centerX, e.centerY); 293 | p.colorize(0xffcc00); 294 | p.setFadeS(1, 0, 0.5); 295 | p.dy = -3; 296 | p.frict = 0.85; 297 | 298 | var p = allocTopNormal(e.spr.tile, e.centerX, e.centerY); 299 | p.setFadeS(1, 0, 0.5); 300 | p.dy = -3; 301 | p.frict = 0.85; 302 | 303 | } 304 | 305 | public function openDoor(e:en.Door) { 306 | var n = 30; 307 | for(i in 0...n) { 308 | var p = allocTopNormal(getTile("fxFragment"), e.centerX+rnd(0,4,true), e.centerY+rnd(0,4,true)); 309 | p.colorize(e.gold ? 0xffcc00 : 0x445577); 310 | p.dx = rnd(0, 1.5, true); 311 | p.dy = -rnd(1.5,3); 312 | p.rotation = rnd(0,6.28); 313 | p.setFadeS(rnd(0.4,0.9), 0, rnd(0.1,0.2) ); 314 | p.gy = rnd(0.12,0.20); 315 | p.groundY = p.y+rnd(6,10); 316 | p.onBounce = function() { 317 | p.gy = p.dy = 0; 318 | } 319 | p.frict = rnd(0.80,0.83); 320 | p.lifeS = rnd(1,1.5); 321 | } 322 | } 323 | 324 | public function angle(x:Float, y:Float, ang:Float, dist:Float, ?sec=3.0, ?c=0xFF00FF) { 325 | #if debug 326 | var p = allocTopAdd(getTile("fxLineDir"), x,y); 327 | p.setCenterRatio(0,0.5); 328 | p.rotation = ang; 329 | p.setFadeS(1, 0, 0.06); 330 | p.colorize(c); 331 | p.scaleX = dist/p.t.width; 332 | p.lifeS = sec; 333 | #end 334 | } 335 | 336 | function _bloodLand(p:HParticle) { 337 | p.gy = 0; 338 | p.dy = 0; 339 | p.scaleX = rnd(1,3); 340 | } 341 | 342 | public function hit(e:Entity, dir:Int) { 343 | var c = game.cd.has("kidMode") ? 0xffcc00 : 0x791616; 344 | var x = e.spr.x; 345 | var y = e.spr.y; 346 | for(i in 0...25) { 347 | var p = allocTopNormal(getTile("pixel"), x+rnd(0,1,true), y+rnd(0,1,true)); 348 | p.colorize(c); 349 | p.setFadeS(rnd(0.3,0.8), 0, rnd(0.1,0.3)); 350 | p.dx = -dir*rnd(1,5); 351 | p.dy = -rnd(2, 2.5); 352 | p.frict = rnd(0.92, 0.96); 353 | p.gy = rnd(0.04,0.12); 354 | p.groundY = y+rnd(4,8); 355 | p.lifeS = rnd(0.3,1.2); 356 | p.onBounce = function() _bloodLand(p); 357 | } 358 | var p = allocBgNormal(getTile("fxSmoke"), x+rnd(0,2,true), y+rnd(0,2,true)); 359 | p.setFadeS(rnd(0.3,0.5), 0, rnd(1,2)); 360 | p.colorize(c); 361 | p.rotation = rnd(0,6.28); 362 | p.setScale(rnd(0.2,0.3,true)); 363 | p.scaleMul = rnd(0.97,0.99); 364 | p.dr = rnd(0,0.03,true); 365 | p.dy = -rnd(0.1,0.2); 366 | p.lifeS = rnd(0.3, 0.7); 367 | p.frict = 0.96; 368 | } 369 | 370 | public function tail(e:Entity, c:UInt, ?alpha=0.4, ?durationS=0.03, ?thick=1.0, ?offY=0.) { 371 | var a = Math.atan2(e.footY-e.lastFootY, e.footX-e.lastFootX); 372 | var d = M.dist(e.footX, e.footY+offY, e.lastFootX, e.lastFootY+offY); 373 | var p = allocBgAdd(getTile("fxLine"), e.lastFootX, e.lastFootY+offY); 374 | p.setFadeS(0.6*alpha, 0, durationS); 375 | p.colorize(c); 376 | p.setCenterRatio(0.5,0.5); 377 | p.scaleX = 2*d / (p.t.width-10); 378 | p.scaleY = thick; 379 | p.rotation = a; 380 | p.lifeS = 0; 381 | } 382 | 383 | public function bloodTail(e:Entity, dir:Int) { 384 | var x = e.spr.x; 385 | var y = e.spr.y; 386 | for(i in 0...15) { 387 | var p = allocBgNormal(getTile("pixel"), x+rnd(0,1,true), y+rnd(0,1,true)); 388 | p.colorize(0x791616); 389 | p.setFadeS(rnd(0.3,0.8), 0, rnd(0.1,0.3)); 390 | p.dx = dir*rnd(0.1,0.4); 391 | p.dy = -rnd(0.1, 0.2); 392 | p.frict = rnd(0.87, 0.96); 393 | p.gy = rnd(0.01,0.05); 394 | p.groundY = y+rnd(4,8); 395 | p.lifeS = rnd(0.3,1.2); 396 | } 397 | var p = allocBgNormal(getTile("fxSmoke"), x+rnd(0,2,true), y+rnd(0,2,true)); 398 | p.setFadeS(rnd(0.3,0.5), 0, rnd(1,2)); 399 | p.colorize(0x791616); 400 | p.rotation = rnd(0,6.28); 401 | p.setScale(rnd(0.2,0.3,true)); 402 | p.scaleMul = rnd(0.97,0.99); 403 | p.dr = rnd(0,0.03,true); 404 | p.dy = -rnd(0.1,0.2); 405 | p.lifeS = rnd(0.3, 0.7); 406 | p.frict = 0.96; 407 | } 408 | 409 | public function bulletWall(x:Float, y:Float, ang:Float) { 410 | // Dots 411 | for(i in 0...15) { 412 | var p = allocTopAdd(getTile("pixel"), x+rnd(0,1,true), y+rnd(0,1,true)); 413 | p.setFadeS(rnd(0.3,0.8), 0, rnd(0.1,0.3)); 414 | p.moveAng(ang+M.PI+rnd(0,0.1,true), rnd(0.2,2)); 415 | p.frict = rnd(0.87, 0.96); 416 | p.gy = rnd(0.01,0.05); 417 | p.colorize( Color.interpolateInt(0xffcc00,0xff0000,rnd(0,1)) ); 418 | p.lifeS = rnd(0.3,0.6); 419 | } 420 | // Smoke 421 | for(i in 0...4) { 422 | var p = allocTopNormal(getTile("fxSmoke"), x+rnd(0,2,true), y+rnd(0,2,true)); 423 | p.setFadeS(rnd(0.3,0.5), 0, rnd(1,2)); 424 | p.colorize(0x772b2b); 425 | p.rotation = rnd(0,6.28); 426 | p.setScale(rnd(0.2,0.3,true)); 427 | p.scaleMul = rnd(0.97,0.99); 428 | p.dr = rnd(0,0.03,true); 429 | p.dy = -rnd(0.1,0.2); 430 | p.frict = 0.96; 431 | } 432 | } 433 | 434 | public function bulletBleed(x:Float, y:Float, ang:Float) { 435 | var c = game.cd.has("kidMode") ? 0xffcc00 : 0x791616; 436 | 437 | // Dots 438 | for(i in 0...25) { 439 | var p = (i<=8 ? allocTopNormal : allocBgNormal)(getTile("pixel"), x+rnd(0,1,true), y+rnd(0,1,true)); 440 | p.setFadeS(rnd(0.3,0.8), 0, rnd(0.1,0.3)); 441 | p.moveAng(ang+M.PI+rnd(0,0.1,true), rnd(0.2,2)); 442 | p.frict = rnd(0.87, 0.96); 443 | p.gy = rnd(0.01,0.05); 444 | p.colorize(c); 445 | p.lifeS = rnd(0.3,0.6); 446 | } 447 | // Smoke 448 | for(i in 0...4) { 449 | var p = allocTopNormal(getTile("fxSmoke"), x+rnd(0,3,true), y+rnd(0,3,true)); 450 | p.setFadeS(rnd(0.1,0.3), 0, rnd(0.3,0.6)); 451 | p.colorize(c); 452 | p.rotation = rnd(0,6.28); 453 | p.setScale(rnd(0.2,0.3,true)); 454 | p.scaleMul = rnd(0.97,0.99); 455 | p.dr = rnd(0,0.03,true); 456 | p.dy = -rnd(0.1,0.2); 457 | p.frict = 0.96; 458 | } 459 | } 460 | 461 | public function shoot(x:Float, y:Float, ang:Float, c:UInt) { 462 | // Dots bullet 463 | for(i in 0...20) { 464 | var p = allocTopAdd(getTile("pixel"), x+rnd(0,1,true), y+rnd(0,1,true)); 465 | p.setFadeS(rnd(0.6,0.9), 0, rnd(0.1,0.3)); 466 | p.moveAng(ang+rnd(0,0.1,true), rnd(0.03,2)); 467 | p.frict = rnd(0.94, 0.96); 468 | p.lifeS = rnd(0.1,0.2); 469 | p.colorize( Color.interpolateInt(0xffcc00,0xff7700,rnd(0,1)) ); 470 | } 471 | // Dots source 472 | for(i in 0...25) { 473 | var p = allocTopAdd(getTile("pixel"), x+rnd(0,4,true), y+rnd(0,4,true)); 474 | p.colorize(0x817da5); 475 | p.setFadeS(rnd(0.2,0.5), 0, rnd(0.1,0.3)); 476 | p.moveAng(ang+rnd(0.1,0.3,true), rnd(0.03,2)); 477 | // p.moveAwayFrom(x,y, rnd(0.05,0.3)); 478 | p.frict = rnd(0.94, 0.96); 479 | p.lifeS = rnd(0.1,0.2); 480 | } 481 | // Line 482 | var p = allocTopAdd(getTile("fxLineDir"), x,y); 483 | p.colorize(c); 484 | p.rotation = ang; 485 | p.setFadeS(0.6, 0, 0.1); 486 | p.setCenterRatio(1,0.5); 487 | p.scaleX = -1; 488 | p.dsX = -0.1; 489 | p.dsFrict = 0.8; 490 | p.lifeS = 0.06; 491 | // Smoke 492 | // for(i in 0...4) { 493 | // var p = allocTopNormal(getTile("fxSmoke"), x+rnd(0,1,true), y+rnd(0,1,true)); 494 | // p.setFadeS(rnd(0.1,0.2), 0, rnd(0.2,0.4)); 495 | // p.colorize(c); 496 | // p.rotation = rnd(0,6.28); 497 | // p.setScale(rnd(0.2,0.4,true)); 498 | // p.scaleMul = rnd(1,1.01); 499 | // p.dr = rnd(0,0.03,true); 500 | // p.dy = -rnd(0.1,0.2); 501 | // p.frict = 0.96; 502 | // } 503 | } 504 | 505 | public function throwAngle(x:Float, y:Float, ang:Float) { 506 | var p = allocTopAdd(getTile("fxLineDir"), x,y); 507 | p.setCenterRatio(1,0.5); 508 | p.rotation = ang; 509 | p.setFadeS(1, 0, 0.06); 510 | p.colorize(0x6d60c5); 511 | p.scaleX = -1; 512 | p.scaleY = 3; 513 | p.lifeS = 0; 514 | } 515 | 516 | public function viewCone(x:Float, y:Float, ang:Float, ?c=0x7a9aff) { 517 | var p = allocTopAdd(getTile("viewCone"), x,y); 518 | p.setCenterRatio(0,0.5); 519 | p.rotation = ang; 520 | p.setFadeS(0.2, 0, 0.06); 521 | p.colorize(c); 522 | p.setScale(0.25); 523 | p.lifeS = 0; 524 | } 525 | 526 | public function sweat(e:Entity) { 527 | var p = allocBgNormal(getTile("fxSweat"), e.headX-e.dir*2+rnd(0,1,true), e.headY+rnd(0,1,true)); 528 | p.setFadeS(rnd(0.4,0.6), 0, 0.06); 529 | p.rotation = rnd(0,0.1,true); 530 | p.scaleX = e.dir; 531 | p.lifeS = rnd(0.06,0.15); 532 | } 533 | 534 | public function fire(x:Float, y:Float) { 535 | // var t = rnd(0.2,0.3); 536 | var p = allocBgNormal(getTile("fxSmoke"), x,y); 537 | p.colorize(0x440000); 538 | p.setFadeS(rnd(0.2,0.5), 0.2, 0.6); 539 | p.rotation = rnd(0,6.28); 540 | p.setScale(rnd(0.5,1.2,true)); 541 | p.lifeS = 0.2; 542 | p.dy = -rnd(0.4,1); 543 | p.frict = rnd(0.92,0.94); 544 | 545 | for(i in 0...2) { 546 | var p = allocTopAdd(getTile("fxLargeFlame"), x+rnd(0,3,true), y+rnd(0,3,true)); 547 | p.setCenterRatio(0.5, rnd(0.7,1)); 548 | p.setFadeS(rnd(0.8,1), 0.2, 0.1); 549 | p.colorAnimS(0xffcc00, 0xc52424, rnd(0.3,0.4)); 550 | p.scaleXMul = rnd(0.98,1.01); 551 | p.dsY = rnd(0.01,0.03); 552 | p.dsFrict = rnd(0.88,0.90); 553 | p.scaleX = rnd(0.6,0.9,true); 554 | p.scaleY = rnd(0.3,0.6); 555 | 556 | p.frict = rnd(0.92,0.94); 557 | p.lifeS = rnd(0.3,0.8); 558 | p.delayS = rnd(0,0.5); 559 | } 560 | } 561 | 562 | override function update() { 563 | super.update(); 564 | 565 | pool.update(game.tmod); 566 | } 567 | } -------------------------------------------------------------------------------- /src/Game.hx: -------------------------------------------------------------------------------- 1 | import dn.Process; 2 | import hxd.Key; 3 | 4 | class Game extends Process { 5 | public static var ME : Game; 6 | 7 | public var ca : ControllerAccess; 8 | public var fx : Fx; 9 | public var camera : Camera; 10 | public var scroller : h2d.Layers; 11 | public var level : Level; 12 | public var hud : ui.Hud; 13 | 14 | public var hero : en.Hero; 15 | 16 | public function new() { 17 | super(Main.ME); 18 | ME = this; 19 | ca = Main.ME.controller.createAccess("game"); 20 | ca.setLeftDeadZone(0.2); 21 | ca.setRightDeadZone(0.2); 22 | createRootInLayers(Main.ME.root, Const.DP_BG); 23 | 24 | scroller = new h2d.Layers(); 25 | root.add(scroller, Const.DP_BG); 26 | 27 | camera = new Camera(); 28 | fx = new Fx(); 29 | hud = new ui.Hud(); 30 | 31 | startLevel("intro"); 32 | } 33 | 34 | public function nextLevel() { 35 | if( level.data.getStr("nextLevel")!="" ) 36 | startLevel(level.data.getStr("nextLevel")); 37 | else { 38 | var ogmoProj = new ogmo.Project(hxd.Res.map.ld45_ogmo, false); 39 | if( ogmoProj.getLevelByName("level"+(level.lid+1))==null ) 40 | startLevel("level"+level.lid); 41 | else 42 | startLevel("level"+(level.lid+1)); 43 | } 44 | } 45 | 46 | public function restartLevel() { 47 | startLevel(level.data.name); 48 | } 49 | 50 | public function startLevel(name:String) { 51 | var mask = new h2d.Bitmap(h2d.Tile.fromColor(0x0)); 52 | root.add(mask, Const.DP_MASK); 53 | mask.scaleX = M.ceil( w()/Const.SCALE ); 54 | mask.scaleY = M.ceil( h()/Const.SCALE ); 55 | tw.createS(mask.alpha, 0, 0.5).end( mask.remove ); 56 | 57 | if( level!=null ) { 58 | level.destroy(); 59 | for(e in Entity.ALL) 60 | e.destroy(); 61 | gc(); 62 | fx.clear(); 63 | } 64 | 65 | var ogmoProj = new ogmo.Project(hxd.Res.map.ld45_ogmo, false); 66 | var data = ogmoProj.getLevelByName(name); 67 | level = new Level(data); 68 | 69 | var pt = level.getEntityPt("hero"); 70 | hero = new en.Hero(pt.cx, pt.cy); 71 | camera.target = hero; 72 | camera.recenter(); 73 | 74 | for(e in level.getEntities("exit")) new en.Exit(e.cx, e.cy); 75 | for(e in level.getEntities("door")) new en.Door(e.cx, e.cy, e.getStr("color")=="gold"); 76 | for(e in level.getEntities("turret")) new en.mob.Turret(e); 77 | for(e in level.getEntities("guard")) new en.mob.Guard(e); 78 | for(e in level.getEntities("item")) new en.Item(e.cx, e.cy, e.getEnum("type",ItemType)); 79 | for(e in level.getEntities("spikes")) new en.Spike(e.cx, e.cy, false); 80 | for(e in level.getEntities("spikesFragile")) new en.Spike(e.cx, e.cy, true); 81 | 82 | if( en.Mob.ALL.length==0 ) 83 | level.specialEndingCondition = true; 84 | 85 | if( level.lid>=0 ) 86 | bigText("Level "+(level.lid+1)); 87 | cd.unset("levelDone"); 88 | hud.invalidate(); 89 | } 90 | 91 | public function onCdbReload() { 92 | } 93 | 94 | public function bigText(str:Dynamic, ?c=0xffcc00) { 95 | var tf = new h2d.Text(Assets.fontLarge); 96 | root.add(tf, Const.DP_UI); 97 | tf.blendMode = Add; 98 | tf.text = Std.string(str); 99 | tf.textColor = c; 100 | tf.x = Std.int( w()/Const.SCALE*0.5- tf.textWidth*0.5 ); 101 | tf.y = Std.int( h()/Const.SCALE*0.5- tf.textHeight*0.5 ); 102 | tw.createS(tf.alpha, 0>1, 0.1).end( function() { 103 | tw.createS(tf.alpha, 500|0, 1).end( tf.remove ); 104 | }); 105 | } 106 | 107 | 108 | function gc() { 109 | if( Entity.GC==null || Entity.GC.length==0 ) 110 | return; 111 | 112 | for(e in Entity.GC) 113 | e.dispose(); 114 | Entity.GC = []; 115 | } 116 | 117 | override function onDispose() { 118 | super.onDispose(); 119 | 120 | fx.destroy(); 121 | for(e in Entity.ALL) 122 | e.destroy(); 123 | gc(); 124 | } 125 | 126 | override function update() { 127 | super.update(); 128 | 129 | // Updates 130 | for(e in Entity.ALL) if( !e.destroyed ) e.preUpdate(); 131 | for(e in Entity.ALL) if( !e.destroyed ) e.update(); 132 | Entity.ALL.sort( function(a,b) return Reflect.compare(a.footY+a.sprOffY+a.zPriorityOffset, b.footY+b.sprOffY+b.zPriorityOffset)); // Z-sort 133 | for(e in Entity.ALL) if( !e.destroyed ) { 134 | e.zOver(); 135 | e.postUpdate(); 136 | } 137 | for(e in Entity.ALL) if( !e.destroyed ) e.frameEnd(); 138 | gc(); 139 | 140 | // Victory check 141 | if( !level.specialEndingCondition ) { 142 | var any = false; 143 | for(e in Mob.ALL) 144 | if( e.isAlive() ) { 145 | any = true; 146 | break; 147 | } 148 | if( !any && !cd.hasSetS("levelDone",Const.INFINITE) ) { 149 | cd.setS("autoNext", 2); 150 | bigText("Mission complete", 0xff0000); 151 | } 152 | if( cd.has("levelDone") && !cd.has("autoNext") ) { 153 | var mask = new h2d.Bitmap(h2d.Tile.fromColor(0x0)); 154 | cd.setS("autoNext",2); 155 | root.add(mask, Const.DP_MASK); 156 | mask.scaleX = M.ceil( w()/Const.SCALE ); 157 | mask.scaleY = M.ceil( h()/Const.SCALE ); 158 | tw.createS(mask.alpha, 0>1, 0.5).end( function() { 159 | mask.remove(); 160 | nextLevel(); 161 | } ); 162 | } 163 | 164 | } 165 | 166 | if( !ui.Console.ME.isActive() && !ui.Modal.hasAny() ) { 167 | // Exit 168 | if( ca.isKeyboardPressed(Key.X) ) 169 | if( !cd.hasSetS("exitWarn",3) ) 170 | trace(Lang.t._("Press X again to exit.")); 171 | else { 172 | #if( debug && hl ) 173 | hxd.System.exit(); 174 | #else 175 | destroy(); 176 | new Title(); 177 | #end 178 | } 179 | 180 | if( ca.selectPressed() ) 181 | restartLevel(); 182 | 183 | // Kid mode 184 | if( ca.isKeyboardPressed(Key.K ) ) { 185 | if( cd.has("kidMode") ) 186 | cd.unset("kidMode"); 187 | else 188 | cd.setS("kidMode", Const.INFINITE); 189 | bigText("Kid mode: "+(cd.has("kidMode")?"ON":"off")); 190 | } 191 | 192 | #if debug 193 | // Debug 194 | if( ca.isKeyboardPressed(Key.N) ) 195 | nextLevel(); 196 | 197 | // if( ca.isKeyboardPressed(Key.K) ) 198 | // for(e in Mob.ALL) e.hit(999); 199 | 200 | if( ca.isKeyboardPressed(Key.G) ) 201 | Main.ME.startGame(); 202 | 203 | if( ca.isKeyboardPressed(Key.T) ) 204 | startLevel("test"); 205 | #end 206 | } 207 | } 208 | } 209 | 210 | -------------------------------------------------------------------------------- /src/Lang.hx: -------------------------------------------------------------------------------- 1 | import dn.data.GetText; 2 | 3 | class Lang { 4 | static var _initDone = false; 5 | static var DEFAULT = "en"; 6 | public static var CUR = "??"; 7 | public static var t : GetText; 8 | 9 | public static function init(?lid:String) { 10 | if( _initDone ) 11 | return; 12 | 13 | _initDone = true; 14 | CUR = lid==null ? DEFAULT : lid; 15 | 16 | t = new GetText(); 17 | t.readPo( hxd.Res.load("lang/"+CUR+".po").entry.getBytes() ); 18 | } 19 | 20 | public static function untranslated(str:Dynamic) : LocaleString { 21 | init(); 22 | return t.untranslated(str); 23 | } 24 | } -------------------------------------------------------------------------------- /src/LdtkWorld.hx: -------------------------------------------------------------------------------- 1 | private typedef _Tmp = 2 | haxe.macro.MacroType<[ ldtk.Project.build("res/map/ld45.ldtk") ]>; -------------------------------------------------------------------------------- /src/Level.hx: -------------------------------------------------------------------------------- 1 | class Level extends dn.Process { 2 | public var game(get,never) : Game; inline function get_game() return Game.ME; 3 | public var fx(get,never) : Fx; inline function get_fx() return Game.ME.fx; 4 | 5 | public var wid(get,never) : Int; inline function get_wid() return M.ceil(data.pxWid/Const.GRID); 6 | public var hei(get,never) : Int; inline function get_hei() return M.ceil(data.pxHei/Const.GRID); 7 | 8 | public var lid(get,never) : Int; 9 | var invalidatedColls = true; 10 | var invalidated = true; 11 | public var data : ogmo.Level; 12 | var layerRenders : Map = new Map(); 13 | 14 | var damageMap : Map = new Map(); 15 | var collMap : Map = new Map(); 16 | 17 | var roofBitmaps : Map = new Map(); 18 | var texts : h2d.Object; 19 | public var pf : dn.pathfinder.AStar; 20 | 21 | public var specialEndingCondition = false; 22 | 23 | public function new(l:ogmo.Level) { 24 | super(Game.ME); 25 | data = l; 26 | 27 | for(cy in 0...hei) 28 | for(cx in 0...wid) 29 | collMap.set( coordId(cx,cy), data.getLayerByName("collisions").getIntGrid(cx,cy)>=1 ); 30 | 31 | for(l in data.layersReversed) { 32 | var o = new h2d.Object(); 33 | game.scroller.add(o, switch l.name { 34 | case "roofs" : Const.DP_TOP; 35 | case _ : Const.DP_BG; 36 | }); 37 | 38 | switch l.name { 39 | case _ : layerRenders.set(l.name, o); 40 | } 41 | } 42 | 43 | texts = new h2d.Object(); 44 | game.scroller.add(texts, Const.DP_BG); 45 | 46 | pf = new dn.pathfinder.AStar(function(cx,cy) return new CPoint(cx,cy)); 47 | } 48 | 49 | function get_lid() { 50 | var reg = ~/[A-Z\-_.]*([0-9]+)/gi; 51 | if( !reg.match(data.name) ) 52 | return -1; 53 | else 54 | return Std.parseInt( reg.matched(1) ); 55 | } 56 | 57 | override function onDispose() { 58 | super.onDispose(); 59 | for(l in layerRenders) 60 | l.remove(); 61 | for(e in roofBitmaps) 62 | e.remove(); 63 | texts.remove(); 64 | data = null; 65 | pf = null; 66 | } 67 | 68 | public inline function getDamage(cx,cy) { 69 | return isValid(cx,cy) && damageMap.exists(coordId(cx,cy)) ? damageMap.get(coordId(cx,cy)) : 0.; 70 | } 71 | 72 | public inline function damage(cx,cy, pow:Float) { 73 | if( !isValid(cx,cy) || getDamage(cx,cy)>=1 ) 74 | return; 75 | 76 | damageMap.set( coordId(cx,cy), M.fclamp(getDamage(cx,cy)+pow, 0, 1) ); 77 | } 78 | 79 | public inline function isValid(cx,cy) return cx>=0 && cx=0 && cy0?1:0)*Const.GRID, 204 | (3+cid-1)*Const.GRID, 205 | Const.GRID, Const.GRID 206 | ) 207 | ); 208 | 209 | // Wall shadows 210 | if( cid!=5 && data.getLayerByName("collisions").getIntGrid(cx,cy+1)<=0 ) 211 | tg.addAlpha( cx*Const.GRID, (cy+1)*Const.GRID, 0.3, tile.sub(irnd(3,5)*Const.GRID, 0, Const.GRID, Const.GRID) ); 212 | } 213 | } 214 | 215 | } 216 | } 217 | 218 | public function hasRoof(cx,cy) return isValid(cx,cy) && data.getLayerByName("roofs").getTileId(cx,cy)>=0; 219 | // public inline function hasRoof(cx,cy) return isValid(cx,cy) && roofBitmaps.exists(coordId(cx,cy)); 220 | public function hasVisibleRoof(cx,cy) return roofBitmaps.exists(coordId(cx,cy)) && getRoofBitmap(cx,cy).alpha>=0.9; 221 | inline function getRoofBitmap(cx,cy) : Null return hasRoof(cx,cy) ? roofBitmaps.get(coordId(cx,cy)) : null; 222 | var roofEraseMarks : Map = new Map(); 223 | public inline function eraseRoofFrom(cx,cy) { 224 | if( hasRoof(cx,cy) ) 225 | roofEraseMarks.set( coordId(cx,cy), true ); 226 | } 227 | 228 | public inline function clearRoofErase() { 229 | roofEraseMarks = new Map(); 230 | } 231 | 232 | function onCollisionChange() { 233 | invalidatedColls = false; 234 | 235 | pf.init(wid,hei, hasCollision); 236 | } 237 | 238 | var pBushes : h2d.Object; 239 | var pFog : h2d.Object; 240 | var pBack0: h2d.Object; 241 | var pBack1: h2d.Object; 242 | function updateParallax() { 243 | if( data.name!="intro2.json") 244 | return; 245 | 246 | if( pBushes==null ) { 247 | var baseCy = 9; 248 | 249 | pFog = new h2d.Object(); 250 | game.scroller.add(pFog, Const.DP_TOP); 251 | for(i in 0...2) { 252 | var e = Assets.tiles.h_getRandom("forestFog", pFog); 253 | e.setCenterRatio(0,1); 254 | e.x = i*e.tile.width; 255 | e.y = Const.GRID*baseCy+6; 256 | e.alpha = 0.4; 257 | e.colorize( Color.hexToInt("#dbba84") ); 258 | } 259 | 260 | pBushes = new h2d.Object(); 261 | game.scroller.add(pBushes, Const.DP_TOP); 262 | for(i in 0...3) { 263 | var e = Assets.tiles.h_getRandom("forestBushes", pBushes); 264 | e.setCenterRatio(0,1); 265 | e.x = i*e.tile.width; 266 | e.y = Const.GRID*baseCy+6; 267 | e.colorize(0x0); 268 | } 269 | 270 | pBack1 = new h2d.Object(); 271 | game.scroller.add(pBack1, Const.DP_BG); 272 | pBack1.scale(0.75); 273 | for(i in 0...2) { 274 | var e = Assets.tiles.h_getRandom("forestBg", pBack1); 275 | e.setCenterRatio(0,1); 276 | e.x = i*e.tile.width; 277 | e.y = Const.GRID*baseCy+30; 278 | e.colorize( Color.hexToInt("#322745") ); 279 | } 280 | 281 | pBack0 = new h2d.Object(); 282 | game.scroller.add(pBack0, Const.DP_BG); 283 | for(i in 0...2) { 284 | var e = Assets.tiles.h_getRandom("forestBg", pBack0); 285 | e.setCenterRatio(0,1); 286 | e.x = i*e.tile.width; 287 | e.y = Const.GRID*baseCy; 288 | e.colorize( Color.hexToInt("#242b31") ); 289 | } 290 | 291 | } 292 | // pBushes.x = -game.scroller.x*0.3; 293 | pFog.x = -game.scroller.x*0.2; 294 | pBack0.x = -game.scroller.x*0.3-40; 295 | pBack1.x = -game.scroller.x*0.5-50; 296 | } 297 | 298 | 299 | override function postUpdate() { 300 | super.postUpdate(); 301 | 302 | updateParallax(); 303 | 304 | if( invalidated ) render(); 305 | if( invalidatedColls ) onCollisionChange(); 306 | 307 | for(cy in 0...hei) 308 | for(cx in 0...wid) { 309 | if( !cd.has("fireFx") && getDamage(cx,cy)>0 && ( hasCollision(cx,cy) || hasRoof(cx,cy) && hasVisibleRoof(cx,cy) ) ) 310 | fx.fire((cx+rnd(0.3,0.7))*Const.GRID, (cy+rnd(0.2,1))*Const.GRID); 311 | 312 | // Roof anim 313 | if( hasRoof(cx,cy) ) { 314 | var b = getRoofBitmap(cx,cy); 315 | if( !roofEraseMarks.exists(coordId(cx,cy)) && b.alpha<1 ) 316 | b.alpha += (1-b.alpha)*0.1; 317 | if( roofEraseMarks.exists(coordId(cx,cy)) && b.alpha>0 ) { 318 | b.alpha += (0-b.alpha)*0.4; 319 | if( b.alpha<=0.4 ) { 320 | eraseRoofFrom(cx-1,cy); 321 | eraseRoofFrom(cx+1,cy); 322 | eraseRoofFrom(cx,cy-1); 323 | eraseRoofFrom(cx,cy+1); 324 | } 325 | } 326 | } 327 | } 328 | cd.hasSetS("fireFx",0.15); 329 | } 330 | } -------------------------------------------------------------------------------- /src/Main.hx: -------------------------------------------------------------------------------- 1 | import Data; 2 | import hxd.Key; 3 | 4 | class Main extends dn.Process { 5 | public static var ME : Main; 6 | public var controller : Controller; 7 | public var ca : ControllerAccess; 8 | var overlay : dn.heaps.filter.OverlayTexture; 9 | 10 | public function new(s:h2d.Scene) { 11 | super(); 12 | ME = this; 13 | 14 | createRoot(s); 15 | root.filter = new h2d.filter.ColorMatrix(); // force rendering for pixel perfect 16 | 17 | // Engine settings 18 | hxd.Timer.wantedFPS = Const.FPS; 19 | engine.backgroundColor = 0xff<<24|0x111133; 20 | #if( hl && !debug ) 21 | engine.fullScreen = true; 22 | #end 23 | 24 | // Resources 25 | #if debug 26 | hxd.Res.initLocal(); 27 | #else 28 | hxd.Res.initEmbed(); 29 | #end 30 | 31 | // Hot reloading 32 | #if debug 33 | hxd.res.Resource.LIVE_UPDATE = true; 34 | hxd.Res.data.watch(function() { 35 | delayer.cancelById("cdb"); 36 | 37 | delayer.addS("cdb", function() { 38 | Data.load( hxd.Res.data.entry.getBytes().toString() ); 39 | if( Game.ME!=null ) 40 | Game.ME.onCdbReload(); 41 | }, 0.2); 42 | }); 43 | #end 44 | 45 | // Assets & data init 46 | hxd.snd.Manager.get(); 47 | Lang.init("en"); 48 | Assets.init(); 49 | Data.load( hxd.Res.data.entry.getText() ); 50 | 51 | // Console 52 | new ui.Console(Assets.fontTiny, s); 53 | 54 | // Game filter 55 | overlay = new dn.heaps.filter.OverlayTexture(); 56 | Boot.ME.s2d.filter = overlay; 57 | overlay.alpha = 0.3; 58 | overlay.textureStyle = Soft; 59 | 60 | // Game controller 61 | controller = new Controller(s); 62 | ca = controller.createAccess("main"); 63 | controller.bind(AXIS_LEFT_X_NEG, Key.LEFT, Key.Q, Key.A); 64 | controller.bind(AXIS_LEFT_X_POS, Key.RIGHT, Key.D); 65 | controller.bind(AXIS_LEFT_Y_NEG, Key.UP, Key.Z, Key.W); 66 | controller.bind(AXIS_LEFT_Y_POS, Key.DOWN, Key.S); 67 | controller.bind(A, Key.SPACE, Key.F, Key.E); 68 | controller.bind(B, Key.ESCAPE, Key.BACKSPACE); 69 | controller.bind(SELECT, Key.R); 70 | 71 | // Start 72 | new dn.heaps.GameFocusHelper(Boot.ME.s2d, Assets.fontMedium); 73 | delayer.addF( start, 1 ); 74 | } 75 | 76 | function start() { 77 | // Music 78 | #if !debug 79 | Assets.playMusic(); 80 | #end 81 | 82 | #if debug 83 | startGame(); 84 | #else 85 | new Title(); 86 | #end 87 | } 88 | 89 | public function startGame() { 90 | if( Game.ME!=null ) { 91 | Game.ME.destroy(); 92 | delayer.addS(function() { 93 | new Game(); 94 | },0.1); 95 | } 96 | else 97 | new Game(); 98 | } 99 | 100 | override public function onResize() { 101 | super.onResize(); 102 | 103 | // Auto scaling 104 | if( Const.AUTO_SCALE_TARGET_WID>0 ) 105 | Const.SCALE = M.ceil( h()/Const.AUTO_SCALE_TARGET_WID ); 106 | else if( Const.AUTO_SCALE_TARGET_HEI>0 ) 107 | Const.SCALE = M.floor( h()/Const.AUTO_SCALE_TARGET_HEI ); 108 | root.setScale(Const.SCALE); 109 | 110 | overlay.size = Std.int( Const.SCALE ); 111 | } 112 | 113 | override function update() { 114 | Assets.tiles.tmod = tmod; 115 | 116 | if( ca.isKeyboardPressed(Key.M) ) 117 | Assets.toggleMusicPause(); 118 | super.update(); 119 | } 120 | } -------------------------------------------------------------------------------- /src/Title.hx: -------------------------------------------------------------------------------- 1 | class Title extends dn.Process { 2 | var img : h2d.Bitmap; 3 | // var blink : h2d.Bitmap; 4 | var color : h3d.Vector; 5 | var hero : HSprite; 6 | var parachute : HSprite; 7 | var birds : Array<{ e:HSprite, x:Float, y:Float }> = []; 8 | public var ca : ControllerAccess; 9 | var heroX = 0.; 10 | var heroY = 0.; 11 | 12 | public function new() { 13 | super(Main.ME); 14 | 15 | ca = Main.ME.controller.createAccess("title", false); 16 | 17 | createRootInLayers(Main.ME.root, Const.DP_UI); 18 | img = new h2d.Bitmap(hxd.Res.title.toTile(), root); 19 | 20 | cd.setS("lock",0.2); 21 | color = new h3d.Vector(); 22 | color.setColor(0xe5ae00); 23 | img.colorAdd = color; 24 | 25 | parachute = Assets.tiles.h_getAndPlay("parachute", root); 26 | parachute.colorAdd = color; 27 | 28 | hero = Assets.tiles.h_getAndPlay("heroGlide", root); 29 | hero.anim.setSpeed(0.4); 30 | hero.colorAdd = color; 31 | 32 | birds.push({ e:Assets.tiles.h_getAndPlay("bird"), x:360, y:85 }); 33 | birds.push({ e:Assets.tiles.h_getAndPlay("bird"), x:322, y:104 }); 34 | birds.push({ e:Assets.tiles.h_getAndPlay("bird"), x:360, y:114 }); 35 | birds.push({ e:Assets.tiles.h_getAndPlay("bird"), x:290, y:77 }); 36 | birds.push({ e:Assets.tiles.h_getAndPlay("bird"), x:281, y:87 }); 37 | 38 | for(b in birds) { 39 | root.addChild(b.e); 40 | b.e.setCenterRatio(0.5,0.5); 41 | b.e.anim.setSpeed(rnd(0.3, 0.4)); 42 | b.e.colorAdd = color; 43 | } 44 | 45 | dn.Process.resizeAll(); 46 | } 47 | 48 | override function onDispose() { 49 | super.onDispose(); 50 | ca.dispose(); 51 | } 52 | 53 | var done = false; 54 | function skip() { 55 | if( done ) 56 | return; 57 | color.setColor(0xffcc44); 58 | done = true; 59 | } 60 | 61 | override function onResize() { 62 | super.onResize(); 63 | 64 | img.x = ( w()/Const.SCALE*0.5 - img.tile.width*0.5 ); 65 | } 66 | 67 | var rseed = new dn.Rand(0); 68 | override function postUpdate() { 69 | super.postUpdate(); 70 | 71 | parachute.x = heroX + img.x + 183 + Math.cos(ftime*0.030)*2; 72 | parachute.y = heroY + img.y + 31 + Math.sin(1+ftime*0.019)*3; 73 | 74 | hero.x = heroX + img.x + 230 + Math.cos(0.5+ftime*0.030)*2; 75 | hero.y = heroY + img.y + 114 + Math.sin(1.5+ftime*0.019)*3; 76 | 77 | rseed.initSeed(0); 78 | for(b in birds) { 79 | b.e.x = img.x + b.x + Math.cos(rseed.rand()*6.28 + ftime * rseed.range(0.01,0.04) * rseed.sign() )*rseed.irange(1,2); 80 | b.e.y = img.y + b.y + Math.sin(rseed.rand()*6.28 + ftime * rseed.range(0.01,0.04) * rseed.sign() )*rseed.irange(1,2); 81 | } 82 | 83 | if( !done ) { 84 | color.r*=Math.pow(0.99,tmod); 85 | color.g*=Math.pow(0.96,tmod); 86 | color.b*=Math.pow(0.98,tmod); 87 | } 88 | else { 89 | heroX+=0.3*tmod; 90 | heroY+=0.1*tmod; 91 | var s = 0.01; 92 | color.r = M.fmax(-1, color.r - s*tmod ); 93 | color.g = M.fmax(-1, color.g - s*tmod ); 94 | color.b = M.fmax(-1, color.b - s*tmod ); 95 | if( color.r<=-1 && color.g<=-1 && color.b<=-1 ) { 96 | Main.ME.startGame(); 97 | destroy(); 98 | } 99 | } 100 | } 101 | 102 | override function update() { 103 | super.update(); 104 | 105 | if( !cd.has("lock") ) { 106 | if( ca.isKeyboardPressed(hxd.Key.ESCAPE) ) 107 | hxd.System.exit(); 108 | 109 | if( ca.isKeyboardPressed(hxd.Key.ENTER) ) 110 | hxd.System.exit(); 111 | 112 | if( ca.aPressed() || ca.bPressed() || ca.xPressed() || ca.yPressed() 113 | || ca.selectPressed() || ca.startPressed() ) 114 | skip(); 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /src/Types.hx: -------------------------------------------------------------------------------- 1 | enum ItemType { 2 | Barrel; 3 | Gun; 4 | Knife; 5 | Grenade; 6 | GoldKey; 7 | SilverKey; 8 | Heal; 9 | ItchIo; 10 | } -------------------------------------------------------------------------------- /src/en/Bullet.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Bullet extends Entity { 4 | var source : Entity; 5 | public function new(e:Entity, ang:Float, ?spd=1.0) { 6 | super(0,0); 7 | 8 | source = e; 9 | hei = 0; 10 | frict = 1; 11 | hasCollisions = false; 12 | 13 | setPosPixel(e.footX+Math.cos(ang)*5, e.footY-4+Math.sin(ang)*5); 14 | 15 | spd*=0.2; 16 | dx = Math.cos(ang)*spd; 17 | dy = Math.sin(ang)*spd; 18 | 19 | spr.anim.playAndLoop("bulletSmallMob").setSpeed(0.3); 20 | } 21 | 22 | function onBulletHitObstacle() { 23 | fx.bulletWall(centerX, centerY, Math.atan2(dy,dx)); 24 | destroy(); 25 | } 26 | 27 | function checkHit(e:Entity, ?extraBounds=0) { 28 | return e.isAlive() && isAlive() && e!=source 29 | && footX>=e.footX-3-extraBounds && footX<=e.footX+3+extraBounds 30 | && footY>=e.headY+2-extraBounds && footY<=e.footY+extraBounds; 31 | } 32 | 33 | override function postUpdate() { 34 | super.postUpdate(); 35 | if( !cd.hasSetS("tail",0.02) ) 36 | fx.tail(this, source.is(Hero) ? 0x2266ff : 0xff0000, 0.3, source.is(Hero) ? 0.2 : 0.4, 1, -3); 37 | } 38 | 39 | override function update() { 40 | super.update(); 41 | if( level.hasCollision(cx,cy) ) { 42 | var a = Math.atan2(dy,dx); 43 | if( level.hasCollision(Std.int(cx+xr+Math.cos(a)*0.3), Std.int(cy+yr+Math.sin(a)*0.3)) ) 44 | onBulletHitObstacle(); 45 | } 46 | if( !level.isValid(cx,cy) ) 47 | destroy(); 48 | 49 | if( source.is(en.Mob) && checkHit(hero) ) { 50 | hero.hit(this, 1); 51 | fx.bulletBleed(centerX, centerY, Math.atan2(dy,dx)); 52 | destroy(); 53 | } 54 | for(e in Mob.ALL) 55 | if( checkHit(e,5) ) { 56 | e.hit(this, e.armor || e.isGrabbed() ? 1 : source.is(Hero) ? 1 : 3); 57 | e.stunS(3); 58 | fx.bulletBleed(centerX, centerY, Math.atan2(dy,dx)); 59 | destroy(); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/en/Cadaver.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Cadaver extends Entity { 4 | public var loot : Null; 5 | 6 | public function new(e:Entity, sprId:String, ?l:ItemType) { 7 | super(0,0); 8 | loot = l; 9 | setPosCase(e.cx, e.cy, e.xr, e.yr); 10 | frict = 0.92; 11 | 12 | spr.set(sprId,0); 13 | dir = -e.lastHitDir; 14 | 15 | initLife(e.maxLife); 16 | life = 0; 17 | showLifeChange(e.maxLife); 18 | 19 | var a = e.lastHitAng; 20 | if( e.lastHitSource!=null ) 21 | bump(Math.cos(a)*rnd(0.2,0.3), Math.sin(a)*0.2, rnd(0.11,0.15)); 22 | else 23 | bump(Math.cos(a)*rnd(0.1,0.2), Math.sin(a)*0.1, rnd(0.14,0.17)); 24 | cd.setS("lootLock", Const.INFINITE); 25 | } 26 | 27 | override function onZLand() { 28 | super.onZLand(); 29 | cd.setS("landed", Const.INFINITE); 30 | spr.setFrame(1); 31 | cd.unset("lootLock"); 32 | } 33 | 34 | override function postUpdate() { 35 | super.postUpdate(); 36 | if( !cd.has("landed") ) 37 | fx.bloodTail(this, M.sign(dxTotal)); 38 | else 39 | spr.alpha += ( 0.33 - spr.alpha ) * 0.006; 40 | } 41 | 42 | override function update() { 43 | super.update(); 44 | 45 | 46 | // Mob collisions 47 | if( !cd.has("landed") ) 48 | for(e in Mob.ALL) 49 | if( e.isAlive() && distCase(e)<=1.3 && !e.cd.has("touchLock") ) { 50 | e.bumpAwayFrom(this, 0.1, 0.1); 51 | e.stunS(3); 52 | e.hit(e,1); 53 | e.triggerAlarm(); 54 | e.cd.setS("touchLock", 1); 55 | break; 56 | } 57 | 58 | if( loot!=null && !cd.has("lootLock") ) { 59 | var e = new Item(cx,cy, loot); 60 | e.setPosCase(cx,cy,xr,yr); 61 | e.bump(0,0, 0.15); 62 | e.cd.setS("grabLock",0.2); 63 | loot = null; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/en/Door.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Door extends Entity { 4 | public static var ALL : Array = []; 5 | 6 | var isVertical = false; 7 | var isOpen = false; 8 | public var gold = false; 9 | 10 | public function new(x,y, g) { 11 | super(x,y); 12 | gold = g; 13 | yr = 1; 14 | ALL.push(this); 15 | hasCollisions = false; 16 | 17 | isVertical = level.hasCollision(cx,cy+1); 18 | spr.set(level.hasCollision(cx,cy+1) ? gold?"doorV":"doorSilverV" : gold?"doorH":"doorSilverH"); 19 | if( isVertical ) { 20 | if( level.hasRoof(cx-1,cy) ) 21 | xr = 0.9; 22 | else 23 | xr = 0.1; 24 | spr.setCenterRatio(0.5,1); 25 | } 26 | else { 27 | xr = 0; 28 | spr.setCenterRatio(0,1); 29 | } 30 | updateCollisions(); 31 | disableShadow(); 32 | } 33 | 34 | function updateCollisions() { 35 | if( level!=null && !level.destroyed ) 36 | level.setCollision(cx,cy, !isOpen); 37 | } 38 | 39 | public function open() { 40 | if( isOpen ) 41 | return; 42 | isOpen = true; 43 | updateCollisions(); 44 | zPriorityOffset = -99; 45 | } 46 | 47 | override function dispose() { 48 | super.dispose(); 49 | isOpen = true; 50 | updateCollisions(); 51 | } 52 | override function postUpdate() { 53 | super.postUpdate(); 54 | if( cd.has("shake") ) { 55 | spr.x +=Math.cos(ftime*2) * cd.getRatio("shake")*1; 56 | } 57 | } 58 | 59 | override function update() { 60 | cancelVelocities(); 61 | super.update(); 62 | 63 | if( isOpen ) 64 | if( isVertical ) 65 | sprScaleY += (0.2-sprScaleY)*0.2; 66 | else 67 | sprScaleX += (0.2-sprScaleX)*0.2; 68 | 69 | if( !isOpen && ( hero.at(cx,cy-1) || hero.at(cx,cy+1) || hero.at(cx-1,cy) || hero.at(cx+1,cy) ) && !cd.hasSetS("heroShake",0.4) ) { 70 | cd.setS("shake", 0.2); 71 | if( hero.hasPermaItem(gold?GoldKey:SilverKey) ) { 72 | open(); 73 | // fx.openDoor(this); 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/en/Exit.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Exit extends Entity { 4 | public function new(x,y) { 5 | super(x,y); 6 | disableShadow(); 7 | spr.set("exit"); 8 | spr.setCenterRatio(0.5,0.5); 9 | hasCollisions = false; 10 | level.specialEndingCondition = true; 11 | } 12 | 13 | override function update() { 14 | super.update(); 15 | if( hero.at(cx,cy) && !cd.hasSetS("once", Const.INFINITE) ) 16 | game.nextLevel(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/en/Hero.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Hero extends Entity { 4 | var ca : ControllerAccess; 5 | public var grabbedEnt: Null; 6 | var throwAngle : Float; 7 | 8 | var permaItems : Map = new Map(); 9 | 10 | var ammoBar : Null; 11 | 12 | public function new(x,y) { 13 | super(x,y); 14 | ca = Main.ME.controller.createAccess("hero"); 15 | 16 | spr.anim.registerStateAnim("heroHit", 10, function() return isLocked() && cd.has("recentHit") ); 17 | spr.anim.registerStateAnim("heroUseGun", 2, 0.05, function() return isLocked() && cd.has("usingGun") ); 18 | spr.anim.registerStateAnim("heroThrow", 2, 0.10, function() return isLocked() && cd.has("throwingItem") ); 19 | spr.anim.registerStateAnim("heroGrab", 2, function() return isLocked() && cd.has("grabbingItem") ); 20 | spr.anim.registerStateAnim("heroRun", 1, 0.2, function() return isMoving()); 21 | spr.anim.registerStateAnim("heroIdleBack", 0, 0.4, function() return cd.has("lookingBack")); 22 | spr.anim.registerStateAnim("heroIdle", 0, 0.4); 23 | 24 | ammoBar = new h2d.Flow(); 25 | game.scroller.add(ammoBar, Const.DP_UI); 26 | ammoBar.visible = false; 27 | ammoBar.verticalAlign = Middle; 28 | ammoBar.horizontalSpacing = 1; 29 | ammoBar.verticalAlign = Middle; 30 | 31 | initLife(3); 32 | } 33 | 34 | public function addPermaItem(k:ItemType) { 35 | switch k { 36 | case GoldKey, SilverKey: 37 | Assets.SFX.item0(1); 38 | 39 | case Heal: 40 | heal(maxLife); 41 | Assets.SFX.hero2(1); 42 | return; 43 | 44 | case _: 45 | } 46 | permaItems.set(k,true); 47 | game.hud.invalidate(); 48 | } 49 | public function hasPermaItem(k) return permaItems.get(k)==true; 50 | 51 | 52 | override function hit(?from:Entity, dmg:Int) { 53 | if( isGrabbing(en.Mob) ) { 54 | grabbedEnt.hit(from, dmg); 55 | if( from!=null ) 56 | bump(from.dirTo(this)*0.1, 0, 0); 57 | lockS(0.1); 58 | } 59 | else if( !game.cd.has("kidMode") ) 60 | super.hit(from, dmg); 61 | } 62 | 63 | override function onDamage(dmg:Int) { 64 | super.onDamage(dmg); 65 | // releaseGrab(); 66 | fx.flashBangS(0xff0000,0.3, 0.4); 67 | if( lastHitSource!=null ) { 68 | var a = lastHitAng; 69 | bump(Math.cos(a)*0.07, Math.sin(a)*0.01, 0.1); 70 | } 71 | lockS(0.3); 72 | cd.setS("recentHit", getLockS()); 73 | Assets.SFX.hero0(1); 74 | } 75 | 76 | override function onDie() { 77 | super.onDie(); 78 | new en.Cadaver(this, "heroDead"); 79 | fx.flashBangS(0xff0000, 0.3, 2); 80 | game.delayer.addS("restart", function() game.restartLevel(), 1); 81 | } 82 | 83 | override function dispose() { 84 | super.dispose(); 85 | ammoBar.remove(); 86 | releaseGrab(); 87 | ca.dispose(); 88 | } 89 | 90 | public inline function isGrabbing(c:Class) return grabbedEnt!=null && grabbedEnt.isAlive() && Std.isOfType(grabbedEnt, c); 91 | public inline function isGrabbingItem(k:ItemType) return isGrabbing(en.Item) && grabbedEnt.as(Item).item==k; 92 | public inline function consumeItemUse() { 93 | if( isGrabbing(en.Item) ) { 94 | grabbedEnt.as(Item).consumeUse(); 95 | updateAmmo(); 96 | } 97 | } 98 | 99 | function releaseGrab() { 100 | if( grabbedEnt==null ) 101 | return; 102 | 103 | if( !grabbedEnt.isAlive() || !isAlive() ) { 104 | grabbedEnt = null; 105 | return; 106 | } 107 | 108 | grabbedEnt.setPosCase(cx,cy,xr,yr); 109 | grabbedEnt.bump(dir*0.06, 0, 0.2); 110 | grabbedEnt.stunS(0.4); 111 | grabbedEnt.setSpriteOffset(); 112 | grabbedEnt.spr.rotation = 0; 113 | grabbedEnt.cd.setS("grabLock",1); 114 | grabbedEnt = null; 115 | // cd.setS("grabLock",0.5); 116 | } 117 | 118 | function throwGrab() { 119 | if( grabbedEnt==null || !grabbedEnt.isAlive() ) 120 | return; 121 | 122 | var e = grabbedEnt; 123 | game.delayer.addS( function() { 124 | if( isAlive() && e.isAlive() ) { 125 | releaseGrab(); 126 | var s = 0.4; 127 | e.bump(Math.cos(throwAngle)*s, Math.sin(throwAngle)*s, 0.03); 128 | e.cd.setS("violentThrow",1.2); 129 | } 130 | }, 0.1); 131 | lockS(0.2); 132 | grabbedEnt.stunS(1.2); 133 | grabbedEnt.cd.setS("grabLock",1); 134 | // cd.setS("grabLock",0.5); 135 | throwAngle = getCleverAngle(false, e); 136 | cd.setS("throwingItem", getLockS()-0.1); 137 | } 138 | 139 | function grab(e:Entity) { 140 | Assets.SFX.item2(0.6); 141 | releaseGrab(); 142 | dx*=0.3; 143 | dy*=0.3; 144 | dir = dirTo(e); 145 | e.cancelVelocities(); 146 | grabbedEnt = e; 147 | lockS(0.09); 148 | cd.setS("grabbingItem", 0.3); 149 | 150 | if( e.is(Mob) ) 151 | Assets.SFX.grab1(1); 152 | else 153 | Assets.SFX.grab4(1); 154 | 155 | if( e.is(Item) ) { 156 | var i = e.as(Item); 157 | i.onGrab(); 158 | updateAmmo(); 159 | } 160 | } 161 | 162 | function updateAmmo() { 163 | if( !isGrabbing(Item) ) 164 | return; 165 | var i = grabbedEnt.as(Item); 166 | ammoBar.removeChildren(); 167 | for(n in 0...i.maxUses) { 168 | var a = Assets.tiles.h_get("pixel", ammoBar); 169 | a.alpha = n+1<=i.uses ? 1 : 0.2; 170 | a.scaleY = 2; 171 | } 172 | } 173 | 174 | override function postUpdate() { 175 | super.postUpdate(); 176 | 177 | if( grabbedEnt!=null ) { 178 | grabbedEnt.setPosCase(cx,cy,xr,yr); 179 | if( cd.has("grabbingItem") ) { 180 | grabbedEnt.setSpriteOffset(dir*4, 1); 181 | grabbedEnt.zPriorityOffset = 20; 182 | if( !grabbedEnt.cd.hasSetS("blinkGrab",1) ) 183 | grabbedEnt.blink(); 184 | } 185 | else if( cd.has("throwingItem") ) { 186 | grabbedEnt.spr.rotation = 0; 187 | grabbedEnt.setSpriteOffset(-dir*4, -8); 188 | } 189 | else if( cd.has("usingGun") ) { 190 | grabbedEnt.zPriorityOffset = 20; 191 | grabbedEnt.setSpriteOffset(dir*5, 2); 192 | grabbedEnt.dir = dir; 193 | grabbedEnt.spr.rotation = 0; 194 | } 195 | else if( isGrabbingItem(Knife) ) { 196 | grabbedEnt.zPriorityOffset = 20; 197 | if( cd.has("knifePunching") ) 198 | grabbedEnt.setSpriteOffset(dir*10, -5); 199 | else 200 | grabbedEnt.setSpriteOffset(dir*5, -4); 201 | grabbedEnt.dir = dir; 202 | grabbedEnt.spr.rotation = 0; 203 | } 204 | else { 205 | if( isGrabbing(en.Item) ) { 206 | grabbedEnt.zPriorityOffset = -10; 207 | grabbedEnt.dir = dir; 208 | grabbedEnt.spr.rotation = dir*0.2; 209 | if( isMoving() ) 210 | grabbedEnt.setSpriteOffset(-dir*2, -3); 211 | else 212 | grabbedEnt.setSpriteOffset(-dir*3, -2); 213 | 214 | if( isGrabbingItem(Gun) ) { 215 | grabbedEnt.sprOffX+=dir*4; 216 | grabbedEnt.sprOffY-=5; 217 | grabbedEnt.spr.rotation = dir*-1.3; 218 | } 219 | } 220 | else if( isGrabbing(en.Mob) ) { 221 | grabbedEnt.zPriorityOffset = 20; 222 | grabbedEnt.dir = dir; 223 | grabbedEnt.setSpriteOffset(dir*2, 1); 224 | } 225 | } 226 | grabbedEnt.postUpdate(); 227 | } 228 | 229 | ammoBar.x = Std.int( spr.x - ammoBar.outerWidth*0.5 ); 230 | ammoBar.y = Std.int( spr.y - hei - ammoBar.outerHeight ); 231 | ammoBar.visible = grabbedEnt!=null && grabbedEnt.is(Item) && grabbedEnt.as(Item).maxUses>1; 232 | 233 | } 234 | 235 | function getCleverAngle(forEnemy:Bool, ?exclude:Entity) { 236 | var leftDist = M.dist(0,0, ca.lxValue(), ca.lyValue()); 237 | var leftPushed = leftDist>=0.3; 238 | var leftAng = Math.atan2(-ca.lyValue(), ca.lxValue()); 239 | 240 | var dh = new dn.DecisionHelper(Entity.ALL); 241 | // var dh = new dn.DecisionHelper(Mob.ALL); 242 | if( forEnemy ) 243 | dh.keepOnly( function(e) return e.isAlive() && ( e.is(Mob) || e.is(Spike) && !e.as(Spike).broken || e.is(Item) && e.as(Item).item==Barrel )); 244 | else 245 | dh.keepOnly( function(e) return e.isAlive() && e.is(Mob) ); 246 | dh.keepOnly( function(e) return e.isAlive() && ( exclude==null || e!=exclude ) && sightCheckEnt(e) && distCase(e)<=8 && !e.isGrabbed() ); 247 | if( leftPushed && !ca.isKeyboard() ) 248 | dh.remove( function(e) return M.radDistance(leftAng, angTo(e))>1 ); 249 | dh.score( function(e) return isLookingAt(e) ? 10 : 0 ); 250 | dh.score( function(e) return e.is(Mob) && e.as(Mob).hasAlarm() ? 3 : 0 ); 251 | dh.score( function(e) return -distCase(e)*2 ); 252 | if( leftPushed ) 253 | dh.score( function(e) return M.radDistance(leftAng, angTo(e))<=0.7 ? 50 : 0 ); 254 | 255 | var e = dh.getBest(); 256 | if( e!=null ) { 257 | // fx.markerEntity(e, true); 258 | lookAt(e); 259 | } 260 | 261 | return e==null ? leftPushed ? leftAng : dirToAng() : angTo(e); 262 | } 263 | 264 | override function update() { 265 | super.update(); 266 | 267 | var leftDist = M.dist(0,0, ca.lxValue(), ca.lyValue()); 268 | var leftPushed = leftDist>=0.3; 269 | var leftAng = Math.atan2(-ca.lyValue(), ca.lxValue()); 270 | 271 | // Throw aiming 272 | if( isLocked() && cd.has("throwingItem") ) { 273 | if( leftPushed ) 274 | throwAngle = getCleverAngle(true); 275 | if( !cd.hasSetS("throwFx",0.02) ) 276 | fx.throwAngle(footX, footY, throwAngle); 277 | } 278 | 279 | if( !isLocked() ) { 280 | // Move 281 | if( leftPushed ) { 282 | var s = 0.014 * leftDist * tmod * ( isGrabbing(Item) ? 1-grabbedEnt.as(Item).getSpeedReductionOnGrab() : 1.0 ); 283 | dx+=Math.cos(leftAng)*s; 284 | dy+=Math.sin(leftAng)*s; 285 | if( ca.lxValue()<0.3 ) dir = -1; 286 | if( ca.lxValue()>0.3 ) dir = 1; 287 | } 288 | else { 289 | dx *= Math.pow(0.6,tmod); 290 | dy *= Math.pow(0.6,tmod); 291 | } 292 | 293 | // Auto pick perma items 294 | for(e in Item.ALL) 295 | if( e.isAlive() && e.isPermaItem() && !e.cd.has("autoPickLock") && distCase(e)<=1 && sightCheckEnt(e) ) { 296 | var e = e.as(Item); 297 | addPermaItem(e.item); 298 | fx.pickPerma(e, e.item==Heal ? 0x1cdb83 : 0x2b5997); 299 | e.destroy(); 300 | } 301 | 302 | // Grab item/mob 303 | if( ca.aPressed() && !cd.has("grabLock") && grabbedEnt==null ) { 304 | var dh = new dn.DecisionHelper(Entity.ALL); 305 | dh.keepOnly( function(e) return e.canBeGrabbed() && distCase(e)<=Const.GRAB_REACH && sightCheckEnt(e) ); 306 | dh.score( function(e) return -distCase(e) ); 307 | dh.score( function(e) return e.is(Item) ? 1 : 0 ); 308 | var e = dh.getBest(); 309 | if( e!=null ) 310 | grab(e); 311 | else { 312 | spr.anim.play("heroGrab").setSpeed(0.2); 313 | lockS(0.06); 314 | } 315 | } 316 | else if( ca.aPressed() && grabbedEnt!=null ) { 317 | // Use item 318 | if( isGrabbing(Item) && grabbedEnt.as(Item).canUse() ) { 319 | var i = grabbedEnt.as(Item); 320 | switch i.item { 321 | case Barrel, Grenade, ItchIo: 322 | throwGrab(); 323 | consumeItemUse(); 324 | Assets.SFX.throw3(1); 325 | 326 | case Gun: 327 | // Shoot 328 | cancelVelocities(); 329 | var a = getCleverAngle(false); 330 | new Bullet(this, a, 2); 331 | cd.setS("usingGun", 0.2); 332 | lockS(0.1); 333 | game.camera.shakeS(0.1, 0.3); 334 | consumeItemUse(); 335 | Assets.SFX.throw0(1); 336 | 337 | case Knife: 338 | lockS(0.15); 339 | spr.anim.play("heroPunch").setSpeed(0.8); 340 | cd.setS("knifePunching",0.1); 341 | var any = false; 342 | for(e in Mob.ALL) { 343 | if( e.isAlive() && distCase(e)<=Const.MELEE_REACH && sightCheckEnt(e) ) { 344 | if( e.armor ) 345 | e.blink(); 346 | else 347 | e.hit(this, 2); 348 | e.bumpAwayFrom(this, 0.1); 349 | e.stunS(1.5); 350 | fx.hit(e, dirTo(e)); 351 | any = true; 352 | } 353 | } 354 | for(e in Item.ALL) { 355 | if( e.isAlive() && distCase(e)<=Const.MELEE_REACH && sightCheckEnt(e) ) { 356 | e.bumpAwayFrom(this, 0.1); 357 | if( e.onPunch(true) ) 358 | any = true; 359 | } 360 | } 361 | if( any ) 362 | consumeItemUse(); 363 | 364 | 365 | case GoldKey, SilverKey, Heal: 366 | } 367 | } 368 | if( isGrabbing(Mob) ) 369 | throwGrab(); 370 | } 371 | else if( ca.bPressed() && grabbedEnt!=null ) 372 | releaseGrab(); 373 | 374 | 375 | // Melee punch 376 | // if( ca.aPressed() && grabbedEnt==null && !cd.has("punch") ) { 377 | // lockS(0.2); 378 | // spr.anim.play("heroPunch").setSpeed(0.4); 379 | // for(e in Mob.ALL) { 380 | // if( e.isAlive() && distCase(e)<=Const.MELEE_REACH && sightCheckEnt(e) ) { 381 | // dir = dirTo(e); 382 | // bump(dir*0.02, 0, 0); 383 | // e.blink(0xffffff); 384 | // var a = getCleverAngle(true, e); 385 | // e.stunS(1.1); 386 | // e.bump(Math.cos(a)*0.4, Math.sin(a)*0.2, 0.05); 387 | // e.cd.setS("punched",0.4); 388 | // e.onPunch(); 389 | // game.camera.shakeS(0.2, 0.2); 390 | // } 391 | // } 392 | // for(e in Item.ALL) { 393 | // if( e.isAlive() && distCase(e)<=Const.MELEE_REACH && sightCheckEnt(e) ) { 394 | // e.bumpAwayFrom(this, 0.1); 395 | // e.onPunch(false); 396 | // } 397 | // } 398 | // } 399 | 400 | #if debug 401 | if( ca.dpadUpPressed() ) { 402 | fx.explosion(centerX, centerY, Const.GRID*3); 403 | } 404 | #end 405 | } 406 | 407 | // Bump into enemies 408 | for(e in en.Mob.ALL) { 409 | if( !e.isAlive() || distCase(e)>0.5 || e.isGrabbed() ) 410 | continue; 411 | if( !cd.hasSetS("mobBump",0.03) ) { 412 | bumpAwayFrom(e, 0.05, 0); 413 | e.bumpAwayFrom(this, 0.02, 0); 414 | e.triggerAlarm(); 415 | } 416 | } 417 | 418 | 419 | // Lost item 420 | if( grabbedEnt!=null && !grabbedEnt.isAlive() ) 421 | grabbedEnt = null; 422 | 423 | #if debug 424 | if( ca.yPressed() ) { 425 | Assets.SFX.explode0(1); 426 | } 427 | #end 428 | 429 | // Roof anim 430 | if( level.hasRoof(cx,cy) ) 431 | level.eraseRoofFrom(cx,cy); 432 | else 433 | level.clearRoofErase(); 434 | 435 | if( isMoving() ) 436 | cd.setS("lookBackLock", 0.4); 437 | if( !isMoving() && zr==0 && !cd.has("lookBackLock") ) { 438 | cd.setS("lookingBack",0.5); 439 | cd.setS("lookBackLock",rnd(2.5,4)); 440 | } 441 | 442 | if( ui.Console.ME.hasFlag("fps") ) debug(Std.int(hxd.Timer.fps())+" tmod="+pretty(tmod,2)); 443 | } 444 | } -------------------------------------------------------------------------------- /src/en/Item.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Item extends Entity { 4 | public static var ALL : Array = []; 5 | public var item : ItemType; 6 | 7 | public var uses : Int; 8 | public var maxUses(default,null) : Int; 9 | 10 | public function new(x,y,i:ItemType) { 11 | super(x,y); 12 | ALL.push(this); 13 | item = i; 14 | spr.set(item.getName()); 15 | 16 | cd.setS("autoPickLock", 0.3); 17 | 18 | maxUses = uses = switch i { 19 | case Barrel: 1; 20 | case ItchIo: 1; 21 | case Grenade: 1; 22 | case Gun: 12; 23 | case Knife: 4; 24 | case SilverKey: 1; 25 | case GoldKey: 1; 26 | case Heal: 1; 27 | } 28 | } 29 | 30 | public function isPermaItem() return switch item { 31 | case GoldKey, SilverKey, Heal: true; 32 | case _ : false; 33 | } 34 | 35 | public function getGrabDist() : Float { 36 | return 1.5; 37 | return switch item { 38 | case Barrel: 0.5; 39 | case _: 0.7; 40 | } 41 | } 42 | 43 | public function getSpeedReductionOnGrab() : Float { 44 | return switch item { 45 | case Barrel: 0.66; 46 | case _: 0.; 47 | } 48 | } 49 | 50 | override function canBeGrabbed():Bool { 51 | return isAlive() && !isGrabbed() && !isDepleted() && !cd.has("grabLock") && !isPermaItem(); 52 | } 53 | 54 | public function canUse() return isAlive() && isGrabbed() && !isDepleted(); 55 | public function isDepleted() return uses<=0; 56 | 57 | public function onGrab() { 58 | if( item==ItchIo ) 59 | for(e in Mob.ALL ) 60 | if( e.isAlive() ) { 61 | e.triggerAlarm(); 62 | e.lookAt(hero); 63 | e.lockS(1.5); 64 | } 65 | } 66 | 67 | public function consumeUse() { 68 | uses--; 69 | if( uses<=0 ) { 70 | cd.setS("grabLock",Const.INFINITE); 71 | switch item { 72 | case Barrel, Grenade: trigger(1); 73 | case ItchIo: trigger(2); 74 | case _: 75 | cd.setS("selfDestructing", Const.INFINITE); 76 | cd.setS("selfDestruct", 0.2); 77 | } 78 | } 79 | } 80 | 81 | public function onPunch(withWeapon:Bool) { 82 | switch item { 83 | case Barrel: 84 | if( withWeapon ) { 85 | trigger(1); 86 | return true; 87 | } 88 | 89 | case _: 90 | } 91 | return false; 92 | } 93 | 94 | public function trigger(sec:Float) { 95 | cd.setS("trigger", sec); 96 | uses = 0; 97 | } 98 | 99 | override function onZLand() { 100 | super.onZLand(); 101 | } 102 | 103 | override function dispose() { 104 | super.dispose(); 105 | ALL.remove(this); 106 | } 107 | 108 | function onSelfDestruct() { 109 | fx.destroyItem(this); 110 | destroy(); 111 | } 112 | 113 | function explosion(rCase:Float, dmg:Int) { 114 | game.camera.shakeS(0.6, 0.3); 115 | cd.setS("exploded", Const.INFINITE); 116 | fx.explosion(centerX, centerY, Const.GRID*(rCase-1)); 117 | for(e in Mob.ALL) 118 | if( e.isAlive() && distCase(e)<=rCase && ( sightCheckEnt(e) || distCase(e)<=3 ) ) { 119 | e.stunS(4); 120 | e.hit(this, dmg); 121 | } 122 | 123 | for(e in Item.ALL) 124 | if( e!=this && e.isAlive() && distCase(e)<=rCase && ( sightCheckEnt(e) || distCase(e)<=3 ) && !e.cd.has("exploded") ) 125 | e.onExplosion(this); 126 | } 127 | 128 | public function onExplosion(from:Entity) { 129 | bumpAwayFrom(from, 0.2, rnd(0.2,0.3)); 130 | switch item { 131 | case Barrel, Grenade: trigger(0.2); 132 | case _: 133 | } 134 | } 135 | 136 | function onTrigger() { 137 | switch item { 138 | case Barrel: explosion(6,11); Assets.SFX.explode2(1); destroy(); 139 | case Grenade: explosion(4,9); Assets.SFX.explode0(1); destroy(); 140 | case ItchIo: explosion(5,99); Assets.SFX.explode0(1); destroy(); 141 | case _: 142 | } 143 | } 144 | 145 | override function update() { 146 | super.update(); 147 | 148 | // Entity collisions 149 | if( isMoving() || zr<0 ) 150 | for(e in Mob.ALL) 151 | if( e.isAlive() && distCase(e)<=1.3 && !e.cd.has("touchLock"+uid) ) { 152 | if( cd.has("violentThrow") && !cd.has("trigger") ) { 153 | e.bump(dirTo(e)*0.15, 0, 0.2); 154 | e.stunS(0.4); 155 | e.hit(e,1); 156 | e.triggerAlarm(); 157 | } 158 | e.cd.setS("touchLock"+uid, 1); 159 | onTrigger(); 160 | break; 161 | } 162 | 163 | if( isDepleted() && cd.has("selfDestructing") && !cd.has("selfDestruct") ) 164 | onSelfDestruct(); 165 | 166 | if( cd.has("trigger") && !cd.hasSetS("blink", cd.getS("trigger")<=0.3 ? 0.1 : 0.15) ) 167 | blink(0xffcc00); 168 | 169 | switch item { 170 | case Barrel, Grenade: 171 | if( isDepleted() && !cd.has("trigger") ) 172 | onTrigger(); 173 | 174 | case _: 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/en/Mob.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Mob extends Entity { 4 | public static var ALL : Array = []; 5 | 6 | var loot : Null; 7 | var patrolPts : Array = []; 8 | var lastAlarmPt : CPoint; 9 | var curPatrolIdx = 0; 10 | var curPatrolPt(get,never) : CPoint; inline function get_curPatrolPt() return patrolPts[curPatrolIdx]; 11 | var path : Array = []; 12 | public var armor = false; 13 | 14 | 15 | public var lookAng : Float; 16 | var viewCone : HSprite; 17 | 18 | public function new(data:ogmo.Entity) { 19 | super(data.cx, data.cy); 20 | ALL.push(this); 21 | lastAlarmPt = new CPoint(cx,cy); 22 | 23 | if( data.getStr("loot","")!="" ) 24 | loot = Type.createEnum(ItemType, data.getStr("loot")); 25 | 26 | 27 | dir = Std.random(2)*2-1; 28 | lookAng = dirToAng(); 29 | 30 | if( data.getBool("static") ) { 31 | // Immobile 32 | patrolPts = [ new CPoint(cx,cy) ]; 33 | dir = data.getStr("patrol")=="left" ? -1 : 1; 34 | lookAng = switch data.getStr("patrol") { 35 | case "up": -M.PIHALF; 36 | case "right": 0; 37 | case "down": M.PIHALF; 38 | case "left": M.PI; 39 | case _ : 0; 40 | } 41 | } 42 | else { 43 | // Parse patrol 44 | if( data.nodes.length>0 ) { 45 | var lastPt = new CPoint(cx,cy); 46 | for(n in data.nodes) { 47 | var segment = []; 48 | dn.Bresenham.iterateThinLine( lastPt.cx, lastPt.cy, n.cx, n.cy, function(x,y) segment.push( new CPoint(x, y) ) ); 49 | if( segment[0].cx!=lastPt.cx || segment[0].cy!=lastPt.cy ) 50 | segment.reverse(); 51 | patrolPts = patrolPts.concat(segment); 52 | lastPt.set(n.cx, n.cy); 53 | } 54 | var i = 0; 55 | while( i=patrolPts.length ) 281 | curPatrolIdx = 0; 282 | } 283 | } 284 | else { 285 | // Track alarm source 286 | if( !cd.hasSetS("trackPath",0.2) ) { 287 | goto(lastAlarmPt.cx, lastAlarmPt.cy); 288 | } 289 | } 290 | 291 | 292 | // Follow path 293 | if( path.length>0 && !isLocked() ) { 294 | var next = path[0]; 295 | while( next!=null && next.distCase(this)<=0.2 ) { 296 | path.shift(); 297 | next = path[0]; 298 | } 299 | if( next!=null ) { 300 | // Movement 301 | if( ui.Console.ME.hasFlag("path") ) 302 | fx.markerCase(next.cx, next.cy, 0.1); 303 | var s = hasAlarm() ? 0.008 : spr.frame==1 ? 0.003 : 0.006; 304 | var a = Math.atan2(next.footY-footY, next.footX-footX); 305 | dx+=Math.cos(a)*s*tmod; 306 | dy+=Math.sin(a)*s*tmod; 307 | 308 | // Try to stick to cell center 309 | var a = Math.atan2(0.5-yr, 0.5-xr); 310 | dx+=Math.cos(a)*0.001*tmod; 311 | dy+=Math.sin(a)*0.001*tmod; 312 | 313 | if( hasAlarm() ) 314 | dir = lastAlarmPt.cxcx ? 1 : dir; 315 | else 316 | dir = next.cxcx ? 1 : dir; 317 | 318 | if( hasAlarm() && distPxFree(lastAlarmPt.footX, lastAlarmPt.footY) >= Const.GRID*0.5 ) 319 | lookAng = Math.atan2(lastAlarmPt.footY-footY, lastAlarmPt.footX-footX); 320 | 321 | if( !hasAlarm() && distPxFree(next.footX, next.footY) >= Const.GRID*0.5 ) 322 | lookAng = Math.atan2(next.footY-footY, next.footX-footX); 323 | 324 | } 325 | } 326 | } 327 | 328 | 329 | // Sound emit fx 330 | if( distCase(hero)<=10 && level.hasVisibleRoof(cx,cy) ) { 331 | if( !hasAlarm() && !cd.hasSetS("soundFx", 1) ) 332 | fx.emitSound(footX, footY); 333 | if( hasAlarm() && !cd.hasSetS("soundFxAlarm", 0.4) ) 334 | fx.emitSound(footX, footY, 0xff0000); 335 | } 336 | } 337 | } -------------------------------------------------------------------------------- /src/en/Spike.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Spike extends Entity { 4 | public static var ALL : Array = []; 5 | public var fragile : Bool; 6 | public var broken = false; 7 | 8 | public function new(x,y, f) { 9 | super(x,y); 10 | fragile = f; 11 | ALL.push(this); 12 | hasCollisions = false; 13 | spr.set(fragile ? "spikeFragile" : "spike"); 14 | disableShadow(); 15 | } 16 | 17 | function hasSpike(x,y) { 18 | for(e in ALL) 19 | if( e.at(x,y) ) 20 | return true; 21 | return false; 22 | } 23 | 24 | override function dispose() { 25 | super.dispose(); 26 | } 27 | override function postUpdate() { 28 | super.postUpdate(); 29 | } 30 | 31 | override function update() { 32 | if( !cd.hasSetS("initDone", Const.INFINITE) ) { 33 | if( level.hasCollision(cx,cy+1) && !hasSpike(cx,cy-1) ) { 34 | yr = 1; 35 | } 36 | else if( level.hasCollision(cx,cy-1) && !hasSpike(cx,cy+1) ) { 37 | yr = 0; 38 | spr.rotation = M.PI; 39 | sprOffY = -2; 40 | } 41 | else if( level.hasCollision(cx-1,cy) ) { 42 | xr = 0; 43 | spr.rotation = M.PIHALF; 44 | } 45 | else if( level.hasCollision(cx+1,cy) ) { 46 | xr = 1; 47 | spr.rotation = -M.PIHALF; 48 | } 49 | } 50 | 51 | cancelVelocities(); 52 | super.update(); 53 | 54 | if( !broken ) 55 | for(e in Mob.ALL) 56 | if( e.isAlive() && distCase(e)<=1 && !e.cd.has("spikeHit") && ( e.isStunned() || e.cd.has("violentThrow") ) ) { 57 | e.hit(this, 99); 58 | e.stunS(1); 59 | fx.wallImpact(centerX, centerY, angTo(e), 0xff0000); 60 | e.cancelVelocities(); 61 | e.bumpAwayFrom(this, 0.07); 62 | e.cd.setS("spikeHit",0.4); 63 | spr.set(fragile ? "spikeFragileBlood" : "spikeBlood"); 64 | if( fragile ) 65 | broken = true; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/en/mob/Guard.hx: -------------------------------------------------------------------------------- 1 | package en.mob; 2 | 3 | class Guard extends en.Mob { 4 | public function new(data) { 5 | super(data); 6 | 7 | // Anims 8 | spr.anim.registerStateAnim("guardGrabbed", 20, 0.1, function() return isGrabbed()); 9 | spr.anim.registerStateAnim("guardHit", 10, 0.15, function() return isStunned()); 10 | spr.anim.registerStateAnim("guardRun", 1, 0.2, function() return isMoving() && hasAlarm()); 11 | spr.anim.registerStateAnim("guardWalk", 1, 0.2, function() return isMoving()); 12 | spr.anim.registerStateAnim("guardIdle", 0, 0.4); 13 | initLife(3); 14 | } 15 | 16 | override function onDie() { 17 | super.onDie(); 18 | new en.Cadaver(this, "guardDead", loot); 19 | } 20 | 21 | override function postUpdate() { 22 | super.postUpdate(); 23 | 24 | if( !isStunned() && hasAlarm() && !cd.has("sawHero") && !cd.hasSetS("sweat",0.1) ) 25 | fx.sweat(this); 26 | } 27 | 28 | override function update() { 29 | super.update(); 30 | 31 | if( hero.isAlive() ) { 32 | // See hero 33 | var viewAng = hasAlarm() ? M.PI*0.8 : M.PI*0.2; 34 | var viewDist = hasAlarm() ? 9 : 5; 35 | if( ui.Console.ME.hasFlag("cone") ) { 36 | fx.angle(footX, footY, lookAng+viewAng*0.5, viewDist*Const.GRID, 0.03, 0xff0000); 37 | fx.angle(footX, footY, lookAng-viewAng*0.5, viewDist*Const.GRID, 0.03, 0xff0000); 38 | } 39 | if( M.radDistance(angTo(hero),lookAng)<=viewAng*0.5 && distCase(hero)<=viewDist && sightCheckEnt(hero) ) { 40 | cd.setS("sawHero", 0.5, false); 41 | } 42 | 43 | // Continue to track hero longer after last sight 44 | if( !isStunned() && cd.has("sawHero") ) { 45 | if( !hasAlarm() ) 46 | fx.alarm(this); 47 | 48 | triggerAlarm(); 49 | } 50 | } 51 | 52 | // Shoot 53 | if( !isGrabbed() && !isLocked() && cd.has("sawHero") && distCase(hero)<=8 && !cd.has("shootLock")) { 54 | lockS(0.3); 55 | var a = angTo(hero); 56 | Assets.SFX.hit6(1); 57 | spr.anim.play("guardShoot").setSpeed(0.2); 58 | dir = hero.centerX>centerX ? 1 : -1; 59 | game.delayer.addS(function() { 60 | if( !isAlive() || isStunned() || isGrabbed() ) 61 | return; 62 | var e = new en.Bullet(this, a); 63 | fx.shoot(e.footX, e.footY-2, a, 0xff0000); 64 | },0.2); 65 | cd.setS("shootLock", 1); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/en/mob/Turret.hx: -------------------------------------------------------------------------------- 1 | package en.mob; 2 | 3 | class Turret extends en.Mob { 4 | var shootCount = 0; 5 | 6 | public function new(data) { 7 | super(data); 8 | initLife(12); 9 | armor = true; 10 | bumpReduction = 1.0; 11 | spr.setCenterRatio(0.5,0.5); 12 | spr.anim.registerStateAnim("turret",0); 13 | } 14 | 15 | override function hit(?from:Entity, dmg:Int) { 16 | super.hit(from, dmg); 17 | } 18 | 19 | override function onDie() { 20 | super.onDie(); 21 | var rCase = 5; 22 | cd.setS("exploded", Const.INFINITE); 23 | fx.explosion(centerX, centerY, Const.GRID*(rCase-1)); 24 | for(e in Mob.ALL) 25 | if( e.isAlive() && distCase(e)<=rCase && ( sightCheckEnt(e) || distCase(e)<=3 ) ) 26 | e.hit(this, 99); 27 | 28 | for(e in Item.ALL) 29 | if( e.isAlive() && distCase(e)<=rCase && ( sightCheckEnt(e) || distCase(e)<=3 ) && !e.cd.has("exploded") ) 30 | e.onExplosion(this); 31 | } 32 | 33 | override function postUpdate() { 34 | super.postUpdate(); 35 | spr.scaleX = sprScaleX; // no dir 36 | viewCone.visible = false; 37 | } 38 | 39 | override function canBeGrabbed():Bool { 40 | return false; 41 | } 42 | 43 | override function goto(x:Int, y:Int) { 44 | // nope 45 | } 46 | 47 | override function update() { 48 | super.update(); 49 | var shootRange = 8; 50 | 51 | if( sightCheckEnt(hero) && distCase(hero)<=shootRange ) { 52 | if( !hasAlarm() ) 53 | fx.alarm(this); 54 | triggerAlarm(1); 55 | } 56 | 57 | // Shoot 58 | if( hasAlarm() && !isLocked() && !isStunned() && distCase(hero)<=shootRange && !cd.has("shootLock")) { 59 | lockS(0.3); 60 | cd.setS("shootLock", 1.5); 61 | shootCount = 3; 62 | } 63 | 64 | if( !isStunned() && shootCount>0 && !cd.hasSetS("shoot",0.15) ) { 65 | var a = angTo(hero); 66 | Assets.SFX.hit6(1); 67 | var e = new en.Bullet(this, a, 0.66); 68 | fx.shoot(e.footX, e.footY-2, a, 0xff0000); 69 | shootCount--; 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/import.hx: -------------------------------------------------------------------------------- 1 | import dn.M; 2 | import dn.Lib; 3 | import dn.legacy.Color; 4 | import dn.legacy.Controller; 5 | import dn.Tweenie; 6 | import dn.data.GetText; 7 | import dn.heaps.slib.*; 8 | import tools.*; 9 | import Types; 10 | import en.*; -------------------------------------------------------------------------------- /src/tools/CPoint.hx: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | class CPoint { 4 | public var cx : Int; 5 | public var cy : Int; 6 | public var xr : Float; 7 | public var yr : Float; 8 | 9 | public var footX(get,never) : Float; inline function get_footX() return (cx+xr)*Const.GRID; 10 | public var footY(get,never) : Float; inline function get_footY() return (cy+yr)*Const.GRID; 11 | public var centerX(get,never) : Float; inline function get_centerX() return footX; 12 | public var centerY(get,never) : Float; inline function get_centerY() return footY-Const.GRID*0.5; 13 | 14 | public function new(x,y, ?xr=0.5, ?yr=0.5) { 15 | cx = x; 16 | cy = y; 17 | this.xr = xr; 18 | this.yr = yr; 19 | } 20 | 21 | public function set(x,y,?xr=0.5,?yr=0.5) { 22 | this.cx = x; 23 | this.cy = y; 24 | this.xr = xr; 25 | this.yr = yr; 26 | } 27 | 28 | public function is(x,y) return cx==x && cy==y; 29 | 30 | public inline function distCase(?e:Entity, ?pt:CPoint, ?cx=0, ?cy=0, ?xr=0.5, ?yr=0.5) { 31 | if( e!=null ) 32 | return M.dist(this.cx+this.xr, this.cy+this.yr, e.cx+e.xr, e.cy+e.yr); 33 | else if( pt!=null ) 34 | return M.dist(this.cx+this.xr, this.cy+this.yr, pt.cx+pt.xr, pt.cy+pt.yr); 35 | else 36 | return M.dist(this.cx+this.xr, this.cy+this.yr, cx+xr, cy+yr); 37 | } 38 | 39 | public inline function distPx(?e:Entity, ?pt:CPoint, ?x=0., ?y=0.) { 40 | if( e!=null ) 41 | return M.dist(footX, footY, e.footX, e.footY); 42 | else if( pt!=null ) 43 | return M.dist(footX, footY, pt.footX, pt.footY); 44 | else 45 | return M.dist(footX, footY, x, y); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/ui/Console.hx: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | class Console extends h2d.Console { 4 | public static var ME : Console; 5 | #if debug 6 | var flags : Map; 7 | #end 8 | 9 | public function new(f:h2d.Font, p:h2d.Object) { 10 | super(f, p); 11 | 12 | scale(2); // TODO smarter scaling for 4k screens 13 | 14 | // Settings 15 | ME = this; 16 | #if debug 17 | h2d.Console.HIDE_LOG_TIMEOUT = 30; 18 | #end 19 | Lib.redirectTracesToH2dConsole(this); 20 | 21 | // Debug flags 22 | #if debug 23 | flags = new Map(); 24 | this.addCommand("set", [{ name:"k", t:AString }], function(k:String) { 25 | setFlag(k,true); 26 | log("+ "+k, 0x80FF00); 27 | }); 28 | this.addCommand("unset", [{ name:"k", t:AString, opt:true } ], function(?k:String) { 29 | if( k==null ) { 30 | log("Reset all.",0xFF0000); 31 | flags = new Map(); 32 | } 33 | else { 34 | log("- "+k,0xFF8000); 35 | setFlag(k,false); 36 | } 37 | }); 38 | this.addAlias("+","set"); 39 | this.addAlias("-","unset"); 40 | #end 41 | } 42 | 43 | #if debug 44 | public function setFlag(k:String,v) return flags.set(k,v); 45 | public function hasFlag(k:String) return flags.get(k)==true; 46 | #else 47 | public function hasFlag(k:String) return false; 48 | #end 49 | } -------------------------------------------------------------------------------- /src/ui/Hud.hx: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | class Hud extends dn.Process { 4 | public var game(get,never) : Game; inline function get_game() return Game.ME; 5 | public var fx(get,never) : Fx; inline function get_fx() return Game.ME.fx; 6 | public var level(get,never) : Level; inline function get_level() return Game.ME.level; 7 | 8 | var flow : h2d.Flow; 9 | var invalidated = true; 10 | 11 | public function new() { 12 | super(Game.ME); 13 | 14 | createRootInLayers(game.root, Const.DP_UI); 15 | 16 | flow = new h2d.Flow(root); 17 | flow.horizontalSpacing = 0; 18 | flow.blendMode = Add; 19 | flow.verticalAlign = Middle; 20 | flow.y = -5; 21 | } 22 | 23 | override function onDispose() { 24 | super.onDispose(); 25 | } 26 | 27 | public inline function invalidate() invalidated = true; 28 | 29 | function render() { 30 | flow.removeChildren(); 31 | if( game.hero.hasPermaItem(GoldKey) ) Assets.tiles.h_get("GoldKey", flow); 32 | if( game.hero.hasPermaItem(SilverKey) ) Assets.tiles.h_get("SilverKey", flow); 33 | } 34 | 35 | override function postUpdate() { 36 | super.postUpdate(); 37 | 38 | if( invalidated ) { 39 | invalidated = false; 40 | render(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/ui/Modal.hx: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | class Modal extends ui.Window { 4 | public static var ALL : Array = []; 5 | static var COUNT = 0; 6 | 7 | var ca : ControllerAccess; 8 | var mask : h2d.Bitmap; 9 | var modalIdx : Int; 10 | 11 | public function new() { 12 | super(); 13 | 14 | ALL.push(this); 15 | modalIdx = COUNT++; 16 | if( modalIdx==0 ) 17 | Game.ME.pause(); 18 | 19 | ca = Main.ME.controller.createAccess("modal", true); 20 | mask = new h2d.Bitmap(h2d.Tile.fromColor(0x0, 1, 1, 0.6), root); 21 | root.under(mask); 22 | dn.Process.resizeAll(); 23 | } 24 | 25 | public static function hasAny() { 26 | for(e in ALL) 27 | if( !e.destroyed ) 28 | return true; 29 | return false; 30 | } 31 | 32 | override function onDispose() { 33 | super.onDispose(); 34 | ca.dispose(); 35 | ALL.remove(this); 36 | COUNT--; 37 | if( !hasAny() ) 38 | Game.ME.resume(); 39 | } 40 | 41 | function closeAllModals() { 42 | for(e in ALL) 43 | if( !e.destroyed ) 44 | e.close(); 45 | } 46 | 47 | override function onResize() { 48 | super.onResize(); 49 | if( mask!=null ) { 50 | var w = M.ceil( w()/Const.UI_SCALE ); 51 | var h = M.ceil( h()/Const.UI_SCALE ); 52 | mask.scaleX = w; 53 | mask.scaleY = h; 54 | } 55 | } 56 | 57 | override function postUpdate() { 58 | super.postUpdate(); 59 | mask.visible = modalIdx==0; 60 | win.alpha = modalIdx==COUNT-1 ? 1 : 0.6; 61 | } 62 | 63 | override function update() { 64 | super.update(); 65 | if( ca.bPressed() || ca.isKeyboardPressed(hxd.Key.ESCAPE) ) 66 | close(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/ui/Window.hx: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | class Window extends dn.Process { 4 | public var win: h2d.Flow; 5 | 6 | public function new() { 7 | super(Main.ME); 8 | 9 | createRootInLayers(Boot.ME.s2d, Const.DP_UI); 10 | root.scale(Const.UI_SCALE); 11 | 12 | win = new h2d.Flow(root); 13 | win.backgroundTile = h2d.Tile.fromColor(0xffffff, 32,32); 14 | win.borderWidth = 7; 15 | win.borderHeight = 7; 16 | win.layout = Vertical; 17 | win.verticalSpacing = 2; 18 | 19 | dn.Process.resizeAll(); 20 | } 21 | 22 | public function clearWindow() { 23 | win.removeChildren(); 24 | } 25 | 26 | public inline function add(e:h2d.Flow) { 27 | win.addChild(e); 28 | onResize(); 29 | } 30 | 31 | override function onResize() { 32 | super.onResize(); 33 | var w = M.ceil( w()/Const.UI_SCALE ); 34 | var h = M.ceil( h()/Const.UI_SCALE ); 35 | win.x = Std.int( w*0.5 - win.outerWidth*0.5 ); 36 | win.y = Std.int( h*0.5 - win.outerHeight*0.5 ); 37 | } 38 | 39 | function onClose() {} 40 | public function close() { 41 | if( !destroyed ) { 42 | destroy(); 43 | onClose(); 44 | } 45 | } 46 | } 47 | --------------------------------------------------------------------------------