├── .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 | Fullscreen
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 |
--------------------------------------------------------------------------------