├── .gitignore ├── .vscode ├── commandbar.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── art ├── fontStyle.psd ├── logo.png ├── logo.psd ├── tiles.psd └── tiles.tps ├── base.hxml ├── hl.debug.hxml ├── hl.dx.hxml ├── hl.hxml ├── hl.sdl.hxml ├── js.debug.hxml ├── js.html ├── js.hxml ├── langParser.hxml ├── led ├── editor │ ├── app.html │ ├── css │ │ ├── app.css │ │ ├── app.min.css │ │ └── app.scss │ ├── fonts │ │ ├── LICENSE.txt │ │ ├── RobotoCondensed-Bold.ttf │ │ ├── RobotoCondensed-BoldItalic.ttf │ │ ├── RobotoCondensed-Italic.ttf │ │ ├── RobotoCondensed-Light.ttf │ │ ├── RobotoCondensed-LightItalic.ttf │ │ └── RobotoCondensed-Regular.ttf │ ├── img │ │ ├── grid.png │ │ ├── icons │ │ │ ├── drag.png │ │ │ ├── entity.png │ │ │ ├── intGrid.png │ │ │ ├── layer.png │ │ │ ├── level.png │ │ │ ├── list.png │ │ │ ├── mouseLeft.png │ │ │ ├── mouseMiddle.png │ │ │ ├── mouseRight.png │ │ │ ├── mouseWheel.png │ │ │ ├── projectSettings.png │ │ │ └── tile.png │ │ ├── key.png │ │ └── stripes.png │ ├── js │ │ ├── app.js │ │ ├── app.js.map │ │ ├── html5sortable.min.js │ │ └── jquery-3.5.1.js │ ├── package.json │ ├── tpl │ │ ├── editEntityDefs.html │ │ ├── editLayerDefs.html │ │ ├── editTilesetDefs.html │ │ ├── help.html │ │ ├── levelList.html │ │ └── projectSettings.html │ └── userFiles │ │ ├── atlas │ │ ├── SystemShock.png │ │ ├── cavesofgallet_tiles.png │ │ ├── gif87a.gif │ │ └── s4m_ur4i_huge-assetpack-tilemap.png │ │ ├── gridLab.json │ │ ├── map1.json │ │ ├── map2.json │ │ ├── map3.json │ │ ├── map4.json │ │ ├── resize.json │ │ ├── test.json │ │ ├── testImages │ │ ├── gif87a.gif │ │ ├── gif89.8colors.gif │ │ ├── gif89a.gif │ │ ├── jpeg.35colors.jpg │ │ ├── jpeg.bw.jpg │ │ ├── jpeg.color.jpg │ │ ├── jpeg.fullcolor.jpg │ │ ├── jpeg.gray.jpg │ │ ├── jpeg2.color.jpg │ │ └── png.png │ │ └── undo.json ├── runEditor.nwjs.cmd └── src.api │ └── led │ ├── Definitions.hx │ ├── JsonTools.hx │ ├── LedTypes.hx │ ├── Level.hx │ ├── Project.hx │ ├── def │ ├── EntityDef.hx │ ├── EnumDef.hx │ ├── FieldDef.hx │ ├── LayerDef.hx │ └── TilesetDef.hx │ └── inst │ ├── EntityInstance.hx │ ├── FieldInstance.hx │ └── LayerInstance.hx ├── redist ├── directx.zip ├── directx │ └── DumberDwarves │ │ ├── DumberDwarves.exe │ │ ├── OpenAL32.dll │ │ ├── d3dcompiler_47.dll │ │ ├── directx.hdll │ │ ├── fmt.hdll │ │ ├── hlboot.dat │ │ ├── libhl.dll │ │ ├── msvcr120.dll │ │ ├── openal.hdll │ │ ├── ssl.hdll │ │ ├── ui.hdll │ │ └── uv.hdll ├── js.zip ├── js │ ├── client.js │ └── index.html ├── sdl_mac.zip ├── sdl_mac │ └── DumberDwarves │ │ ├── DumberDwarves │ │ ├── hlboot.dat │ │ ├── libSDL2-2.0.0.dylib │ │ ├── libhl.dylib │ │ ├── libmbedtls.10.dylib │ │ ├── libopenal.1.dylib │ │ ├── libpng16.16.dylib │ │ ├── libuv.1.dylib │ │ ├── libvorbis.0.dylib │ │ └── libvorbisfile.3.dylib ├── sdl_win.zip └── sdl_win │ └── DumberDwarves │ ├── DumberDwarves.exe │ ├── OpenAL32.dll │ ├── SDL2.dll │ ├── fmt.hdll │ ├── hlboot.dat │ ├── libhl.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 ├── ld │ ├── tileset.png │ └── world.json └── props.json ├── screenshots ├── dumberDwarves-cover.png ├── god0.png ├── s0.png ├── s1.png ├── s2.png ├── s3.png ├── s4.gif ├── s5.avi ├── s6.avi ├── s7.avi ├── s8.mp4 └── s9.png ├── src.langParser └── LangParser.hx ├── src ├── Assets.hx ├── Boot.hx ├── Camera.hx ├── Const.hx ├── Entity.hx ├── Fx.hx ├── Game.hx ├── Lang.hx ├── Level.hx ├── Main.hx ├── Types.hx ├── en │ ├── Ai.hx │ ├── BossDoor.hx │ ├── Breakable.hx │ ├── Cart.hx │ ├── Item.hx │ ├── Label.hx │ ├── MobGen.hx │ ├── Pointer.hx │ └── ai │ │ ├── Dwarf.hx │ │ ├── Mob.hx │ │ └── mob │ │ ├── Boss.hx │ │ └── Goblin.hx ├── import.hx ├── tools │ ├── CPoint.hx │ └── MouseCoords.hx └── ui │ ├── Bar.hx │ ├── Console.hx │ ├── Hud.hx │ ├── Modal.hx │ └── Window.hx └── swf.hxml /.gitignore: -------------------------------------------------------------------------------- 1 | res/.tmp 2 | redist.* 3 | bin/*.* 4 | art/export_* -------------------------------------------------------------------------------- /.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", 51 | "color": "lightgreen", 52 | "command": "haxelib run redistHelper hl.dx.hxml hl.sdl.hxml js.hxml -p DumberDwarves -zip", 53 | "alignment": "right", 54 | "skipTerminateQuickPick": false, 55 | "priority": -50 56 | } 57 | ] 58 | } -------------------------------------------------------------------------------- /.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 | "name": "Chrome JS debug", 17 | "request": "launch", 18 | "type": "chrome", 19 | "file": "${workspaceFolder}/js.html", 20 | "preLaunchTask": "JS debug" 21 | }, 22 | { 23 | "name": "Firefox JS debug", 24 | "request": "launch", 25 | "type": "firefox", 26 | "file": "${workspaceFolder}/js.html", 27 | "preLaunchTask": "JS debug" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "titleBar.inactiveBackground": "#494949", 4 | "titleBar.activeBackground": "#6d6d6d", 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-absolute", "$haxe", "$haxe-error", "$haxe-trace" ], 16 | "group": { 17 | "kind": "build", 18 | "isDefault": true 19 | } 20 | }, 21 | 22 | { 23 | "label": "HL release", 24 | "type": "hxml", 25 | "file": "hl.dx.hxml", 26 | "presentation": { 27 | "reveal": "never", 28 | "panel": "dedicated", 29 | "clear": true 30 | }, 31 | "problemMatcher": [ "$haxe-absolute", "$haxe", "$haxe-error", "$haxe-trace" ], 32 | }, 33 | 34 | { 35 | "label": "JS release", 36 | "type": "hxml", 37 | "file": "js.hxml", 38 | "presentation": { 39 | "reveal": "never", 40 | "panel": "dedicated", 41 | "clear": true 42 | }, 43 | "problemMatcher": [ "$haxe-absolute", "$haxe", "$haxe-error", "$haxe-trace" ], 44 | }, 45 | 46 | { 47 | "label": "Flash release", 48 | "type": "hxml", 49 | "file": "swf.hxml", 50 | "presentation": { 51 | "reveal": "never", 52 | "panel": "dedicated", 53 | "clear": true 54 | }, 55 | "problemMatcher": [ "$haxe-absolute", "$haxe", "$haxe-error", "$haxe-trace" ], 56 | }, 57 | 58 | { 59 | "label": "Lang", 60 | "type": "hxml", 61 | "file": "langParser.hxml", 62 | "presentation": { 63 | "reveal": "always", 64 | "panel": "shared", 65 | "clear": true 66 | }, 67 | "problemMatcher": [ "$haxe-absolute", "$haxe", "$haxe-error", "$haxe-trace" ], 68 | }, 69 | 70 | { 71 | "label": "JS debug", 72 | "type": "hxml", 73 | "file": "js.debug.hxml", 74 | "presentation": { 75 | "reveal": "never", 76 | "panel": "dedicated", 77 | "clear": true 78 | }, 79 | "problemMatcher": ["$haxe"], 80 | } 81 | ] 82 | } 83 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-NonCommercial-ShareAlike 4.0 International 2 | (BY-NC-SA 4.0) 3 | 4 | You are free to: 5 | 6 | Share — copy and redistribute the material in any medium or format 7 | Adapt — remix, transform, and build upon the material 8 | 9 | The licensor cannot revoke these freedoms as long as you follow the license terms. 10 | 11 | 12 | Under the following terms: 13 | 14 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 15 | 16 | NonCommercial — You may not use the material for commercial purposes. 17 | 18 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 19 | 20 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 21 | 22 | 23 | Notices: 24 | 25 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 26 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 27 | 28 | Full license here: 29 | https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | Dumber Dwarves is a dungeon crawler where you can’t control the adventurers directly and they are not the sharpest tool in the shed. Slap them or throw some meat on the battlefield to give your “instructions”. 4 | 5 | The game was created in 48h (well, more like 35h) for the GMTK 2020 game jam. The theme was “Out of Control“. 6 | 7 | Play it here: https://deepnight.net/games/dumber-dwarves/ 8 | 9 | ## Compiling 10 | 11 | You'll need: 12 | 13 | * **Haxe** compiler 14 | * **HeapsIO** framework 15 | * my libs: run ``haxelib install deepnightLibs`` 16 | 17 | It is based on my GameBase repository: 18 | 19 | * GitHub: https://github.com/deepnight/gameBase 20 | * Doc: https://deepnight.net/tutorial/using-my-gamebase-to-create-a-heaps-game/ 21 | 22 | -------------------------------------------------------------------------------- /art/fontStyle.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/art/fontStyle.psd -------------------------------------------------------------------------------- /art/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/art/logo.png -------------------------------------------------------------------------------- /art/logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/art/logo.psd -------------------------------------------------------------------------------- /art/tiles.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/art/tiles.psd -------------------------------------------------------------------------------- /base.hxml: -------------------------------------------------------------------------------- 1 | -cp led/src.api 2 | -cp src 3 | -lib heaps 4 | -lib deepnightLibs 5 | -main Boot 6 | -dce full -------------------------------------------------------------------------------- /hl.debug.hxml: -------------------------------------------------------------------------------- 1 | hl.dx.hxml 2 | -debug -------------------------------------------------------------------------------- /hl.dx.hxml: -------------------------------------------------------------------------------- 1 | hl.hxml 2 | -lib hldx -------------------------------------------------------------------------------- /hl.hxml: -------------------------------------------------------------------------------- 1 | base.hxml 2 | -D windowSize=2000x1400 3 | -hl bin/client.hl 4 | -------------------------------------------------------------------------------- /hl.sdl.hxml: -------------------------------------------------------------------------------- 1 | hl.hxml 2 | -lib hlsdl -------------------------------------------------------------------------------- /js.debug.hxml: -------------------------------------------------------------------------------- 1 | js.hxml 2 | -debug -------------------------------------------------------------------------------- /js.html: -------------------------------------------------------------------------------- 1 | 2 | base2D 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /led/editor/app.html: -------------------------------------------------------------------------------- 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 |
some useful tips
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 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /led/editor/fonts/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /led/editor/fonts/RobotoCondensed-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/fonts/RobotoCondensed-Bold.ttf -------------------------------------------------------------------------------- /led/editor/fonts/RobotoCondensed-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/fonts/RobotoCondensed-BoldItalic.ttf -------------------------------------------------------------------------------- /led/editor/fonts/RobotoCondensed-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/fonts/RobotoCondensed-Italic.ttf -------------------------------------------------------------------------------- /led/editor/fonts/RobotoCondensed-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/fonts/RobotoCondensed-Light.ttf -------------------------------------------------------------------------------- /led/editor/fonts/RobotoCondensed-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/fonts/RobotoCondensed-LightItalic.ttf -------------------------------------------------------------------------------- /led/editor/fonts/RobotoCondensed-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/fonts/RobotoCondensed-Regular.ttf -------------------------------------------------------------------------------- /led/editor/img/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/grid.png -------------------------------------------------------------------------------- /led/editor/img/icons/drag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/drag.png -------------------------------------------------------------------------------- /led/editor/img/icons/entity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/entity.png -------------------------------------------------------------------------------- /led/editor/img/icons/intGrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/intGrid.png -------------------------------------------------------------------------------- /led/editor/img/icons/layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/layer.png -------------------------------------------------------------------------------- /led/editor/img/icons/level.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/level.png -------------------------------------------------------------------------------- /led/editor/img/icons/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/list.png -------------------------------------------------------------------------------- /led/editor/img/icons/mouseLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/mouseLeft.png -------------------------------------------------------------------------------- /led/editor/img/icons/mouseMiddle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/mouseMiddle.png -------------------------------------------------------------------------------- /led/editor/img/icons/mouseRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/mouseRight.png -------------------------------------------------------------------------------- /led/editor/img/icons/mouseWheel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/mouseWheel.png -------------------------------------------------------------------------------- /led/editor/img/icons/projectSettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/projectSettings.png -------------------------------------------------------------------------------- /led/editor/img/icons/tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/icons/tile.png -------------------------------------------------------------------------------- /led/editor/img/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/key.png -------------------------------------------------------------------------------- /led/editor/img/stripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/img/stripes.png -------------------------------------------------------------------------------- /led/editor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "led", 3 | "version": "0.0.1", 4 | "description": "L-Ed, a lightweight & efficient 2D level editor", 5 | 6 | "window" : { 7 | "title" : "LEd", 8 | "width" : 800, 9 | "height" : 600, 10 | "show" : true 11 | }, 12 | "main" : "app.html", 13 | "chromium-args":"--enable-spell-checking", 14 | "js-flags": "--expose-gc", 15 | 16 | "build": { 17 | "nwVersion": "0.46.4" 18 | } 19 | } -------------------------------------------------------------------------------- /led/editor/tpl/editEntityDefs.html: -------------------------------------------------------------------------------- 1 |
2 |

3 |
4 | Project entities 5 |

6 |
7 | ENTITIES are generic data that can be placed in your levels, such as the Player start position or Items to pick up. Each entity can have various custom editable properties as defined below. 8 |
9 |
You need to create at least one ENTITY LAYER in order to insert entities in your levels.
10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 | 20 |
21 |
22 |
23 |
24 | 25 | 62 | 63 |
64 | 65 |
66 | 67 |
68 | 69 | 70 |
71 |
72 | 73 |
74 | 118 |
-------------------------------------------------------------------------------- /led/editor/tpl/editLayerDefs.html: -------------------------------------------------------------------------------- 1 |
2 |

3 |
4 | Project layers 5 |

6 |
7 | Each LEVEL in your project has LAYERS, as defined below. The layers content can be of various types, including Image Tiles or Integer values. 8 |
9 |
10 | 11 |
12 | 13 |
14 | 15 | 16 |
17 |
18 | 19 | 20 | 72 | -------------------------------------------------------------------------------- /led/editor/tpl/editTilesetDefs.html: -------------------------------------------------------------------------------- 1 |
2 |

3 |
4 | Project tilesets 5 |

6 |
7 | Tilesets are large images in which you pick sub-parts to draw them in your levels. 8 |
9 |
You need to create at least one TILE LAYER in order to draw tiles in a level.
10 |
11 | 12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 | 20 | 53 | -------------------------------------------------------------------------------- /led/editor/tpl/help.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Draw
4 | 5 |
6 |
Erase
7 | 8 |
SPACE +
9 |
Move the current level view
10 | 11 |
12 |
Zoom
13 |
14 | 15 |
16 |
H
17 |
Show this help
18 | 19 |
TAB
20 |
Toggle compact mode
21 | 22 |
CTRL S
23 |
Save
24 |
25 | -------------------------------------------------------------------------------- /led/editor/tpl/levelList.html: -------------------------------------------------------------------------------- 1 |
2 |

3 |
4 | Project levels 5 |

6 |
7 | 8 |
9 | 10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 | 23 | 24 | -------------------------------------------------------------------------------- /led/editor/tpl/projectSettings.html: -------------------------------------------------------------------------------- 1 |

2 |
3 | Project settings 4 |

5 | 6 |
7 | 8 | 9 | 10 |
11 | 12 | 34 | 35 |
36 | Enumerations (Enums) are special value types of Entities. 37 |
38 | 39 |
40 | 41 |
42 | 43 | 44 |
45 |
46 | 47 | -------------------------------------------------------------------------------- /led/editor/userFiles/atlas/SystemShock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/atlas/SystemShock.png -------------------------------------------------------------------------------- /led/editor/userFiles/atlas/cavesofgallet_tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/atlas/cavesofgallet_tiles.png -------------------------------------------------------------------------------- /led/editor/userFiles/atlas/gif87a.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/atlas/gif87a.gif -------------------------------------------------------------------------------- /led/editor/userFiles/atlas/s4m_ur4i_huge-assetpack-tilemap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/atlas/s4m_ur4i_huge-assetpack-tilemap.png -------------------------------------------------------------------------------- /led/editor/userFiles/map2.json: -------------------------------------------------------------------------------- 1 | { 2 | "dataVersion":1, 3 | "nextUniqId":2, 4 | "defs":{ 5 | "layers":[ 6 | { 7 | "uid":1, 8 | "type":{ 9 | "id":0, 10 | "p":[ 11 | 12 | ] 13 | }, 14 | "name":"test", 15 | "gridSize":16, 16 | "displaydisplayOpacity":1, 17 | "intGridValues":[ 18 | { 19 | "color":8234606 20 | } 21 | ] 22 | } 23 | ], 24 | "entities":[ 25 | 26 | ], 27 | "tilesets":[ 28 | 29 | ] 30 | }, 31 | "levels":[ 32 | { 33 | "uid":0, 34 | "pxWid":512, 35 | "pxHei":256, 36 | "layerInstances":[ 37 | { 38 | "levelId":0, 39 | "layerDefId":1, 40 | "intGrid":[ 41 | { 42 | "coordId":144, 43 | "v":0 44 | }, 45 | { 46 | "coordId":145, 47 | "v":0 48 | }, 49 | { 50 | "coordId":146, 51 | "v":0 52 | }, 53 | { 54 | "coordId":147, 55 | "v":0 56 | }, 57 | { 58 | "coordId":148, 59 | "v":0 60 | }, 61 | { 62 | "coordId":149, 63 | "v":0 64 | }, 65 | { 66 | "coordId":182, 67 | "v":0 68 | }, 69 | { 70 | "coordId":183, 71 | "v":0 72 | }, 73 | { 74 | "coordId":184, 75 | "v":0 76 | }, 77 | { 78 | "coordId":217, 79 | "v":0 80 | }, 81 | { 82 | "coordId":248, 83 | "v":0 84 | }, 85 | { 86 | "coordId":279, 87 | "v":0 88 | }, 89 | { 90 | "coordId":294, 91 | "v":0 92 | }, 93 | { 94 | "coordId":295, 95 | "v":0 96 | }, 97 | { 98 | "coordId":296, 99 | "v":0 100 | }, 101 | { 102 | "coordId":297, 103 | "v":0 104 | }, 105 | { 106 | "coordId":311, 107 | "v":0 108 | }, 109 | { 110 | "coordId":325, 111 | "v":0 112 | }, 113 | { 114 | "coordId":356, 115 | "v":0 116 | }, 117 | { 118 | "coordId":388, 119 | "v":0 120 | }, 121 | { 122 | "coordId":421, 123 | "v":0 124 | }, 125 | { 126 | "coordId":430, 127 | "v":0 128 | }, 129 | { 130 | "coordId":454, 131 | "v":0 132 | }, 133 | { 134 | "coordId":455, 135 | "v":0 136 | }, 137 | { 138 | "coordId":461, 139 | "v":0 140 | }, 141 | { 142 | "coordId":462, 143 | "v":0 144 | }, 145 | { 146 | "coordId":488, 147 | "v":0 148 | }, 149 | { 150 | "coordId":489, 151 | "v":0 152 | }, 153 | { 154 | "coordId":490, 155 | "v":0 156 | }, 157 | { 158 | "coordId":491, 159 | "v":0 160 | }, 161 | { 162 | "coordId":492, 163 | "v":0 164 | } 165 | ], 166 | "gridTiles":[ 167 | 168 | ], 169 | "entityInstances":[ 170 | 171 | ] 172 | } 173 | ] 174 | } 175 | ], 176 | "name":"New project", 177 | "defaultPivotX":0, 178 | "defaultPivotY":0, 179 | "defaultGridSize":16, 180 | "bgColor":16777215 181 | } -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/gif87a.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/gif87a.gif -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/gif89.8colors.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/gif89.8colors.gif -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/gif89a.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/gif89a.gif -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/jpeg.35colors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/jpeg.35colors.jpg -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/jpeg.bw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/jpeg.bw.jpg -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/jpeg.color.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/jpeg.color.jpg -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/jpeg.fullcolor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/jpeg.fullcolor.jpg -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/jpeg.gray.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/jpeg.gray.jpg -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/jpeg2.color.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/jpeg2.color.jpg -------------------------------------------------------------------------------- /led/editor/userFiles/testImages/png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/led/editor/userFiles/testImages/png.png -------------------------------------------------------------------------------- /led/runEditor.nwjs.cmd: -------------------------------------------------------------------------------- 1 | @start nw editor/ -------------------------------------------------------------------------------- /led/src.api/led/Definitions.hx: -------------------------------------------------------------------------------- 1 | package led; 2 | 3 | import led.LedTypes; 4 | 5 | class Definitions { 6 | var _project : Project; 7 | 8 | public var layers: Array = []; 9 | public var entities: Array = []; 10 | public var tilesets: Array = []; 11 | public var enums: Array = []; 12 | 13 | 14 | public function new(project:Project) { 15 | this._project = project; 16 | } 17 | 18 | public function toJson() : Dynamic { 19 | return { 20 | layers: layers.map( function(ld) return ld.toJson() ), 21 | entities: entities.map( function(ed) return ed.toJson() ), 22 | tilesets: tilesets.map( function(td) return td.toJson() ), 23 | enums: enums.map( function(ed) return ed.toJson() ), 24 | } 25 | } 26 | 27 | public static function fromJson(p:Project, json:Dynamic) { 28 | var d = new Definitions(p); 29 | 30 | for( layerJson in JsonTools.readArray(json.layers) ) 31 | d.layers.push( led.def.LayerDef.fromJson(p.dataVersion, layerJson) ); 32 | 33 | for( entityJson in JsonTools.readArray(json.entities) ) 34 | d.entities.push( led.def.EntityDef.fromJson(p.dataVersion, entityJson) ); 35 | 36 | for( tilesetJson in JsonTools.readArray(json.tilesets) ) 37 | d.tilesets.push( led.def.TilesetDef.fromJson(p.dataVersion, tilesetJson) ); 38 | 39 | for( enumJson in JsonTools.readArray(json.enums) ) 40 | d.enums.push( led.def.EnumDef.fromJson(p.dataVersion, enumJson) ); 41 | 42 | return d; 43 | } 44 | 45 | public function tidy(p:Project) { 46 | _project = p; 47 | } 48 | 49 | /** LAYER DEFS *****************************************/ 50 | 51 | public function hasLayerType(t:LayerType) { 52 | for(ld in layers) 53 | if( ld.type==t ) 54 | return true; 55 | return false; 56 | } 57 | 58 | public function getLayerDef(uid:Int) : Null { 59 | for(ld in layers) 60 | if( ld.uid==uid ) 61 | return ld; 62 | return null; 63 | } 64 | 65 | public function createLayerDef(type:LayerType, ?name:String) : led.def.LayerDef { 66 | var l = new led.def.LayerDef(_project.makeUniqId(), type); 67 | 68 | #if editor 69 | if( name==null && isLayerNameValid( Lang.getLayerType(type).toString() ) ) // dirty fix for string comparison issue 70 | l.name = Lang.getLayerType(type); 71 | else if( name!=null && isLayerNameValid(name) ) 72 | l.name = name; 73 | #end 74 | 75 | l.gridSize = _project.defaultGridSize; 76 | layers.push(l); 77 | _project.tidy(); 78 | return l; 79 | } 80 | 81 | public function isLayerNameValid(name:String) { 82 | if( name==null || StringTools.trim(name).length==0 ) 83 | return false; 84 | 85 | for(ld in layers) 86 | if( ld.name==name ) 87 | return false; 88 | return true; 89 | } 90 | 91 | public function removeLayerDef(ld:led.def.LayerDef) { 92 | if( !layers.remove(ld) ) 93 | throw "Unknown layerDef"; 94 | 95 | _project.tidy(); 96 | } 97 | 98 | public function sortLayerDef(from:Int, to:Int) : Null { 99 | if( from<0 || from>=layers.length || from==to ) 100 | return null; 101 | 102 | if( to<0 || to>=layers.length ) 103 | return null; 104 | 105 | _project.tidy(); 106 | 107 | var moved = layers.splice(from,1)[0]; 108 | layers.insert(to, moved); 109 | return moved; 110 | } 111 | 112 | 113 | 114 | /** ENTITY DEFS *****************************************/ 115 | 116 | public function getEntityDef(uid:Int) : Null { 117 | for(ed in entities) 118 | if( ed.uid==uid ) 119 | return ed; 120 | return null; 121 | } 122 | 123 | public function createEntityDef(?name:String) : led.def.EntityDef { 124 | var ed = new led.def.EntityDef(_project.makeUniqId()); 125 | entities.push(ed); 126 | 127 | ed.setPivot( _project.defaultPivotX, _project.defaultPivotY ); 128 | 129 | if( isEntityNameValid(name) ) 130 | ed.name = name; 131 | 132 | return ed; 133 | } 134 | 135 | public function removeEntityDef(ed:led.def.EntityDef) { 136 | entities.remove(ed); 137 | _project.tidy(); 138 | } 139 | 140 | public function isEntityNameValid(name:String) { 141 | if( name==null || name.length==0 ) 142 | return false; 143 | 144 | for(ed in entities) 145 | if( ed.name==name ) 146 | return false; 147 | return true; 148 | } 149 | 150 | public function sortEntityDef(from:Int, to:Int) : Null { 151 | if( from<0 || from>=entities.length || from==to ) 152 | return null; 153 | 154 | if( to<0 || to>=entities.length ) 155 | return null; 156 | 157 | _project.tidy(); 158 | 159 | var moved = entities.splice(from,1)[0]; 160 | entities.insert(to, moved); 161 | 162 | return moved; 163 | } 164 | 165 | 166 | 167 | /** FIELD DEFS *****************************************/ 168 | 169 | public function getFieldDef(id:Int) : Null { 170 | for(ed in entities) 171 | for(fd in ed.fieldDefs) 172 | if( fd.uid==id ) 173 | return fd; 174 | 175 | return null; 176 | } 177 | 178 | 179 | /** TILESET DEFS *****************************************/ 180 | 181 | public function createTilesetDef() : led.def.TilesetDef { 182 | var td = new led.def.TilesetDef(_project.makeUniqId() ); 183 | tilesets.push(td); 184 | _project.tidy(); 185 | return td; 186 | } 187 | 188 | public function getTilesetDef(uid:Int) : Null { 189 | for(td in tilesets) 190 | if( td.uid==uid ) 191 | return td; 192 | return null; 193 | } 194 | 195 | 196 | /** ENUM DEFS *****************************************/ 197 | 198 | public function createEnumDef() : led.def.EnumDef { 199 | var uid = _project.makeUniqId(); 200 | var ed = new led.def.EnumDef(uid, "LedEnum"+uid); 201 | enums.push(ed); 202 | _project.tidy(); 203 | return ed; 204 | } 205 | 206 | public function removeEnumDef(ed:led.def.EnumDef) { 207 | if( !enums.remove(ed) ) 208 | throw "EnumDef not found"; 209 | _project.tidy(); 210 | } 211 | 212 | function isEnumNameValid(name:String) { 213 | name = led.def.EnumDef.cleanUpString(name); 214 | for(ed in enums) 215 | if( ed.name==name ) 216 | return false; 217 | return true; 218 | } 219 | 220 | public function getEnumDef(uid:Int) : Null { 221 | for(ed in enums) 222 | if( ed.uid==uid ) 223 | return ed; 224 | return null; 225 | } 226 | 227 | } -------------------------------------------------------------------------------- /led/src.api/led/JsonTools.hx: -------------------------------------------------------------------------------- 1 | package led; 2 | 3 | class JsonTools { 4 | 5 | public static function writeEnum(e:EnumValue, canBeNull:Bool) { 6 | if( e==null ) 7 | if( canBeNull ) 8 | return null; 9 | else 10 | throw "Enum is null"; 11 | 12 | return { id:e.getIndex(), p:e.getParameters() } 13 | } 14 | 15 | public static function readEnum(e:Enum, o:{ id:Int, p:Array}, allowNull:Bool, ?def:T) : T { 16 | if( o==null ) { 17 | if( def==null && !allowNull ) 18 | throw "Couldn't create "+e+", object is null"; 19 | else 20 | return def; 21 | } 22 | 23 | try { 24 | return cast Type.createEnumIndex(e, o.id, o.p); 25 | } 26 | catch( err:Dynamic ) { 27 | if( def!=null ) 28 | return def; 29 | 30 | if( !Reflect.hasField(o,"id") || Math.isNaN(o.id) ) 31 | throw "Missing enum ID in "+o; 32 | else 33 | throw "Couldn't create "+e+" from "+o; 34 | } 35 | } 36 | 37 | public static function readString(v:Dynamic, allowNull=false) : Null { 38 | if( v==null && !allowNull ) 39 | throw "Couldn't read String "+v; 40 | 41 | return v==null ? null : Std.string(v); 42 | } 43 | 44 | public static function readInt(v:Dynamic, ?defaultIfMissing:Int) : Int { 45 | if( v==null && defaultIfMissing!=null ) 46 | return defaultIfMissing; 47 | 48 | if( v==null || Type.typeof(v)!=TInt ) 49 | throw "Couldn't read Int "+v; 50 | 51 | return Std.int(v); 52 | } 53 | 54 | public static function readNullableInt(v:Dynamic) : Null { 55 | if( v==null ) 56 | return null; 57 | 58 | if( Type.typeof(v)!=TInt ) 59 | throw "Couldn't read Nullable Int "+v; 60 | 61 | return Std.int(v); 62 | } 63 | 64 | public static function readFloat(v:Dynamic, ?defaultIfMissing:Float) : Float { 65 | if( v==null && defaultIfMissing!=null ) 66 | return defaultIfMissing; 67 | 68 | if( v==null || Type.typeof(v)!=TInt && Type.typeof(v)!=TFloat ) 69 | throw "Couldn't read Float "+v; 70 | 71 | return v*1.0; 72 | } 73 | 74 | public static function readNullableFloat(v:Dynamic) : Null { 75 | if( v==null ) 76 | return null; 77 | 78 | if( Type.typeof(v)!=TInt && Type.typeof(v)!=TFloat ) 79 | throw "Couldn't read Float "+v; 80 | 81 | return v*1.0; 82 | } 83 | 84 | public static function clampFloatPrecision(v:Float, precision=3) { 85 | var p = Math.pow(10, precision); 86 | return dn.M.round(v*p)/p; 87 | } 88 | 89 | public static function readBool(v:Dynamic, ?defaultIfMissing:Bool) : Bool { 90 | if( v==null && defaultIfMissing!=null ) 91 | return defaultIfMissing; 92 | 93 | if( v==null || Type.typeof(v)!=TBool ) 94 | throw "Couldn't read Bool "+v; 95 | 96 | return v==true; 97 | } 98 | 99 | public static function readArray(arr:Dynamic) : Array { 100 | switch Type.typeof(arr) { 101 | case TClass(Array): 102 | case _: throw "Not an array ("+Type.typeof(arr)+")"; 103 | } 104 | return arr; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /led/src.api/led/LedTypes.hx: -------------------------------------------------------------------------------- 1 | package led; 2 | 3 | /* 4 | WARNING: all the follow types are serialized when saving a Project: 5 | - do not remove Enum values, 6 | - always add new Enum values at the end of the Enum, 7 | - Enum values can be renamed (they are stored as enum indexes) 8 | - do not rename Typedef fields or change their type 9 | */ 10 | 11 | enum LayerType { 12 | IntGrid; 13 | Entities; 14 | Tiles; 15 | } 16 | 17 | 18 | typedef IntGridValueDef = { 19 | var name : Null; 20 | var color : UInt; 21 | } 22 | 23 | enum FieldType { 24 | F_Int; 25 | F_Float; 26 | F_String; 27 | F_Bool; 28 | F_Color; 29 | } 30 | 31 | enum ValueWrapper { 32 | V_Int(v:Int); 33 | V_Float(v:Float); 34 | V_Bool(v:Bool); 35 | V_String(v:String); 36 | } 37 | 38 | enum FieldDisplayMode { 39 | Hidden; 40 | ValueOnly; 41 | NameAndValue; 42 | } 43 | 44 | enum FieldDisplayPosition { 45 | Above; 46 | Beneath; 47 | } 48 | 49 | typedef TilesetSelection = { 50 | var ids : Array; 51 | var mode : TileEditMode; 52 | } 53 | 54 | enum TileEditMode { 55 | Stamp; 56 | Random; 57 | } -------------------------------------------------------------------------------- /led/src.api/led/Level.hx: -------------------------------------------------------------------------------- 1 | package led; 2 | 3 | class Level { 4 | var _project : Project; 5 | 6 | public var uid(default,null) : Int; 7 | public var customName: Null; // TODO save 8 | public var pxWid : Int; 9 | public var pxHei : Int; 10 | public var layerInstances : Map = new Map(); 11 | 12 | 13 | @:allow(led.Project) 14 | private function new(project:Project, uid:Int) { 15 | this.uid = uid; 16 | pxWid = Project.DEFAULT_LEVEL_WIDTH; 17 | pxHei = Project.DEFAULT_LEVEL_HEIGHT; 18 | this._project = project; 19 | 20 | for(ld in _project.defs.layers) 21 | layerInstances.set( ld.uid, new led.inst.LayerInstance(_project, uid, ld.uid) ); 22 | } 23 | 24 | public inline function getName() return customName!=null ? customName : getDefaultName(); 25 | 26 | public function getDefaultName() return "Level#"+uid; 27 | 28 | @:keep public function toString() { 29 | return Type.getClassName(Type.getClass(this)); 30 | } 31 | 32 | public function toJson() { 33 | var layersJson = []; 34 | for(li in layerInstances) 35 | layersJson.push( li.toJson() ); 36 | 37 | return { 38 | uid: uid, 39 | pxWid: pxWid, 40 | pxHei: pxHei, 41 | layerInstances : layersJson, 42 | customName: customName, 43 | } 44 | } 45 | 46 | public static function fromJson(p:Project, json:Dynamic) { 47 | var l = new Level( p, JsonTools.readInt(json.uid) ); 48 | l.pxWid = JsonTools.readInt( json.pxWid, Project.DEFAULT_LEVEL_WIDTH ); 49 | l.pxHei = JsonTools.readInt( json.pxHei, Project.DEFAULT_LEVEL_HEIGHT ); 50 | l.customName = json.customName; 51 | 52 | for( layerJson in JsonTools.readArray(json.layerInstances) ) { 53 | var li = led.inst.LayerInstance.fromJson(p, layerJson); 54 | l.layerInstances.set(li.layerDefId, li); 55 | } 56 | 57 | return l; 58 | } 59 | 60 | public inline function inBounds(x:Int, y:Int) { 61 | return x>=0 && x=0 && yVoid ) { 111 | var i = _project.defs.layers.length-1; 112 | while( i>=0 ) { 113 | eachLayer( getLayerInstance(_project.defs.layers[i]) ); 114 | i--; 115 | } 116 | } 117 | 118 | #if heaps 119 | 120 | public function renderAllLayers(target:h2d.Object) { 121 | iterateLayerInstancesInRenderOrder( function(li) { 122 | li.render(target); 123 | }); 124 | } 125 | 126 | #else 127 | 128 | @:deprecated("Not implemented on this platform") 129 | public function renderAllLayers(target:Dynamic) {} 130 | 131 | #end 132 | } 133 | -------------------------------------------------------------------------------- /led/src.api/led/Project.hx: -------------------------------------------------------------------------------- 1 | package led; 2 | 3 | class Project { 4 | public static var DEFAULT_LEVEL_WIDTH = 256; // px 5 | public static var DEFAULT_LEVEL_HEIGHT = 256; // px 6 | public static var DEFAULT_GRID_SIZE = 16; // px 7 | 8 | public static var DATA_VERSION = 1; 9 | /* DATA VERSION CHANGELOG: 10 | 1. initial release 11 | */ 12 | 13 | 14 | var nextUniqId = 0; 15 | public var defs : Definitions; 16 | public var levels : Array = []; 17 | 18 | public var dataVersion : Int; 19 | public var name : String; 20 | public var defaultPivotX : Float; 21 | public var defaultPivotY : Float; 22 | public var defaultGridSize : Int; 23 | public var bgColor : UInt; 24 | 25 | private function new() { 26 | name = "New project"; 27 | dataVersion = Project.DATA_VERSION; 28 | defaultGridSize = Project.DEFAULT_GRID_SIZE; 29 | bgColor = 0x7f8093; 30 | defaultPivotX = defaultPivotY = 0; 31 | 32 | defs = new Definitions(this); 33 | } 34 | 35 | public static function createEmpty() { 36 | var p = new Project(); 37 | p.createLevel(); 38 | 39 | return p; 40 | } 41 | 42 | public function makeUniqId() return nextUniqId++; 43 | 44 | @:keep public function toString() { 45 | return '$name(levels=${levels.length}, layerDefs=${defs.layers.length}, entDefs=${defs.entities.length})'; 46 | } 47 | 48 | public static function fromJson(json:Dynamic) { 49 | var p = new Project(); 50 | p.dataVersion = JsonTools.readInt(json.dataVersion, 0); 51 | p.nextUniqId = JsonTools.readInt( json.nextUniqId, 0 ); 52 | p.name = JsonTools.readString( json.name ); 53 | p.defaultPivotX = JsonTools.readFloat( json.defaultPivotX, 0 ); 54 | p.defaultPivotY = JsonTools.readFloat( json.defaultPivotY, 0 ); 55 | p.defaultGridSize = JsonTools.readInt( json.defaultGridSize, Project.DEFAULT_GRID_SIZE ); 56 | p.bgColor = JsonTools.readInt( json.bgColor, 0xffffff ); 57 | 58 | p.defs = Definitions.fromJson(p, json.defs); 59 | 60 | for( lvlJson in JsonTools.readArray(json.levels) ) 61 | p.levels.push( Level.fromJson(p, lvlJson) ); 62 | 63 | p.dataVersion = Project.DATA_VERSION; // always uses latest version 64 | return p; 65 | } 66 | 67 | public function toJson(excludeLevels=false) { 68 | return { 69 | dataVersion: dataVersion, 70 | nextUniqId: nextUniqId, 71 | defs: defs.toJson(), 72 | levels: excludeLevels ? [] : levels.map( function(l) return l.toJson() ), 73 | 74 | name: name, 75 | defaultPivotX: JsonTools.clampFloatPrecision( defaultPivotX ), 76 | defaultPivotY: JsonTools.clampFloatPrecision( defaultPivotY ), 77 | defaultGridSize: defaultGridSize, 78 | bgColor: bgColor, 79 | } 80 | } 81 | 82 | public function tidy() { 83 | for(level in levels) 84 | level.tidy(this); 85 | 86 | defs.tidy(this); 87 | } 88 | 89 | 90 | /** LEVELS *****************************************/ 91 | 92 | public function createLevel() { 93 | var l = new Level(this, makeUniqId()); 94 | levels.push(l); 95 | tidy(); // will create layer instances 96 | return l; 97 | } 98 | 99 | public function removeLevel(l:Level) { 100 | if( !levels.remove(l) ) 101 | throw "Level not found in this Project"; 102 | 103 | tidy(); 104 | } 105 | 106 | public function getLevel(?name:String, ?uid:Int) : Null { 107 | for(l in levels) 108 | if( l.uid==uid || l.getName()==name ) 109 | return l; 110 | return null; 111 | } 112 | 113 | public function sortLevel(from:Int, to:Int) : Null { 114 | if( from<0 || from>=levels.length || from==to ) 115 | return null; 116 | 117 | if( to<0 || to>=levels.length ) 118 | return null; 119 | 120 | tidy(); 121 | 122 | var moved = levels.splice(from,1)[0]; 123 | levels.insert(to, moved); 124 | return moved; 125 | } 126 | 127 | 128 | 129 | 130 | 131 | #if debug 132 | public static function createTest() : Project { 133 | var p = new Project(); 134 | 135 | // Hero 136 | var ed = p.defs.createEntityDef("Hero"); 137 | ed.color = 0x00ff00; 138 | ed.width = 24; 139 | ed.height = 32; 140 | ed.maxPerLevel = 1; 141 | ed.setPivot(0.5,1); 142 | 143 | // // Hero.life 144 | var fd = ed.createField(p, F_Int); 145 | fd.name = "life"; 146 | fd.setDefault(Std.string(3)); 147 | fd.setMin("1"); 148 | fd.setMax("10"); 149 | 150 | // Collision layer 151 | var ld = p.defs.layers[0]; 152 | ld.name = "Collisions"; 153 | ld.getIntGridValueDef(0).name = "walls"; 154 | ld.addIntGridValue(0x00ff00, "grass"); 155 | ld.addIntGridValue(0x0000ff, "water"); 156 | 157 | // Entity layer 158 | var ld = p.defs.createLayerDef(Entities,"Entities"); 159 | 160 | // Decoration layer 161 | var ld = p.defs.createLayerDef(IntGrid,"Decorations"); 162 | ld.gridSize = 8; 163 | ld.displayOpacity = 0.7; 164 | ld.getIntGridValueDef(0).color = 0x00ff00; 165 | 166 | p.tidy(); 167 | 168 | return p; 169 | } 170 | #end 171 | } 172 | -------------------------------------------------------------------------------- /led/src.api/led/def/EntityDef.hx: -------------------------------------------------------------------------------- 1 | package led.def; 2 | 3 | import led.LedTypes; 4 | 5 | class EntityDef { 6 | public var uid(default,null) : Int; 7 | public var name : String; 8 | public var width : Int; 9 | public var height : Int; 10 | public var color : UInt; 11 | public var maxPerLevel : Int; 12 | public var discardExcess : Bool; // what to do when maxPerLevel is reached 13 | public var pivotX(default,set) : Float; 14 | public var pivotY(default,set) : Float; 15 | 16 | public var fieldDefs : Array = []; 17 | 18 | 19 | public function new(uid:Int) { 20 | this.uid = uid; 21 | color = 0xff0000; 22 | width = height = 16; 23 | maxPerLevel = 0; 24 | discardExcess = true; 25 | name = "New entity "+uid; 26 | setPivot(0.5,1); 27 | } 28 | 29 | @:keep public function toString() { 30 | return '$name($width x $height)[' 31 | + fieldDefs.map( function(fd) return fd.name+":"+fd.type ).join(",") 32 | + "]"; 33 | } 34 | 35 | public static function fromJson(dataVersion:Int, json:Dynamic) { 36 | var o = new EntityDef( JsonTools.readInt(json.uid) ); 37 | o.name = JsonTools.readString( json.name ); 38 | o.width = JsonTools.readInt( json.width, 16 ); 39 | o.height = JsonTools.readInt( json.height, 16 ); 40 | o.color = JsonTools.readInt( json.color, 0x0 ); 41 | o.maxPerLevel = JsonTools.readInt( json.maxPerLevel, 0 ); 42 | o.pivotX = JsonTools.readFloat( json.pivotX, 0 ); 43 | o.pivotY = JsonTools.readFloat( json.pivotY, 0 ); 44 | o.discardExcess = JsonTools.readBool( json.discardExcess, true ); 45 | 46 | for(defJson in JsonTools.readArray(json.fieldDefs) ) 47 | o.fieldDefs.push( FieldDef.fromJson(dataVersion, defJson) ); 48 | 49 | return o; 50 | } 51 | 52 | public function toJson() { 53 | return { 54 | uid: uid, 55 | name: name, 56 | width: width, 57 | height: height, 58 | color: color, 59 | maxPerLevel: maxPerLevel, 60 | discardExcess: discardExcess, 61 | pivotX: JsonTools.clampFloatPrecision( pivotX ), 62 | pivotY: JsonTools.clampFloatPrecision( pivotY ), 63 | 64 | fieldDefs: fieldDefs.map( function(fd) return fd.toJson() ), 65 | } 66 | } 67 | 68 | 69 | public inline function setPivot(x,y) { 70 | pivotX = x; 71 | pivotY = y; 72 | } 73 | 74 | inline function set_pivotX(v) return pivotX = dn.M.fclamp(v, 0, 1); 75 | inline function set_pivotY(v) return pivotY = dn.M.fclamp(v, 0, 1); 76 | 77 | 78 | public function createField(project:Project, type:FieldType) : FieldDef { 79 | var f = new FieldDef(project.makeUniqId(), type); 80 | fieldDefs.push(f); 81 | return f; 82 | } 83 | 84 | public function removeField(project:Project, fd:FieldDef) { 85 | if( !fieldDefs.remove(fd) ) 86 | throw "Unknown fieldDef"; 87 | 88 | project.tidy(); 89 | } 90 | 91 | public function sortField(from:Int, to:Int) : Null { 92 | if( from<0 || from>=fieldDefs.length || from==to ) 93 | return null; 94 | 95 | if( to<0 || to>=fieldDefs.length ) 96 | return null; 97 | 98 | var moved = fieldDefs.splice(from,1)[0]; 99 | fieldDefs.insert(to, moved); 100 | 101 | return moved; 102 | } 103 | 104 | // TODO either 105 | public function getFieldDef(?name:String, ?id:Int) : Null { 106 | if( name==null && id==null ) 107 | throw "Need 1 parameter"; 108 | 109 | for(fd in fieldDefs) 110 | if( fd.uid==id || fd.name==name ) 111 | return fd; 112 | return null; 113 | } 114 | 115 | } -------------------------------------------------------------------------------- /led/src.api/led/def/EnumDef.hx: -------------------------------------------------------------------------------- 1 | package led.def; 2 | 3 | class EnumDef { 4 | public var uid(default,null) : Int; 5 | public var name(default,set) : String; 6 | public var values : Array = []; 7 | 8 | public function new(uid:Int, name:String) { 9 | this.uid = uid; 10 | this.name = name; 11 | } 12 | 13 | function set_name(v:String) { 14 | name = cleanUpString(v); 15 | return name; 16 | } 17 | 18 | @:keep public function toString() { 19 | return '$name(' + values.join(",")+")"; 20 | } 21 | 22 | public static function fromJson(dataVersion:Int, json:Dynamic) { 23 | var ed = new EnumDef(JsonTools.readInt(json.uid), json.name); 24 | 25 | for(v in JsonTools.readArray(json.values)) 26 | ed.values.push(v); 27 | 28 | return ed; 29 | } 30 | 31 | public function toJson() { 32 | return { 33 | uid: uid, 34 | name: name, 35 | values: values, 36 | }; 37 | } 38 | 39 | public static inline function cleanUpString(str:String) { 40 | str = StringTools.trim(str); 41 | var reg = ~/[^0-9a-zA-Z_]+/gm; 42 | str = reg.replace(str, "_"); 43 | return str; 44 | } 45 | 46 | function hasValue(v:String) { 47 | v = cleanUpString(v).toLowerCase(); 48 | if( v.length==0 ) 49 | return false; 50 | 51 | for(ev in values) 52 | if( ev.toLowerCase()==v ) 53 | return true; 54 | return false; 55 | } 56 | 57 | public function isValueNameValid(v:String) { 58 | v = cleanUpString(v); 59 | return v.length>0 && !hasValue(v); 60 | } 61 | 62 | public function addValue(v:String) { 63 | if( !isValueNameValid(v) ) 64 | return false; 65 | 66 | v = cleanUpString(v); 67 | values.push(v); 68 | return true; 69 | } 70 | 71 | 72 | public function tidy(p:Project) { 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /led/src.api/led/def/FieldDef.hx: -------------------------------------------------------------------------------- 1 | package led.def; 2 | 3 | class FieldDef { 4 | public var uid(default,null) : Int; 5 | public var type(default,null) : led.LedTypes.FieldType; 6 | public var name : String; 7 | public var canBeNull : Bool; 8 | public var editorDisplayMode : led.LedTypes.FieldDisplayMode; 9 | public var editorDisplayPos : led.LedTypes.FieldDisplayPosition; 10 | 11 | #if editor 12 | @:allow(ui.modal.panel.EditEntityDefs) 13 | #end 14 | var defaultOverride : Null; 15 | 16 | public var min : Null; 17 | public var max : Null; 18 | 19 | @:allow(led.def.EntityDef) 20 | private function new(uid:Int, t:led.LedTypes.FieldType) { 21 | this.uid = uid; 22 | type = t; 23 | editorDisplayMode = Hidden; 24 | editorDisplayPos = Above; 25 | name = "New field "+uid; 26 | canBeNull = type==F_String; 27 | min = max = null; 28 | defaultOverride = null; 29 | } 30 | 31 | @:keep public function toString() { 32 | return '$name(' 33 | + ( canBeNull ? 'Null<$type>' : '$type' ) 34 | + ', default=${getDefault()})' 35 | + ( type==F_Int || type==F_Float ? '[$min-$max]' : "" ); 36 | } 37 | 38 | public static function fromJson(dataVersion:Int, json:Dynamic) { 39 | var o = new FieldDef( JsonTools.readInt(json.uid), JsonTools.readEnum(led.LedTypes.FieldType, json.type, false) ); 40 | o.name = JsonTools.readString(json.name); 41 | o.canBeNull = JsonTools.readBool(json.canBeNull); 42 | o.editorDisplayMode = JsonTools.readEnum(led.LedTypes.FieldDisplayMode, json.editorDisplayMode, false, Hidden); 43 | o.editorDisplayPos = JsonTools.readEnum(led.LedTypes.FieldDisplayPosition, json.editorDisplayPos, false, Above); 44 | o.min = JsonTools.readNullableFloat(json.min); 45 | o.max = JsonTools.readNullableFloat(json.max); 46 | o.defaultOverride = JsonTools.readEnum(led.LedTypes.ValueWrapper, json.defaultOverride, true); 47 | return o; 48 | } 49 | 50 | public function toJson() { 51 | return { 52 | uid: uid, 53 | type: JsonTools.writeEnum(type, false), 54 | name: name, 55 | canBeNull: canBeNull, 56 | editorDisplayMode: JsonTools.writeEnum(editorDisplayMode, false), 57 | editorDisplayPos: JsonTools.writeEnum(editorDisplayPos, false), 58 | min: min==null ? null : JsonTools.clampFloatPrecision(min), 59 | max: max==null ? null : JsonTools.clampFloatPrecision(max), 60 | defaultOverride: JsonTools.writeEnum(defaultOverride, true), 61 | } 62 | } 63 | 64 | 65 | #if editor 66 | public function getDescription() { 67 | var infinity = "∞"; 68 | return Lang.getFieldType(type) 69 | + ( canBeNull ? " nullable" : "" ) 70 | + "=" + ( type==F_String && getDefault()!=null ? '"${getDefault()}"' : getDefault() ) 71 | + ( min==null && max==null ? "" : 72 | ( type==F_Int ? " ["+(min==null?"-"+infinity:""+dn.M.round(min))+";"+(max==null?"+"+infinity:""+dn.M.round(max))+"]" : "" ) 73 | + ( type==F_Float ? " ["+(min==null?"-"+infinity:""+min)+";"+(max==null?infinity:""+max)+"]" : "" ) 74 | ); 75 | } 76 | #end 77 | 78 | public inline function require(type:led.LedTypes.FieldType) { 79 | if( this.type!=type ) 80 | throw "Only available on "+type+" fields"; 81 | } 82 | 83 | public function iClamp(v:Null) { 84 | if( v==null ) 85 | return v; 86 | 87 | if( min!=null ) 88 | v = dn.M.imax(v, dn.M.round(min)); 89 | 90 | if( max!=null ) 91 | v = dn.M.imin(v, dn.M.round(max)); 92 | 93 | return v; 94 | } 95 | 96 | public function fClamp(v:Null) { 97 | if( v==null ) 98 | return v; 99 | 100 | if( min!=null ) 101 | v = dn.M.fmax(v, min); 102 | 103 | if( max!=null ) 104 | v = dn.M.fmin(v, max); 105 | 106 | return v; 107 | } 108 | 109 | public function getUntypedDefault() : Dynamic { 110 | return switch defaultOverride { 111 | case null: null; 112 | case V_Int(v): v; 113 | case V_Float(v): v; 114 | case V_Bool(v): v; 115 | case V_String(v): v; 116 | } 117 | } 118 | 119 | public function getBoolDefault() : Null { 120 | require(F_Bool); 121 | return switch defaultOverride { 122 | case null: canBeNull ? null : false; 123 | case V_Bool(v): v; 124 | case _: null; 125 | } 126 | } 127 | 128 | public function getColorDefault() : Null { 129 | require(F_Color); 130 | return switch defaultOverride { 131 | case null: canBeNull ? null : 0x0; 132 | case V_Int(v): v; 133 | case _: null; 134 | } 135 | } 136 | 137 | public function getIntDefault() : Null { 138 | require(F_Int); 139 | return iClamp(switch defaultOverride { 140 | case null: canBeNull ? null : 0; 141 | case V_Int(v): v; 142 | case _: null; 143 | }); 144 | } 145 | 146 | public function getFloatDefault() : Null { 147 | require(F_Float); 148 | return fClamp( switch defaultOverride { 149 | case null: canBeNull ? null : 0.; 150 | case V_Float(v): v; 151 | case _: null; 152 | }); 153 | } 154 | 155 | public function getStringDefault() : Null { 156 | require(F_String); 157 | return switch defaultOverride { 158 | case null: canBeNull ? null : ""; 159 | case V_String(v): v; 160 | case _: null; 161 | } 162 | } 163 | 164 | public function restoreDefault() { 165 | defaultOverride = null; 166 | } 167 | 168 | public function setDefault(rawDef:Null) { 169 | if( rawDef==null ) 170 | defaultOverride = null; 171 | else switch type { 172 | case F_Int: 173 | var def = Std.parseInt(rawDef); 174 | defaultOverride = !dn.M.isValidNumber(def) ? null : V_Int( iClamp(def) ); 175 | 176 | case F_Color: 177 | var def = dn.Color.hexToInt(rawDef); 178 | defaultOverride = !dn.M.isValidNumber(def) ? null : V_Int(def); 179 | 180 | case F_Float: 181 | var def = Std.parseFloat(rawDef); 182 | defaultOverride = !dn.M.isValidNumber(def) ? null : V_Float( fClamp(def) ); 183 | 184 | case F_String: 185 | rawDef = StringTools.trim(rawDef); 186 | defaultOverride = rawDef=="" ? null : V_String(rawDef); 187 | 188 | case F_Bool: 189 | rawDef = StringTools.trim(rawDef).toLowerCase(); 190 | if( rawDef=="true" ) defaultOverride = V_Bool(true); 191 | else if( rawDef=="false" ) defaultOverride = V_Bool(false); 192 | else defaultOverride = null; 193 | 194 | } 195 | } 196 | 197 | public function getDefault() : Dynamic { 198 | return switch type { 199 | case F_Int: getIntDefault(); 200 | case F_Color: getColorDefault(); 201 | case F_Float: getFloatDefault(); 202 | case F_String: getStringDefault(); 203 | case F_Bool: getBoolDefault(); 204 | } 205 | } 206 | 207 | 208 | public function setMin(raw:Null) { 209 | if( raw==null ) 210 | min = null; 211 | else { 212 | switch type { 213 | case F_Int: 214 | var v = Std.parseInt(raw); 215 | if( !dn.M.isValidNumber(v) ) 216 | min = null; 217 | else 218 | min = v; 219 | 220 | case F_Float: 221 | var v = Std.parseFloat(raw); 222 | if( !dn.M.isValidNumber(v) ) 223 | min = null; 224 | else 225 | min = v; 226 | 227 | case _: 228 | } 229 | } 230 | checkMinMax(); 231 | } 232 | 233 | public function setMax(raw:Null) { 234 | if( raw==null ) 235 | max = null; 236 | else { 237 | switch type { 238 | case F_Int: 239 | var v = Std.parseInt(raw); 240 | if( !dn.M.isValidNumber(v) ) 241 | max = null; 242 | else 243 | max = v; 244 | 245 | case F_Float: 246 | var v = Std.parseFloat(raw); 247 | if( !dn.M.isValidNumber(v) ) 248 | max = null; 249 | else 250 | max = v; 251 | 252 | case _: 253 | } 254 | } 255 | checkMinMax(); 256 | } 257 | 258 | function checkMinMax() { 259 | if( type!=F_Int && type!=F_Float ) 260 | return; 261 | 262 | // Swap reversed min/max 263 | if( min!=null && max!=null && max = []; 14 | 15 | // Tileset 16 | public var tilesetDefId : Null; 17 | public var tilePivotX(default,set) : Float; 18 | public var tilePivotY(default,set) : Float; 19 | 20 | public function new(uid:Int, t:LayerType) { 21 | this.uid = uid; 22 | type = t; 23 | #if editor 24 | name = Lang.getLayerType(type)+" #"+uid; 25 | #else 26 | name = type+"#"+uid; 27 | #end 28 | addIntGridValue(0x0); 29 | } 30 | 31 | @:keep public function toString() { 32 | return '$name($type, ${gridSize}px)'; 33 | } 34 | 35 | public static function fromJson(dataVersion:Int, json:Dynamic) { 36 | var o = new LayerDef( JsonTools.readInt(json.uid), JsonTools.readEnum(LayerType, json.type, false)); 37 | o.name = JsonTools.readString(json.name); 38 | o.gridSize = JsonTools.readInt(json.gridSize, Project.DEFAULT_GRID_SIZE); 39 | o.displayOpacity = JsonTools.readFloat(json.displayOpacity, 1); 40 | 41 | o.intGridValues = []; 42 | for( v in JsonTools.readArray(json.intGridValues) ) 43 | o.intGridValues.push(v); 44 | 45 | o.tilesetDefId = JsonTools.readNullableInt(json.tilesetDefId); 46 | o.tilePivotX = JsonTools.readFloat(json.tilePivotX, 0); 47 | o.tilePivotY = JsonTools.readFloat(json.tilePivotY, 0); 48 | 49 | return o; 50 | } 51 | 52 | public function toJson() { 53 | return { 54 | uid: uid, 55 | type: JsonTools.writeEnum(type, false), 56 | name: name, 57 | gridSize: gridSize, 58 | displayOpacity: JsonTools.clampFloatPrecision(displayOpacity), 59 | 60 | intGridValues: intGridValues, 61 | 62 | tilesetDefId: tilesetDefId, 63 | tilePivotX: tilePivotX, 64 | tilePivotY: tilePivotY, 65 | } 66 | } 67 | 68 | 69 | public function addIntGridValue(col:UInt, ?name:String) { 70 | if( !isIntGridValueNameValid(name) ) 71 | throw "Invalid intGrid value name "+name; 72 | intGridValues.push({ 73 | color: col, 74 | name: name, 75 | }); 76 | } 77 | 78 | public function getIntGridValueDef(idx:Int) : Null { 79 | return intGridValues[idx]; 80 | } 81 | 82 | public inline function getAllIntGridValues() return intGridValues; 83 | public inline function countIntGridValues() return intGridValues.length; 84 | 85 | 86 | public function isIntGridValueUsedInProject(p:Project, idx:Int) { 87 | for(level in p.levels) { 88 | var li = level.getLayerInstance(this); 89 | if( li!=null ) { 90 | for(cx in 0...li.cWid) 91 | for(cy in 0...li.cHei) 92 | if( li.getIntGrid(cx,cy)==idx ) 93 | return true; 94 | } 95 | } 96 | return false; 97 | } 98 | 99 | public function isIntGridValueNameValid(name:Null) { 100 | if( name==null ) 101 | return true; 102 | 103 | for(v in intGridValues) 104 | if( v.name==name ) 105 | return false; 106 | 107 | return true; 108 | } 109 | 110 | 111 | 112 | public function hasTileset() return tilesetDefId!=null; 113 | 114 | 115 | inline function set_tilePivotX(v) return tilePivotX = dn.M.fclamp(v, 0, 1); 116 | inline function set_tilePivotY(v) return tilePivotY = dn.M.fclamp(v, 0, 1); 117 | 118 | } -------------------------------------------------------------------------------- /led/src.api/led/def/TilesetDef.hx: -------------------------------------------------------------------------------- 1 | package led.def; 2 | 3 | import led.LedTypes; 4 | 5 | class TilesetDef { 6 | public var uid : Int; 7 | public var fileBase64(default,set) : Null; 8 | public var path : Null; 9 | public var customName : Null; 10 | public var pxWid = 0; 11 | public var pxHei = 0; 12 | public var tileGridSize : Int = Project.DEFAULT_GRID_SIZE; 13 | public var tileGridSpacing : Int = 0; 14 | public var savedSelections : Array = []; 15 | 16 | #if heaps 17 | var texture(get,never) : Null; 18 | var _textureCache : Null; 19 | 20 | var pixels(get,never) : Null; 21 | var _pixelsCache : Null; 22 | #end 23 | 24 | public var cWid(get,never) : Int; inline function get_cWid() return !hasAtlas() ? 0 : dn.M.ceil( pxWid / tileGridSize ); 25 | public var cHei(get,never) : Int; inline function get_cHei() return !hasAtlas() ? 0 : dn.M.ceil( pxHei / tileGridSize ); 26 | 27 | 28 | public function new(uid:Int) { 29 | this.uid = uid; 30 | } 31 | 32 | public function getName() { 33 | return customName!=null ? customName : getDefaultName(); 34 | } 35 | 36 | public function getDefaultName() { 37 | return path!=null ? dn.FilePath.extractFileWithExt(path) : "Empty tileset "+uid; 38 | } 39 | 40 | public function getFileName() : Null { 41 | if( path==null || !hasAtlas() ) 42 | return null; 43 | 44 | return dn.FilePath.extractFileWithExt(path); 45 | } 46 | 47 | function set_fileBase64(str:String) { 48 | disposeAtlasCache(); 49 | return fileBase64 = str; 50 | } 51 | 52 | public function disposeAtlasCache() { 53 | #if heaps 54 | if( _textureCache!=null ) 55 | _textureCache.dispose(); 56 | _textureCache = null; 57 | 58 | if( _pixelsCache!=null ) 59 | _pixelsCache.dispose(); 60 | _pixelsCache = null; 61 | #end 62 | } 63 | 64 | public function clearAtlas() { 65 | fileBase64 = null; 66 | path = null; 67 | savedSelections = []; 68 | } 69 | 70 | public inline function hasAtlas() return fileBase64!=null; 71 | 72 | 73 | public function toJson() { 74 | return { 75 | uid: uid, 76 | fileBase64: fileBase64, 77 | path: path, 78 | customName: customName, 79 | pxWid: pxWid, 80 | pxHei: pxHei, 81 | tileGridSize: tileGridSize, 82 | tileGridSpacing: tileGridSpacing, 83 | savedSelections: savedSelections.map( function(sel) { 84 | return { ids:sel.ids, mode:JsonTools.writeEnum(sel.mode, false) } 85 | }), 86 | } 87 | } 88 | 89 | 90 | public static function fromJson(dataVersion:Int, json:Dynamic) { 91 | var td = new TilesetDef( JsonTools.readInt(json.uid) ); 92 | td.tileGridSize = JsonTools.readInt(json.tileGridSize, Project.DEFAULT_GRID_SIZE); 93 | td.tileGridSpacing = JsonTools.readInt(json.tileGridSpacing, 0); 94 | td.pxWid = JsonTools.readInt( json.pxWid ); 95 | td.pxHei = JsonTools.readInt( json.pxHei ); 96 | td.fileBase64 = json.fileBase64; 97 | td.path = json.path; 98 | td.customName = json.customName; 99 | 100 | var arr = JsonTools.readArray( json.savedSelections ); 101 | td.savedSelections = json.savedSelections==null ? [] : arr.map( function(jsonSel:Dynamic) { 102 | return { 103 | mode: JsonTools.readEnum(TileEditMode, jsonSel.mode, false, Stamp), 104 | ids: jsonSel.ids, 105 | } 106 | }) ; 107 | return td; 108 | } 109 | 110 | public function importImage(filePath:String, fileContent:haxe.io.Bytes) : Bool { 111 | clearAtlas(); 112 | 113 | var img = dn.ImageDecoder.decode(fileContent); 114 | if( img==null ) 115 | return false; 116 | 117 | path = dn.FilePath.fromFile(filePath).useSlashes().full; 118 | fileBase64 = haxe.crypto.Base64.encode(fileContent); 119 | pxWid = img.width; 120 | pxHei = img.height; 121 | return true; 122 | } 123 | 124 | public function getTileId(tcx,tcy) { 125 | return tcx + tcy * cWid; 126 | } 127 | 128 | public inline function getTileCx(tileId:Int) { 129 | return tileId - cWid * Std.int( tileId / cWid ); 130 | } 131 | 132 | public inline function getTileCy(tileId:Int) { 133 | return Std.int( tileId / cWid ); 134 | } 135 | 136 | public inline function getTileSourceX(tileId:Int) { 137 | return getTileCx(tileId) * ( tileGridSize + tileGridSpacing ); 138 | } 139 | 140 | public inline function getTileSourceY(tileId:Int) { 141 | return getTileCy(tileId) * ( tileGridSize + tileGridSpacing ); 142 | } 143 | 144 | public function dispose() { 145 | disposeAtlasCache(); 146 | fileBase64 = null; 147 | } 148 | 149 | 150 | public function saveSelection(tsSel:TilesetSelection) { 151 | // Remove existing overlapping saved selections 152 | for(tid in tsSel.ids) { 153 | var saved = getSavedSelectionFor(tid); 154 | if( saved!=null ) 155 | savedSelections.remove(saved); 156 | } 157 | 158 | if( tsSel.ids.length>1 ) 159 | savedSelections.push({ 160 | mode: tsSel.mode, 161 | ids: tsSel.ids.copy(), 162 | }); 163 | } 164 | 165 | public inline function hasSavedSelectionFor(tid:Int) : Bool { 166 | return getSavedSelectionFor(tid)!=null; 167 | } 168 | 169 | public function getSavedSelectionFor(tid:Int) : Null< TilesetSelection > { 170 | for(sel in savedSelections) 171 | for(stid in sel.ids) 172 | if( stid==tid ) 173 | return sel; 174 | return null; 175 | } 176 | 177 | 178 | 179 | /*** HEAPS API *********************************/ 180 | #if heaps 181 | 182 | public inline function getAtlasTile() : Null { 183 | return texture==null ? null : h2d.Tile.fromTexture(texture); 184 | } 185 | 186 | public inline function getTile(tileId:Int) { 187 | return getAtlasTile().sub( getTileSourceX(tileId), getTileSourceY(tileId), tileGridSize, tileGridSize ); 188 | } 189 | 190 | function get_texture() { 191 | if( _textureCache==null && pixels!=null ) 192 | _textureCache = h3d.mat.Texture.fromPixels(pixels); 193 | return _textureCache; 194 | } 195 | 196 | function get_pixels() { 197 | if( _pixelsCache==null && fileBase64!=null ) { 198 | var bytes = haxe.crypto.Base64.decode( fileBase64 ); 199 | _pixelsCache = dn.ImageDecoder.decodePixels(bytes); 200 | } 201 | return _pixelsCache; 202 | } 203 | 204 | #end 205 | 206 | 207 | 208 | /*** JS API *********************************/ 209 | #if js 210 | 211 | public function createAtlasHtmlImage() : js.html.Image { 212 | var img = new js.html.Image(); 213 | if( hasAtlas() ) 214 | img.src = 'data:image/png;base64,$fileBase64'; 215 | return img; 216 | } 217 | 218 | #if editor 219 | public function drawAtlasToCanvas(canvas:js.jquery.JQuery) { 220 | if( !canvas.is("canvas") ) 221 | throw "Not a canvas"; 222 | 223 | if( !hasAtlas() ) 224 | return; 225 | 226 | var canvas = Std.downcast(canvas.get(0), js.html.CanvasElement); 227 | var ctx = canvas.getContext2d(); 228 | ctx.clearRect(0, 0, canvas.width, canvas.height); 229 | 230 | var img = new js.html.Image(pixels.width, pixels.height); 231 | img.src = 'data:image/png;base64,$fileBase64'; 232 | img.onload = function() { 233 | ctx.drawImage(img, 0, 0); 234 | } 235 | } 236 | 237 | public function drawTileToCanvas(canvas:js.jquery.JQuery, tileId:Int, toX:Int, toY:Int) { 238 | if( pixels==null ) 239 | return; 240 | 241 | if( !canvas.is("canvas") ) 242 | throw "Not a canvas"; 243 | 244 | if( getTileSourceX(tileId)+tileGridSize>=pxWid || getTileSourceY(tileId)+tileGridSize>=pxHei ) 245 | return; // out of bounds 246 | 247 | var subPixels = pixels.sub(getTileSourceX(tileId), getTileSourceY(tileId), tileGridSize, tileGridSize); 248 | var canvas = Std.downcast(canvas.get(0), js.html.CanvasElement); 249 | var ctx = canvas.getContext2d(); 250 | var img = new js.html.Image(subPixels.width, subPixels.height); 251 | var b64 = haxe.crypto.Base64.encode( subPixels.toPNG() ); 252 | img.src = 'data:image/png;base64,$b64'; 253 | img.onload = function() { 254 | ctx.drawImage(img, toX, toY); 255 | } 256 | } 257 | #end 258 | 259 | #end 260 | } -------------------------------------------------------------------------------- /led/src.api/led/inst/EntityInstance.hx: -------------------------------------------------------------------------------- 1 | package led.inst; 2 | 3 | class EntityInstance { 4 | public var _project : Project; 5 | public var def(get,never) : led.def.EntityDef; inline function get_def() return _project.defs.getEntityDef(defId); 6 | 7 | public var defId(default,null) : Int; 8 | public var x : Int; 9 | public var y : Int; 10 | var fieldInstances : Map = new Map(); 11 | 12 | public var left(get,never) : Int; inline function get_left() return Std.int( x - def.width*def.pivotX ); 13 | public var right(get,never) : Int; inline function get_right() return left + def.width-1; 14 | public var top(get,never) : Int; inline function get_top() return Std.int( y - def.height*def.pivotY ); 15 | public var bottom(get,never) : Int; inline function get_bottom() return top + def.height-1; 16 | 17 | 18 | public function new(p:Project, entityDefId:Int) { 19 | _project = p; 20 | defId = entityDefId; 21 | } 22 | 23 | @:keep public function toString() { 24 | return 'Instance<${def.name}>@$x,$y'; 25 | } 26 | 27 | public function toJson() { 28 | var fieldsJson = []; 29 | for(fi in fieldInstances) 30 | fieldsJson.push( fi.toJson() ); 31 | 32 | return { 33 | defId: defId, 34 | x: x, 35 | y: y, 36 | fieldInstances: fieldsJson, 37 | } 38 | } 39 | 40 | public static function fromJson(project:Project, json:Dynamic) { 41 | var ei = new EntityInstance(project, JsonTools.readInt(json.defId)); 42 | ei.x = JsonTools.readInt( json.x, 0 ); 43 | ei.y = JsonTools.readInt( json.y, 0 ); 44 | 45 | for( fieldJson in JsonTools.readArray(json.fieldInstances) ) { 46 | var fi = FieldInstance.fromJson(project, fieldJson); 47 | ei.fieldInstances.set(fi.defId, fi); 48 | } 49 | 50 | return ei; 51 | } 52 | 53 | // TODO get rid of this parameter 54 | public function getCx(ld:led.def.LayerDef) { 55 | return Std.int( ( x + (def.pivotX==1 ? -1 : 0) ) / ld.gridSize ); 56 | } 57 | 58 | public function getCy(ld:led.def.LayerDef) { 59 | return Std.int( ( y + (def.pivotY==1 ? -1 : 0) ) / ld.gridSize ); 60 | } 61 | 62 | public function isOver(levelX:Int, levelY:Int) { 63 | return levelX >= left && levelX <= right && levelY >= top && levelY <= bottom; 64 | } 65 | 66 | public function tidy(p:led.Project) { 67 | _project = p; 68 | 69 | // Remove field instances whose def was removed 70 | for(e in fieldInstances.keyValueIterator()) 71 | if( e.value.def==null ) 72 | fieldInstances.remove(e.key); 73 | 74 | for(fi in fieldInstances) 75 | fi.tidy(_project); 76 | } 77 | 78 | 79 | // ** FIELDS ********************************** 80 | 81 | public function getFieldInstance(fieldDef:led.def.FieldDef) { 82 | if( !fieldInstances.exists(fieldDef.uid) ) 83 | fieldInstances.set(fieldDef.uid, new led.inst.FieldInstance(_project, fieldDef.uid)); 84 | return fieldInstances.get( fieldDef.uid ); 85 | } 86 | 87 | public function getStringField(name:String) : Null { 88 | var fd = def.getFieldDef(name); 89 | fd.require(F_String); 90 | return getFieldInstance(fd).getString(); 91 | } 92 | 93 | public function getFloatField(name:String) : Null { 94 | var fd = def.getFieldDef(name); 95 | fd.require(F_Float); 96 | return getFieldInstance(fd).getFloat(); 97 | } 98 | 99 | public function getIntField(name:String) : Null { 100 | var fd = def.getFieldDef(name); 101 | fd.require(F_Int); 102 | return getFieldInstance(fd).getInt(); 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /led/src.api/led/inst/FieldInstance.hx: -------------------------------------------------------------------------------- 1 | package led.inst; 2 | 3 | import led.LedTypes; 4 | 5 | class FieldInstance { 6 | public var _project : Project; 7 | public var def(get,never) : led.def.FieldDef; inline function get_def() return _project.defs.getFieldDef(defId); 8 | 9 | public var defId: Int; 10 | var internalValue : Null; 11 | 12 | @:allow(led.inst.EntityInstance) 13 | private function new(p:Project, fieldDefId:Int) { 14 | _project = p; 15 | defId = fieldDefId; 16 | internalValue = null; 17 | } 18 | 19 | @:keep 20 | public function toString() { 21 | return 22 | '${def.name} = ' 23 | + getForDisplay() 24 | + ' [ $internalValue ]'; 25 | } 26 | 27 | public static function fromJson(project:Project, json:Dynamic) { 28 | var o = new FieldInstance( project, JsonTools.readInt(json.defId) ); 29 | o.internalValue = JsonTools.readEnum(ValueWrapper, json.internalValue, true); 30 | return o; 31 | } 32 | 33 | public function toJson() { 34 | return { 35 | defId: defId, 36 | internalValue: JsonTools.writeEnum(internalValue,true), 37 | } 38 | } 39 | 40 | inline function require(type:FieldType) { 41 | if( def.type!=type ) 42 | throw "Only available on "+type+" fields"; 43 | } 44 | 45 | function setInternal(fv:Null) { 46 | internalValue = fv; 47 | } 48 | 49 | public function isUsingDefault() { 50 | return internalValue==null; 51 | } 52 | 53 | 54 | public function parseValue(raw:Null) { 55 | if( raw==null ) 56 | setInternal(null); 57 | else switch def.type { 58 | case F_Int: 59 | var v = Std.parseInt(raw); 60 | if( !dn.M.isValidNumber(v) ) 61 | setInternal(null); 62 | else { 63 | v = def.iClamp(v); 64 | setInternal( V_Int(v) ); 65 | } 66 | 67 | case F_Color: 68 | setInternal( raw==null ? null : V_Int(dn.Color.hexToInt(raw)) ); 69 | 70 | case F_Float: 71 | var v = Std.parseFloat(raw); 72 | if( !dn.M.isValidNumber(v) ) 73 | setInternal(null); 74 | else { 75 | v = def.fClamp(v); 76 | setInternal( V_Float(v) ); 77 | } 78 | 79 | case F_String: 80 | raw = StringTools.trim(raw); 81 | if( raw.length==0 ) 82 | setInternal(null); 83 | else 84 | setInternal(V_String(raw) ); 85 | 86 | case F_Bool: 87 | raw = StringTools.trim(raw).toLowerCase(); 88 | if( raw=="true" ) setInternal( V_Bool(true) ); 89 | else if( raw=="false" ) setInternal( V_Bool(false) ); 90 | else setInternal(null); 91 | } 92 | } 93 | 94 | public function valueIsNull() { 95 | var v : Dynamic = switch def.type { 96 | case F_Int: getInt(); 97 | case F_Color: getColorAsInt(); 98 | case F_Float: getFloat(); 99 | case F_String: getString(); 100 | case F_Bool: getBool(); 101 | } 102 | return v == null; 103 | } 104 | 105 | public function getForDisplay() : String { 106 | var v : Dynamic = switch def.type { 107 | case F_Int: getInt(); 108 | case F_Color: getColorAsHexStr(); 109 | case F_Float: getFloat(); 110 | case F_String: getString(); 111 | case F_Bool: getBool(); 112 | } 113 | if( v==null ) 114 | return "null"; 115 | else switch def.type { 116 | case F_Int, F_Float, F_Bool, F_Color: return Std.string(v); 117 | case F_String: return '"$v"'; 118 | } 119 | } 120 | 121 | public function getInt() : Null { 122 | require(F_Int); 123 | return isUsingDefault() ? def.getIntDefault() : switch internalValue { 124 | case V_Int(v): def.iClamp(v); 125 | case _: throw "unexpected"; 126 | } 127 | } 128 | 129 | public function getColorAsInt() : Null { 130 | require(F_Color); 131 | return isUsingDefault() ? def.getColorDefault() : switch internalValue { 132 | case V_Int(v): v; 133 | case _: throw "unexpected"; 134 | } 135 | } 136 | 137 | public function getColorAsHexStr() : Null { 138 | require(F_Color); 139 | return isUsingDefault() 140 | ? def.getColorDefault()==null ? null : dn.Color.intToHex(def.getColorDefault()) 141 | : switch internalValue { 142 | case V_Int(v): dn.Color.intToHex(v); 143 | case _: throw "unexpected"; 144 | } 145 | } 146 | 147 | public function getFloat() : Null { 148 | require(F_Float); 149 | return isUsingDefault() ? def.getFloatDefault() : switch internalValue { 150 | case V_Float(v): def.fClamp(v); 151 | case _: throw "unexpected"; 152 | } 153 | } 154 | 155 | public function getBool() : Bool { 156 | require(F_Bool); 157 | return isUsingDefault() ? def.getBoolDefault() : switch internalValue { 158 | case V_Bool(v): v; 159 | case _: throw "unexpected"; 160 | } 161 | } 162 | 163 | public function getString() : String { 164 | require(F_String); 165 | return isUsingDefault() ? def.getStringDefault() : switch internalValue { 166 | case V_String(v): v; 167 | case _: throw "unexpected"; 168 | } 169 | } 170 | 171 | public function tidy(p:Project) { 172 | _project = p; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /led/src.api/led/inst/LayerInstance.hx: -------------------------------------------------------------------------------- 1 | package led.inst; 2 | 3 | import led.LedTypes; 4 | 5 | class LayerInstance { 6 | var _project : Project; 7 | public var def(get,never) : led.def.LayerDef; inline function get_def() return _project.defs.getLayerDef(layerDefId); 8 | public var level(get,never) : Level; function get_level() return _project.getLevel(levelId); 9 | 10 | public var levelId : Int; 11 | public var layerDefId : Int; 12 | public var pxOffsetX : Int = 0; 13 | public var pxOffsetY : Int = 0; 14 | 15 | // Layer content 16 | var intGrid : Map = new Map(); // 17 | public var entityInstances : Array = []; 18 | public var gridTiles : Map = []; // 19 | 20 | public var cWid(get,never) : Int; inline function get_cWid() return dn.M.ceil( level.pxWid / def.gridSize ); 21 | public var cHei(get,never) : Int; inline function get_cHei() return dn.M.ceil( level.pxHei / def.gridSize ); 22 | 23 | 24 | public function new(p:Project, levelId:Int, layerDefId:Int) { 25 | _project = p; 26 | this.levelId = levelId; 27 | this.layerDefId = layerDefId; 28 | } 29 | 30 | 31 | @:keep public function toString() { 32 | return 'LayerInstance#<${def.name}:${def.type}>'; 33 | } 34 | 35 | 36 | public function toJson() { 37 | return { 38 | levelId: levelId, 39 | layerDefId: layerDefId, 40 | pxOffsetX: pxOffsetX, 41 | pxOffsetY: pxOffsetY, 42 | intGrid: { 43 | var arr = []; 44 | for(e in intGrid.keyValueIterator()) 45 | arr.push({ 46 | coordId: e.key, 47 | v: e.value, 48 | }); 49 | arr; 50 | }, 51 | gridTiles: { 52 | var arr = []; 53 | for(e in gridTiles.keyValueIterator()) 54 | arr.push({ 55 | coordId: e.key, 56 | v: e.value, 57 | }); 58 | arr; 59 | }, 60 | entityInstances: entityInstances.map( function(ei) return ei.toJson() ), 61 | } 62 | } 63 | 64 | public static function fromJson(p:Project, json:Dynamic) { 65 | var li = new led.inst.LayerInstance( p, JsonTools.readInt(json.levelId), JsonTools.readInt(json.layerDefId) ); 66 | 67 | for( intGridJson in JsonTools.readArray(json.intGrid) ) 68 | li.intGrid.set( intGridJson.coordId, intGridJson.v ); 69 | 70 | for( gridTilesJson in JsonTools.readArray(json.gridTiles) ) 71 | li.gridTiles.set( gridTilesJson.coordId, gridTilesJson.v ); 72 | 73 | for( entityJson in JsonTools.readArray(json.entityInstances) ) 74 | li.entityInstances.push( EntityInstance.fromJson(p, entityJson) ); 75 | 76 | li.pxOffsetX = JsonTools.readInt(json.pxOffsetX, 0); 77 | li.pxOffsetY = JsonTools.readInt(json.pxOffsetY, 0); 78 | 79 | return li; 80 | } 81 | 82 | inline function requireType(t:LayerType) { 83 | if( def.type!=t ) 84 | throw 'Only works on $t layer!'; 85 | } 86 | 87 | public inline function isValid(cx:Int,cy:Int) { 88 | return cx>=0 && cx=0 && cy= def.countIntGridValues() ) 112 | removeIntGrid(cx,cy); 113 | } 114 | 115 | case Entities: 116 | // Remove lost entities (def removed) 117 | var i = 0; 118 | while( i=0 && newCx=0 && newCy=0 && newCx=0 && newCy { 200 | var v = def.getIntGridValueDef( getIntGrid(cx,cy) ); 201 | return v==null ? null : v.color; 202 | } 203 | 204 | public function setIntGrid(cx:Int, cy:Int, v:Int) { 205 | requireType(IntGrid); 206 | if( isValid(cx,cy) ) 207 | intGrid.set( coordId(cx,cy), v ); 208 | } 209 | 210 | public inline function hasIntGrid(cx:Int, cy:Int) { 211 | requireType(IntGrid); 212 | return getIntGrid(cx,cy)!=-1; 213 | } 214 | 215 | public function removeIntGrid(cx:Int, cy:Int) { 216 | requireType(IntGrid); 217 | if( isValid(cx,cy) ) 218 | intGrid.remove( coordId(cx,cy) ); 219 | } 220 | 221 | 222 | /** ENTITY INSTANCE *******************/ 223 | 224 | public function createEntityInstance(ed:led.def.EntityDef) : Null { 225 | requireType(Entities); 226 | if( ed.maxPerLevel>0 ) { 227 | var all = entityInstances.filter( function(ei) return ei.defId==ed.uid ); 228 | if( ed.discardExcess ) 229 | while( all.length>=ed.maxPerLevel ) 230 | removeEntityInstance( all.shift() ); 231 | else if( all.length>=ed.maxPerLevel ) 232 | return null; 233 | } 234 | 235 | var ei = new EntityInstance(_project, ed.uid); 236 | entityInstances.push(ei); 237 | return ei; 238 | } 239 | 240 | public function duplicateEntityInstance(ei:EntityInstance) : EntityInstance { 241 | var copy = EntityInstance.fromJson( _project, ei.toJson() ); 242 | entityInstances.push(copy); 243 | return copy; 244 | } 245 | 246 | public function removeEntityInstance(e:EntityInstance) { 247 | requireType(Entities); 248 | if( !entityInstances.remove(e) ) 249 | throw "Unknown instance "+e; 250 | } 251 | 252 | 253 | 254 | /** TILES *******************/ 255 | 256 | public function setGridTile(cx:Int, cy:Int, tileId:Int) { 257 | if( isValid(cx,cy) ) 258 | gridTiles.set( coordId(cx,cy), tileId ); 259 | } 260 | 261 | public function removeGridTile(cx:Int, cy:Int) { 262 | if( isValid(cx,cy) ) 263 | gridTiles.remove( coordId(cx,cy) ); 264 | } 265 | 266 | public function getGridTile(cx:Int, cy:Int) : Null { 267 | return !isValid(cx,cy) || !gridTiles.exists( coordId(cx,cy) ) ? null : gridTiles.get( coordId(cx,cy) ); 268 | } 269 | 270 | public inline function hasGridTile(cx:Int, cy:Int) : Bool { 271 | return getGridTile(cx,cy)!=null; 272 | } 273 | 274 | 275 | 276 | 277 | /** RENDERING *******************/ 278 | 279 | #if heaps 280 | 281 | public function render(target:h2d.Object) { 282 | switch def.type { 283 | case IntGrid: 284 | var g = new h2d.Graphics(target); 285 | for(cy in 0...cHei) 286 | for(cx in 0...cWid) { 287 | var id = getIntGrid(cx,cy); 288 | if( id<0 ) 289 | continue; 290 | 291 | g.beginFill( getIntGridColorAt(cx,cy) ); 292 | g.drawRect(cx*def.gridSize, cy*def.gridSize, def.gridSize, def.gridSize); 293 | } 294 | 295 | case Entities: 296 | // not meant to be rendered 297 | 298 | case Tiles: 299 | for(cy in 0...cHei) 300 | for(cx in 0...cWid) { 301 | if( getGridTile(cx,cy)==null ) 302 | continue; 303 | 304 | var td = _project.defs.getTilesetDef(def.tilesetDefId); 305 | var t = td.getTile( getGridTile(cx,cy) ); 306 | t.setCenterRatio(def.tilePivotX, def.tilePivotY); 307 | var bmp = new h2d.Bitmap(t, target); 308 | bmp.x = (cx + def.tilePivotX) * def.gridSize; 309 | bmp.y = (cy + def.tilePivotY) * def.gridSize; 310 | } 311 | 312 | } 313 | } 314 | 315 | #else 316 | 317 | @:deprecated("Not implemented on this platform") 318 | public function render(target:Dynamic) {} 319 | 320 | #end 321 | } -------------------------------------------------------------------------------- /redist/directx.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx.zip -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/DumberDwarves.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/DumberDwarves.exe -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/OpenAL32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/OpenAL32.dll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/d3dcompiler_47.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/d3dcompiler_47.dll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/directx.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/directx.hdll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/fmt.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/fmt.hdll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/hlboot.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/hlboot.dat -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/libhl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/libhl.dll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/msvcr120.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/msvcr120.dll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/openal.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/openal.hdll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/ssl.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/ssl.hdll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/ui.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/ui.hdll -------------------------------------------------------------------------------- /redist/directx/DumberDwarves/uv.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/directx/DumberDwarves/uv.hdll -------------------------------------------------------------------------------- /redist/js.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/js.zip -------------------------------------------------------------------------------- /redist/js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DumberDwarves 6 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /redist/sdl_mac.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac.zip -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/DumberDwarves: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/DumberDwarves -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/hlboot.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/hlboot.dat -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libSDL2-2.0.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libSDL2-2.0.0.dylib -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libhl.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libhl.dylib -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libmbedtls.10.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libmbedtls.10.dylib -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libopenal.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libopenal.1.dylib -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libpng16.16.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libpng16.16.dylib -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libuv.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libuv.1.dylib -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libvorbis.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libvorbis.0.dylib -------------------------------------------------------------------------------- /redist/sdl_mac/DumberDwarves/libvorbisfile.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_mac/DumberDwarves/libvorbisfile.3.dylib -------------------------------------------------------------------------------- /redist/sdl_win.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win.zip -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/DumberDwarves.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/DumberDwarves.exe -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/OpenAL32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/OpenAL32.dll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/SDL2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/SDL2.dll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/fmt.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/fmt.hdll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/hlboot.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/hlboot.dat -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/libhl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/libhl.dll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/msvcr120.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/msvcr120.dll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/openal.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/openal.hdll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/sdl.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/sdl.hdll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/ssl.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/ssl.hdll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/ui.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/ui.hdll -------------------------------------------------------------------------------- /redist/sdl_win/DumberDwarves/uv.hdll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/redist/sdl_win/DumberDwarves/uv.hdll -------------------------------------------------------------------------------- /res/atlas/tiles.atlas: -------------------------------------------------------------------------------- 1 | 2 | tiles.png 3 | size: 256,256 4 | format: RGBA8888 5 | filter: Linear,Linear 6 | repeat: none 7 | a_atk0 8 | rotate: false 9 | xy: 35, 44 10 | size: 32, 16 11 | orig: 32, 16 12 | offset: 0, 0 13 | index: -1 14 | a_atk1 15 | rotate: false 16 | xy: 1, 46 17 | size: 32, 16 18 | orig: 32, 16 19 | offset: 0, 0 20 | index: -1 21 | a_atk2 22 | rotate: false 23 | xy: 68, 44 24 | size: 32, 16 25 | orig: 32, 16 26 | offset: 0, 0 27 | index: -1 28 | a_atk_charge0 29 | rotate: false 30 | xy: 77, 105 31 | size: 16, 16 32 | orig: 16, 16 33 | offset: 0, 0 34 | index: -1 35 | a_idle0 36 | rotate: false 37 | xy: 76, 122 38 | size: 16, 16 39 | orig: 16, 16 40 | offset: 0, 0 41 | index: -1 42 | a_idle1 43 | rotate: false 44 | xy: 173, 87 45 | size: 16, 16 46 | orig: 16, 16 47 | offset: 0, 0 48 | index: -1 49 | a_walk0 50 | rotate: false 51 | xy: 146, 93 52 | size: 16, 16 53 | orig: 16, 16 54 | offset: 0, 0 55 | index: -1 56 | a_walk1 57 | rotate: false 58 | xy: 120, 105 59 | size: 16, 16 60 | orig: 16, 16 61 | offset: 0, 0 62 | index: -1 63 | a_walk2 64 | rotate: false 65 | xy: 190, 87 66 | size: 16, 16 67 | orig: 16, 16 68 | offset: 0, 0 69 | index: -1 70 | bossDoor 71 | rotate: false 72 | xy: 101, 44 73 | size: 26, 33 74 | orig: 26, 33 75 | offset: 0, 0 76 | index: -1 77 | bubble 78 | rotate: false 79 | xy: 77, 87 80 | size: 17, 17 81 | orig: 17, 17 82 | offset: 0, 0 83 | index: -1 84 | cart 85 | rotate: false 86 | xy: 173, 67 87 | size: 21, 19 88 | orig: 21, 19 89 | offset: 0, 0 90 | index: -1 91 | crate0-60 92 | rotate: false 93 | xy: 207, 87 94 | size: 16, 16 95 | orig: 16, 16 96 | offset: 0, 0 97 | index: -1 98 | crate0-61 99 | rotate: false 100 | xy: 207, 87 101 | size: 16, 16 102 | orig: 16, 16 103 | offset: 0, 0 104 | index: -1 105 | crate0-63 106 | rotate: false 107 | xy: 207, 87 108 | size: 16, 16 109 | orig: 16, 16 110 | offset: 0, 0 111 | index: -1 112 | crate0-65 113 | rotate: false 114 | xy: 207, 87 115 | size: 16, 16 116 | orig: 16, 16 117 | offset: 0, 0 118 | index: -1 119 | crate0-66 120 | rotate: false 121 | xy: 207, 87 122 | size: 16, 16 123 | orig: 16, 16 124 | offset: 0, 0 125 | index: -1 126 | crate0-69 127 | rotate: false 128 | xy: 207, 87 129 | size: 16, 16 130 | orig: 16, 16 131 | offset: 0, 0 132 | index: -1 133 | crate0 134 | rotate: false 135 | xy: 224, 87 136 | size: 16, 16 137 | orig: 16, 16 138 | offset: 0, 0 139 | index: -1 140 | d_act0 141 | rotate: false 142 | xy: 121, 80 143 | size: 24, 24 144 | orig: 24, 24 145 | offset: 0, 0 146 | index: -1 147 | d_act1 148 | rotate: false 149 | xy: 27, 87 150 | size: 24, 24 151 | orig: 24, 24 152 | offset: 0, 0 153 | index: -1 154 | d_atk_charge0 155 | rotate: false 156 | xy: 1, 89 157 | size: 24, 24 158 | orig: 24, 24 159 | offset: 0, 0 160 | index: -1 161 | d_atkA0 162 | rotate: false 163 | xy: 150, 17 164 | size: 48, 24 165 | orig: 48, 24 166 | offset: 0, 0 167 | index: -1 168 | d_atkA1 169 | rotate: false 170 | xy: 199, 17 171 | size: 48, 24 172 | orig: 48, 24 173 | offset: 0, 0 174 | index: -1 175 | d_atkA2 176 | rotate: false 177 | xy: 1, 19 178 | size: 48, 24 179 | orig: 48, 24 180 | offset: 0, 0 181 | index: -1 182 | d_atkA3 183 | rotate: false 184 | xy: 1, 89 185 | size: 24, 24 186 | orig: 24, 24 187 | offset: 0, 0 188 | index: -1 189 | d_atkB0 190 | rotate: false 191 | xy: 50, 19 192 | size: 48, 24 193 | orig: 48, 24 194 | offset: 0, 0 195 | index: -1 196 | d_atkB1 197 | rotate: false 198 | xy: 99, 19 199 | size: 48, 24 200 | orig: 48, 24 201 | offset: 0, 0 202 | index: -1 203 | d_atkB2 204 | rotate: false 205 | xy: 148, 42 206 | size: 48, 24 207 | orig: 48, 24 208 | offset: 0, 0 209 | index: -1 210 | d_hit0 211 | rotate: false 212 | xy: 52, 87 213 | size: 24, 24 214 | orig: 24, 24 215 | offset: 0, 0 216 | index: -1 217 | d_idle0 218 | rotate: false 219 | xy: 95, 104 220 | size: 24, 24 221 | orig: 24, 24 222 | offset: 0, 0 223 | index: -1 224 | d_walk0 225 | rotate: false 226 | xy: 26, 112 227 | size: 24, 24 228 | orig: 24, 24 229 | offset: 0, 0 230 | index: -1 231 | d_walk1 232 | rotate: false 233 | xy: 1, 114 234 | size: 24, 24 235 | orig: 24, 24 236 | offset: 0, 0 237 | index: -1 238 | d_walk2 239 | rotate: false 240 | xy: 51, 112 241 | size: 24, 24 242 | orig: 24, 24 243 | offset: 0, 0 244 | index: -1 245 | danger 246 | rotate: false 247 | xy: 242, 45 248 | size: 13, 14 249 | orig: 13, 14 250 | offset: 0, 0 251 | index: -1 252 | empty 253 | rotate: false 254 | xy: 148, 19 255 | size: 1, 1 256 | orig: 1, 1 257 | offset: 0, 0 258 | index: -1 259 | emptyBone 260 | rotate: false 261 | xy: 180, 104 262 | size: 15, 8 263 | orig: 15, 8 264 | offset: 0, 0 265 | index: -1 266 | fxCircle0 267 | rotate: false 268 | xy: 1, 164 269 | size: 16, 16 270 | orig: 16, 16 271 | offset: 0, 0 272 | index: -1 273 | fxDot0 274 | rotate: false 275 | xy: 27, 79 276 | size: 3, 3 277 | orig: 3, 3 278 | offset: 0, 0 279 | index: -1 280 | fxExplosion0 281 | rotate: false 282 | xy: 147, 67 283 | size: 25, 25 284 | orig: 25, 25 285 | offset: 0, 0 286 | index: -1 287 | fxExplosion1 288 | rotate: false 289 | xy: 34, 61 290 | size: 25, 25 291 | orig: 25, 25 292 | offset: 0, 0 293 | index: -1 294 | fxExplosion2 295 | rotate: false 296 | xy: 1, 63 297 | size: 25, 25 298 | orig: 25, 25 299 | offset: 0, 0 300 | index: -1 301 | fxExplosion3 302 | rotate: false 303 | xy: 60, 61 304 | size: 25, 25 305 | orig: 25, 25 306 | offset: 0, 0 307 | index: -1 308 | fxExplosion4 309 | rotate: false 310 | xy: 95, 78 311 | size: 25, 25 312 | orig: 25, 25 313 | offset: 0, 0 314 | index: -1 315 | fxGib0 316 | rotate: false 317 | xy: 248, 39 318 | size: 6, 5 319 | orig: 6, 5 320 | offset: 0, 0 321 | index: -1 322 | fxGib1 323 | rotate: false 324 | xy: 248, 25 325 | size: 7, 6 326 | orig: 7, 6 327 | offset: 0, 0 328 | index: -1 329 | fxGib2 330 | rotate: false 331 | xy: 27, 63 332 | size: 6, 5 333 | orig: 6, 5 334 | offset: 0, 0 335 | index: -1 336 | fxImpact0 337 | rotate: false 338 | xy: 76, 139 339 | size: 15, 9 340 | orig: 15, 9 341 | offset: 0, 0 342 | index: -1 343 | fxLine0 344 | rotate: false 345 | xy: 221, 13 346 | size: 33, 3 347 | orig: 33, 3 348 | offset: 0, 0 349 | index: -1 350 | fxLineDir0 351 | rotate: false 352 | xy: 1, 44 353 | size: 33, 1 354 | orig: 33, 1 355 | offset: 0, 0 356 | index: -1 357 | fxProhib 358 | rotate: false 359 | xy: 248, 17 360 | size: 7, 7 361 | orig: 7, 7 362 | offset: 0, 0 363 | index: -1 364 | fxSmallCircle0 365 | rotate: false 366 | xy: 248, 32 367 | size: 6, 6 368 | orig: 6, 6 369 | offset: 0, 0 370 | index: -1 371 | fxSmoke0 372 | rotate: false 373 | xy: 197, 42 374 | size: 44, 44 375 | orig: 44, 44 376 | offset: 0, 0 377 | index: -1 378 | fxSplatter0 379 | rotate: false 380 | xy: 150, 1 381 | size: 70, 15 382 | orig: 70, 15 383 | offset: 0, 0 384 | index: -1 385 | fxSplatter1 386 | rotate: false 387 | xy: 79, 1 388 | size: 70, 17 389 | orig: 70, 17 390 | offset: 0, 0 391 | index: -1 392 | fxSplatter2 393 | rotate: false 394 | xy: 1, 1 395 | size: 77, 17 396 | orig: 77, 17 397 | offset: 0, 0 398 | index: -1 399 | fxStar0 400 | rotate: false 401 | xy: 27, 73 402 | size: 3, 5 403 | orig: 3, 5 404 | offset: 0, 0 405 | index: -1 406 | fxTail0 407 | rotate: false 408 | xy: 221, 1 409 | size: 33, 11 410 | orig: 33, 11 411 | offset: 0, 0 412 | index: -1 413 | gen 414 | rotate: false 415 | xy: 128, 44 416 | size: 18, 18 417 | orig: 18, 18 418 | offset: 0, 0 419 | index: -1 420 | gStone0 421 | rotate: false 422 | xy: 1, 181 423 | size: 16, 16 424 | orig: 16, 16 425 | offset: 0, 0 426 | index: -1 427 | gStone1 428 | rotate: false 429 | xy: 1, 198 430 | size: 16, 16 431 | orig: 16, 16 432 | offset: 0, 0 433 | index: -1 434 | gStone2 435 | rotate: false 436 | xy: 1, 215 437 | size: 16, 16 438 | orig: 16, 16 439 | offset: 0, 0 440 | index: -1 441 | i_Bait 442 | rotate: false 443 | xy: 1, 232 444 | size: 16, 16 445 | orig: 16, 16 446 | offset: 0, 0 447 | index: -1 448 | i_BaitFull 449 | rotate: false 450 | xy: 18, 164 451 | size: 16, 16 452 | orig: 16, 16 453 | offset: 0, 0 454 | index: -1 455 | i_BaitPart 456 | rotate: false 457 | xy: 18, 181 458 | size: 16, 16 459 | orig: 16, 16 460 | offset: 0, 0 461 | index: -1 462 | i_Bomb 463 | rotate: false 464 | xy: 18, 198 465 | size: 16, 16 466 | orig: 16, 16 467 | offset: 0, 0 468 | index: -1 469 | i_Cart 470 | rotate: false 471 | xy: 128, 63 472 | size: 18, 16 473 | orig: 18, 16 474 | offset: 0, 0 475 | index: -1 476 | i_Gem 477 | rotate: false 478 | xy: 26, 137 479 | size: 24, 24 480 | orig: 24, 24 481 | offset: 0, 0 482 | index: -1 483 | i_HeartFull 484 | rotate: false 485 | xy: 242, 60 486 | size: 13, 13 487 | orig: 13, 13 488 | offset: 0, 0 489 | index: -1 490 | i_HeartHollow 491 | rotate: false 492 | xy: 242, 74 493 | size: 13, 13 494 | orig: 13, 13 495 | offset: 0, 0 496 | index: -1 497 | i_HeartPart 498 | rotate: false 499 | xy: 86, 61 500 | size: 13, 13 501 | orig: 13, 13 502 | offset: 0, 0 503 | index: -1 504 | pixel 505 | rotate: false 506 | xy: 148, 21 507 | size: 1, 1 508 | orig: 1, 1 509 | offset: 0, 0 510 | index: -1 511 | pointer 512 | rotate: false 513 | xy: 93, 129 514 | size: 15, 12 515 | orig: 15, 12 516 | offset: 0, 0 517 | index: -1 518 | uiBaitOff 519 | rotate: false 520 | xy: 137, 110 521 | size: 16, 12 522 | orig: 16, 12 523 | offset: 0, 0 524 | index: -1 525 | uiBaitOn 526 | rotate: false 527 | xy: 120, 122 528 | size: 16, 12 529 | orig: 16, 12 530 | offset: 0, 0 531 | index: -1 532 | uiBar 533 | rotate: false 534 | xy: 27, 69 535 | size: 6, 3 536 | orig: 6, 3 537 | offset: 0, 0 538 | index: -1 539 | uiBarBg 540 | rotate: false 541 | xy: 86, 75 542 | size: 8, 5 543 | orig: 8, 5 544 | offset: 0, 0 545 | index: -1 546 | wall0 547 | rotate: false 548 | xy: 1, 139 549 | size: 24, 24 550 | orig: 24, 24 551 | offset: 0, 0 552 | index: -1 553 | wall1 554 | rotate: false 555 | xy: 51, 137 556 | size: 24, 24 557 | orig: 24, 24 558 | offset: 0, 0 559 | index: -1 560 | wallDetail0 561 | rotate: false 562 | xy: 18, 215 563 | size: 16, 16 564 | orig: 16, 16 565 | offset: 0, 0 566 | index: -1 567 | wallDetail1 568 | rotate: false 569 | xy: 18, 232 570 | size: 16, 16 571 | orig: 16, 16 572 | offset: 0, 0 573 | index: -1 574 | wallDetail2 575 | rotate: false 576 | xy: 163, 104 577 | size: 16, 16 578 | orig: 16, 16 579 | offset: 0, 0 580 | index: -1 581 | -------------------------------------------------------------------------------- /res/atlas/tiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/res/atlas/tiles.png -------------------------------------------------------------------------------- /res/data.cdb: -------------------------------------------------------------------------------- 1 | { 2 | "sheets": [], 3 | "customTypes": [], 4 | "compress": false 5 | } -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/res/fonts/barlow_condensed_medium_regular_11.png -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/res/fonts/barlow_condensed_medium_regular_17.png -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/res/fonts/barlow_condensed_medium_regular_32.png -------------------------------------------------------------------------------- /res/fonts/barlow_condensed_medium_regular_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/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/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/res/fonts/minecraftiaOutline.png -------------------------------------------------------------------------------- /res/lang/en.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/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-10-29 15:17+0100\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.4\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:30 8 | msgid "Game is ready." 9 | msgstr "" 10 | 11 | #: src/Game.hx:69 12 | msgid "Press ESCAPE again to exit." 13 | msgstr "" 14 | 15 | 16 | -------------------------------------------------------------------------------- /res/ld/tileset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/res/ld/tileset.png -------------------------------------------------------------------------------- /res/props.json: -------------------------------------------------------------------------------- 1 | { 2 | "fs.convert" : { 3 | "wav" : "mp3" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /screenshots/dumberDwarves-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/dumberDwarves-cover.png -------------------------------------------------------------------------------- /screenshots/god0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/god0.png -------------------------------------------------------------------------------- /screenshots/s0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s0.png -------------------------------------------------------------------------------- /screenshots/s1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s1.png -------------------------------------------------------------------------------- /screenshots/s2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s2.png -------------------------------------------------------------------------------- /screenshots/s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s3.png -------------------------------------------------------------------------------- /screenshots/s4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s4.gif -------------------------------------------------------------------------------- /screenshots/s5.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s5.avi -------------------------------------------------------------------------------- /screenshots/s6.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s6.avi -------------------------------------------------------------------------------- /screenshots/s7.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s7.avi -------------------------------------------------------------------------------- /screenshots/s8.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s8.mp4 -------------------------------------------------------------------------------- /screenshots/s9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deepnight/gmtk20-dumberDwarves/dfcd5191facf168a3548f9166dc72a0d5dcdc24f/screenshots/s9.png -------------------------------------------------------------------------------- /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 cdbs = findAll("res", "cdb"); 8 | try { 9 | var data = GetText.doParseGlobal({ 10 | codePath: "src", 11 | codeIgnore: null, 12 | cdbFiles: cdbs, 13 | cdbSpecialId: [], 14 | potFile: "res/lang/"+name+".pot", 15 | }); 16 | } 17 | catch(e:String) { 18 | Sys.println(""); 19 | Sys.println(e); 20 | Sys.println("Extraction failed: fatal error!"); 21 | Sys.println(""); 22 | Sys.exit(1); 23 | } 24 | Sys.println("Done."); 25 | } 26 | 27 | static function findAll(path:String, ext:String, ?cur:Array) { 28 | var ext = "."+ext; 29 | var all = cur==null ? [] : cur; 30 | for(e in sys.FileSystem.readDirectory(path)) { 31 | e = path+"/"+e; 32 | if( e.indexOf(ext)>=0 && e.lastIndexOf(ext)==e.length-ext.length ) 33 | all.push(e); 34 | if( sys.FileSystem.isDirectory(e) && e.indexOf(".tmp")<0 ) 35 | findAll(e, ext, all); 36 | } 37 | return all; 38 | } 39 | } -------------------------------------------------------------------------------- /src/Assets.hx: -------------------------------------------------------------------------------- 1 | import dn.heaps.slib.*; 2 | 3 | class Assets { 4 | public static var fontPixel : h2d.Font; 5 | public static var fontTiny : h2d.Font; 6 | public static var fontSmall : h2d.Font; 7 | public static var fontMedium : h2d.Font; 8 | public static var fontLarge : h2d.Font; 9 | public static var tiles : SpriteLib; 10 | 11 | static var initDone = false; 12 | public static function init() { 13 | if( initDone ) 14 | return; 15 | initDone = true; 16 | 17 | fontPixel = hxd.Res.fonts.minecraftiaOutline.toFont(); 18 | fontTiny = hxd.Res.fonts.barlow_condensed_medium_regular_9.toFont(); 19 | fontSmall = hxd.Res.fonts.barlow_condensed_medium_regular_11.toFont(); 20 | fontMedium = hxd.Res.fonts.barlow_condensed_medium_regular_17.toFont(); 21 | fontLarge = hxd.Res.fonts.barlow_condensed_medium_regular_32.toFont(); 22 | tiles = dn.heaps.assets.Atlas.load("atlas/tiles.atlas"); 23 | 24 | tiles.defineAnim("a_walk", "0(2), 1, 2(2), 1"); 25 | tiles.defineAnim("a_atk", "0, 1(1), 2(2)"); 26 | 27 | tiles.defineAnim("d_walk", "0(2), 1, 2(2), 1"); 28 | tiles.defineAnim("d_atkA", "0, 1(2), 2(2), 3(3)"); 29 | tiles.defineAnim("d_atkB", "0, 1(2), 2(2)"); 30 | } 31 | } -------------------------------------------------------------------------------- /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.BACKSPACE) || Main.ME.ca.dpadDownPressed() ) 28 | speed = speed>=1 ? 0.2 : 1; 29 | #end 30 | 31 | var tmod = hxd.Timer.tmod * speed; 32 | #if debug 33 | tmod *= hxd.Key.isDown(hxd.Key.CTRL) ? 0.2 : hxd.Key.isDown(hxd.Key.SPACE) || Main.ME!=null && Main.ME.ca.ltDown() ? 5 : 1; 34 | #end 35 | dn.heaps.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 | var bumpOffX = 0.; 10 | var bumpOffY = 0.; 11 | 12 | public function new() { 13 | super(Game.ME); 14 | x = y = 0; 15 | dx = dy = 0; 16 | } 17 | 18 | function get_wid() { 19 | return M.ceil( Game.ME.w() / Const.SCALE ); 20 | } 21 | 22 | function get_hei() { 23 | return M.ceil( Game.ME.h() / Const.SCALE ); 24 | } 25 | 26 | public function trackTarget(e:Entity, immediate:Bool) { 27 | target = e; 28 | if( immediate ) 29 | recenter(); 30 | } 31 | 32 | public inline function stopTracking() { 33 | target = null; 34 | } 35 | 36 | public function recenter() { 37 | if( target!=null ) { 38 | x = target.centerX; 39 | y = target.centerY; 40 | } 41 | } 42 | 43 | public inline function scrollerToGlobalX(v:Float) return v*Const.SCALE + Game.ME.scroller.x; 44 | public inline function scrollerToGlobalY(v:Float) return v*Const.SCALE + Game.ME.scroller.y; 45 | 46 | var shakePower = 1.0; 47 | public function shakeS(t:Float, ?pow=1.0) { 48 | cd.setS("shaking", t, false); 49 | shakePower = pow; 50 | } 51 | 52 | override function update() { 53 | super.update(); 54 | 55 | // Follow target entity 56 | if( target!=null ) { 57 | var s = 0.006; 58 | var deadZone = 5; 59 | var tx = target.footX; 60 | var ty = target.footY; 61 | 62 | var d = M.dist(x,y, tx, ty); 63 | if( d>=deadZone ) { 64 | var a = Math.atan2( ty-y, tx-x ); 65 | dx += Math.cos(a) * (d-deadZone) * s * tmod; 66 | dy += Math.sin(a) * (d-deadZone) * s * tmod; 67 | } 68 | } 69 | 70 | // Follow all dwarves 71 | if( en.ai.Dwarf.ALL.length>0 ) { 72 | var s = 0.006; 73 | var deadZone = 5; 74 | var tx = 0.; 75 | var ty = 0.; 76 | for(e in en.ai.Dwarf.ALL) { 77 | tx+=e.footX; 78 | ty+=e.footY; 79 | } 80 | tx/=en.ai.Dwarf.ALL.length; 81 | ty/=en.ai.Dwarf.ALL.length; 82 | 83 | var d = M.dist(x,y, tx, ty); 84 | if( d>=deadZone ) { 85 | var a = Math.atan2( ty-y, tx-x ); 86 | dx += Math.cos(a) * (d-deadZone) * s * tmod; 87 | dy += Math.sin(a) * (d-deadZone) * s * tmod; 88 | } 89 | } 90 | 91 | 92 | var frict = 0.89; 93 | x += dx*tmod; 94 | dx *= Math.pow(frict,tmod); 95 | 96 | y += dy*tmod; 97 | dy *= Math.pow(frict,tmod); 98 | } 99 | 100 | public inline function bumpAng(a, dist) { 101 | bumpOffX+=Math.cos(a)*dist; 102 | bumpOffY+=Math.sin(a)*dist; 103 | } 104 | 105 | public inline function bump(x,y) { 106 | bumpOffX+=x; 107 | bumpOffY+=y; 108 | } 109 | 110 | 111 | override function postUpdate() { 112 | super.postUpdate(); 113 | 114 | if( !ui.Console.ME.hasFlag("scroll") ) { 115 | var level = Game.ME.level; 116 | var scroller = Game.ME.scroller; 117 | 118 | // Update scroller 119 | if( wid > = new Map(); 23 | var invalidated = true; 24 | public var levelId : Int; 25 | public var data : led.Level; 26 | 27 | var fastCollGrid: Map; 28 | public var pf : dn.pathfinder.AStar; 29 | 30 | public function new(idx:Int, data:led.Level) { 31 | super(Game.ME); 32 | levelId = idx; 33 | this.data = data; 34 | wid = Std.int(data.pxWid/Const.GRID); 35 | hei= Std.int(data.pxHei/Const.GRID); 36 | createRootInLayers(Game.ME.scroller, Const.DP_BG); 37 | 38 | initCollisions(); 39 | pf = new dn.pathfinder.AStar( function(x,y) return new CPoint(x,y,0.5,0.5) ); 40 | pf.init(wid, hei, hasCollision); 41 | } 42 | 43 | public function initCollisions() { 44 | fastCollGrid = new Map(); 45 | 46 | var li = data.getLayerInstance("Collisions"); 47 | for(cy in 0...hei) 48 | for(cx in 0...wid) 49 | fastCollGrid.set( coordId(cx,cy), li.getIntGrid(cx,cy) ); 50 | } 51 | 52 | public inline function isValid(cx,cy) return cx>=0 && cx=0 && cy0 ) 65 | Const.SCALE = M.ceil( w()/Const.AUTO_SCALE_TARGET_WID ); 66 | else if( Const.AUTO_SCALE_TARGET_HEI>0 ) 67 | Const.SCALE = M.ceil( h()/Const.AUTO_SCALE_TARGET_HEI ); 68 | 69 | Const.UI_SCALE = Const.SCALE; 70 | } 71 | 72 | override function update() { 73 | Assets.tiles.tmod = tmod; 74 | super.update(); 75 | } 76 | } -------------------------------------------------------------------------------- /src/Types.hx: -------------------------------------------------------------------------------- 1 | enum Affect { 2 | Stun; 3 | } 4 | 5 | enum LevelMark { 6 | } 7 | 8 | enum ItemType { 9 | Gem; 10 | BaitFull; 11 | BaitPart; 12 | Bomb; 13 | } 14 | 15 | enum Task { 16 | Wait(untilFrame:Float); 17 | Idle; 18 | Grab(e:en.Item); 19 | Break(e:en.Breakable); 20 | BringToCart; 21 | AttackDwarf(e:en.ai.Dwarf); 22 | WaitWithItem(e:en.Item); 23 | ExitLevel; 24 | FleeBoss(e:en.ai.mob.Boss); 25 | } 26 | -------------------------------------------------------------------------------- /src/en/Ai.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Ai extends Entity { 4 | public static var ALL : Array = []; 5 | 6 | var task : Task; 7 | var detectRadius = 5; 8 | var path : Array = []; 9 | var origin : CPoint; 10 | var atkRange = 1.0; // case 11 | var bubble : Null; 12 | var prohibiteds : Array<{ e:Entity, sec:Float }> = []; 13 | var baseSpeed = rnd(0.005,0.007); 14 | 15 | private function new(x,y) { 16 | super(x,y); 17 | 18 | origin = this.makePoint(); 19 | spr.filter = new dn.heaps.filter.PixelOutline(); 20 | 21 | ALL.push(this); 22 | task = Idle; 23 | enableShadow(); 24 | 25 | doTask(Idle); 26 | } 27 | 28 | public function prohibit(e:Entity) { 29 | if( !e.isAlive() ) 30 | return; 31 | 32 | for(p in prohibiteds) 33 | if( p.e==e ) 34 | return; 35 | 36 | var t = 20; 37 | if( e.is(Item) ) 38 | t = switch e.as(Item).type { 39 | case Gem: 8; 40 | case BaitFull, BaitPart: t; 41 | case Bomb: t; 42 | } 43 | 44 | prohibiteds.push({ 45 | e: e, 46 | sec: t, 47 | }); 48 | } 49 | 50 | override function chargeAction(id:String, sec:Float, cb:() -> Void) { 51 | super.chargeAction(id, sec, cb); 52 | dx*=0.2; 53 | dy*=0.2; 54 | bdx*=0.2; 55 | bdy*=0.2; 56 | } 57 | 58 | public function isProhibited(e:Entity) { 59 | for(p in prohibiteds) 60 | if( p.e==e ) 61 | return true; 62 | return false; 63 | } 64 | 65 | public function isItemProhibited(it:ItemType) { 66 | for(p in prohibiteds) 67 | if( p.e.is(Item) && p.e.as(Item).type==it ) 68 | return true; 69 | return false; 70 | } 71 | 72 | public function isWalking() { 73 | return canAct() && ( M.fabs(dx)>=0.004 || M.fabs(dy)>=0.004 ); 74 | } 75 | 76 | public function canDetect(e:Entity) { 77 | return isAlive() && e.isAlive() && distCase(e)<=detectRadius && sightCheckEnt(e); 78 | } 79 | 80 | override function dispose() { 81 | super.dispose(); 82 | ALL.remove(this); 83 | origin = null; 84 | path = null; 85 | prohibiteds = null; 86 | 87 | 88 | if( bubble!=null ) { 89 | bubble.remove(); 90 | bubble = null; 91 | } 92 | } 93 | 94 | function setBubble(iconId:String, resize=true) { 95 | clearBubble(); 96 | bubble = new h2d.Object(); 97 | game.scroller.add(bubble, Const.DP_UI); 98 | 99 | var bg = Assets.tiles.getBitmap("bubble",0, 0.5,1, bubble); 100 | 101 | var icon = Assets.tiles.getBitmap(iconId,0, 0.5, 0.5, bubble); 102 | icon.x = 1; 103 | icon.y = Std.int( -bg.tile.height*0.5 - 3 ); 104 | if( resize ) 105 | icon.setScale(0.66); 106 | icon.alpha = 0.7; 107 | icon.smooth = true; 108 | } 109 | 110 | function clearBubble() { 111 | if( bubble!=null ) { 112 | bubble.remove(); 113 | bubble = null; 114 | } 115 | } 116 | 117 | function cancelPath() { 118 | path = []; 119 | } 120 | 121 | public function doTask(t:Task) { 122 | cancelPath(); 123 | task = t; 124 | clearBubble(); 125 | } 126 | 127 | override function slap(x:Int,y:Int) { 128 | super.slap(x,y); 129 | 130 | switch task { 131 | case Idle: 132 | popText("??"); 133 | 134 | case Wait(_): 135 | 136 | case ExitLevel: 137 | popText("I need to go!"); 138 | 139 | case Grab(i): 140 | prohibit(i); 141 | releaseCarriedEnt(true); 142 | 143 | case Break(e): 144 | prohibit(e); 145 | 146 | case WaitWithItem(e): 147 | prohibit(e); 148 | releaseCarriedEnt(true); 149 | 150 | case BringToCart: 151 | if( isCarrying(Item) ) 152 | prohibit( carriedEnt ); 153 | releaseCarriedEnt(true); 154 | 155 | case AttackDwarf(e): 156 | 157 | case FleeBoss(e): 158 | popText("??"); 159 | } 160 | 161 | doTask( Idle ); 162 | } 163 | 164 | 165 | function showTaskFocus(e:Entity) {} 166 | 167 | 168 | public function goto(tcx:Int, tcy:Int) { 169 | path = game.level.pf.getPath(cx,cy, tcx,tcy); 170 | 171 | } 172 | 173 | function updateAi() { 174 | // Run task 175 | switch task { 176 | 177 | case Idle: 178 | 179 | case Wait(until): 180 | if( ftime>=until ) { 181 | doTask(Idle); 182 | return; 183 | } 184 | 185 | if( !cd.hasSetS("jumpWait",0.3) ) 186 | dz = -0.11; 187 | 188 | case WaitWithItem(e): 189 | if( carriedEnt==null ) 190 | doTask(Idle); 191 | 192 | case Grab(i): 193 | if( !i.isAlive() || i.isCarried && i.getCarrier()!=this ) { 194 | // Lost target 195 | doTask(Idle); 196 | return; 197 | } 198 | 199 | // Seek target 200 | releaseCarriedEnt(); 201 | goto(i.cx,i.cy); 202 | showTaskFocus(i); 203 | setBubble(i.spr.groupName, i.type!=Bomb); 204 | // setBubble("i_"+Std.string(i.type), i.type!=Bomb); 205 | if( distCase(i)<=0.8 ) { 206 | var t = switch i.type { 207 | case BaitFull, BaitPart: 0.3; 208 | case Gem: 0.6; 209 | case _: 1; 210 | } 211 | chargeAction("pick", t, function() { 212 | if( i.isCarried || !i.isAlive() ) { 213 | popText("?"); 214 | return; 215 | } 216 | switch i.type { 217 | case Gem: 218 | carry(i); 219 | doTask(BringToCart); 220 | 221 | case BaitFull, BaitPart: 222 | i.consume(this); 223 | doTask(Idle); 224 | 225 | case Bomb: 226 | carry(i); 227 | doTask(WaitWithItem(i)); 228 | } 229 | }); 230 | } 231 | 232 | case BringToCart: 233 | if( carriedEnt==null ) { 234 | doTask(Idle); 235 | return; 236 | } 237 | var c = en.Cart.ME; 238 | showTaskFocus(c); 239 | setBubble("i_Cart", false); 240 | goto(c.cx, c.cy); 241 | if( distCase(c)<=1 ) 242 | chargeAction("drop", 1, function() { 243 | carriedEnt.destroy(); 244 | c.onDropGem(); 245 | doTask(Idle); 246 | }); 247 | 248 | case FleeBoss(e): 249 | if( distCase(e)>=8 ) { 250 | doTask(Idle); 251 | return; 252 | } 253 | 254 | setBubble("danger", false); 255 | 256 | if( !cd.hasSetS("pickFleePt",0.5) ) { 257 | var dh = new dn.DecisionHelper( dn.Bresenham.getDisc(cx,cy,7) ); 258 | dh.keepOnly( function(pt) return !level.hasCollision(pt.x,pt.y) && sightCheckCase(pt.x,pt.y) ); 259 | dh.score( function(pt) return e.distCaseFree(pt.x, pt.y) ); 260 | dh.score( function(pt) return !e.sightCheckCase(pt.x, pt.y) ? 3 : 0 ); 261 | dh.useBest( function(pt) { 262 | goto(pt.x, pt.y); 263 | }); 264 | } 265 | 266 | case ExitLevel: 267 | var c = en.Cart.ME; 268 | setBubble("i_Cart", false); 269 | goto(c.cx, c.cy); 270 | if( distCase(c)<=1 ) 271 | destroy(); 272 | 273 | case Break(e): 274 | setBubble("crate"); 275 | showTaskFocus(e); 276 | goto(e.cx,e.cy); 277 | 278 | case AttackDwarf(e): 279 | if( !e.isAlive() ) { 280 | // Lost target 281 | doTask(Idle); 282 | return; 283 | } 284 | 285 | if( distCase(e)>2 || !sightCheckEnt(e) ) { 286 | showTaskFocus(e); 287 | goto(e.cx, e.cy); 288 | } 289 | else { 290 | cancelPath(); 291 | var a = angTo(e); 292 | var spd = getSpeed(); 293 | dx += Math.cos(a) * spd * tmod; 294 | dy += Math.sin(a) * spd * tmod; 295 | } 296 | } 297 | 298 | // Remove reached path nodes 299 | while( path.length>0 && distCaseFree(path[0].cx, path[0].cy)<=0.3 ) 300 | path.shift(); 301 | 302 | // Follow path 303 | if( path.length>0 && !cd.has("stepLock") ) { 304 | var pt = path[0]; 305 | dir = pt.footX { 330 | return []; 331 | } 332 | 333 | var curAtkTarget : Null; 334 | function chargeAtk(e:Entity) { 335 | curAtkTarget = e; 336 | } 337 | 338 | function updateAutoAttack() { 339 | if( isChargingAction("atk") || !canAct() && !isChargingAction() ) 340 | return; 341 | 342 | for(e in getAttackables()) 343 | if( e.isAlive() && distCase(e)<=atkRange && !e.is(en.ai.mob.Boss) && sightCheckEnt(e) ) { 344 | cancelAction(); 345 | dir = dirTo(e); 346 | dx*=0.8; 347 | dy*=0.8; 348 | chargeAtk(e); 349 | break; 350 | } 351 | } 352 | 353 | function getSpeed() { 354 | return baseSpeed; 355 | } 356 | 357 | inline function lockAtk(s:Float) { 358 | cd.setS("atkLock",s); 359 | } 360 | 361 | override function update() { 362 | super.update(); 363 | 364 | if( canAct() ) 365 | updateAi(); 366 | 367 | if( !cd.has("atkLock") ) 368 | updateAutoAttack(); 369 | 370 | // Garbage collect prohibiteds 371 | var i = 0; 372 | while( i0 ) { 38 | timeS -= tmod/Const.FPS; 39 | tf.text = Std.string( Std.int(timeS) ); 40 | tf.x = Std.int( -tf.textWidth*0.5-1 ); 41 | tf.y = -20; 42 | if( timeS<=10 && !cd.hasSetS("jump",1) ) 43 | dz = -0.05; 44 | 45 | if( timeS<=0 ) { 46 | var b = new en.ai.mob.Boss(cx,cy+1); 47 | b.dz = -0.2; 48 | b.dy = 0.06; 49 | b.lockAiS(2); 50 | game.announce("Boss has arrived!!", 0xff0000, true); 51 | } 52 | } 53 | else 54 | tf.visible = false; 55 | } 56 | } -------------------------------------------------------------------------------- /src/en/Breakable.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Breakable extends Entity { 4 | public static var ALL : Array = []; 5 | 6 | public function new(x,y) { 7 | super(x,y); 8 | initLife(3); 9 | spr.set("crate"); 10 | ALL.push(this); 11 | weight = 3; 12 | enableShadow(); 13 | bumpFrict*=0.8; 14 | toBack(); 15 | } 16 | 17 | override function onDie(?from:Entity) { 18 | super.onDie(from); 19 | fx.dirtExplosion(centerX, centerY, 0xb57a40); 20 | } 21 | 22 | override function dispose() { 23 | super.dispose(); 24 | ALL.remove(this); 25 | } 26 | } -------------------------------------------------------------------------------- /src/en/Cart.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Cart extends Entity { 4 | public static var ME : Cart; 5 | 6 | public var score : Int; 7 | 8 | public function new(x,y) { 9 | super(x,y); 10 | spr.set("cart"); 11 | ME = this; 12 | weight = 20; 13 | enableShadow(); 14 | } 15 | 16 | public function onDropGem() { 17 | score++; 18 | fx.sparks(centerX, centerY, 0x06b4ed); 19 | popText("+1 GEM"); 20 | game.refillBaits(); 21 | if( game.countRemainingGems()>0 ) 22 | game.announce("Gem stolen!", "Food restored. "+game.countRemainingGems()+" gems remaining", 0x1ebae1, false); 23 | else 24 | game.announce("Level wiped!", 0xffcc00, true); 25 | 26 | dz = -0.08; 27 | 28 | var g = new h2d.Bitmap(Assets.tiles.getTile("i_Gem"), spr); 29 | g.tile = g.tile.sub(0,0, g.tile.width, Std.int( g.tile.height*rnd(0.7,1) )); 30 | g.tile.setCenterRatio(0.5,1); 31 | g.x = 1 + irnd(0,6,true); 32 | g.y = -7; 33 | g.setScale( rnd(0.5,0.8) ); 34 | } 35 | 36 | override function onBeforePhysics() { 37 | super.onBeforePhysics(); 38 | dy = 0; 39 | bdy = 0; 40 | } 41 | 42 | override function postUpdate() { 43 | super.postUpdate(); 44 | if( score>0 ) 45 | fx.shine(this, 0x0088ff); 46 | } 47 | 48 | override function dispose() { 49 | super.dispose(); 50 | if( ME==this ) 51 | ME = null; 52 | } 53 | } -------------------------------------------------------------------------------- /src/en/Item.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Item extends Entity { 4 | public static var ALL : Array = []; 5 | 6 | public var type : ItemType; 7 | public var bombTimerS = 0.; 8 | 9 | public function new(x,y, t:ItemType) { 10 | super(x,y); 11 | 12 | if( t==null ) 13 | throw "Unknown item type"; 14 | 15 | ALL.push(this); 16 | type = t; 17 | enableShadow(); 18 | hei = Const.GRID*1.05; 19 | 20 | if( type!=Gem ) 21 | spr.filter = new dn.heaps.filter.PixelOutline(); 22 | 23 | refreshIcon(); 24 | cd.setS("jump",rnd(0,1)); 25 | } 26 | 27 | public function refreshIcon() { 28 | if( game.kidMode && type==BaitFull ) 29 | spr.set("i_HeartFull"); 30 | else if( game.kidMode && type==BaitPart ) 31 | spr.set("i_HeartPart"); 32 | else 33 | spr.set("i_"+type.getName()); 34 | } 35 | 36 | override function dispose() { 37 | super.dispose(); 38 | ALL.remove(this); 39 | } 40 | 41 | public function consume(by:en.Ai) { 42 | switch type { 43 | case Gem: 44 | case Bomb: 45 | 46 | case BaitFull: 47 | type = BaitPart; 48 | refreshIcon(); 49 | dz = -0.1; 50 | blink(0xffcc00); 51 | by.prohibit(this); 52 | 53 | case BaitPart: 54 | fx.emptyBone(this); 55 | destroy(); 56 | } 57 | } 58 | 59 | override function postUpdate() { 60 | super.postUpdate(); 61 | if( type==Gem && !cd.hasSetS("shine",0.1) ) 62 | fx.shine(this, 0x78deff); 63 | } 64 | 65 | override function update() { 66 | super.update(); 67 | 68 | if( !isCarried && type==Gem && zr==0 && !cd.hasSetS("jump",1) ) 69 | dz = -0.05; 70 | 71 | if( type==Bomb && ( isCarried || bombTimerS>0 ) ) { 72 | bombTimerS += tmod/Const.FPS; 73 | if( !cd.hasSetS("warn",0.2) ) 74 | blink(0xffffff, 0.1); 75 | 76 | if( bombTimerS>=2 ) { 77 | if( isCarried ) { 78 | getCarrier().hit(9999,this); 79 | fx.flashBangS(0xffcc00, 0.5, 0.5); 80 | game.camera.shakeS(2, 0.2); 81 | } 82 | fx.explosion(centerX, centerY); 83 | destroy(); 84 | } 85 | } 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /src/en/Label.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class Label extends Entity { 4 | public function new(x,y, str:String) { 5 | super(x,y); 6 | 7 | spr.set("empty"); 8 | var tf = new h2d.Text(Assets.fontTiny, spr); 9 | tf.text = str; 10 | tf.maxWidth = 150; 11 | tf.x = Std.int(-tf.textWidth*0.5); 12 | tf.y = Std.int(-tf.textHeight ); 13 | } 14 | 15 | override function postUpdate() { 16 | super.postUpdate(); 17 | spr.visible = !Console.ME.hasFlag("screen"); 18 | } 19 | } -------------------------------------------------------------------------------- /src/en/MobGen.hx: -------------------------------------------------------------------------------- 1 | package en; 2 | 3 | class MobGen extends Entity { 4 | public static var ALL : Array = []; 5 | 6 | var children : Array = []; 7 | public var maxChildren = 5; 8 | public var perSpawn = 2; 9 | public var delay = 5.; 10 | 11 | public function new(x,y) { 12 | super(x,y); 13 | ALL.push(this); 14 | spr.set("gen"); 15 | enableShadow(); 16 | game.scroller.add(spr, Const.DP_BG); 17 | } 18 | 19 | override function dispose() { 20 | super.dispose(); 21 | ALL.remove(this); 22 | children = null; 23 | } 24 | 25 | function spawn() { 26 | var e = new en.ai.mob.Goblin(cx,cy); 27 | e.dz = -rnd(0.2,0.4); 28 | e.dx = rnd(0,0.2,true); 29 | e.dy = rnd(0,0.2,true); 30 | return e; 31 | } 32 | 33 | override function postUpdate() { 34 | super.postUpdate(); 35 | spr.alpha = 0.6; 36 | } 37 | 38 | override function update() { 39 | super.update(); 40 | 41 | // GC 42 | var i = 0; 43 | while( i0 && children.length = []; 5 | 6 | public function new(x,y) { 7 | super(x,y); 8 | 9 | initLife(999); 10 | ALL.push(this); 11 | weight = 8; 12 | detectRadius = 12; 13 | atkRange = 1.5; 14 | 15 | spr.anim.registerStateAnim("d_hit", 10, 0.15, function() return hasAffect(Stun) ); 16 | spr.anim.registerStateAnim("d_atk_charge", 3, 0.15, function() return isChargingAction("atk") ); 17 | spr.anim.registerStateAnim("d_act", 2, 0.15, function() return isChargingAction() ); 18 | spr.anim.registerStateAnim("d_walk", 1, rnd(0.11,0.15), function() return isWalking() ); 19 | spr.anim.registerStateAnim("d_idle", 0, 0.1); 20 | game.scroller.add(spr, Const.DP_DWARF); 21 | 22 | doTask( Wait(ftime+1.5*Const.FPS) ); 23 | } 24 | 25 | override function dispose() { 26 | super.dispose(); 27 | 28 | ALL.remove(this); 29 | } 30 | 31 | override function onDamage(dmg:Int, from:Null) { 32 | super.onDamage(dmg, from); 33 | 34 | cancelAction(); 35 | if( isAlive() ) 36 | releaseCarriedEnt(true); 37 | 38 | blink(0xffffff); 39 | 40 | setAffectS(Stun,0.45); 41 | fx.flashBangS(0xff0000, 0.1, 0.2); 42 | 43 | if( from!=null ) 44 | bumpFrom(from, 0.08); 45 | } 46 | 47 | override function onDie(?from:Entity) { 48 | super.onDie(from); 49 | if( ALL.length==1 ) 50 | game.gameOver(); 51 | fx.bloodExplosion(centerX, centerY); 52 | game.announce("Dwarf obliterated", 0xff0000, true); 53 | } 54 | 55 | override function getSpeed():Float { 56 | return super.getSpeed(); 57 | } 58 | 59 | function takeDecision() { 60 | if( game.countRemainingGems()==0 && Cart.ME!=null ) { 61 | doTask(ExitLevel); 62 | return; 63 | } 64 | 65 | var boss = en.ai.mob.Boss.ME; 66 | if( boss!=null && distCase(boss)<=4 && ( sightCheckEnt(boss) || boss.isChargingAction("atk") ) ) { 67 | doTask(FleeBoss(boss)); 68 | return; 69 | } 70 | 71 | var dh = new dn.DecisionHelper(Entity.ALL); 72 | dh.keepOnly( function(e) return e.is(Item) || e.is(Breakable) ); 73 | dh.keepOnly( function(e) return e.isAlive() && !isProhibited(e) && canDetect(e) ); 74 | dh.score( function(e) return rnd(0,2) ); 75 | dh.score( function(e) return -distCase(e)*0.2 ); 76 | 77 | // Score based on itemType 78 | dh.score( function(e) { 79 | return 80 | if( e.is(Item) ) 81 | switch e.as(Item).type { 82 | case Gem: 2; 83 | case BaitFull, BaitPart: 5; 84 | case Bomb: 0.75; 85 | } 86 | else if( e.is(Breakable) ) 87 | 0.75; 88 | else 89 | 0; 90 | }); 91 | 92 | dh.useBest( function(e) { 93 | if( e.is(Item) ) 94 | doTask( Grab(e.as(Item)) ); 95 | else if( e.is(Breakable) ) 96 | doTask( Break(e.as(Breakable)) ); 97 | }); 98 | } 99 | 100 | override function doTask(t:Task) { 101 | if( t==Idle && task!=Idle ) 102 | cd.setS("decision", rnd(0.2,0.3)); 103 | 104 | super.doTask(t); 105 | } 106 | 107 | override function showTaskFocus(e:Entity) { 108 | super.showTaskFocus(e); 109 | 110 | if( !cd.hasSetS("focusFx",0.1) ) 111 | fx.focus(this, e); 112 | } 113 | 114 | override function updateAi() { 115 | super.updateAi(); 116 | 117 | switch task { 118 | case Idle: 119 | if( !cd.has("pickIdlePt") ) { 120 | cd.setS("pickIdlePt",rnd(1,1.5)); 121 | var dh = new dn.DecisionHelper( dn.Bresenham.getDisc(cx,cy, 4) ); 122 | dh.keepOnly( function(pt) return !level.hasCollision(pt.x,pt.y) && sightCheckCase(pt.x,pt.y) ); 123 | dh.score( function(pt) return rnd(0,1,true) + distCaseFree(pt.x,pt.y)*0.5 ); 124 | for(d in ALL) 125 | if( d!=this && distCase(d)<=5 ) 126 | dh.score( function(pt) return d.distCaseFree(pt.x,pt.y)*0.08 ); 127 | 128 | dh.useBest( function(pt) { 129 | goto(pt.x,pt.y); 130 | }); 131 | } 132 | 133 | if( !cd.hasSetS("decision", 0.6) ) 134 | takeDecision(); 135 | 136 | case Break(e): 137 | if( !e.isAlive() ) { 138 | doTask(Idle); 139 | return; 140 | } 141 | if( distCase(e)<=1 ) 142 | chargeAtk(e); 143 | 144 | case WaitWithItem(e): 145 | if( !cd.hasSetS("huh",3) ) 146 | popText("Huh?", 0xff6600); 147 | 148 | case _: 149 | } 150 | } 151 | 152 | 153 | var atkA = true; 154 | override function chargeAtk(e) { 155 | super.chargeAtk(e); 156 | 157 | chargeAction("atk", 0.07, function() { 158 | spr.anim.play(atkA ? "d_atkA" : "d_atkB").setSpeed(0.2); 159 | lockAiS(atkA ? 0.1 : 0.3); 160 | cd.setS("resetAtk",0.4); 161 | atkA = !atkA; 162 | 163 | if( !e.isAlive() || distCase(e)>atkRange*2 ) 164 | return; 165 | 166 | e.hit(1, this); 167 | if( atkA && path.length==0 ) { 168 | dx += Math.cos(angTo(e))*0.05; 169 | dy += Math.sin(angTo(e))*0.05; 170 | } 171 | else 172 | bumpEnt(e, rnd(0.08,0.09)); 173 | 174 | game.camera.shakeS(0.2,0.2); 175 | game.camera.bump(dir*4,0); 176 | fx.impact(e.headX, e.headY, angTo(e)); 177 | if( e.is(Mob) ) { 178 | fx.bloodImpact(e.headX, e.headY, angTo(e)); 179 | fx.blood(e.headX, e.headY, angTo(e)); 180 | } 181 | else 182 | fx.dirtImpact(e.centerX, e.centerY, 0xb57a40, angTo(e)); 183 | }); 184 | } 185 | 186 | override function getAttackables() : Array { 187 | return cast Mob.ALL; 188 | } 189 | 190 | override function postUpdate() { 191 | super.postUpdate(); 192 | if( bubble!=null ) { 193 | bubble.x = Std.int( headX ); 194 | bubble.y = Std.int( headY-3 - M.fabs( Math.cos(ftime*0.1)*2 ) ); 195 | } 196 | } 197 | 198 | override function update() { 199 | super.update(); 200 | 201 | if( !atkA && !cd.has("resetAtk") ) 202 | atkA = true; 203 | } 204 | } -------------------------------------------------------------------------------- /src/en/ai/Mob.hx: -------------------------------------------------------------------------------- 1 | package en.ai; 2 | 3 | class Mob extends en.Ai { 4 | public static var ALL : Array = []; 5 | 6 | private function new(x,y) { 7 | super(x,y); 8 | ALL.push(this); 9 | detectRadius = 7; 10 | weight = 1; 11 | } 12 | 13 | override function onDamage(dmg:Int, from:Null) { 14 | super.onDamage(dmg, from); 15 | } 16 | 17 | override function dispose() { 18 | super.dispose(); 19 | ALL.remove(this); 20 | } 21 | 22 | 23 | override function updateAi() { 24 | super.updateAi(); 25 | updateAggro(); 26 | } 27 | 28 | function updateAggro() { 29 | if( task==Idle ) { 30 | for(e in Dwarf.ALL) 31 | if( distCase(e)<=detectRadius && sightCheckEnt(e) ) { 32 | for(m in ALL) 33 | if( m!=this && m.isAlive() && distCase(m)<=4 && sightCheckEnt(m) ) 34 | m.doTask( AttackDwarf(e) ); 35 | doTask( AttackDwarf(e) ); 36 | } 37 | } 38 | } 39 | 40 | override function getAttackables() { 41 | return cast Dwarf.ALL; 42 | } 43 | } -------------------------------------------------------------------------------- /src/en/ai/mob/Boss.hx: -------------------------------------------------------------------------------- 1 | package en.ai.mob; 2 | 3 | class Boss extends en.ai.Mob { 4 | public static var ME : Boss; 5 | 6 | public function new(x,y) { 7 | super(x,y); 8 | ME = this; 9 | initLife(9999); 10 | atkRange = 2; 11 | weight = 1; 12 | sprScaleX = sprScaleY = 3; 13 | 14 | spr.anim.registerStateAnim("a_atk_charge", 2, 0.15, function() return isChargingAction("atk") ); 15 | spr.anim.registerStateAnim("a_walk", 1, 0.15, function() return isWalking() ); 16 | spr.anim.registerStateAnim("a_idle", 0, 0.1); 17 | } 18 | 19 | override function dispose() { 20 | super.dispose(); 21 | if( ME==this ) 22 | ME = null; 23 | } 24 | 25 | override function getSpeed():Float { 26 | return super.getSpeed()*0.55; 27 | } 28 | 29 | override function onBeforePhysics() { 30 | super.onBeforePhysics(); 31 | bdx*=Math.pow(0.1,tmod); 32 | bdy*=Math.pow(0.1,tmod); 33 | } 34 | 35 | override function chargeAtk(e:Entity) { 36 | super.chargeAtk(e); 37 | 38 | bumpTo(e, 0.05); 39 | chargeAction("atk", 2, function() { 40 | dir = dirTo(e); 41 | 42 | spr.anim.play("a_atk").setSpeed(0.2); 43 | lockAiS(1); 44 | 45 | var a = angTo(e); 46 | fx.bossAtk(footX+Math.cos(a)*atkRange*Const.GRID, footY+Math.sin(a)*atkRange*Const.GRID); 47 | game.camera.shakeS(0.4, 1); 48 | 49 | if( !e.isAlive() || distCase(e)>atkRange*2 || !sightCheckEnt(e) ) 50 | return; 51 | 52 | lockAtk(1); 53 | e.hit(99999, this); 54 | game.addSlowMo("boss",0.5, 0.3); 55 | fx.bloodImpact(e.headX, e.headY, angTo(e)); 56 | }); 57 | } 58 | 59 | 60 | override function updateAggro() { 61 | if( Dwarf.ALL.length==0 ) 62 | return; 63 | 64 | if( task==Idle ) 65 | doTask( AttackDwarf(Dwarf.ALL[0]) ); 66 | 67 | if( !cd.hasSetS("aggroBoss", 1) ) { 68 | var dh = new dn.DecisionHelper(Dwarf.ALL); 69 | dh.keepOnly( function(e) return e.isAlive() ); 70 | dh.score( function(e) return -distCase(e)*0.2 ); 71 | dh.score( function(e) return sightCheckEnt(e) ? 3 : 0 ); 72 | dh.useBest( function(e) { 73 | doTask( AttackDwarf(e) ); 74 | }); 75 | } 76 | } 77 | 78 | override function showTaskFocus(e:Entity) { 79 | super.showTaskFocus(e); 80 | fx.focus(this, e, 0xff0000); 81 | } 82 | 83 | 84 | override function postUpdate() { 85 | super.postUpdate(); 86 | if( isChargingAction("atk") && !cd.has("blinkBoss") ) { 87 | if( getActionRemainingSec("atk")<=1 ) { 88 | blink(0xffff00, 0.1); 89 | cd.setS("blinkBoss", 0.15); 90 | } 91 | // else { 92 | // blink(0xff0000); 93 | // cd.setS("blinkBoss", 0.4); 94 | // } 95 | } 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /src/en/ai/mob/Goblin.hx: -------------------------------------------------------------------------------- 1 | package en.ai.mob; 2 | 3 | class Goblin extends en.ai.Mob { 4 | public function new(x,y) { 5 | super(x,y); 6 | initLife( irnd(1,2) ); 7 | detectRadius = 6; 8 | atkRange = 0.8; 9 | weight = 1; 10 | 11 | spr.anim.registerStateAnim("a_atk_charge", 2, 0.15, function() return isChargingAction("atk") ); 12 | spr.anim.registerStateAnim("a_walk", 1, 0.15, function() return isWalking() ); 13 | spr.anim.registerStateAnim("a_idle", 0, 0.1); 14 | } 15 | 16 | override function onDamage(dmg:Int, from:Null) { 17 | super.onDamage(dmg, from); 18 | cancelAction(); 19 | lockAiS(rnd(0.6,0.8)); 20 | blink(0xffffff); 21 | } 22 | 23 | override function onDie(?from:Entity) { 24 | super.onDie(from); 25 | fx.gibs(centerX, centerY, from.angTo(this), 0x748954); 26 | } 27 | 28 | override function getSpeed():Float { 29 | return super.getSpeed()*2; 30 | } 31 | 32 | 33 | override function chargeAtk(e:Entity) { 34 | super.chargeAtk(e); 35 | 36 | bumpTo(e, 0.05); 37 | chargeAction("atk", 0.5, function() { 38 | dir = dirTo(e); 39 | 40 | spr.anim.play("a_atk").setSpeed(0.2); 41 | lockAiS(1); 42 | 43 | 44 | if( !e.isAlive() || distCase(e)>2 ) 45 | return; 46 | 47 | lockAtk(1); 48 | e.hit(1, this); 49 | fx.bloodImpact(e.headX, e.headY, angTo(e)); 50 | }); 51 | } 52 | } -------------------------------------------------------------------------------- /src/import.hx: -------------------------------------------------------------------------------- 1 | import dn.M; 2 | import dn.Lib; 3 | import dn.Color; 4 | import dn.Color as C; 5 | import dn.Tweenie; 6 | import dn.data.GetText; 7 | import dn.heaps.slib.*; 8 | import ui.Console; 9 | import tools.*; 10 | import Types; -------------------------------------------------------------------------------- /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 setPixel(x:Float, y:Float) { 29 | cx = Std.int(x/Const.GRID); 30 | cy = Std.int(y/Const.GRID); 31 | xr = (x-cx*Const.GRID)/Const.GRID; 32 | yr = (y-cy*Const.GRID)/Const.GRID; 33 | } 34 | 35 | public function setEntity(e:Entity) { 36 | cx = e.cx; 37 | cy = e.cy; 38 | xr = e.xr; 39 | yr = e.yr; 40 | } 41 | 42 | public function distCase(?e:Entity, ?pt:CPoint, ?cx=0, ?cy=0, ?xr=0.5, ?yr=0.5) { 43 | if( e!=null ) 44 | return M.dist(this.cx+this.xr, this.cy+this.yr, e.cx+e.xr, e.cy+e.yr); 45 | else if( pt!=null ) 46 | return M.dist(this.cx+this.xr, this.cy+this.yr, pt.cx+pt.xr, pt.cy+pt.yr); 47 | else 48 | return M.dist(this.cx+this.xr, this.cy+this.yr, cx+xr, cy+yr); 49 | } 50 | 51 | public inline function distPx(?e:Entity, ?pt:CPoint, ?x=0., ?y=0.) { 52 | if( e!=null ) 53 | return M.dist(footX, footY, e.footX, e.footY); 54 | else if( pt!=null ) 55 | return M.dist(footX, footY, pt.footX, pt.footY); 56 | else 57 | return M.dist(footX, footY, x, y); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/tools/MouseCoords.hx: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | class MouseCoords { 4 | public var gx : Float; 5 | public var gy : Float; 6 | 7 | public var levelX(get,never) : Int; 8 | inline function get_levelX() return M.round( ( gx - game.scroller.x ) / Const.SCALE ); 9 | 10 | public var levelY(get,never) : Int; 11 | inline function get_levelY() return M.round( ( gy - game.scroller.y ) / Const.SCALE ); 12 | 13 | public var cx(get,never) : Int; 14 | inline function get_cx() return M.floor( levelX / Const.GRID ); 15 | 16 | public var cy(get,never) : Int; 17 | inline function get_cy() return M.floor( levelY / Const.GRID ); 18 | 19 | var game(get,never) : Game; inline function get_game() return Game.ME; 20 | 21 | public function new(gx:Float,gy:Float) { 22 | this.gx = gx; 23 | this.gy = gy; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/ui/Bar.hx: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | class Bar extends h2d.Object { 4 | var cd : dn.Cooldown; 5 | var bg : h2d.ScaleGrid; 6 | var bar : h2d.ScaleGrid; 7 | var oldBar : Null; 8 | 9 | public var innerBarMaxWidth(get,never) : Float; 10 | public var innerBarHeight(get,never) : Float; 11 | public var outerWidth(get,never) : Float; 12 | public var outerHeight(get,never) : Float; 13 | public var color(default,set) : UInt; 14 | public var defaultColor(default,null) : UInt; 15 | var padding : Int; 16 | var oldBarSpeed : Float; 17 | 18 | var blinkColor : h3d.Vector; 19 | var gradTg : Null; 20 | 21 | var curValue : Float; 22 | var curMax : Float; 23 | 24 | public function new(wid:Int, hei:Int, c:UInt, ?p:h2d.Object) { 25 | super(p); 26 | 27 | curValue = 0; 28 | curMax = 1; 29 | cd = new dn.Cooldown(Const.FPS); 30 | 31 | bg = new h2d.ScaleGrid( Assets.tiles.getTile("uiBarBg"), 2, 2, this ); 32 | bg.colorAdd = blinkColor = new h3d.Vector(); 33 | 34 | bar = new h2d.ScaleGrid( Assets.tiles.getTile("uiBar"), 1,1, this ); 35 | 36 | setSize(wid,hei,1); 37 | defaultColor = color = c; 38 | } 39 | 40 | public function enableOldValue(oldBarColor:UInt, speed=1.0) { 41 | if( oldBar!=null ) 42 | oldBar.remove(); 43 | oldBar = new h2d.ScaleGrid( h2d.Tile.fromColor(oldBarColor,3,3), 1, 1 ); 44 | this.addChildAt( oldBar, this.getChildIndex(bar) ); 45 | oldBar.height = bar.height; 46 | oldBar.width = 0; 47 | oldBar.setPosition(padding,padding); 48 | 49 | oldBarSpeed = speed; 50 | } 51 | 52 | public function setGraduationPx(step:Int, ?alpha=0.5) { 53 | if( step<=1 ) 54 | throw "Invalid bar graduation "+step; 55 | 56 | if( gradTg!=null ) 57 | gradTg.remove(); 58 | 59 | gradTg = new h2d.TileGroup(Assets.tiles.tile, this); 60 | gradTg.colorAdd = blinkColor; 61 | gradTg.setDefaultColor(0x0, alpha); 62 | 63 | var x = step-1; 64 | var t = Assets.tiles.getTile("pixel"); 65 | while( xbar.width) { 114 | cd.setS("oldMaintain",0.06); 115 | oldBar.width = oldWidth; 116 | } 117 | } 118 | 119 | function renderBar() { 120 | bar.visible = curValue>0; 121 | bar.width = innerBarMaxWidth * (curValue/curMax); 122 | } 123 | 124 | public function skipOldValueBar() { 125 | if( oldBar!=null ) 126 | oldBar.width = 0; 127 | } 128 | 129 | public function blink(?c:UInt, ?a=1.0) { 130 | blinkColor.setColor( Color.addAlphaF(c==null ? color : c,a) ); 131 | cd.setS("blinkMaintain", 0.15 * 1/oldBarSpeed); 132 | } 133 | 134 | override function sync(ctx:h2d.RenderContext) { 135 | var tmod = Game.ME.tmod; 136 | cd.update(tmod); 137 | 138 | // Decrease oldValue bar 139 | if( oldBar!=null ) { 140 | if( !cd.has("oldMaintain") ) 141 | oldBar.width = M.fmax(0, oldBar.width - oldBarSpeed*2*tmod); 142 | oldBar.visible = oldBar.width>0; 143 | } 144 | 145 | // Blink fade 146 | if( !cd.has("blinkMaintain") ) { 147 | blinkColor.r*=Math.pow(0.60, tmod); 148 | blinkColor.g*=Math.pow(0.55, tmod); 149 | blinkColor.b*=Math.pow(0.50, tmod); 150 | } 151 | 152 | super.sync(ctx); 153 | } 154 | } -------------------------------------------------------------------------------- /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 | h2d.Console.HIDE_LOG_TIMEOUT = 30; 17 | Lib.redirectTracesToH2dConsole(this); 18 | 19 | // Debug flags 20 | #if debug 21 | flags = new Map(); 22 | this.addCommand("set", [{ name:"k", t:AString }], function(k:String) { 23 | setFlag(k,true); 24 | log("+ "+k.toLowerCase(), 0x80FF00); 25 | }); 26 | this.addCommand("unset", [{ name:"k", t:AString, opt:true } ], function(?k:String) { 27 | if( k==null ) { 28 | log("Reset all.",0xFF0000); 29 | for(k in flags.keys()) 30 | setFlag(k,false); 31 | } 32 | else { 33 | log("- "+k,0xFF8000); 34 | setFlag(k,false); 35 | } 36 | }); 37 | this.addCommand("list", [], function() { 38 | for(k in flags.keys()) 39 | log(k, 0x80ff00); 40 | }); 41 | this.addAlias("+","set"); 42 | this.addAlias("-","unset"); 43 | #end 44 | } 45 | 46 | override function handleCommand(command:String) { 47 | var flagReg = ~/[\/ \t]*\+[ \t]*([\w]+)/g; // cleanup missing spaces 48 | super.handleCommand( flagReg.replace(command, "/+ $1") ); 49 | } 50 | 51 | public function error(msg:Dynamic) { 52 | log("[ERROR] "+Std.string(msg), 0xff0000); 53 | h2d.Console.HIDE_LOG_TIMEOUT = Const.INFINITE; 54 | } 55 | 56 | #if debug 57 | public function setFlag(k:String,v) { 58 | k = k.toLowerCase(); 59 | var hadBefore = hasFlag(k); 60 | 61 | if( v ) 62 | flags.set(k,v); 63 | else 64 | flags.remove(k); 65 | 66 | if( v && !hadBefore || !v && hadBefore ) 67 | onFlagChange(k,v); 68 | return v; 69 | } 70 | public function hasFlag(k:String) return flags.get( k.toLowerCase() )==true; 71 | #else 72 | public function hasFlag(k:String) return false; 73 | #end 74 | 75 | public function onFlagChange(k:String, v:Bool) {} 76 | } -------------------------------------------------------------------------------- /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 | var lastBaits = 0; 11 | 12 | public function new() { 13 | super(Game.ME); 14 | 15 | createRootInLayers(game.root, Const.DP_UI); 16 | root.filter = new h2d.filter.ColorMatrix(); // force pixel perfect rendering 17 | 18 | flow = new h2d.Flow(root); 19 | flow.layout = Vertical; 20 | // flow.backgroundTile = h2d.Tile.fromColor(0x0); 21 | flow.padding = 2; 22 | } 23 | 24 | override function onResize() { 25 | super.onResize(); 26 | root.setScale(Const.UI_SCALE); 27 | flow.x = 2; 28 | flow.y = Std.int( h()/Const.UI_SCALE*0.5 - flow.outerHeight*0.5 ); 29 | } 30 | 31 | public inline function invalidate() invalidated = true; 32 | 33 | function render() { 34 | flow.removeChildren(); 35 | for(i in 0...Const.BAITS) { 36 | var active = i+1<=game.baits; 37 | var k = "uiBait"+(active?"On":"Off"); 38 | if( game.kidMode ) 39 | k = active ? "i_HeartFull" : "i_HeartHollow"; 40 | var e = Assets.tiles.h_get(k, flow); 41 | e.scale(2); 42 | if( active && i+1>lastBaits ) { 43 | var a = Assets.tiles.h_get("fxExplosion", flow); 44 | a.blendMode = Add; 45 | a.colorize(0x9effa5); 46 | a.setCenterRatio(0.5,0.5); 47 | a.rotation = M.PI; 48 | a.scale(2); 49 | 50 | a.anim.play("fxExplosion"); 51 | a.anim.killAfterPlay(); 52 | a.anim.setSpeed(0.2); 53 | 54 | flow.getProperties(a).isAbsolute = true; 55 | flow.reflow(); 56 | a.x = e.x + e.tile.width*0.5 * e.scaleX; 57 | a.y = e.y + e.tile.height*0.5 * e.scaleY; 58 | } 59 | } 60 | lastBaits = game.baits; 61 | } 62 | 63 | override function postUpdate() { 64 | super.postUpdate(); 65 | 66 | if( invalidated ) { 67 | invalidated = false; 68 | render(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /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 : dn.heaps.Controller.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(Game.ME); 8 | 9 | createRootInLayers(Game.ME.root, Const.DP_UI); 10 | root.filter = new h2d.filter.ColorMatrix(); // force pixel perfect rendering 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 | 34 | root.scale(Const.UI_SCALE); 35 | 36 | var w = M.ceil( w()/Const.UI_SCALE ); 37 | var h = M.ceil( h()/Const.UI_SCALE ); 38 | win.x = Std.int( w*0.5 - win.outerWidth*0.5 ); 39 | win.y = Std.int( h*0.5 - win.outerHeight*0.5 ); 40 | } 41 | 42 | function onClose() {} 43 | public function close() { 44 | if( !destroyed ) { 45 | destroy(); 46 | onClose(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /swf.hxml: -------------------------------------------------------------------------------- 1 | base.hxml 2 | -swf bin/client.swf 3 | -swf-header 1400:700:60:000000 4 | -swf-version 24.0 5 | --------------------------------------------------------------------------------