aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--LICENSE.md27
-rw-r--r--README.md44
-rw-r--r--Sprite-0001.asebin0 -> 8209 bytes
-rw-r--r--Sprite-0001.json840
-rw-r--r--Sprite-0001.pngbin0 -> 1214 bytes
-rw-r--r--Tiles.tsx4
-rw-r--r--maps/map0.tmx25
-rw-r--r--maps/map1.tmx25
-rw-r--r--maps/map2.tmx25
-rw-r--r--maps/map3.tmx25
-rw-r--r--maps/map4.tmx25
-rw-r--r--maps/map5.tmx25
-rw-r--r--maps/map6.tmx25
-rw-r--r--maps/map7.tmx25
-rw-r--r--maps/map8.tmx25
-rw-r--r--pal.pal19
-rw-r--r--scripts/00-Tiled2HC.py133
-rw-r--r--scripts/01-ExtractTiles.py120
-rw-r--r--scripts/02-AddMapData.py30
-rw-r--r--src/FCTR.HC221
-rw-r--r--src/Load.HC5
-rw-r--r--src/Map.HC57
-rw-r--r--src/Math.HC95
-rw-r--r--src/Palette.HC11
-rw-r--r--src/PaletteZeal.ZC11
-rw-r--r--src/Player.HC202
-rw-r--r--src/PxBlot.HC61
-rw-r--r--src/Run.HC2
-rw-r--r--src/TOSMods.HC8
-rw-r--r--tileset.pngbin0 -> 2297 bytes
-rw-r--r--tos_project.toml6
32 files changed, 2125 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9030e6e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+build
+out
+output
+temp.txt
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..2e61574
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,27 @@
+# DON'T BE A DICK PUBLIC LICENSE
+
+> Version 1.1, December 2016
+
+> Copyright (C) 2022 Slendi <slendi@socopon.com>
+
+Everyone is permitted to copy and distribute verbatim or modified
+copies of this license document.
+
+> DON'T BE A DICK PUBLIC LICENSE
+> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+1. Do whatever you like with the original work, just don't be a dick.
+
+ Being a dick includes - but is not limited to - the following instances:
+
+ 1a. Outright copyright infringement - Don't just copy this and change the name.
+ 1b. Selling the unmodified original with no work done what-so-ever, that's REALLY being a dick.
+ 1c. Modifying the original work to contain hidden harmful content. That would make you a PROPER dick.
+
+2. If you become rich through modifications, related works/services, or supporting the original work,
+share the love. Only a dick would make loads off this work and not buy the original work's
+creator(s) a pint.
+
+3. Code is provided with no warranty. Using somebody else's code and bitching when it goes wrong makes
+you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..eefefdf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,44 @@
+TempleOS Factorunner
+====================
+
+What's this?
+------------
+
+This is a TempleOS and ZealOS port of my game [Factorunner](https://tic80.com/play?cart=2081).
+
+Ok how do I run this thing?
+---------------------------
+
+Right now the build system is kinda scuffed, you need to have:
+ * powershell core
+ * python3
+ * python3-pillow
+
+For VM:
+ * bash, qemu-system-x86\_64 (if on Linux)
+ * archiso (if on Arch)
+
+K i now have this shit, what do I do now?
+-----------------------------------------
+
+You simply run `./Build.ps1`. This will start the build process. If you wish to build for ZealOS instead,
+you can run `./Build.ps1 -zeal $true` or `$ ZEAL=ON ./Build.ps1`.
+
+After that is done, on Linux, you will be asked if you want to start a VM if you chose not to build for ZealOS.
+
+For TempleOS, the ISO.C file is located under the `tos` directory under the name of `factorunner.ISO.C`.
+For ZealOS, the ISO.C file is located in the root of the repository under the name of `factorunner_zeal.ISO.C`.
+
+VM?
+---
+
+Yes, if you are on linux, you can start a VM using `cd tos && ./tos.sh run`. This will automatically configure a VM for you (except the base installation of TempleOS).
+
+Archiso, optionally, is then used to install the GRUB2 bootloader which allows you to boot without manually pressing `1`.
+
+When the VM boots up fully, you can then use the macro in the terminal to launch the game.
+
+LICENSE
+-------
+
+This software is licensed under the DBAD license. Click [here](LICENSE.md) for more details.
diff --git a/Sprite-0001.ase b/Sprite-0001.ase
new file mode 100644
index 0000000..5fac9eb
--- /dev/null
+++ b/Sprite-0001.ase
Binary files differ
diff --git a/Sprite-0001.json b/Sprite-0001.json
new file mode 100644
index 0000000..9e7123a
--- /dev/null
+++ b/Sprite-0001.json
@@ -0,0 +1,840 @@
+{ "frames": {
+ "Sprite-0001 0.ase": {
+ "frame": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 1.ase": {
+ "frame": { "x": 8, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 2.ase": {
+ "frame": { "x": 16, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 3.ase": {
+ "frame": { "x": 24, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 4.ase": {
+ "frame": { "x": 32, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 5.ase": {
+ "frame": { "x": 40, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 6.ase": {
+ "frame": { "x": 48, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 7.ase": {
+ "frame": { "x": 56, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 8.ase": {
+ "frame": { "x": 64, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 9.ase": {
+ "frame": { "x": 72, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 10.ase": {
+ "frame": { "x": 80, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 11.ase": {
+ "frame": { "x": 88, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 12.ase": {
+ "frame": { "x": 96, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 13.ase": {
+ "frame": { "x": 104, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 14.ase": {
+ "frame": { "x": 112, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 15.ase": {
+ "frame": { "x": 120, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 16.ase": {
+ "frame": { "x": 128, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 17.ase": {
+ "frame": { "x": 136, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 18.ase": {
+ "frame": { "x": 144, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 19.ase": {
+ "frame": { "x": 152, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 20.ase": {
+ "frame": { "x": 160, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 21.ase": {
+ "frame": { "x": 168, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 22.ase": {
+ "frame": { "x": 176, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 23.ase": {
+ "frame": { "x": 184, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 24.ase": {
+ "frame": { "x": 192, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 25.ase": {
+ "frame": { "x": 200, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 26.ase": {
+ "frame": { "x": 208, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 27.ase": {
+ "frame": { "x": 216, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 28.ase": {
+ "frame": { "x": 224, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 29.ase": {
+ "frame": { "x": 232, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 30.ase": {
+ "frame": { "x": 240, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 31.ase": {
+ "frame": { "x": 248, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 32.ase": {
+ "frame": { "x": 256, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 33.ase": {
+ "frame": { "x": 264, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 34.ase": {
+ "frame": { "x": 272, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 35.ase": {
+ "frame": { "x": 280, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 36.ase": {
+ "frame": { "x": 288, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 37.ase": {
+ "frame": { "x": 296, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 38.ase": {
+ "frame": { "x": 304, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 39.ase": {
+ "frame": { "x": 312, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 40.ase": {
+ "frame": { "x": 320, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 41.ase": {
+ "frame": { "x": 328, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 42.ase": {
+ "frame": { "x": 336, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 43.ase": {
+ "frame": { "x": 344, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 44.ase": {
+ "frame": { "x": 352, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 45.ase": {
+ "frame": { "x": 360, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 46.ase": {
+ "frame": { "x": 368, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 47.ase": {
+ "frame": { "x": 376, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 48.ase": {
+ "frame": { "x": 384, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 49.ase": {
+ "frame": { "x": 392, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 50.ase": {
+ "frame": { "x": 400, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 51.ase": {
+ "frame": { "x": 408, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 52.ase": {
+ "frame": { "x": 416, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 53.ase": {
+ "frame": { "x": 424, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 54.ase": {
+ "frame": { "x": 432, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 55.ase": {
+ "frame": { "x": 440, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 56.ase": {
+ "frame": { "x": 448, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 57.ase": {
+ "frame": { "x": 456, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 58.ase": {
+ "frame": { "x": 464, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 59.ase": {
+ "frame": { "x": 472, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 60.ase": {
+ "frame": { "x": 480, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 61.ase": {
+ "frame": { "x": 488, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 62.ase": {
+ "frame": { "x": 496, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 63.ase": {
+ "frame": { "x": 504, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 64.ase": {
+ "frame": { "x": 512, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 65.ase": {
+ "frame": { "x": 520, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 66.ase": {
+ "frame": { "x": 528, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 67.ase": {
+ "frame": { "x": 536, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 68.ase": {
+ "frame": { "x": 544, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 69.ase": {
+ "frame": { "x": 552, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 70.ase": {
+ "frame": { "x": 560, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 71.ase": {
+ "frame": { "x": 568, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 72.ase": {
+ "frame": { "x": 576, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 73.ase": {
+ "frame": { "x": 584, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 74.ase": {
+ "frame": { "x": 592, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 75.ase": {
+ "frame": { "x": 600, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 76.ase": {
+ "frame": { "x": 608, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 77.ase": {
+ "frame": { "x": 616, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 78.ase": {
+ "frame": { "x": 624, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 79.ase": {
+ "frame": { "x": 632, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 80.ase": {
+ "frame": { "x": 640, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 81.ase": {
+ "frame": { "x": 648, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 82.ase": {
+ "frame": { "x": 656, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 83.ase": {
+ "frame": { "x": 664, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 84.ase": {
+ "frame": { "x": 672, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 85.ase": {
+ "frame": { "x": 680, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 86.ase": {
+ "frame": { "x": 688, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 87.ase": {
+ "frame": { "x": 696, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 88.ase": {
+ "frame": { "x": 704, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 89.ase": {
+ "frame": { "x": 712, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 90.ase": {
+ "frame": { "x": 720, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 91.ase": {
+ "frame": { "x": 728, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 92.ase": {
+ "frame": { "x": 736, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 93.ase": {
+ "frame": { "x": 744, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 94.ase": {
+ "frame": { "x": 752, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 95.ase": {
+ "frame": { "x": 760, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 96.ase": {
+ "frame": { "x": 768, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 97.ase": {
+ "frame": { "x": 776, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 98.ase": {
+ "frame": { "x": 784, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 99.ase": {
+ "frame": { "x": 792, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 100.ase": {
+ "frame": { "x": 800, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 101.ase": {
+ "frame": { "x": 808, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ },
+ "Sprite-0001 102.ase": {
+ "frame": { "x": 816, "y": 0, "w": 8, "h": 8 },
+ "rotated": false,
+ "trimmed": false,
+ "spriteSourceSize": { "x": 0, "y": 0, "w": 8, "h": 8 },
+ "sourceSize": { "w": 8, "h": 8 },
+ "duration": 100
+ }
+ },
+ "meta": {
+ "app": "https://github.com/LibreSprite/LibreSprite/",
+ "version": "1.0-dev",
+ "image": "/home/slendi/Documents/Code/FactorunnerTOS/Sprite-0001.png",
+ "format": "I8",
+ "size": { "w": 824, "h": 8 },
+ "scale": "1",
+ "frameTags": [
+ ],
+ "layers": [
+ { "name": "Layer 1", "opacity": 255, "blendMode": "normal" }
+ ]
+ }
+}
diff --git a/Sprite-0001.png b/Sprite-0001.png
new file mode 100644
index 0000000..daaa9b6
--- /dev/null
+++ b/Sprite-0001.png
Binary files differ
diff --git a/Tiles.tsx b/Tiles.tsx
new file mode 100644
index 0000000..0467225
--- /dev/null
+++ b/Tiles.tsx
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tileset version="1.5" tiledversion="1.7.2" name="tileset" tilewidth="8" tileheight="8" tilecount="103" columns="103">
+ <image source="tileset.png" width="824" height="8"/>
+</tileset>
diff --git a/maps/map0.tmx b/maps/map0.tmx
new file mode 100644
index 0000000..d26cce8
--- /dev/null
+++ b/maps/map0.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,86,87,88,0,0,0,0,0,
+0,0,0,0,0,0,70,71,72,73,74,75,76,77,78,79,80,81,82,85,84,85,89,90,91,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+</data>
+ </layer>
+</map>
diff --git a/maps/map1.tmx b/maps/map1.tmx
new file mode 100644
index 0000000..da99369
--- /dev/null
+++ b/maps/map1.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,25,3,14,13,2,25,11,22,10,2,22,10,7,2,14,7,8,22,2,3,16,6,2,2,1,2,
+2,1,2,2,2,2,2,20,11,9,10,22,2,3,20,20,17,25,2,13,7,27,21,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,32,31,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,34,2,2,2,2,2,35,2,2,2,2,2,2,35,2,2,2,2,2,2,2,35,2,2,2,33,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/maps/map2.tmx b/maps/map2.tmx
new file mode 100644
index 0000000..b0d6b46
--- /dev/null
+++ b/maps/map2.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,5,17,14,14,7,5,22,2,3,14,14,2,103,103,103,2,22,17,2,18,3,21,21,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,22,10,7,2,14,7,24,7,14,21,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,23,21,7,2,29,40,2,101,2,17,20,2,37,38,39,2,22,17,2,12,23,15,18,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,44,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,35,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,35,2,2,1,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,35,2,2,2,1,1,43,2,2,41,1,2,2,1,2,2,2,2,35,1,2,
+2,1,34,2,2,35,2,2,1,1,42,42,42,1,1,1,2,2,41,1,2,35,1,1,42,2,2,33,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/maps/map3.tmx b/maps/map3.tmx
new file mode 100644
index 0000000..55e0d2c
--- /dev/null
+++ b/maps/map3.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,7,16,12,17,27,1,2,
+2,1,2,2,2,2,2,2,2,2,2,35,33,1,2,2,2,2,2,2,2,2,2,2,2,51,2,2,1,2,
+2,1,2,2,2,2,2,35,2,42,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,41,1,2,
+2,1,2,2,2,2,1,1,1,1,1,2,2,2,2,2,2,2,35,42,2,2,2,2,2,2,35,41,1,2,
+2,1,42,35,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,42,42,2,2,2,2,1,2,
+2,1,1,1,2,2,2,2,2,2,2,2,35,42,1,2,2,2,2,2,1,1,1,1,1,1,2,2,1,2,
+2,1,2,2,42,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,35,1,2,
+2,1,2,2,1,1,2,2,42,2,1,2,2,2,2,2,2,2,2,35,2,2,2,2,2,2,2,1,1,2,
+2,1,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,2,2,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,35,2,2,2,1,1,2,2,2,42,2,2,2,1,1,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,2,1,2,
+2,1,34,2,2,2,35,42,42,1,1,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/maps/map4.tmx b/maps/map4.tmx
new file mode 100644
index 0000000..e1fe0c0
--- /dev/null
+++ b/maps/map4.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,1,1,1,1,1,43,2,2,2,2,41,1,1,1,43,2,2,2,2,2,2,2,2,2,52,53,1,2,
+2,1,1,1,1,44,44,2,2,2,2,2,41,1,1,1,43,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,1,1,1,43,2,2,2,2,2,2,41,1,1,44,2,2,2,2,2,2,2,42,35,42,2,33,1,2,
+2,1,44,44,44,2,2,2,2,2,2,2,2,44,2,2,2,2,2,2,2,41,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,42,2,2,2,2,2,2,2,2,42,35,2,2,2,2,2,2,44,44,44,1,2,
+2,1,2,2,42,2,2,1,1,1,2,2,2,2,2,2,2,1,1,43,2,2,2,2,2,2,2,2,1,2,
+2,1,43,2,1,35,2,2,2,44,2,2,35,2,2,2,2,2,2,2,2,2,35,2,2,2,2,2,1,2,
+2,1,2,41,1,1,2,2,2,2,2,41,1,2,2,2,2,2,2,2,2,41,1,2,2,2,2,2,1,2,
+2,1,2,2,2,1,1,43,2,2,2,2,1,2,2,2,42,35,2,2,2,41,1,1,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,35,2,1,2,2,2,1,1,2,2,2,2,2,2,2,2,35,2,1,2,
+2,1,2,2,2,2,2,35,2,41,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,41,1,2,1,2,
+2,1,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,34,2,35,42,42,1,42,42,42,42,42,42,42,42,42,42,42,42,42,35,42,42,1,42,42,42,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/maps/map5.tmx b/maps/map5.tmx
new file mode 100644
index 0000000..f883301
--- /dev/null
+++ b/maps/map5.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,41,1,43,44,44,44,41,1,2,
+2,1,2,2,2,2,2,2,35,1,2,2,2,35,2,2,2,2,2,2,2,41,1,43,2,2,2,41,1,2,
+2,1,2,2,2,35,2,2,1,2,2,41,1,1,43,2,35,42,2,2,2,41,1,43,2,2,33,41,1,2,
+2,1,2,2,2,1,1,2,2,2,2,2,2,2,2,41,1,1,2,2,2,2,44,2,2,2,2,41,1,2,
+2,1,35,2,2,2,2,2,2,2,35,2,2,2,2,2,2,2,2,2,2,2,2,2,35,2,2,2,1,2,
+2,1,1,43,2,2,2,35,2,1,2,2,2,2,2,2,2,2,1,2,2,35,2,2,1,2,2,2,1,2,
+2,1,2,2,2,2,2,1,2,2,42,2,2,2,2,2,2,41,1,2,2,2,2,2,2,2,42,35,1,2,
+2,1,2,2,41,1,2,2,2,2,1,1,43,2,2,2,35,41,1,2,2,2,1,42,2,2,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,35,2,2,2,2,41,1,1,1,2,2,2,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,41,1,1,2,2,35,2,2,2,2,2,2,2,1,1,1,1,1,1,1,2,
+2,1,2,2,2,35,1,1,2,2,2,2,2,41,1,2,2,2,2,2,2,2,1,1,1,1,1,1,1,2,
+2,1,2,2,41,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,2,
+2,1,2,2,41,1,1,1,42,42,42,42,42,42,42,42,42,42,42,42,42,42,1,1,1,1,1,1,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/maps/map6.tmx b/maps/map6.tmx
new file mode 100644
index 0000000..6102edf
--- /dev/null
+++ b/maps/map6.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,7,28,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,35,2,2,2,35,2,2,2,2,1,2,
+2,1,33,2,2,2,2,2,2,35,42,2,35,42,2,2,2,2,2,2,42,2,42,2,2,2,2,2,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,43,2,2,1,2,
+2,1,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,2,2,2,44,44,44,1,43,2,2,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,41,1,43,35,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,41,1,43,1,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,41,1,2,2,2,44,2,2,2,2,1,2,
+2,1,2,2,2,2,35,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,1,1,2,
+2,1,2,2,2,41,1,2,2,2,2,42,35,2,2,35,44,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,41,1,2,1,1,2,41,1,2,2,2,2,2,2,35,2,2,41,1,2,1,2,
+2,1,2,2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,34,2,1,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,1,42,42,42,42,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/maps/map7.tmx b/maps/map7.tmx
new file mode 100644
index 0000000..de233df
--- /dev/null
+++ b/maps/map7.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,44,44,44,44,44,44,44,1,44,44,44,44,44,44,44,44,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,33,2,2,2,2,2,41,1,43,2,2,2,2,2,2,41,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,41,1,43,2,2,2,2,2,2,41,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,41,1,43,2,2,2,2,2,2,35,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,35,2,2,2,2,2,2,2,2,2,1,2,2,2,2,1,43,2,2,2,2,2,44,44,44,44,1,2,
+2,1,1,43,2,2,2,2,2,2,2,2,1,2,2,1,1,1,2,2,2,2,2,2,2,2,2,41,1,2,
+2,1,2,2,2,2,35,2,2,2,2,2,35,1,35,2,2,2,2,2,2,2,2,2,2,2,2,41,1,2,
+2,1,2,2,2,1,43,2,2,2,2,2,2,2,1,2,1,1,42,2,42,2,2,35,2,2,2,2,1,2,
+2,1,42,42,42,42,42,42,1,42,42,1,42,42,42,42,1,1,1,1,1,1,43,41,1,2,2,35,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,2,
+2,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,35,2,2,2,1,1,1,2,
+2,1,1,1,1,1,2,2,35,2,2,2,2,2,2,2,2,2,2,1,1,2,2,1,2,1,1,1,1,2,
+2,1,34,2,2,2,2,41,1,2,2,42,35,2,2,42,1,1,1,1,1,2,42,1,42,1,1,1,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/maps/map8.tmx b/maps/map8.tmx
new file mode 100644
index 0000000..96cf131
--- /dev/null
+++ b/maps/map8.tmx
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="8" tileheight="8" infinite="0" nextlayerid="2" nextobjectid="1">
+ <tileset firstgid="1" source="../Tiles.tsx"/>
+ <layer id="1" name="Tile Layer 1" width="30" height="17">
+ <data encoding="csv">
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,34,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,
+2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
+</data>
+ </layer>
+</map>
diff --git a/pal.pal b/pal.pal
new file mode 100644
index 0000000..9ae3238
--- /dev/null
+++ b/pal.pal
@@ -0,0 +1,19 @@
+JASC-PAL
+0100
+16
+20 12 12
+36 36 36
+109 60 48
+24 24 24
+182 125 97
+138 138 138
+208 70 72
+0 145 8
+186 105 20
+210 125 44
+137 137 137
+125 125 125
+40 40 40
+101 101 101
+117 117 177
+222 222 214
diff --git a/scripts/00-Tiled2HC.py b/scripts/00-Tiled2HC.py
new file mode 100644
index 0000000..5710cc7
--- /dev/null
+++ b/scripts/00-Tiled2HC.py
@@ -0,0 +1,133 @@
+import os
+import glob
+import xml.etree.ElementTree as ET
+
+dir_path = os.path.dirname(os.path.realpath(__file__)) + '/..'
+cwd = os.getcwd()
+os.chdir(dir_path)
+
+def get_layer(fname: str):
+ tree = ET.parse(fname)
+ root = tree.getroot()
+
+ # Get first layer
+ layer = root.find('layer')
+ if layer is None:
+ layer = root.find('objectgroup')
+ if layer is None:
+ return None
+
+ # Get layer data, assume it's CSV
+ data = layer.find('data')
+ if data is None:
+ return None
+
+ # Get layer data, assume it's CSV
+ csv = data.text
+ if csv is None:
+ return None
+
+ # Split CSV into lines
+ lines = csv.split('\n')
+ if len(lines) == 0:
+ return None
+
+ # Remove empty lines
+ lines = [line for line in lines if len(line) > 0]
+ if len(lines) == 0:
+ return None
+
+ # Remove whitespace
+ lines = [line.strip() for line in lines]
+ if len(lines) == 0:
+ return None
+
+ # Remove commas at the end if any
+ lines = [line.rstrip(',') for line in lines]
+
+ # Split lines into cells, cells are all ints
+ cells = []
+ for line in lines:
+ cells.append([int(cell)-1 for cell in line.split(',')])
+
+ return cells
+
+SOURCE_FOLDER = 'build/maps'
+
+maps = []
+maps_glob = glob.glob('maps/*.tmx')
+maps_glob.sort()
+for map in maps_glob:
+ maps.append(get_layer(map))
+
+function = '''public U0 LoadMapData(MapData* target, I64 MapIndex, Player *p) {
+ Point *coinLoc = 0;
+ I64 x, y, i, id;
+
+ target->data = MAlloc(sizeof(I64) * MAP_SIZE_X * MAP_SIZE_Y);
+ if (p->coinLocations != NULL) Free(p->coinLocations);
+ p->coinCount = 0;
+ switch (MapIndex) {
+'''
+
+nignog = ''
+
+def clearBit(n, k):
+ return (n & ( ~(1 << (k - 1))))
+
+for index, map in enumerate(maps):
+ index += 1
+
+ data_raw = []
+ data = map
+ for row in data:
+ for img in row:
+ #if width < x+1: width = x+1
+ #if height < y+1: height = y+1
+ img = clearBit(img, 32)
+ img = clearBit(img, 31)
+ img = clearBit(img, 30)
+ data_raw.append(img)
+
+ final_data = ''
+ final_data += f'I64 level_data_{index}[{len(data_raw)}] = {{'
+ final_data += ','.join([str(i) for i in data_raw])
+ final_data += '};\n'
+
+ function += f'''
+ case {index}:
+ MemCpy(target->data, level_data_{index}, sizeof(level_data_{index}));
+ '''
+ function += '''
+ break;
+ '''
+
+ nignog += final_data
+
+function += '''
+ default:
+ "No level %d\\n", MapIndex;
+ throw;
+ }
+ i=0;
+ for (y=0; y<MAP_SIZE_Y; y++) {
+ for (x=0; x<MAP_SIZE_X; x++) {
+ id = target->data[y*MAP_SIZE_X+x];
+ if (id >= SPRITE_COIN_MIN && id <= SPRITE_COIN_MAX) {
+ p->coinCount++;
+ coinLoc = MAlloc(sizeof(Point));
+ coinLoc->x = x;
+ coinLoc->y = y;
+ p->coinLocations = RAlloc(p->coinLocations, sizeof(Point*) * p->coinCount);
+ p->coinLocations[i++] = coinLoc;
+ }
+ }
+ }
+'''
+nignog += function + '}\n'
+os.makedirs('temp', exist_ok=True)
+with open('temp' + os.path.sep + 'MapData.HC', 'w') as f:
+ f.write(nignog)
+ f.close()
+
+os.chdir(cwd)
diff --git a/scripts/01-ExtractTiles.py b/scripts/01-ExtractTiles.py
new file mode 100644
index 0000000..15c4893
--- /dev/null
+++ b/scripts/01-ExtractTiles.py
@@ -0,0 +1,120 @@
+import os
+import re
+import json
+from PIL import Image
+
+dir_path = os.path.dirname(os.path.realpath(__file__)) + '/..'
+cwd = os.getcwd()
+os.chdir(dir_path)
+
+OUTPUT_FOLDER = 'build/tiles'
+SUFFIX = ' -> '
+
+def is_monochromatic_image(src: Image):
+ flag = True
+ prev = None
+ for pixel in src.getdata():
+ if prev == None:
+ prev = pixel
+ else:
+ if prev != pixel:
+ flag = False
+ break
+
+ return flag
+
+print(SUFFIX + 'Loading images.')
+
+data = {}
+with open('Sprite-0001.json', 'r') as f:
+ data = json.load(f)
+ f.close()
+
+sheet = Image.open(os.path.basename(data['meta']['image']))
+
+images = []
+
+for frame in data['frames'].values():
+ new_frame = sheet.crop(
+ (
+ frame['frame']['x'],
+ frame['frame']['y'],
+ frame['frame']['x'] + frame['frame']['w'],
+ frame['frame']['y'] + frame['frame']['h']
+ )
+ )
+ images.append(new_frame)
+
+print(SUFFIX + 'Started image processing.')
+
+modified_images = []
+for i in images:
+ modified_images.append(i)
+
+print(SUFFIX + 'Saving sprites.')
+
+os.makedirs(OUTPUT_FOLDER + '_png', exist_ok=True)
+
+for f in os.listdir(OUTPUT_FOLDER + '_png'):
+ os.remove(f'{OUTPUT_FOLDER}_png/{f}')
+
+for i, image in enumerate(modified_images):
+ image.save(f'{OUTPUT_FOLDER}_png/{i}.png')
+
+print(SUFFIX + 'Loading sprites for HolyC.')
+fin_hc = '''
+#ifndef SPRITES_HC
+#define SPRITES_HC
+
+#include "PxBlot"
+'''
+for i, image in enumerate(modified_images):
+ fin_hc += '''PxData IMG_%d = {
+ %d, %d, 0
+ };\n''' % (i, image.width, image.height);
+ im_data = ','.join([str(pixel) for pixel in image.getdata()])
+ fin_hc += '''U8 IMG_BODY_%d[%d] = {''' % (i, len(image.getdata()))
+ fin_hc += im_data
+ fin_hc += '''};\n'''
+
+fin_hc += '''
+public U0 InitSprites() {
+'''
+
+for i, image in enumerate(modified_images):
+ fin_hc += 'IMG_%d.body = MAlloc(sizeof(IMG_BODY_%d));\n' % (i, i)
+ fin_hc += 'MemCpy(IMG_%d.body, IMG_BODY_%d, sizeof(IMG_BODY_%d));\n' % (i, i, i)
+
+fin_hc += '''}
+
+public U0 PutSprite(CDC *dc, I64 X=0, I64 Y=0, I64 SpriteIndex=0, F64 scale=1) {
+switch (SpriteIndex) {
+'''
+for i, _ in enumerate(modified_images):
+ fin_hc += f'''
+ case {i}:
+ PxBlot(dc, &IMG_{i}, X, Y, scale);
+ break;
+ '''
+
+fin_hc += '''}}
+#endif // SPRITES_HC'''
+
+with open('build' + os.path.sep + 'Images.HC', 'w') as f:
+ f.write(fin_hc)
+ f.close()
+
+print(SUFFIX + 'Exporting tilesheet for Tiled.')
+
+dirlist = sorted(os.listdir(OUTPUT_FOLDER + '_png'))
+dirlist.sort(key=lambda f: int(re.sub('\D', '', f)))
+
+new_image = Image.new('RGB', (len(dirlist) * data['meta']['size']['h'], data['meta']['size']['h']))
+for i, f in enumerate(dirlist):
+ temp = Image.open(f'{OUTPUT_FOLDER}_png/{f}')
+ temp.convert('RGB')
+ new_image.paste(temp, (i * data['meta']['size']['h'], 0))
+
+new_image.save('tileset.png')
+
+os.chdir(cwd)
diff --git a/scripts/02-AddMapData.py b/scripts/02-AddMapData.py
new file mode 100644
index 0000000..03d8409
--- /dev/null
+++ b/scripts/02-AddMapData.py
@@ -0,0 +1,30 @@
+import os
+import shutil
+
+dir_path = os.path.dirname(os.path.realpath(__file__)) + '/..'
+cwd = os.getcwd()
+os.chdir(dir_path)
+
+print(' -> Inserting map data')
+
+print(' -> Reading map data')
+map_data = ""
+with open('temp/MapData.HC', 'r') as f:
+ map_data = f.read()
+
+print(' -> Reading source code')
+data = ""
+with open('build/Map.HC', 'r') as f:
+ data = f.read()
+
+print(' -> Replacing')
+data = data.replace('%map_data%', map_data)
+
+print(' -> Replacing source code')
+with open('build/Map.HC', 'w') as f:
+ f.write(data)
+
+print(' -> Removing temp folder')
+shutil.rmtree('temp')
+
+os.chdir(cwd)
diff --git a/src/FCTR.HC b/src/FCTR.HC
new file mode 100644
index 0000000..3f706f0
--- /dev/null
+++ b/src/FCTR.HC
@@ -0,0 +1,221 @@
+#include "Map"
+#include "TOSMods"
+#include "PxBlot"
+#include "Images"
+#include "Player"
+
+#define SLEEP_TIME 20
+
+I64 map_index = 1;
+MapData *data;
+
+U8 *original_mouse = gr.fp_draw_ms;
+
+I64 t=0;
+
+U0 GrChar(CDC *dc=gr.dc, U8 ch, I64 x, I64 y, F64 scale=1)
+{
+ I64 i,j,k=0;
+ for (i=0; i<FONT_HEIGHT; i++) {
+ for (j=0; j<FONT_WIDTH; j++) {
+ if (Bt(&text.font[ch],k++)) {
+ GrRect(dc, x+j*scale, y+i*scale, scale, scale);
+ }
+ }
+ }
+}
+
+U0 GrPrintS(CDC *dc=gr.dc, I64 x, I64 y, U8 *str, F64 scale=1)
+{
+ I64 i;
+ for (i=0; str[i]; i++) {
+ GrChar(dc, str[i], x+i*FONT_WIDTH*scale, y, scale);
+ }
+}
+
+I64 menu_choice = 0;
+I64 screen = 0;
+
+U0 DrawMenu(CDC *dc)
+{
+ dc->color=15;
+ GrPrintS(dc, 0, dc->height-FONT_HEIGHT*TILE_SCALE, "Made by xSlendiX", TILE_SCALE/2);
+
+ I64 y=60*TILE_SCALE+PADDING_Y, x=((136/2)+25)*TILE_SCALE+PADDING_X;
+ GrPrintS(dc, x, y, "Start game", TILE_SCALE/2);
+ y += FONT_HEIGHT*TILE_SCALE;
+ GrPrintS(dc, x, y, "Statistics (WIP)", TILE_SCALE/2);
+ y += FONT_HEIGHT*TILE_SCALE;
+ GrPrintS(dc, x, y, "Quit", TILE_SCALE/2);
+
+ y = 64*TILE_SCALE+PADDING_Y;
+ y += menu_choice*FONT_HEIGHT*TILE_SCALE;
+ x -= FONT_WIDTH*TILE_SCALE;
+ PutSprite(dc, x, y, 99, TILE_SCALE/2);
+}
+
+U0 UpdateMenu()
+{
+}
+
+U0 SetMap(I64 index)
+{
+ map_index = index;
+ DeleteMapData(data);
+ data = CreateMapData(map_index,&player);
+ PlayerDie(data);
+}
+
+U0 NextLevel()
+{
+ if (player.coins != player.coinCount) return;
+
+ map_index++;
+ // TODO: Add check for last map
+ SetMap(map_index);
+}
+
+U0 UpdateMap(MapData *map)
+{
+ I64 x = Round(player.x/TILE_SIZE);
+ I64 y = Round(player.y/TILE_SIZE);
+ I64 player_tile = MGet(map, x, y);
+ if (player_tile == SPRITE_GOAL)
+ NextLevel();
+
+ if (player_tile >= SPRITE_COIN_MIN && player_tile <= SPRITE_COIN_MAX)
+ {
+ MSet(map, Round(player.x/TILE_SIZE), Round(player.y/TILE_SIZE), SPRITE_WALLPAPER);
+ player.coins++;
+ // TODO: Play sfx
+ }
+
+ if ((player_tile >= SPRITE_SPIKES_MIN && player_tile <= SPRITE_SPIKES_MAX) || (player_tile >= SPRITE_SPIKES_MIN2 && player_tile <= SPRITE_SPIKES_MAX2))
+ {
+ if (player_tile <= SPRITE_SPIKES_MAX)
+ MSet(map, x, y, player_tile+6);
+
+ player.vx=0;
+ player.vy=0;
+
+ PlayerDie(map);
+ }
+
+ if (t % 10 == 0)
+ SwapCoins(map);
+}
+
+U0 FCTRDrawIt(CTask *, CDC *dc)
+{
+ dc->color = 0;
+ GrRect3(dc, 0, 0, 0, dc->width, dc->height);
+ DrawMap(dc, data);
+
+ if (screen == 0) {
+ DrawMenu(dc);
+ } else {
+ PutPlayer(dc);
+ //PutPlayerDebug(data, dc);
+ //GrPrint(dc, 100, 0, "level: %d", map_index);
+ }
+}
+
+U0 FCTRCleanUp()
+{
+ DocClear();
+}
+
+Bool HandleMenuChoice()
+{
+ switch (menu_choice) {
+ case 0:
+ screen = 1;
+ NextLevel();
+ // TODO: Beign timer etc.
+ return ON;
+ case 1:
+ screen = 2;
+ return ON;
+ case 2:
+ return OFF;
+ }
+}
+
+U0 FCTRDrawMs(CDC *dc, I64 x, I64 y) {}
+
+U0 fctr()
+{
+ I64 sc;
+ CDate d;
+ InitPlayer();
+ data = CreateMapData(map_index,&player);
+
+ InitSprites();
+
+ SettingsPush();
+ AutoComplete();
+ WinBorder();
+ WinMax();
+ DocCursor();
+ DocClear();
+
+ gr.fp_draw_ms = &FCTRDrawMs;
+ Fs->draw_it = &FCTRDrawIt;
+
+ GrPaletteSet(gr_palette_fctr);
+
+ try {
+ while (TRUE) {
+ if (screen == 0) {
+ switch(GetKey(&sc)) {
+ case 0:
+ switch (sc.u8[0]) {
+ case SC_CURSOR_DOWN:
+ menu_choice++;
+ if (menu_choice > 2) menu_choice = 2;
+ break;
+ case SC_CURSOR_UP:
+ menu_choice--;
+ if (menu_choice < 0) menu_choice = 0;
+ break;
+ }
+ break;
+ case 'z':
+ case '\n':
+ if (!HandleMenuChoice()) goto fctr_done;
+ break;
+ case CH_SHIFT_ESC:
+ case CH_ESC:
+ goto fctr_done;
+ }
+ } else {
+ if (Btn(SC_ESC) || Key('q')) {
+ break;
+ }
+
+ UpdateMap(data);
+ if (map_index != 1)
+ UpdatePlayer(data);
+
+ t++;
+
+ LBts(&Fs->task_flags, TASKf_IDLE);
+ Yield;
+ LBtr(&Fs->task_flags, TASKf_IDLE);
+
+ // FIXME: This is pretty hacky
+ Sleep(SLEEP_TIME);
+ }
+ }
+ } catch
+ PutExcept;
+
+fctr_done:
+
+ gr.fp_draw_ms = original_mouse;
+ DeleteMapData(data);
+ FreePlayer();
+
+ SettingsPop();
+ FCTRCleanUp();
+}
diff --git a/src/Load.HC b/src/Load.HC
new file mode 100644
index 0000000..7d6c236
--- /dev/null
+++ b/src/Load.HC
@@ -0,0 +1,5 @@
+#help_index "Games"
+
+#include "FCTR"
+
+#help_index ""
diff --git a/src/Map.HC b/src/Map.HC
new file mode 100644
index 0000000..e68bc65
--- /dev/null
+++ b/src/Map.HC
@@ -0,0 +1,57 @@
+// This file is generated! Please do not edit this file~~
+#ifndef MAP_HC
+#define MAP_HC
+
+#include "Math"
+#include "Palette"
+#include "PxBlot"
+#include "Images"
+#include "Player"
+
+%map_data%
+
+U0 DrawMap(CDC *dc, MapData *map_data)
+{
+ I64 x, y;
+ for (y = 0; y < MAP_SIZE_Y; y++) {
+ for (x = 0; x < MAP_SIZE_X; x++) {
+ I64 id = map_data->data[y * MAP_SIZE_X + x];
+ if (id >= 0)
+ PutSprite(dc, x * FTILE_SIZE + PADDING_X, y * FTILE_SIZE + PADDING_Y, id, TILE_SCALE);
+ }
+ }
+}
+
+U0 GenerateBlankMapData(MapData *map_data)
+{
+ I64 x, y;
+ for (y = 0; y < MAP_SIZE_Y; y++)
+ for (x = 0; x < MAP_SIZE_X; x++)
+ map_data->data[y * MAP_SIZE_X + x] = 0;
+}
+
+MapData* CreateMapData(
+ I64 MapIndex=0, Player *p=NULL
+) {
+ MapData *target = MAlloc(sizeof(MapData));
+
+ if (MapIndex != 0) {
+ LoadMapData(target, MapIndex, p);
+ return target;
+ }
+
+ target->data = MAlloc(sizeof(I64) * MAP_SIZE_X * MAP_SIZE_Y);
+ if (MapIndex == 0) {
+ GenerateBlankMapData(target);
+ }
+
+ return target;
+}
+
+U0 DeleteMapData(MapData *map_data)
+{
+ Free(map_data->data);
+ //Free(map_data);
+}
+
+#endif // MAP_HC
diff --git a/src/Math.HC b/src/Math.HC
new file mode 100644
index 0000000..565cc5a
--- /dev/null
+++ b/src/Math.HC
@@ -0,0 +1,95 @@
+#ifndef MATH_HC
+#define MATH_HC
+
+class Point
+{
+ I64 x, y;
+};
+
+class MapData
+{
+ I64 *data;
+};
+
+// TODO: Move somewhere else
+#define MAP_SIZE_X 30
+#define MAP_SIZE_Y 17
+#define MAP_SIZE (MAP_SIZE_X * MAP_SIZE_Y)
+
+#define TILE_SIZE 8
+#define TILE_SCALE 2.65
+//#define TILE_SCALE 2
+#define TILE_COUNT 94
+
+#define FTILE_SIZE (TILE_SIZE * TILE_SCALE)
+
+#define PADDING_X ((dc->width - MAP_SIZE_X * FTILE_SIZE) / 2)
+#define PADDING_Y ((dc->height - MAP_SIZE_Y * FTILE_SIZE) / 2)
+
+#define SPRITE_COIN_MIN (34)
+#define SPRITE_COIN_MAX (35)
+#define SPRITE_WALLPAPER (1)
+#define SPRITE_GOAL (32)
+
+#define SPRITE_SPIKES_MIN (40)
+#define SPRITE_SPIKES_MAX (43)
+#define SPRITE_SPIKES_MIN2 (46)
+#define SPRITE_SPIKES_MAX2 (49)
+
+U8 *RAlloc(U8 *ptr, U64 new_size)
+{
+ U8 *res;
+
+ if (ptr == NULL) {
+ ptr = MAlloc(new_size);
+ return ptr;
+ }
+
+ if (!new_size) {
+ Free(ptr);
+ return NULL;
+ }
+
+ res = MAlloc(new_size);
+ if (!ptr)
+ return res;
+
+ MemCpy(res, ptr, MinI64(MSize(ptr), new_size));
+
+ return res;
+}
+
+I64 MGet(MapData *map, I64 x, I64 y)
+{
+ return map->data[y * MAP_SIZE_X + x];
+}
+
+U0 MSet(MapData *map, I64 x, I64 y, I64 val)
+{
+ map->data[y * MAP_SIZE_X + x] = val;
+}
+
+Bool Btn(U8 code) {
+ return Bt(kbd.down_bitmap, code);
+}
+
+Bool Key(U8 code) {
+ return Btn(Char2ScanCode(code));
+}
+
+Bool Solid(MapData *map, F64 x, F64 y)
+{
+ return MGet(map, Floor(x/TILE_SIZE), Floor(y/TILE_SIZE)) == 0;
+}
+
+U0 SwapCoins(MapData* map)
+{
+ I64 i;
+ for (i=0; i<MAP_SIZE; i++) {
+ if (map->data[i] >= SPRITE_COIN_MIN && map->data[i] <= SPRITE_COIN_MAX) {
+ map->data[i] = (map->data[i] + 1) % (SPRITE_COIN_MAX - SPRITE_COIN_MIN + 1) + SPRITE_COIN_MIN;
+ }
+ }
+}
+
+#endif // MATH_HC
diff --git a/src/Palette.HC b/src/Palette.HC
new file mode 100644
index 0000000..342485f
--- /dev/null
+++ b/src/Palette.HC
@@ -0,0 +1,11 @@
+#ifndef PALETTE_HC
+#define PALETTE_HC
+
+CBGR48 gr_palette_fctr[COLORS_NUM] = {
+ 0x14140c0c1c1c,0x242424242424,0x6d6d3c3c3030,0x181818181818,
+ 0xb6b67d7d6161,0x8a8a8a8a8a8a,0xd0d046464848,0x000091910808,
+ 0xbaba69691414,0xd2d27d7d2c2c,0x898989898989,0x7d7d7d7d7d7d,
+ 0x1c1c1c1c1c1c,0x656565656565,0x757575757575,0xdedededed6d6
+};
+
+#endif // PALETTE_HC
diff --git a/src/PaletteZeal.ZC b/src/PaletteZeal.ZC
new file mode 100644
index 0000000..1ce5291
--- /dev/null
+++ b/src/PaletteZeal.ZC
@@ -0,0 +1,11 @@
+#ifndef PALETTE_HC
+#define PALETTE_HC
+
+CBGR32 gr_palette_fctr[COLORS_NUM] = {
+ 0x140c1c,0x242424,0x6d3c30,0x181818,
+ 0xb67d61,0x8a8a8a,0xd04648,0x009108,
+ 0xba6914,0xd27d2c,0x898989,0x7d7d7d,
+ 0x1c1c1c,0x656565,0x757575,0xdeded6
+};
+
+#endif // PALETTE_HC
diff --git a/src/Player.HC b/src/Player.HC
new file mode 100644
index 0000000..93fcd50
--- /dev/null
+++ b/src/Player.HC
@@ -0,0 +1,202 @@
+#ifndef PLAYER_HC
+#define PLAYER_HC
+
+#include "Math"
+
+#define PLAYER_SPEED (1.3)
+#define PLAYER_FALL_SPEED (0.3)
+#define PLAYER_JUMP_SPEED (3.5)
+
+#define PLAYER_ORIENTATION_NONE (0)
+#define PLAYER_ORIENTATION_RIGHT (1)
+#define PLAYER_ORIENTATION_LEFT (2)
+
+#define PLAYER_SPRITE_RUNLEFT_1 (92)
+#define PLAYER_SPRITE_RUNLEFT_2 (93)
+#define PLAYER_SPRITE_RUNRIGHT_1 (95)
+#define PLAYER_SPRITE_RUNRIGHT_2 (96)
+#define PLAYER_SPRITE_IDLE_1 (97)
+#define PLAYER_SPRITE_IDLE_2 (98)
+
+class Player {
+ F64 x, y;
+ F64 vx, vy;
+ I64 coins;
+ Bool grounded;
+ I64 orientation;
+ I64 cframe;
+ Point **coinLocations;
+ I64 coinCount;
+};
+
+Player player;
+
+I64 player_t=0;
+
+U0 InitPlayer()
+{
+ player.x = 16;
+ player.y = MAP_SIZE_Y*TILE_SIZE-24;
+ player.vx = 0;
+ player.vy = 0;
+ player.coins = 0;
+ player.grounded = FALSE;
+ player.orientation = 0;
+ player.cframe = 1;
+ player.coinLocations = NULL;
+ player.coinCount = 0;
+}
+
+U0 FreePlayer()
+{
+ I64 i;
+ for (i=0; i<player.coinCount; i++) {
+ if (player.coinLocations[i] != NULL) {
+ Free(player.coinLocations[i]);
+ }
+ }
+}
+
+U0 ResetCoins(MapData *map)
+{
+ I64 i;
+ for (i = 0; i < player.coinCount; i++) {
+ Point *p = player.coinLocations[i];
+ MSet(map, p->x, p->y, SPRITE_COIN_MIN);
+ }
+}
+
+I64 GetFramePlayer()
+{
+ I64 ret;
+ if (player.grounded) {
+ switch (player.orientation) {
+ case PLAYER_ORIENTATION_RIGHT:
+ if (player.cframe == 1)
+ ret = PLAYER_SPRITE_RUNRIGHT_1;
+ else
+ ret = PLAYER_SPRITE_RUNRIGHT_2;
+ break;
+ case PLAYER_ORIENTATION_LEFT:
+ if (player.cframe == 1)
+ ret = PLAYER_SPRITE_RUNLEFT_1;
+ else
+ ret = PLAYER_SPRITE_RUNLEFT_2;
+ break;
+ default:
+ if (player.cframe == 1)
+ ret = PLAYER_SPRITE_IDLE_1;
+ else
+ ret = PLAYER_SPRITE_IDLE_2;
+ break;
+ }
+ } else {
+ switch (player.orientation) {
+ case PLAYER_ORIENTATION_RIGHT:
+ ret = PLAYER_SPRITE_RUNRIGHT_1;
+ break;
+ case PLAYER_ORIENTATION_LEFT:
+ ret = PLAYER_SPRITE_RUNLEFT_1;
+ break;
+ default:
+ ret = PLAYER_SPRITE_IDLE_1;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+U0 PutPlayer(CDC *dc)
+{
+ I64 frame = GetFramePlayer();
+ PutSprite(dc, (player.x)*TILE_SCALE+PADDING_X, (player.y)*TILE_SCALE+PADDING_Y, frame, TILE_SCALE);
+}
+
+U0 PlayerDie(MapData *map, Bool effects=OFF)
+{
+ player.x = 16;
+ player.y = MAP_SIZE_Y*TILE_SIZE-24;
+ player.coins = 0;
+ ResetCoins(map);
+}
+
+U0 UpdatePlayer(MapData *map)
+{
+ if (player.y > 136 || player.x > 240 || player.x < 0) {
+ PlayerDie(map);
+ }
+
+ // TODO: if debug ....
+
+ if (Btn(SC_CURSOR_LEFT) || Key('a')) {
+ player.vx = -PLAYER_SPEED;
+ player.orientation = PLAYER_ORIENTATION_LEFT;
+ } else if (Btn(SC_CURSOR_RIGHT) || Key('d')) {
+ player.vx = PLAYER_SPEED;
+ player.orientation = PLAYER_ORIENTATION_RIGHT;
+ } else {
+ player.vx = 0;
+ player.orientation = PLAYER_ORIENTATION_NONE;
+ }
+
+ if (Solid(map, player.x+player.vx,player.y+player.vy)
+ || Solid(map, player.x+7+player.vx,player.y+player.vy)
+ || Solid(map, player.x+player.vx,player.y+7+player.vy)
+ || Solid(map, player.x+7+player.vx,player.y+7+player.vy)) {
+ player.vx=0;
+ player.orientation = PLAYER_ORIENTATION_NONE;
+ }
+
+ if (Solid(map, player.x,player.y+8+player.vy) || Solid(map, player.x+7,player.y+8+player.vy)) {
+ player.vy=0;
+ player.grounded = TRUE;
+ } else {
+ player.vy+=PLAYER_FALL_SPEED;
+ player.grounded = FALSE;
+ }
+
+ if (player.vy==0 && (Btn(SC_CURSOR_UP) || Key('w') || Key(' ') || Key('z')))
+ if (player.grounded)
+ player.vy = -PLAYER_JUMP_SPEED;
+
+ if (player.vy<0 && (Solid(map, player.x+player.vx, player.y+player.vy) || Solid(map, player.x+7+player.vx, player.y+player.vy))) {
+ player.vy=0;
+ player.grounded = TRUE;
+ }
+
+ player.x += player.vx;
+ player.y += player.vy;
+
+ player_t++;
+ if (player_t % 20 == 0 || player_t == 0)
+ player.cframe++;
+
+ if (player.cframe == 3)
+ player.cframe = 1;
+}
+
+U0 PutPlayerDebug(MapData* map, CDC *dc)
+{
+ dc->color=RED;
+
+ GrPrint(dc, 0, 0, "x: %f", player.x);
+ GrPrint(dc, 0, 8, "y: %f", player.y);
+ GrPrint(dc, 0, 16, "vx: %f", player.vx);
+ GrPrint(dc, 0, 24, "vy: %f", player.vy);
+ GrPrint(dc, 0, 32, "coins: %d", player.coins);
+ GrPrint(dc, 0, 40, "grounded: %d", player.grounded);
+ GrPrint(dc, 0, 48, "orientation: %d", player.orientation);
+ GrPrint(dc, 0, 56, "cframe: %d", player.cframe);
+ GrPrint(dc, 0, 64, "solid: %d", Solid(map, player.x, player.y));
+ GrPrint(dc, 0, 72, "vx+x: %f", player.x+player.vx);
+ GrPrint(dc, 0, 80, "vy+y: %f", player.y+player.vy);
+ GrPrint(dc, 0, 88, "Solid at vel: %d", Solid(map, player.x+player.vx, player.y+player.vy));
+ GrPrint(dc, 0, 96, "roundx: %f", Round(player.x/TILE_SIZE));
+ GrPrint(dc, 0, 104, "roundy: %f", Round(player.y/TILE_SIZE));
+ GrPrint(dc, 0, 112, "Round bl: %d", MGet(map, Round(player.x/TILE_SIZE), Round(player.y/TILE_SIZE)));
+ GrPrint(dc, 0, 120, "coinCount: %d", player.coinCount);
+ GrPrint(dc, 0, 128, "playert: %d", player_t);
+}
+
+#endif // PLAYER_HC
diff --git a/src/PxBlot.HC b/src/PxBlot.HC
new file mode 100644
index 0000000..e70a5bc
--- /dev/null
+++ b/src/PxBlot.HC
@@ -0,0 +1,61 @@
+#ifndef PXBLOT_HC
+#define PXBLOT_HC
+
+class PxData {
+ I32 width;
+ I32 height;
+ U8 *body;
+};
+
+public U0 PxBlot(CDC *dc, PxData *data, I64 x, I64 y, F64 scale=1) {
+ if (data == NULL) return;
+ if (dc == NULL) return;
+
+ // Cull
+ if (x >= dc->width_internal || y >= dc->height ||
+ x+(data->width*scale) < 0 || y+(data->height*scale) < 0) {
+ return;
+ }
+
+ // Clip X
+ I64 minX = 0;
+ if (x < 0) {
+ minX = -x;
+ x = 0;
+ }
+ I64 maxX = data->width*scale;
+ if (maxX+x >= dc->width_internal) {
+ maxX -= maxX+x - dc->width_internal;
+ }
+
+ // Clip Y
+ I64 minY = 0;
+ if (y < 0) {
+ minY = -y;
+ y = 0;
+ }
+ I64 maxY = data->height*scale;
+ if (maxY+y >= dc->height) {
+ maxY -= maxY+y - dc->height;
+ }
+
+ // Draw
+ I64 d = dc->body + y*dc->width_internal + x;
+ y = 0;
+ I64 dy, dx;
+ for (dy=minY; dy<maxY; y++, dy++) {
+ U8 *dst = d + y*dc->width_internal;
+ for (dx=minX; dx<maxX; dx++, dst++) {
+ I64 proj_x = dx / scale;
+ I64 proj_y = dy / scale;
+ U8 color = data->body[proj_y*data->width+proj_x];
+ if (color > 15) color = TRANSPARENT;
+ if (color != TRANSPARENT) {
+ *dst = color;
+ }
+ }
+ }
+
+}
+
+#endif
diff --git a/src/Run.HC b/src/Run.HC
new file mode 100644
index 0000000..9c48192
--- /dev/null
+++ b/src/Run.HC
@@ -0,0 +1,2 @@
+#include "Load"
+fctr;
diff --git a/src/TOSMods.HC b/src/TOSMods.HC
new file mode 100644
index 0000000..e8e9ecb
--- /dev/null
+++ b/src/TOSMods.HC
@@ -0,0 +1,8 @@
+U0 FCTRDrawMs(CDC *dc, I64 x, I64 y)
+{
+ dc->thick=1;
+ dc->flags&=~(DCF_TRANSFORMATION|DCF_SYMMETRY);
+ GrLine3(dc, x, y, 0, x + 3, y + 7, 0);
+ GrLine3(dc, x, y, 0, x + 7, y + 3, 0);
+ GrPlot3(dc, x, y, 0);
+}
diff --git a/tileset.png b/tileset.png
new file mode 100644
index 0000000..932c01b
--- /dev/null
+++ b/tileset.png
Binary files differ
diff --git a/tos_project.toml b/tos_project.toml
new file mode 100644
index 0000000..aaf6a56
--- /dev/null
+++ b/tos_project.toml
@@ -0,0 +1,6 @@
+[General]
+Name="FactorunnerTOS"
+Author="Slendi"
+Version="0.1"
+
+[Dependencies]