From 34ebcff68496ce9f15f784225c4a80d83abee887 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 04:26:48 +0000 Subject: [PATCH 1/3] Initial plan From 9afd9b5f0e557fc8dfd2371c11aae918d5568b4d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 04:39:55 +0000 Subject: [PATCH 2/3] feat: Phaser-ready placeholder asset pack for That One Game Agent-Logs-Url: https://github.com/paulcombs56-ops/That-One-Game/sessions/4ff9e0ba-69f6-412e-9fb2-539ddf7fb795 Co-authored-by: paulcombs56-ops <263761623+paulcombs56-ops@users.noreply.github.com> --- .gitignore | 3 + assets/asset-manifest.json | 266 +++++ assets/atlas/gw/atlas_gw_ui.json | 355 ++++++ assets/atlas/gw/atlas_gw_ui.png | Bin 0 -> 6525 bytes assets/atlas/gw/atlas_gw_world.json | 515 +++++++++ assets/atlas/gw/atlas_gw_world.png | Bin 0 -> 8642 bytes assets/atlas/rw/atlas_rw_ui.json | 315 +++++ assets/atlas/rw/atlas_rw_ui.png | Bin 0 -> 6340 bytes assets/atlas/rw/atlas_rw_world.json | 475 ++++++++ assets/atlas/rw/atlas_rw_world.png | Bin 0 -> 4401 bytes assets/spritesheets/gw/boss_ceo_attack.png | Bin 0 -> 4142 bytes assets/spritesheets/gw/boss_ceo_idle.png | Bin 0 -> 3016 bytes assets/spritesheets/gw/boss_ceo_run.png | Bin 0 -> 4515 bytes assets/spritesheets/gw/boss_ceo_walk.png | Bin 0 -> 3829 bytes .../gw/enemy_accountant_attack.png | Bin 0 -> 1580 bytes .../spritesheets/gw/enemy_accountant_idle.png | Bin 0 -> 1040 bytes .../spritesheets/gw/enemy_accountant_run.png | Bin 0 -> 1816 bytes .../spritesheets/gw/enemy_accountant_walk.png | Bin 0 -> 1331 bytes assets/spritesheets/gw/enemy_dev_attack.png | Bin 0 -> 1557 bytes assets/spritesheets/gw/enemy_dev_idle.png | Bin 0 -> 1031 bytes assets/spritesheets/gw/enemy_dev_run.png | Bin 0 -> 1818 bytes assets/spritesheets/gw/enemy_dev_walk.png | Bin 0 -> 1336 bytes assets/spritesheets/gw/enemy_hr_attack.png | Bin 0 -> 1553 bytes assets/spritesheets/gw/enemy_hr_idle.png | Bin 0 -> 1049 bytes assets/spritesheets/gw/enemy_hr_run.png | Bin 0 -> 1816 bytes assets/spritesheets/gw/enemy_hr_walk.png | Bin 0 -> 1339 bytes .../spritesheets/gw/enemy_intern_attack.png | Bin 0 -> 1592 bytes assets/spritesheets/gw/enemy_intern_idle.png | Bin 0 -> 1053 bytes assets/spritesheets/gw/enemy_intern_run.png | Bin 0 -> 1818 bytes assets/spritesheets/gw/enemy_intern_walk.png | Bin 0 -> 1382 bytes .../spritesheets/gw/enemy_security_attack.png | Bin 0 -> 1520 bytes .../spritesheets/gw/enemy_security_idle.png | Bin 0 -> 1019 bytes assets/spritesheets/gw/enemy_security_run.png | Bin 0 -> 1765 bytes .../spritesheets/gw/enemy_security_walk.png | Bin 0 -> 1327 bytes assets/spritesheets/gw/fx_hitspark.png | Bin 0 -> 2350 bytes assets/spritesheets/gw/fx_pickup.png | Bin 0 -> 1336 bytes assets/spritesheets/gw/fx_projectile.png | Bin 0 -> 1163 bytes assets/spritesheets/gw/fx_slasharc.png | Bin 0 -> 2534 bytes assets/spritesheets/gw/miniboss_vp_attack.png | Bin 0 -> 1616 bytes assets/spritesheets/gw/miniboss_vp_idle.png | Bin 0 -> 1077 bytes assets/spritesheets/gw/miniboss_vp_run.png | Bin 0 -> 1908 bytes assets/spritesheets/gw/miniboss_vp_walk.png | Bin 0 -> 1404 bytes assets/spritesheets/gw/player_gw_attack.png | Bin 0 -> 1548 bytes assets/spritesheets/gw/player_gw_idle.png | Bin 0 -> 1021 bytes assets/spritesheets/gw/player_gw_run.png | Bin 0 -> 1766 bytes assets/spritesheets/gw/player_gw_walk.png | Bin 0 -> 1339 bytes assets/spritesheets/rw/player_rw_attack.png | Bin 0 -> 3602 bytes assets/spritesheets/rw/player_rw_idle.png | Bin 0 -> 2920 bytes assets/spritesheets/rw/player_rw_run.png | Bin 0 -> 3585 bytes assets/spritesheets/rw/player_rw_walk.png | Bin 0 -> 3428 bytes package-lock.json | 458 ++++++++ package.json | 11 + src/AnimationHelper.js | 197 ++++ src/AssetLoader.js | 90 ++ tools/generate-assets.js | 1024 +++++++++++++++++ 55 files changed, 3709 insertions(+) create mode 100644 .gitignore create mode 100644 assets/asset-manifest.json create mode 100644 assets/atlas/gw/atlas_gw_ui.json create mode 100644 assets/atlas/gw/atlas_gw_ui.png create mode 100644 assets/atlas/gw/atlas_gw_world.json create mode 100644 assets/atlas/gw/atlas_gw_world.png create mode 100644 assets/atlas/rw/atlas_rw_ui.json create mode 100644 assets/atlas/rw/atlas_rw_ui.png create mode 100644 assets/atlas/rw/atlas_rw_world.json create mode 100644 assets/atlas/rw/atlas_rw_world.png create mode 100644 assets/spritesheets/gw/boss_ceo_attack.png create mode 100644 assets/spritesheets/gw/boss_ceo_idle.png create mode 100644 assets/spritesheets/gw/boss_ceo_run.png create mode 100644 assets/spritesheets/gw/boss_ceo_walk.png create mode 100644 assets/spritesheets/gw/enemy_accountant_attack.png create mode 100644 assets/spritesheets/gw/enemy_accountant_idle.png create mode 100644 assets/spritesheets/gw/enemy_accountant_run.png create mode 100644 assets/spritesheets/gw/enemy_accountant_walk.png create mode 100644 assets/spritesheets/gw/enemy_dev_attack.png create mode 100644 assets/spritesheets/gw/enemy_dev_idle.png create mode 100644 assets/spritesheets/gw/enemy_dev_run.png create mode 100644 assets/spritesheets/gw/enemy_dev_walk.png create mode 100644 assets/spritesheets/gw/enemy_hr_attack.png create mode 100644 assets/spritesheets/gw/enemy_hr_idle.png create mode 100644 assets/spritesheets/gw/enemy_hr_run.png create mode 100644 assets/spritesheets/gw/enemy_hr_walk.png create mode 100644 assets/spritesheets/gw/enemy_intern_attack.png create mode 100644 assets/spritesheets/gw/enemy_intern_idle.png create mode 100644 assets/spritesheets/gw/enemy_intern_run.png create mode 100644 assets/spritesheets/gw/enemy_intern_walk.png create mode 100644 assets/spritesheets/gw/enemy_security_attack.png create mode 100644 assets/spritesheets/gw/enemy_security_idle.png create mode 100644 assets/spritesheets/gw/enemy_security_run.png create mode 100644 assets/spritesheets/gw/enemy_security_walk.png create mode 100644 assets/spritesheets/gw/fx_hitspark.png create mode 100644 assets/spritesheets/gw/fx_pickup.png create mode 100644 assets/spritesheets/gw/fx_projectile.png create mode 100644 assets/spritesheets/gw/fx_slasharc.png create mode 100644 assets/spritesheets/gw/miniboss_vp_attack.png create mode 100644 assets/spritesheets/gw/miniboss_vp_idle.png create mode 100644 assets/spritesheets/gw/miniboss_vp_run.png create mode 100644 assets/spritesheets/gw/miniboss_vp_walk.png create mode 100644 assets/spritesheets/gw/player_gw_attack.png create mode 100644 assets/spritesheets/gw/player_gw_idle.png create mode 100644 assets/spritesheets/gw/player_gw_run.png create mode 100644 assets/spritesheets/gw/player_gw_walk.png create mode 100644 assets/spritesheets/rw/player_rw_attack.png create mode 100644 assets/spritesheets/rw/player_rw_idle.png create mode 100644 assets/spritesheets/rw/player_rw_run.png create mode 100644 assets/spritesheets/rw/player_rw_walk.png create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/AnimationHelper.js create mode 100644 src/AssetLoader.js create mode 100644 tools/generate-assets.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c25e1e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +*.log diff --git a/assets/asset-manifest.json b/assets/asset-manifest.json new file mode 100644 index 0000000..e8cb0f1 --- /dev/null +++ b/assets/asset-manifest.json @@ -0,0 +1,266 @@ +{ + "spritesheets": [ + { + "key": "player_rw_idle", + "path": "assets/spritesheets/rw/player_rw_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "player_rw_walk", + "path": "assets/spritesheets/rw/player_rw_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "player_rw_run", + "path": "assets/spritesheets/rw/player_rw_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "player_rw_attack", + "path": "assets/spritesheets/rw/player_rw_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "player_gw_idle", + "path": "assets/spritesheets/gw/player_gw_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "player_gw_walk", + "path": "assets/spritesheets/gw/player_gw_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "player_gw_run", + "path": "assets/spritesheets/gw/player_gw_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "player_gw_attack", + "path": "assets/spritesheets/gw/player_gw_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_intern_idle", + "path": "assets/spritesheets/gw/enemy_intern_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_intern_walk", + "path": "assets/spritesheets/gw/enemy_intern_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_intern_run", + "path": "assets/spritesheets/gw/enemy_intern_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_intern_attack", + "path": "assets/spritesheets/gw/enemy_intern_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_hr_idle", + "path": "assets/spritesheets/gw/enemy_hr_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_hr_walk", + "path": "assets/spritesheets/gw/enemy_hr_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_hr_run", + "path": "assets/spritesheets/gw/enemy_hr_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_hr_attack", + "path": "assets/spritesheets/gw/enemy_hr_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_dev_idle", + "path": "assets/spritesheets/gw/enemy_dev_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_dev_walk", + "path": "assets/spritesheets/gw/enemy_dev_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_dev_run", + "path": "assets/spritesheets/gw/enemy_dev_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_dev_attack", + "path": "assets/spritesheets/gw/enemy_dev_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_security_idle", + "path": "assets/spritesheets/gw/enemy_security_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_security_walk", + "path": "assets/spritesheets/gw/enemy_security_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_security_run", + "path": "assets/spritesheets/gw/enemy_security_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_security_attack", + "path": "assets/spritesheets/gw/enemy_security_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_accountant_idle", + "path": "assets/spritesheets/gw/enemy_accountant_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_accountant_walk", + "path": "assets/spritesheets/gw/enemy_accountant_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_accountant_run", + "path": "assets/spritesheets/gw/enemy_accountant_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "enemy_accountant_attack", + "path": "assets/spritesheets/gw/enemy_accountant_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "miniboss_vp_idle", + "path": "assets/spritesheets/gw/miniboss_vp_idle.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "miniboss_vp_walk", + "path": "assets/spritesheets/gw/miniboss_vp_walk.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "miniboss_vp_run", + "path": "assets/spritesheets/gw/miniboss_vp_run.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "miniboss_vp_attack", + "path": "assets/spritesheets/gw/miniboss_vp_attack.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "boss_ceo_idle", + "path": "assets/spritesheets/gw/boss_ceo_idle.png", + "frameWidth": 64, + "frameHeight": 64 + }, + { + "key": "boss_ceo_walk", + "path": "assets/spritesheets/gw/boss_ceo_walk.png", + "frameWidth": 64, + "frameHeight": 64 + }, + { + "key": "boss_ceo_run", + "path": "assets/spritesheets/gw/boss_ceo_run.png", + "frameWidth": 64, + "frameHeight": 64 + }, + { + "key": "boss_ceo_attack", + "path": "assets/spritesheets/gw/boss_ceo_attack.png", + "frameWidth": 64, + "frameHeight": 64 + }, + { + "key": "fx_hitspark", + "path": "assets/spritesheets/gw/fx_hitspark.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "fx_slasharc", + "path": "assets/spritesheets/gw/fx_slasharc.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "fx_projectile", + "path": "assets/spritesheets/gw/fx_projectile.png", + "frameWidth": 32, + "frameHeight": 32 + }, + { + "key": "fx_pickup", + "path": "assets/spritesheets/gw/fx_pickup.png", + "frameWidth": 32, + "frameHeight": 32 + } + ], + "atlases": [ + { + "key": "atlas_rw_world", + "png": "assets/atlas/rw/atlas_rw_world.png", + "json": "assets/atlas/rw/atlas_rw_world.json" + }, + { + "key": "atlas_rw_ui", + "png": "assets/atlas/rw/atlas_rw_ui.png", + "json": "assets/atlas/rw/atlas_rw_ui.json" + }, + { + "key": "atlas_gw_world", + "png": "assets/atlas/gw/atlas_gw_world.png", + "json": "assets/atlas/gw/atlas_gw_world.json" + }, + { + "key": "atlas_gw_ui", + "png": "assets/atlas/gw/atlas_gw_ui.png", + "json": "assets/atlas/gw/atlas_gw_ui.json" + } + ] +} \ No newline at end of file diff --git a/assets/atlas/gw/atlas_gw_ui.json b/assets/atlas/gw/atlas_gw_ui.json new file mode 100644 index 0000000..330ea3d --- /dev/null +++ b/assets/atlas/gw/atlas_gw_ui.json @@ -0,0 +1,355 @@ +{ + "frames": { + "gw_ui_button_normal": { + "frame": { + "x": 2, + "y": 2, + "w": 120, + "h": 40 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 120, + "h": 40 + }, + "sourceSize": { + "w": 120, + "h": 40 + } + }, + "gw_ui_button_hover": { + "frame": { + "x": 124, + "y": 2, + "w": 120, + "h": 40 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 120, + "h": 40 + }, + "sourceSize": { + "w": 120, + "h": 40 + } + }, + "gw_ui_button_pressed": { + "frame": { + "x": 246, + "y": 2, + "w": 120, + "h": 40 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 120, + "h": 40 + }, + "sourceSize": { + "w": 120, + "h": 40 + } + }, + "gw_ui_panel": { + "frame": { + "x": 2, + "y": 44, + "w": 200, + "h": 150 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 200, + "h": 150 + }, + "sourceSize": { + "w": 200, + "h": 150 + } + }, + "gw_ui_health_bar_bg": { + "frame": { + "x": 204, + "y": 44, + "w": 100, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 100, + "h": 16 + }, + "sourceSize": { + "w": 100, + "h": 16 + } + }, + "gw_ui_health_bar_fill": { + "frame": { + "x": 306, + "y": 44, + "w": 100, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 100, + "h": 16 + }, + "sourceSize": { + "w": 100, + "h": 16 + } + }, + "gw_ui_energy_bar_bg": { + "frame": { + "x": 408, + "y": 44, + "w": 100, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 100, + "h": 16 + }, + "sourceSize": { + "w": 100, + "h": 16 + } + }, + "gw_ui_energy_bar_fill": { + "frame": { + "x": 2, + "y": 196, + "w": 100, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 100, + "h": 16 + }, + "sourceSize": { + "w": 100, + "h": 16 + } + }, + "gw_ui_icon_hp": { + "frame": { + "x": 104, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "gw_ui_icon_mp": { + "frame": { + "x": 130, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "gw_ui_icon_exp": { + "frame": { + "x": 156, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "gw_ui_icon_gold": { + "frame": { + "x": 182, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "gw_ui_dialog_box": { + "frame": { + "x": 208, + "y": 196, + "w": 300, + "h": 80 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 300, + "h": 80 + }, + "sourceSize": { + "w": 300, + "h": 80 + } + }, + "gw_ui_cursor": { + "frame": { + "x": 2, + "y": 278, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_ui_minimap_bg": { + "frame": { + "x": 36, + "y": 278, + "w": 128, + "h": 128 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 128, + "h": 128 + }, + "sourceSize": { + "w": 128, + "h": 128 + } + }, + "gw_ui_hud_frame": { + "frame": { + "x": 166, + "y": 278, + "w": 256, + "h": 64 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 256, + "h": 64 + }, + "sourceSize": { + "w": 256, + "h": 64 + } + }, + "gw_ui_level_up_banner": { + "frame": { + "x": 2, + "y": 408, + "w": 200, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 200, + "h": 48 + }, + "sourceSize": { + "w": 200, + "h": 48 + } + } + }, + "meta": { + "app": "asset-generator", + "version": "1.0", + "image": "atlas_gw_ui.png", + "format": "RGBA8888", + "size": { + "w": 512, + "h": 512 + }, + "scale": "1" + } +} \ No newline at end of file diff --git a/assets/atlas/gw/atlas_gw_ui.png b/assets/atlas/gw/atlas_gw_ui.png new file mode 100644 index 0000000000000000000000000000000000000000..7ef446dcad56154f1406230f15593c99defa2456 GIT binary patch literal 6525 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 F|1asU_xk_< literal 0 HcmV?d00001 diff --git a/assets/atlas/gw/atlas_gw_world.json b/assets/atlas/gw/atlas_gw_world.json new file mode 100644 index 0000000..652ce8d --- /dev/null +++ b/assets/atlas/gw/atlas_gw_world.json @@ -0,0 +1,515 @@ +{ + "frames": { + "gw_building_server": { + "frame": { + "x": 2, + "y": 2, + "w": 64, + "h": 96 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 64, + "h": 96 + }, + "sourceSize": { + "w": 64, + "h": 96 + } + }, + "gw_building_arena": { + "frame": { + "x": 68, + "y": 2, + "w": 96, + "h": 96 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 96, + "h": 96 + }, + "sourceSize": { + "w": 96, + "h": 96 + } + }, + "gw_building_portal": { + "frame": { + "x": 166, + "y": 2, + "w": 48, + "h": 64 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 48, + "h": 64 + }, + "sourceSize": { + "w": 48, + "h": 64 + } + }, + "gw_prop_terminal": { + "frame": { + "x": 216, + "y": 2, + "w": 32, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 48 + }, + "sourceSize": { + "w": 32, + "h": 48 + } + }, + "gw_prop_chest": { + "frame": { + "x": 250, + "y": 2, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_prop_barrel": { + "frame": { + "x": 284, + "y": 2, + "w": 24, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 32 + }, + "sourceSize": { + "w": 24, + "h": 32 + } + }, + "gw_prop_crate": { + "frame": { + "x": 310, + "y": 2, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_prop_crystal": { + "frame": { + "x": 344, + "y": 2, + "w": 24, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 32 + }, + "sourceSize": { + "w": 24, + "h": 32 + } + }, + "item_sword": { + "frame": { + "x": 370, + "y": 2, + "w": 16, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 32 + }, + "sourceSize": { + "w": 16, + "h": 32 + } + }, + "item_shield": { + "frame": { + "x": 388, + "y": 2, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "item_potion_red": { + "frame": { + "x": 414, + "y": 2, + "w": 16, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 24 + }, + "sourceSize": { + "w": 16, + "h": 24 + } + }, + "item_potion_blue": { + "frame": { + "x": 432, + "y": 2, + "w": 16, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 24 + }, + "sourceSize": { + "w": 16, + "h": 24 + } + }, + "item_coin": { + "frame": { + "x": 450, + "y": 2, + "w": 16, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 16 + }, + "sourceSize": { + "w": 16, + "h": 16 + } + }, + "item_key": { + "frame": { + "x": 468, + "y": 2, + "w": 16, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 24 + }, + "sourceSize": { + "w": 16, + "h": 24 + } + }, + "item_badge": { + "frame": { + "x": 486, + "y": 2, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "item_power_chip": { + "frame": { + "x": 2, + "y": 100, + "w": 16, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 16 + }, + "sourceSize": { + "w": 16, + "h": 16 + } + }, + "gw_tile_floor_dungeon": { + "frame": { + "x": 20, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_tile_floor_circuit": { + "frame": { + "x": 54, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_tile_wall_dungeon": { + "frame": { + "x": 88, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_tile_wall_circuit": { + "frame": { + "x": 122, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_tile_floor_boss": { + "frame": { + "x": 156, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_env_pillar": { + "frame": { + "x": 190, + "y": 100, + "w": 32, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 48 + }, + "sourceSize": { + "w": 32, + "h": 48 + } + }, + "gw_env_spike": { + "frame": { + "x": 224, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "gw_env_portal_ring": { + "frame": { + "x": 258, + "y": 100, + "w": 48, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 48, + "h": 48 + }, + "sourceSize": { + "w": 48, + "h": 48 + } + }, + "gw_env_data_stream": { + "frame": { + "x": 308, + "y": 100, + "w": 16, + "h": 64 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 64 + }, + "sourceSize": { + "w": 16, + "h": 64 + } + } + }, + "meta": { + "app": "asset-generator", + "version": "1.0", + "image": "atlas_gw_world.png", + "format": "RGBA8888", + "size": { + "w": 512, + "h": 256 + }, + "scale": "1" + } +} \ No newline at end of file diff --git a/assets/atlas/gw/atlas_gw_world.png b/assets/atlas/gw/atlas_gw_world.png new file mode 100644 index 0000000000000000000000000000000000000000..8bd54fdc7472f1fd35fedc92a20e70733fd77810 GIT binary patch literal 8642 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 GKmR{JNQ7tr literal 0 HcmV?d00001 diff --git a/assets/atlas/rw/atlas_rw_ui.json b/assets/atlas/rw/atlas_rw_ui.json new file mode 100644 index 0000000..d8c34d2 --- /dev/null +++ b/assets/atlas/rw/atlas_rw_ui.json @@ -0,0 +1,315 @@ +{ + "frames": { + "ui_button_normal": { + "frame": { + "x": 2, + "y": 2, + "w": 120, + "h": 40 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 120, + "h": 40 + }, + "sourceSize": { + "w": 120, + "h": 40 + } + }, + "ui_button_hover": { + "frame": { + "x": 124, + "y": 2, + "w": 120, + "h": 40 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 120, + "h": 40 + }, + "sourceSize": { + "w": 120, + "h": 40 + } + }, + "ui_button_pressed": { + "frame": { + "x": 246, + "y": 2, + "w": 120, + "h": 40 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 120, + "h": 40 + }, + "sourceSize": { + "w": 120, + "h": 40 + } + }, + "ui_panel": { + "frame": { + "x": 2, + "y": 44, + "w": 200, + "h": 150 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 200, + "h": 150 + }, + "sourceSize": { + "w": 200, + "h": 150 + } + }, + "ui_panel_header": { + "frame": { + "x": 204, + "y": 44, + "w": 200, + "h": 40 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 200, + "h": 40 + }, + "sourceSize": { + "w": 200, + "h": 40 + } + }, + "ui_health_bar_bg": { + "frame": { + "x": 406, + "y": 44, + "w": 100, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 100, + "h": 16 + }, + "sourceSize": { + "w": 100, + "h": 16 + } + }, + "ui_health_bar_fill": { + "frame": { + "x": 2, + "y": 196, + "w": 100, + "h": 16 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 100, + "h": 16 + }, + "sourceSize": { + "w": 100, + "h": 16 + } + }, + "ui_icon_health": { + "frame": { + "x": 104, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "ui_icon_stamina": { + "frame": { + "x": 130, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "ui_icon_coin": { + "frame": { + "x": 156, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "ui_icon_key": { + "frame": { + "x": 182, + "y": 196, + "w": 24, + "h": 24 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 24 + }, + "sourceSize": { + "w": 24, + "h": 24 + } + }, + "ui_dialog_box": { + "frame": { + "x": 208, + "y": 196, + "w": 300, + "h": 80 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 300, + "h": 80 + }, + "sourceSize": { + "w": 300, + "h": 80 + } + }, + "ui_cursor": { + "frame": { + "x": 2, + "y": 278, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "ui_minimap_bg": { + "frame": { + "x": 36, + "y": 278, + "w": 128, + "h": 128 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 128, + "h": 128 + }, + "sourceSize": { + "w": 128, + "h": 128 + } + }, + "ui_minimap_player": { + "frame": { + "x": 166, + "y": 278, + "w": 8, + "h": 8 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 8, + "h": 8 + }, + "sourceSize": { + "w": 8, + "h": 8 + } + } + }, + "meta": { + "app": "asset-generator", + "version": "1.0", + "image": "atlas_rw_ui.png", + "format": "RGBA8888", + "size": { + "w": 512, + "h": 512 + }, + "scale": "1" + } +} \ No newline at end of file diff --git a/assets/atlas/rw/atlas_rw_ui.png b/assets/atlas/rw/atlas_rw_ui.png new file mode 100644 index 0000000000000000000000000000000000000000..63ddf3809a6aeb56d58d095a0198315599feb6c4 GIT binary patch literal 6340 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 literal 0 HcmV?d00001 diff --git a/assets/atlas/rw/atlas_rw_world.json b/assets/atlas/rw/atlas_rw_world.json new file mode 100644 index 0000000..10ffb59 --- /dev/null +++ b/assets/atlas/rw/atlas_rw_world.json @@ -0,0 +1,475 @@ +{ + "frames": { + "building_office": { + "frame": { + "x": 2, + "y": 2, + "w": 64, + "h": 96 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 64, + "h": 96 + }, + "sourceSize": { + "w": 64, + "h": 96 + } + }, + "building_shop": { + "frame": { + "x": 68, + "y": 2, + "w": 64, + "h": 80 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 64, + "h": 80 + }, + "sourceSize": { + "w": 64, + "h": 80 + } + }, + "building_house": { + "frame": { + "x": 134, + "y": 2, + "w": 64, + "h": 64 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 64, + "h": 64 + }, + "sourceSize": { + "w": 64, + "h": 64 + } + }, + "building_apartment": { + "frame": { + "x": 200, + "y": 2, + "w": 48, + "h": 96 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 48, + "h": 96 + }, + "sourceSize": { + "w": 48, + "h": 96 + } + }, + "prop_desk": { + "frame": { + "x": 250, + "y": 2, + "w": 48, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 48, + "h": 32 + }, + "sourceSize": { + "w": 48, + "h": 32 + } + }, + "prop_chair": { + "frame": { + "x": 300, + "y": 2, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "prop_computer": { + "frame": { + "x": 334, + "y": 2, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "prop_plant": { + "frame": { + "x": 368, + "y": 2, + "w": 32, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 48 + }, + "sourceSize": { + "w": 32, + "h": 48 + } + }, + "prop_filing_cabinet": { + "frame": { + "x": 402, + "y": 2, + "w": 32, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 48 + }, + "sourceSize": { + "w": 32, + "h": 48 + } + }, + "prop_coffee_machine": { + "frame": { + "x": 436, + "y": 2, + "w": 32, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 48 + }, + "sourceSize": { + "w": 32, + "h": 48 + } + }, + "prop_water_cooler": { + "frame": { + "x": 470, + "y": 2, + "w": 24, + "h": 48 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 48 + }, + "sourceSize": { + "w": 24, + "h": 48 + } + }, + "prop_printer": { + "frame": { + "x": 2, + "y": 100, + "w": 48, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 48, + "h": 32 + }, + "sourceSize": { + "w": 48, + "h": 32 + } + }, + "tile_floor_office": { + "frame": { + "x": 52, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "tile_floor_carpet": { + "frame": { + "x": 86, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "tile_wall_office": { + "frame": { + "x": 120, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "tile_floor_sidewalk": { + "frame": { + "x": 154, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "tile_floor_road": { + "frame": { + "x": 188, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "tile_grass": { + "frame": { + "x": 222, + "y": 100, + "w": 32, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 32, + "h": 32 + }, + "sourceSize": { + "w": 32, + "h": 32 + } + }, + "env_tree": { + "frame": { + "x": 256, + "y": 100, + "w": 48, + "h": 64 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 48, + "h": 64 + }, + "sourceSize": { + "w": 48, + "h": 64 + } + }, + "env_streetlight": { + "frame": { + "x": 306, + "y": 100, + "w": 16, + "h": 64 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 16, + "h": 64 + }, + "sourceSize": { + "w": 16, + "h": 64 + } + }, + "env_bench": { + "frame": { + "x": 324, + "y": 100, + "w": 48, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 48, + "h": 32 + }, + "sourceSize": { + "w": 48, + "h": 32 + } + }, + "env_trash_can": { + "frame": { + "x": 374, + "y": 100, + "w": 24, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 32 + }, + "sourceSize": { + "w": 24, + "h": 32 + } + }, + "env_mailbox": { + "frame": { + "x": 400, + "y": 100, + "w": 24, + "h": 32 + }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 24, + "h": 32 + }, + "sourceSize": { + "w": 24, + "h": 32 + } + } + }, + "meta": { + "app": "asset-generator", + "version": "1.0", + "image": "atlas_rw_world.png", + "format": "RGBA8888", + "size": { + "w": 512, + "h": 256 + }, + "scale": "1" + } +} \ No newline at end of file diff --git a/assets/atlas/rw/atlas_rw_world.png b/assets/atlas/rw/atlas_rw_world.png new file mode 100644 index 0000000000000000000000000000000000000000..716f170a4da9286bbeb3996373c7649f5cddaa25 GIT binary patch literal 4401 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 Y3SV<2AiOfvY7Z>e*TJA(T(kY{U(k@`F8}}l literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/boss_ceo_attack.png b/assets/spritesheets/gw/boss_ceo_attack.png new file mode 100644 index 0000000000000000000000000000000000000000..e0e9acc7680646448144f4b25b863be37fef28b9 GIT binary patch literal 4142 zcma)930RW%AAgPRW3F|$R?6n^C`+3w%_FhH8Xhz|G%dkWv%_*qYEI>K9dpf=4ojzq zlt;RMQ%pSaK)Q_z(KLyn(xwTDLI#Mw_`?4M?R?s^!SlQ?&+p>*`~1G2&-e2^`z?O! zyxE`41^{3l?wifq0bmO9(+HS39eLeNZw^OZ)AxIA-3;jT-%G6G3;;0h!EN5K^F;1Y z7cVVH9Mm+-qoK_b_D{1p?7Mv4@~Mx@FQq@VS^Q&c_R85C?XUiPz+(*carYN7VY9Az z2zD)W*!{md<}13APkx#HaYp5tX@{(X!+yQ)dv@b~QIu;VDWG@mqrJRy;^tblt9Ue? zRahX={^rC>_{4)qBgxj!LN=uTys-W>hIP9%)S0KTTeQ2!zMqffX;e~T_u;x?HW9XY zIQ|@P$1VYYOB<1+lzeL<_V05RNBwk}j(RLQuie+Ce@J84Ujo3lU!VYB=Y3?+MfL#T zer7Jxbh#=_9xR2b{IFpEgC}Q7i>AVmu!RBMSE}np^N|J9jR0UprE&+5VB5Ux!HJ~4 zmixB}XlEEww=uvxehMDMYD|rQ)DyPQllIFs)Xr@w17sE{W{HwEm;P?|wEFjaH zt?eQ3<@L|>$1;;m1As@|*Fa^GwcjNr!B0t_ySTWp+)@O{v6@(AL@@4Zf1Z}Cc0pq4 zZAc%_Iq_Q~eN%vge(ynSt<0}&J^b*k)4#^bfUW_Me`vv?*CpBuoA}Lxl=Auv2j9nWWYUA@oj%H~yV(159$T)!v zz)Y#z6Eecz!FV|At(gX83P+>%W|m6%AFZ#6zTo9w_R&D+@NJ1+&V(bH1U*+FO_z=X ztY$UlL=f>;c$NiG6&m#t)^VotZ|8!E*zxZWQbfiyNr*`Dfgq#5;N4Adh%Q-^b zuJ5C|Chu7~pbG^)4a&yER|y7QZT21uaLy;{_VJ7_>3-GPDi^eX>DnEVBkag2Q{Prh zvDlZ-=kH1Ciw+MD|5i*6@8^s9#E8mwPN@99OW13z(u?{(3Ee?~+K=E<(H(Jw+wmuDMzwn`#5hGPa5){yk6 z*jI`4q%L$jT!we`f6;R~10%Pn-4!gF{I6h*NmT1CPf8PYXnYDI(e(j_GlW4q?CDSY zNun1>GJHx(ytgZLDR*aOYwnj$ZHXU6$DGFurq6sk8Q3;6Dp@<)T6jkNky~}; zhKH)|J=VQubjzO=apf^^;8i;N`165V9otVL2^8T-C_)YS%vaev5L%v`QMZm%(xb{u z!T-30t%VV;p4HmFm+ML#`9S+b7GB%NU>_)g-el^3BQpU+a;H?%D=*QV zv(9yUH+S8aJSbFFAgl)O!gAN@96mP5a_p3yRb(Tzb9A4*U={0+W(gnM4Vt2EDDB9W z0vHZ$SK{gTYP8o&&;FvAjco1D8ZbI`tw?)@>+MHzh1=*6X-6@PM7Hv=Gm=Dn;fs4w ztKt3jG}Bny#ev>NkcuzV$xS-k#^@rl36^+pZC4vZSEBWtp4@f2IisC4zLl-rl((`x z-F!<*2QOyec#9JKvQS%?XB4a=X0*bmcs?TQDnzpR#7Lc;mIwdQeBLFpb7iHz3ET;q z@_}=W(6K9`M5iS|ct3{>4wVzaxJd8|M{ei3ZbzKe7)`fKoIrQZ7?-emxp5SJ_lk*g zB9l?>6hu+73-hi;A}MZ>8XRfH&{<3xmOLi+v@4p4D6BNjF8Mry%2NfDWHL@hsB$_1 zv1i2x^p469Lp1uN22%lDjRsOwjCbEp;_6 z+L04WiK4i0(Iwj^CHtnb#uV6sv&F>cpCydUKeN8AFKw7iG0thSctzd8NaiypF3&Ui z%3b;H(`gwEUEbdWJvPuftUt0<)MtLfD&b=~X6b~@(7r^L20f2XPaax~tv_hdkW!^>go z3`|W%;?syCta<*Vfhhx*_^&#)W=HE5()nI*h12~fPL@SomdE9!bahUuX*Crb$<{j^ zDPN?~mbq1zhg)zClNE}qV^Zw*UoAbtv%<-`6V|g~D-q|aqq=eGW#!JAl@me++ClYZ zfZJEF!p@@2Bs?$Cq9BW~sv=LXk3`)~E0t87BC~S+b6;I33R2cRSsp9lDl6dUB66s$tGO#>wL~YHm42Z0*>Ki`H6ty-Qg*tL71(w`c zEC)|X;7T_YPQ<*r0{j(qBaouNHLn#4EMwJ-?Y`J8`hjN zm~CrXgSxU0eW+Ymoan&WforZDHBEgHMX90A`rXSA`RtYODoD6@>S(C(-x;9=0bU5? zd}1E5^0wc(KzY~S;U=Yb0+s3%t@B9y!U4f3}sX;}gjG*)}lqd=!H-?dsrVt$TGNOP3ND&Yi zkWd2-NQa;(5eP*rbclcn#RS3uF%Xh_qA=GxqifBNyVkucKTgg$JNe#kf6u%3zInp- z*cK5P5dZ+TSXr9e0{{&A3IjGGp^Mw4d~fK2JY#dr9N-H+Sq;Pl01yqcGC$-PoX#BX zij(z`r?9J-i#)BOtw#^5{Bffe*o;Uk`WTF@)Q?c zdGPxeAH2-KWG|kG0pbq49LQ}_2UN5~%|xj1J8(>XsPIg(W>P3`phh%6)<%r3Pmp$E z1R-|`dBZHPIfZX5dq*V|Q17}s zb>du}t-W>ToSJ!zEt?IUY;S%WJLn@End(6}D5n?NP|fKekB--XMt>FbCw*VPEopc=@kz-NH&}`?@M`zhXoD4|w`tEU_qT#N`(f=&G_i43re}A>ILiDj=#Ii5O zvg(R2IRhtj02W;l^YX)1DOlPRTTh3~kWqD?VDMpak|*^RgE_KtE;&wa|xro z_?={SDS}mHiElYhbFR&ZmB7cWM*5K6qSb?tY`?`b= z9L2c@2a;-2N4X_ko_Rnl;#O2B{S5yF426={dulIZBRG*a43q;P8x>ARlRU#F8pTbQ zeUctd^bw(~VDh+EGIKwk4eIG{y_oO4W>aA`r!mOUa{c23w+zfMQQY- zilo!GouD`$&PpLzCv)Nxs{$6L4>qdS*%vV>5p)!VyZzD{r)y^}V6yVWqSzahyZR#c zQNRwmUXq*u%EHds&7XlU;%>#Zr@A|&s_i3M;Jm^?d~YJR^WUZ@t_%Q<8_-*yaq0Ly zK5It8`IQJqK7MuiMRHWLd{vhiQaH5Xt$$zPk|}Oha4pO5n;X!|ybFctd-it6k(d0vT0Mkn#1g;ZH$E_%yUNuR`klJAMCI z%>~;hXE(a#1@J;yk6%-`^te?1ID9f)7J<*xPyo}==fly$pPjpI6sBL{%4&FlA1UWW zzSB%okS>|iZcG^Y(oE}S|02(V^6>Rr*VleUSIp2j(WyWbv#Pu#V!zq1l|K$B!1rQx zO-3xB9OQsq<$z>_6Luf2UFE&;?QdFzG&6WAdck{W!^H=K1}PBcou1xJ?M<7o51;x` zn-R2A7oHn_rk}1zV-D$HFt)Uf^y(=ENx>(z0475N6kVN_qkhK}WZ}K41I~-)t*5SvMEMm1%YBiVV{j0}6^gpJV zmFmlhVIJ8Iap{?X1lE^-AZQPMR0g2xQonpuihwXw>kbij)_iH8-)T}j03C+IJViNT zjFEYxbtyYxUefMy3o)Yil6Z+EWC{gNq#RtL>+r+6_nl{DzDGij7PyB*usTece`IB1 z_4pM=x|i;Yv1!j4#4HCQ7E6N6X9iir6Pfj+Ki8=L1?5aMLI4a1< z__Aw#o!oC=?$l6OE4=Ws^3KJjo^YcvZYX1SA>N9t=AcmFa};;|h{=}8XAZL?;VGqQqD_hyv7FyMP9 zv0rsSb<>jPri8j5zCdE>8X)6ua(15P$sr2DkY!@eW>8@nOXOva{1SRK+0U4N3vE2V zIU-8|;F({N{94@RNe7kuL2-b?D^tCc1PGz{jp_neKW*XAm4*p?;5^8OrI6)7m*@Bm@#~2E z&FSacko=EFn|EX}H|Lje*@cj~XP1Ke|7_c@Pfdbd7f*McT#5)EknCZ44B&k*u;USX zaN`vw8!Vc=>}tON|3PSRXO z+(mTUb($>og>| z%9M}_?^9+Eg|ur+g8ES$@dBza*jKP{@ nZT}tB8I?oHzd$12(D^88swe;Y`9W!DGzYAX+M1INV}Je^5bnGu literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/boss_ceo_run.png b/assets/spritesheets/gw/boss_ceo_run.png new file mode 100644 index 0000000000000000000000000000000000000000..dcbe6795ea568ad25fc580f6a3ff41d5aa611216 GIT binary patch literal 4515 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 H;dB223(PNi literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/boss_ceo_walk.png b/assets/spritesheets/gw/boss_ceo_walk.png new file mode 100644 index 0000000000000000000000000000000000000000..792a6a7993251a2c02dac947752829786dbe8780 GIT binary patch literal 3829 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 aLYnP8+gk%ePN)$A#7#Rl-r8{B_u%&wNc#U@@3 zv*?-=AbP>EKl{hT1e))w7B&>?t)+im@bqc^>+}<`bNFPdsOkvA=a0@6w9xbYNx_c~ z-hJ@MukCDU1g~E*%P-?6aD8Ve0`hc+FIP_AniOynVjDAIgsckEU;#Q$;f0=2KFq#m zDugwr?o-M{uqf-uav*TY$qeYcJtplwiVVGU4k8`fCNevV0hM#go=jkG(_ocken7}$ z+BS0SfS3rVFYBhD5}_QIiFhUbq}70hS?=TUs$%*pyOh!Ed{cuWDqP6Y+&=IS3NB>H)@aI$9&w>ZQI7*$$ey zeW|3VTJF^r&4eY%V4k*<{ z8M&WH!1@caEN5+S%&r+n@Z-BKv2dWOB!zzjJE!=B%nP*Uh#+ZjnXjmEDk(Ky<(LdIX3Shu50T_%Hv$+~9K!~^uKM+6tC_r)m4uBaJ$w-v;!T!_DptrmRHJ8szQn1?YXc5;)j&+c0q^)aXgfmI5tthxiJ*xN@WhJc#tRK% zHrAdGW?+y-FcU@V^gout3R6=t9aN9V5rq)dS;||vGcc`~Txh5&!K2kfpumoH5<~G7 zeW*u|3S~erg$6lXw6|f+wed3TlW;lS{K~EVXlemcs=7?(I%+85U{FSB^{hF8bC%cf z`92Y^eH6y~b-HTxAAC&fDrwdG=4iAxs4Q1n>jH%f^*+J=^ZjV@fJTEu!h&7hD5@lx zoJI2NNXBEMHAG*TxAyx@F}a#l7w+CCbcw;1i{O^w3J-kxg4Fy~My}*Xu@6YVJ~6r0 zzDWv3v$^?sf2yUS;7#_ML3$J8{qH=6m~4m+6YLgKdM;9kay(2_#D#Bgyq}W_w_8(` zp&+bVI#vGsbZajOv_zVbqh4L}v+Q3ls&iLxZc{slcIT!mWzOra@^a>6$qoO;MjZ)8|5J=nJ1HQs8P_7~Ark z&<#QowRae2M_bi2^V2!cCVElXg+e{Lvk~INu#}w9@e>-2->}U!JTRhd*|C1z%0xP4 zKM48T^>46kmHW4FbJHBId{2NbsMQNoy^#G)q6i==mdi>I+c6OQ_ovbeA0*@90w zYZ9S05EnlEix*etUh=oq7^ACekcUV_?z~6@uPh1jG!RwDb;Qm%HG+sc;-=b9^dw-D zR|aL)q!a#l=0#l915;SF;XFEl3oBbI0^MAnnz**kDHEenhl-c|le%oW`zh$UDRH-%W|DEc@PW5>#+>>K%0?@h literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_accountant_idle.png b/assets/spritesheets/gw/enemy_accountant_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..f2e401ec2212cf0cc6a805902c0424d71e39943d GIT binary patch literal 1040 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lNlJ8k9xW| zhE&XXJJ;4*uygmW%S%X8O!sh5@hbMQ|HL$R0qhCQ=h+wsRnostt5KmYIV_1B5#yFa#n4Q4!} z$nZ>np_rq=lI4I5Qvx5O!SXLt4}6RJ{(6b%_kZU9cGPJ#SYCa{`sLxrz3;R`=kL4r zTfS-kocUZJrR@weoEbnS@Km)}X}lnK=Klub&c5x;6EoGi|+4j}nUzeS~AA8LIemT>O$+FB#-Y;L$X?^LTxvGD8)_;*7(x0D; zCj8l1@<*dOhv|>+&q$^-C;gfG@6DUC!0o{ODfZkB+uqfzjILw)cMN2Hh@Jo2w@zQJ!5{r&cNW0?!k}-?koE5pQUpesGliki(ODxX>KnH z@%&1LXDt8k9dPQY{^)-3z60xrw@2k&?Y$c;zv?p{+xuhji}m&lU>c~o{U^gStd2I2 zKXB)K4MVa0XT~#s&#)VOHwFsC|7~;ql^EqU|LN|^6$aPOq(M)lMO^5=kjcsK)-I4G3T?HYE@2U!KO b`9EXqAvf=3!Qsb&*^R-|)z4*}Q$iB}Hwxz$ literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_accountant_run.png b/assets/spritesheets/gw/enemy_accountant_run.png new file mode 100644 index 0000000000000000000000000000000000000000..06be109db5b435b79dc25d508c9b413e3bdd6ee6 GIT binary patch literal 1816 zcmY+F3se)=7KSGTkn&V7P%J`FkSJ6^r~=_Jv_c_P2ozT+ECB$pp+-mS1popz1lShl*n6t684sAJz84h%81d(NduLpW zRu1DsXx|X1l_@F8KcO0x10no}H~_Hz7hU+)$moft@R4+P3YoOfD?L6w42{4h=GzNP zcGfW9COIj`0@VupdT07AfD|XCZOZCP-gLWiC~iU-7Rz%qv|Dxd!Si>Xx42O45mn9_ zt_W`P8yV%dr2Xf1W_RBA$(3EV83LAMtkS62FP!T;pp^+qK^QwcUg-+>U)2X5U&tXv znYsY%Puhanj~@LV^Of3qFaP~#{H}KjK{PiNt|bD#)@DGbuRQ?tM8KXYxi!z;aOf8q zEA;far(Gmtch)Y5g2#plm%PX9KpXwGjL``WgtpXyul6;pdLaA!z)cewBjh2-Tv`1C z%Z|Oy#)xc3dzSDc_GHrt^++ZSE`&j_J9Y31$hzqqoU_S=x*RoF@Qr9w$^O<@wU{g_MC!Therjuo{-ddq#(m|p zgJL+~#L^6+7kNmy`L~F=sWRy&tS1(CC;=arG9@F!U6Z?9)`$IeD_Cz^@Z^Fuwh0)A z#lQGqFp}!i*8xw)4U$Ud`#Tz5e%jIR-!t89y>aU_rP!TH+wC8{Uqjmf87`pNhJpDG zzS55bA@OQBcTIW-chetz{xR!(u1cP~nB+i5(GYV}EZv5fyChd=I2SP>?Vy$KPXcDA)`_=s(UVLmPgTaQMcvp<`c) zm5gI^QOZ;wXH;7|)gOwH_)WN~)7o*_vil6A@J_eE;hf9?FqIv9<=~NkwRg7$wnvOk7JkeG# zT^K(ujMf>8dP&A6K16s))yWc5T~(f4_<2xHH$_yLGI-#hAxEA&f1H-w?tE+1pujI7L+VYw zSZ1joD3~AxM;Ivj%rr0`)TL%OlX!V*ab~3`L1pDit%#;HclKWny0j?#Mw)hu>VjX+ zR+G=)eY4YTsrt%n79-?u z4_-|NZIaw>(2q2Bf{PAc{{zHJw=Jc=%pt`qMFUk#_Z z?B{r`Pas5lKq!1FCPV2u!|OoLt6_*4=AOBrE#-KTGJ{sA;$B^8G1I4k-AIsfBj!hE zQ4tROuh2ck`mdj}ven||N=713D&@q6=`L$-zRRA1tIKE|(?~r}CRRp~1$n>d!ur>i zjdA9=91z{2)3;e9jB&zrX^|BlbNN3rz4R@A8pprALo!G&`Y49&q@^D1h~x-QXjEtu zK>ehu7bF-xIfRDYWmjsT?8Yu--2+);Vu?@Xu(mrlG&#dB?TI;rRKuBSuLYmIOEX3( z+@oSP34gi9Os@DUQqYDreeiII7PZvEwZYfHEJ5HRYw^BtHeT?eg*g|0EV%;k8tKv(WH4-h@e9&>d6W=2s2oq26<1CQap8lmWJG z9Qk^lh-&5MCI4SWNiti#r*VfDzv0<6$6&3D5y(`mFjG+2N6+4C+JGgX>5VbWVx3hc zAv^~+yB>1i@8D$oeLI?^#|2;W;xzDUx>n9nk(yT8V%2HOxWxC1lC!v&?PL0`-1ujo zeUswjA;cxURld*RZz5~lbT1)`K9iqR>mQ5B(xWIu7(3Do4NNBBKR#+?Y{cz%QqKGj Dl9rF< literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_accountant_walk.png b/assets/spritesheets/gw/enemy_accountant_walk.png new file mode 100644 index 0000000000000000000000000000000000000000..fe1ce735795e775ceaf536da80deceeab6c63c77 GIT binary patch literal 1331 zcmZXU3rrJt9LN6!#-oZ%=5&)tmklfl&fv^OCMe*T1(C=4vJYz%@K9G!_5``~)IrNBA~2HrX7G$q}4TV6{Dp)~iwg9LB;!Lw265m>8@| z+nf1b=U-{MWp6v%r6f!CZOcn$ZqC~(QLJ@7;3(cNZ1?-Q^sT($A3nI+b#ThNG`ZHj zUMybjzP$zia57R`a(nb*x@P=a4H+1&{p==@uFNq75V!8Sz^XC7CG@kJ>8}s6DZ(jn zf)&T*3M*)Fv3&XQ)b~M5JZgB5Vwyb5DQZ0G@3h%&97PEomSxwRl}?`+AimJ*bl7Fg z9WeXHX5z}TqiMlmi^bA9QwbDxJ!$c|nbe>BuKuP`dD`G6i(W`6^yE+Q0ENQ?e)fR5 z@&Bf-hwup!U@%H9SYyWI{i`i=IaHFhs8DtNwnpOun5el4u>HPkr71m+Iz-|DjNtu_ zV8uc3uX%`^KDj~dTTm#I?&(^^+Ve=p5=gw}Mn+lbqqM>6PB!08gzTJ#*#R+v&?4$egvgiEAvF%&t4YBEADSQi zGQexjY+us+q`Ot|b*@c9&jJSHeOY-sy5tO3Cs z>dTGytBw{SwZa)3@5Jl@80DfWud+Tt2A_JsSGhQg7rFmou13*ali2}`3iFl>m?*@u zo}s8qwMMsThw^Kc%Ahd4jmONH`}CS&_5>T_`L`g5K*eVRpA_1&?Kv5t?g&tu^bO{5 zX`FB+oV9vp6xtL8d*AJ%)oV z$cyI6r>9Du+&eSWcU`Geow5~vLpz(GiRPqXDEoHD}B4LAdc zOiEn8F8UZuEEq=g4&S#g1wJ?N6W<&mALF<$L4MBIahMC8myrmFpjyT$?M5Kh?KUDe zwH_d)c)GjGq+`U z=Sx}MT)V|3d^mKY;`xG@aB{ynYRqCOCL?7)s$ZzBzm=Xl{j%Nud1ShmRO2|#o6NSJ z7C&{9NuM4n$e&w()Za5(unyAs%5r1C@ow4gNphj_Z)RaNR4i6l%$V}o&D&({s(#m# z1Cd@5pb?^L6C9mRIY5+)VlFU%xN%GEjzv!I{O5Ai=<9k_<$DnF2z>6{8C=8$-H_*s-%SJ3HU^zHi_A{r~U%6h!ec zU1q)v002|6uV*j-=pmm#wy`1d9;g*G63=f9s5#}0xw||d@&*RGGC>${CpIRQ z%%;f43xCVG7~)&$XYSO0cf_BoV2IjzE{gZ8TQ&(JZBZ1F_Qb+BXez*om&ag}JiEM# za9wj=0fJWiSD=q6vfdew_8hT+ayH@af7sod5} zHqqtQST+njan{yQ(}C<-aVl`=nnf|=*gkNDHVGnaI&0;>iz`tOK`S68-vDqBVgNHc zyiriP{|`$0AMGK@JQ{OQkx)V3zIcPM@6tAEdVIngbFOJcvpR=Bg_ZC$0L0C_HgO;& z+1XHG7ZsXT7_w#$WIL_`TFgvu@THx{=kmG2R^%WVlB+>I!Y-{AgP53qEeW zm2c+e_)xK+Xda6Xgdw?)EHu(ED_pE@pNLNuEZolAt@=1slCg`a*3xYf0|^c8AVGUc zdykZz*Ct#aKe`aaKg+D=tHLZ)45z4;*2{(npOte}U+Z=HX6_YNv8qe@Sx`fzU_e4XTB4FOS7$3vP9!^G>aT<&*SNV<_yi8Hsxb45%Mw zLMQR@nvCr-#-we(9u&$xhZBPP%fSb9%@EO|+FmB-C$pbPwm~lXK>h{Z^8RPt_7FmO zx_W_EeZS5G{-;m6e@wm_W}6TnMwl}@J;1p*h&6xijbD^c4}VYw27n}>C2UG}DCIhn z0yd|9*+*z`Xm2ldLhX~j&2^=VQGx`$XEefYD%^=WczOb1s~D=j;Zmmk*8P2l1N!LRW~NJ~ zdZDNDXgB*E!4^j*g{|RwQ9U4j7mhuhWP#BG$?!A|Bcm=-~MhSehv4uxEy2v n1ER%hqMcLsXw))D?yAyZugN#)M-HrUK_@NQi{i=kh{^pI2d@wB literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_dev_idle.png b/assets/spritesheets/gw/enemy_dev_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..b41cdf567bccdce68b3b2a693301a8bc65d182ef GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lNlJ8_jtNE zhE&XXJ9odoaH7QV{ZHGiEIPQDl?x9Z;Z!Ss{G_9>$Uv)ma(#y|cb3eYo*tjJld?i; zH?6E3SPa#YxaJ&=owcno?)|TQd#moBSKqmX_ie4$r?;Q)#eTM#3bgRRM7N9LXV#oi z`TMVKOJPXG{2!}7`}6$md$7NaVMg$d7}eXaYrO-KD^0UFkH}w(U&o}ge%bBR{^Vx+ z8S_;S%vl+<{#M-k{}yIHnt!fjcqU?(5czA*l~RFCn~an_Z{4ui_2H*=e|eLf$V2|u z%b8|4Gn`RmcqYJ5%+X-UazKVD!S7-5mDcIpvCkKt-F|jOeBFb7kh0)+yBqATycG^A zw-*Je;$t*uX8>uI{K8Qhb!ltPZmmqG^>Sxkem$%{X^DBfU1n}}{H2{s_D}Lt`8%;h z>P79N{wL?HdH3jLn(co3?BCq#tQTd!|J}OwjdlHh-Iofxb(#O2__s$j;h)n^mE3n` zrI)O(dA^RAz5A@){{uCB%=N7x$*4=Zp5~i=yJmR)(tPP&wx8#R^6&1LrL$f|H7_~Y z$5o{Fa!oof*Vcaz<@xOy7_M+XW1jJQr%(pSu|FA}{WJK?=*Igmp>7&O@u4&95~e?z z-*#~&_^o7~c24eV-QSlBs~>-C{~pYE#Q9?lW=x*THg9kC^aWlA;-}j4I_!E^BfE7E@4r)jbQqsavGafX*6FQk zS-8$WgE}o}*up~%801st^G~=xTWq_%T)jYj9E09_fBBw@zaM`z|2Tb~T>{EfFE0Dw z9i;T~6vO$qOI2S6T>8GoWGZ8Qiv4HC56lb=>Sx#uz89-r07b}W#xs8twH$hXJ-rKZ zK+Dgw3#7iD-VI6v2J#2)__G?Q|9H>#Ea^_SecwMWt%iL4e-^(Yna)W56-oe$U1UG7 zL%d$*FHkd710;r#lLsh3XYwb!OSfy-IUg9Lbs&M$^@$T}=1iXS{AS+0)gMdtf7u5N zE%|3A1%Y09%VvwU-{Akp_4hDKf`69Gvf1C-z+5zkhajgvV07FodHQ9!wo|{&zYSOe zPsGms?OX5uyX^h;>*fQa@Pnjd>F<^+cY(e{cJvH%r~YS5%A2MuEq(MjFrzVey85}S Ib4q9e0F;;J>Hq)$ literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_dev_run.png b/assets/spritesheets/gw/enemy_dev_run.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d1f7be45564125e45c35fc3884489089b30399 GIT binary patch literal 1818 zcma)-Yfuwc6vuA@hypggC}>U6Vhh?<#i0s@$MUio5rareu_7tOrWPtHXiy*vafSB}kx%kpY3gNDQwSqy~h95TZ%QCh0Enp=0}@vokw)?z!ijy}$px z|ILlqzIndGG6w*_eCn3aNC0r?5M<4rgT9ATGRz-jSr;aPQ(&zF}I4*UCfkTqiY;Xx@Z(c|Z= zJ6?5zCQ>JrvijYyG;#^F0%Uzv=bIH2@oOqE$`X_5&OF2AZO_x;fa9PdM3y(6!FHWoWsN23uMwEs+{`44+Q zFZzxMyo%6r8YbD^mN?s|jqcBeEHT0Qt2V&X$qqDlE&-s)R_{(fSh>u(JT`89x{cQ_!q5CMZ-<)dqC~FJ;4gi-9q3fcF+! z@khB0{nI8Wy})|YJc-wYmA{K}7J!0l8@ z#oB<~k_+U_kEzqo6@*&-NG^W`wc`U7bvn8$C`3vPFb>~69d~5$0czJzGO3@poE4qB zh6KYClJ-?r3z78S*9!0+C;em9roM@meFqti{oW16(_1vQb}AT+K&i^faO z=_>hBhTL>>?I?{3x77>q#^FMFe0_&kQ**zQ+v)_$$raQSKP=^6GkRPQ)m0;R$JT~d zySwzZiOJR?By*1~rRdS3&y>Zr%iD?vdR{6xaH_>`j;-gm1A_2dWD+brikOjmkfY~A z^9T{8eq-v2(F+e;-D_wzTfdr!Pqal$^=#I@PPq`=uO<(mbeIcEMEW|eI*ET{DL?6(gyoKyquA5Z9*pXq(f zStEwrXC&I@o23(mbq)D;H43(>{Zz<@4?TFu9xa2|@F$~7QZ*_Kc$b%3 z9ol%C*5|KUl)OAd-}H;A26s6I(9h@7t&Z{V>jNj%$KF6Ag|K1-(t-?ai-1Q%PoJy9tj6=S{$P`(lu6QvMY+6?e};;gr+oh4)n$0^5}G6} z=y&xR_u4)E%haN*xMv>0`l*mx3*VUdflJn0;74_Rl!6SnnYfpz)0sUbQQ2tY5zC|v}(5_Z?sYQaCt4*yuamQ0<;)%BUgD zi@iUEDbKAblPVs!#)=(bO)O(q}F1UGn?`Ul4x%)9uWBu^8+%+DnH*J4iROF z{Tq-;!l2xgIaIH&;MHDS9nvS1Vg4EL2|Q?P``WJt^&q~Fqjt0ygmWK3HFEo#l)*Nl z@W|~|r_D(LPdV`UT1&yKxy(?SNC$0n1EUd2nz<5~MTg)3dP^s8OBlcGP-Mv3@BD}1 zwfE+@B9k2?=}XKiQ7t`XmxfPGyoGFJbYopQXS}W3;19m}1i39X5c+1!uhHLb<@KLK n1T}|Ir=%$J-%!Nm|0-gIdb~eEns>6pv0oo`)ArCC!F2ZDR&tpV literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_dev_walk.png b/assets/spritesheets/gw/enemy_dev_walk.png new file mode 100644 index 0000000000000000000000000000000000000000..e5c5881806a82662812342c755e4315e6094eab7 GIT binary patch literal 1336 zcmZ{k3rtgI6vw{;DMDm!LgsjOM6_m&qI0uuJSr216$R8WP>{!DA|f(SK*U}u44Gq- ztv3pWMr&iVb% z`7T6+g*Z97IRXHjxI2UQ0YHPlfWM3mzv{+jtAqYkXh<-ySWiv+FDL+ZI&N^#7pE(A zgIIcG)_a}P;kCaO7Dgr}_-rWO`ltFtrAKO|#}CqBHDmZuftx*Z^=dRR)7Jq#?&Qh*{d*jNJXQa7tqN^$HlRQM0#8!zYy|MqlQfnu$k0o3<^BkrUf}nWhwFPeF_DB4POZy zV{m;`Omi5;J32o<->$C$HMiyA(Xphdzn1B}h0PZDG^gWjFI6hi7$*wg*jZCfH8xEulhn6ALW)83NQ5>XUd*%ifzl`0sBz{fOJCd{0jdgvoV7b=q25)QX| z?i7b02>S_k`*PzMK}iW-+-~X4JJ2;ia#U@tL;+^;lhi#nY|z6XE&Gs7ERyKYol>g0 zr-o4NRDh(49ANtMyPTYOJoC@J z*|{SH->!g(u3C9(<}7ypI^G1NUARa)EIisnxfkh0X2dyl8i;qmig!##dxEr--^42X z&FfQz0iP0iwNT+*`587_Ejwlw>P&`BP>a&1IS!y`eH{Jl+#vN%k_*gwSU+x?fDBG+ zQaTM#_0nEzL>5vtGjX}M?)*^y4Uq^tqjCU_n?cP++c!fnk+bW0^Wbpjs7zE>UmJ z#b%z75-3xr#uflyOfEc7-47F+r99m3Tk90vBr?7}Mm{A7mVx|)w)<#2q;^dl3f3KO zFN?X-BZjfNcuW}A=lt&e{w2zGpop0D*ydi8b4Q~QHd4!&{QIrX2tsyHwFbCk&zFI} zJ(DZ=5B~MYOvZQBU_p}6GOp!i| zjNUPzR?U<+b*|`nX_?^pcu9pRFjW|+JsSh*)aj#gU0)viFz+OF={J`0A_Tb897*pe zOwvs+uvUE8;<-3`w|r^!O^ieFSfL3=PzK>6^}r^S!W6j#?+Wp);R^112ZMLC()cIL6k_{3Zql zH}ka>gbUfE-TWOoxQJWz5m<{YR)k6k|c-8>(OwUn7)+Kw1cnL`BC`)S#dg6i~pRXcE+lBB59i zX??K4L?Z>nfC#k4g^Cg75g^0t#`jSpyQVr$Ma&xHmqW;#i#&i(8;*LUXP8{?J&_U&-HEBVoqojV&X030h`+i(ePGS z{R|t6H6FCgNR$W8>|@e`zndJ7mO0}JUDD1S<=yVmX~BOq-OW2ipp*hxdK$kJ+c>2#VnOu z)SvIf(?M<{R=L6vs3O<`p?vF!&IL&+@A#q|8H*IC)1~#KA@5Ex7SfgD9<~y+?OJ<}yCSNE#?gY;7J@QarbzR;%oGEQxGFn{0ygpLO#^YZpq%?<;@wrt|1X{CK1MZ6odc5A9G?1xZsZJ^gJ{RF#Dbs>aLbcuvL^>=nydMv>+joo9c?$F+fuJ9z-sJG+p9#$B<|%1HMdZE)mucRYbGhT(?8-sdU=A$3 z5jPcr<_;<^4y|n+P4EgAXi6T|^xzSLf;Dm%QJs_qAo++YD_J^28%otlN!q^iC!#d+ zO%xnD?`#3cWM0V;ceg`tgbBJhzLtQPZPB#6p44=gkz^LEKf z@6!p}_4zkZ;jzjHn~9h)K}-M$bNiT8p|0$SN$x@dH#jC@%HfdVI>+Rfqpw#+!tt8@m!L~Wx=~u<97RGH$ zO;LaiG5x;ShqBi+GBvFbSM0iixP8fM&>a2WEatoIi)l$HP9N1qtXY~7#T z-e|63-37uaL{ylX+dj`{$k41+B=+YtILoFOf-jQR!+&aiTON z>UMCRjZ~ti0Vq=TdUWrNtXPh;^f=1>&{CRljct`>zTpUb-Nro^BRLf*n}+)UEa-*9 zVNpvuIu-udf76>Jc30n1_`y&+4v^s^EFE{o5DNQg94f39 z5(AsZDkS&5<=G?pj|4H%B(8@lWPgXWHM z+^X#VJuN&sC!jzH)T6PZ#E`tKYCkws@{6inZuZhd?9EsiCcqt^gKb;-H$k*pzM&`o E2CaS&{r~^~ literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_hr_idle.png b/assets/spritesheets/gw/enemy_hr_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0d6646d2fea0d5219b041aa1e960026319e1c9 GIT binary patch literal 1049 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lNlJ8&w08y zhE&XXJ9odoaG^xI{nK_Uiyz!etv(2XUvHRc>EwGW+so$ zJJrNVZ{65BG>*CWG#2mRUg-Ps>$>~9SJ%u_-?@c%Z?#oT#s2c^d-7F*Ru(LoSl<5h zHTTB_`?uHSJhM~#_v??aa=p@z^@U)(rx^4_*Zvm!?U1GbHDG( z`M~~pGs_I)(2VupUOl*;+H5~#K39U@JK<^H9u-~pJaOnzlS*cB^5*xyXG^bLpzaFP zyOQCV07EfHgC)xW8Kwk2MuT>S8IyneC5X7juAjYj!}Xm%R(}m0K*>>r_z@MLgLQpiO-!Q(C=^1|M?WQH1d#emqU+16iG3j2-&m~j8#(Jtx`sZae z<%|2Jzy;?!_p8)jOMMXPY5X$T{QLVm!Oq+L=C5C~{r8*y(U;x){k?fw!_Iw0 zo>8~EN^V$QNPO;)9UXZ8yUOo#sTLouzc?Sov`qExloH+AdF_2m=12=85qR5pE1w)y;C>?3mXG^9x9)IuW9iaPQ{ptBE3X$de!gTFf>vQX-F%)yf zFaK7y@LNz>xXwR=IxUo-c4jyOj8T#K{1fiZ4$G^z`KR!24a1!K^X+7wem(w}|B=3( ze1gTP*Zs%kkJ!&FY>1zfpB3W7y7lf9y@U{D>aR1ZF%2Pgg&e IbxsLQ07Gf-$N&HU literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_hr_run.png b/assets/spritesheets/gw/enemy_hr_run.png new file mode 100644 index 0000000000000000000000000000000000000000..c127497c60be5b4e4f2a2fae32a9b24b5b2197a5 GIT binary patch literal 1816 zcmbuAc~DbV6vl6`fNUZy3Y0=9sJH?a3pOkd6vY@7w61mJq0~^MEP^bSY{D29I>wqR z5s0av;8=`Wk+6t?szn4M$e@B?z<`8G6S4?-ki7JUG9CMO=gqvibMF5A&Ufyq=q-_U z)}LAf0PM&cBDMiQfK9-fZ2|v-cSWWSivyI%2w*gQztop=VW5p15xzaU_%D7)%4a(q z+0s*PKSrPRd+4*x({YK%QeV4_x${<(e7?@{4f{0PU?sfvZ1rx(c8{LzkCU(6zPc(p znY@42qPZ?!%;k?NZd`m%r7CHCH50)c$8PRny(F)_<17C-LBz4!x9 zviZ}~E@S>?!1<4wS#tBv^TNC*(q&`5p=bCO2EI*0!7F>4r}n-*KW%_RJ=bV%J||=s zH;%JU)X47EC5}jyqgM-3v%CUJ?K0VIPrucb6IB9wujl5ebbEM)E)t;LdLw(;DAuj^ zkON>V>m_IpSZHSBx_GNT!5lcm5r7BLu;-KBBGxYIb-o@WzNYQg2{YyW9Hzqe&}1h8 zI4`Q66I=T`J@|*-cXbt;^ANmSR*N42fPGj2)|YNoWc!Uyq)W=+5tm<{GEFE`<$%`j zbnzUOQiQkx*8bca>*$?Zr(zDj%SG@ENz__P5bJCWI~K!LE@s74`-}`V3l@@JXfexQ zC*M4XT0lk(x_b8{C52R=6n3+e-~-s7K;ndHeh_0f5cOX|!rc}gk@$vfn8xCU=baO^RyR-&8tRnW!)2n-R|RAG|1Cj?Oaq`Uf^^mH^lt{sM83T?1>NA9pa7xH4FPrjpp zXyoZfAY5)HkfrRr@G6FuLH$n{I%C277GcTVhp|A@X+TWW6#5V7$4R;ypSEOK() zy`B?q{NiUG6A8w3fkVg=5Ral&9x)yQnwmaXZtlSkV*E+cf2?lymQq5a2*CF15qIG4 zjO&^PqCRA6r49k+tK#mO!(~)-Qx2{r06$xkLo^bHT@%~_<@&@dganzPLE;K9h6c5rx`He;1SD*}9u|rXig-%(@|8~vav=s8 zaK$b8VOtfEH_vj!#Ick{K@$tGtrQs>#~;YhBks&V=CHtA{)nMXAoV(NKA>_7vEzA_ z>`OY|Af1?}yUG@)6HX=}waaueG~zp4qIuFGU3+<54v|in(dpEF*Xbcu@DU*;|}~xsyQMOcQGE+?iap6#DIJ+})bh zw{H~YuSl=3VGaD#q+Npbp=_IFgDo4u59>?@W1G$RCzoa)MrhlebPT~a(}<)QH=8tW zy_X(QIn@CHr7`vpPBKgy@0Iwv5=x|;Euq*2O-tsPNU=%i6~lGGlpoWO+Qd-EZ&0cB zjAkH{x>q|AXh_KU@0ZlP7{3|#tUlaX16Xo8KS(wOHR>T_o<6jU;EYTjiJaG17u7wWxfS$|%$sC!#lida37c8Xs? z?LjwHX8611yXzTcU7cFd%B(7)J5%p9mW6YMa*)Z^zVBUna3Wyp^Cc(VJ}rU}F9VqA zSktk%R~&^kEUONM%v7;`Y)UpS$fu{RENuKv4GY2d{5ff=s{iU#tb}|91m?zD29qQH zO~S@{%hZEqJ>$XG)*Tm-j4QCF9 AQUCw| literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_hr_walk.png b/assets/spritesheets/gw/enemy_hr_walk.png new file mode 100644 index 0000000000000000000000000000000000000000..0b86eec66b7261bb9f9ccbbf8b8b99bde12025d4 GIT binary patch literal 1339 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 literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_intern_idle.png b/assets/spritesheets/gw/enemy_intern_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..ed1e911bf548838499fc15bcc2cb10014ad20471 GIT binary patch literal 1053 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lNlJ8FL}B+ zhE&XXJ9nf1l>~|Qdi4c-d~U6c7k4B)I`$-Qj?7LAO9|fY$-?zalZCl2T3F0XPBHR% z$K$i9w4}k~$czrl1$??KyJfCt|E|40`Tl2>v$2P_p6A`aC;s;7-%5-?>y_7TV%O2t zU3&Q6zKt6Lf6e(Z`*Zy2zr7Fkw=v8J-W9X-_G@SFfb2rcEY2hH*W%YQ>FA~3PW`>{ zp!}KhLJ8+emM-3Qz5V@hwt545(F1cXiR;YuTmD?>N!@N;PcN&vjq~%j-*(jR`q2J0 znDLAv!!rSfVvYt&mIE?O34DwO%fC!MpyFBe?RNTkp-;ar-gv*^W?awt^*V=k6 zpY+emYSI_?ON9&GciKgVsTZ`;N$^FR7h-M=W-KNJ7D zdLQ`Xuu~=Xor={fxmPQySDc-j@*sUv@^fyPAJSjMbs3E(z4O{NcfY=K_$7Z&`%m9P z56It)f2Mi0_@%}r?<+G`G5tGH_l)@gI|GCN4E}_7&pj7_ zBJvsYjNgYt8nmzIzkim_X`p`QKhG|wzn}6zF?NRC;5#thIser&a~r-pI^U(9S@ghm z@p_@ZI*iYH>NyQSV*h_IC*0|_@2s1~Pz*8`m;!*#L`y558PEI$nPx11;LiCPhGKh= zz}5N<9`6$@b9GPM)lMO>z|`JAH&iA8P=|!EWIR6{XHJ> literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_intern_run.png b/assets/spritesheets/gw/enemy_intern_run.png new file mode 100644 index 0000000000000000000000000000000000000000..f6b9c0c4f057476a70ba7e959dbd49b9e6cc7bda GIT binary patch literal 1818 zcmY*a4^-0E9>180Lo0pi({jOHY1G?NDp#AOXi3ceXs_eSUKz~Sarw%$VUcM3P@67& zjwYut6)E9JHkX;DDGEAGAX`epYi+Uh}!3w|0j{P7|IETRo~MpL+drMEf!-dyAiY6=}L# zd45p-WBMwa$(Kj}ReIP`0N#t=2teLD_Yz96Snq}iS>L&|n4mE>G>~!BeqqQ>^~AlQ zzD$C}en33u32TExaizrdfc07VPS(l$@#@e!aI2GjLOGoLT+synC$Zg`&)SMTDk<@3 z!`avE*4Ms3T`F(y;(SZ%Zp_;gJ$NdlIG|{+plNl=NAGSYa>n_R2`T)TRBD*UBAed5 z0G?5wbl2rV+Vc_5QNXXOX&F+$6moFCS2J-fvcysBZ2JjSDfdDRb&orNIj{IS{R z?Ku1Xm`{9QH305jC(!rf#|;Jp<1+VA@_aWDIx)mw3EBvKYuiq3y}1+H7akW-7MX~K zVEvW3STvxPbZJlo!8o7TB~{qc9e~UwupSirWGp!D3u|j>OwUjNIu0Rw??C~=v%C85 z^Mu@bsI2&&s)yb9>yLQ;zG8`4i($YQe=pa`@X{yn1JALp!L(?`{OL-Oh|FLxglP7L{ZhPj z#6NKLBqvrPLY7eX4Eh(J?2%j?j~k>E+n!49IhiLpibP3IX5I{K+gA^7%)HkZ7)B|H zEG>nmbm-i61xXQtWmA&3;UM@wI(mkO>VvYtyM5a(e0+S1_`8`7oLvQH_Glk+2-NQQW3df;u$(1joy67)2XSOShJ|Qj+G7%A-`h3Tx z(n#I(g2cZSV^ZQci!2YWq%O!WBwG{IZ+rvk{B)*|qkk@3vn<}SJ5b4GUGS6 zNe-)HoNzORdh?A&WN*4(zj>-ZzZ++-g6o~;;nBjsce*+LWWx`Ekk;LwkWYySH&15D zrW25c;+oNI?s-JpdD9Pw*7BSH)enPIm6NqH0@WLzl1;Q7gt33+oz_`sk@e68kHk10 zQb8?`as&h^VkK*4XUTYk>NC^aBEZ$)DMbc@fD;>Texx7T$84_?RtvdDOfN|>f!0lG zW6g)vf3SA-Uvp%7FH&*|oPc#M_=3pzG7Gk{AU9jf3Rh~$7*=$OxXVVG*3$KK+i}*( zH)M*i@7`wd{^X^LZ~h$ZL`YFsHlz z>jrC6CyWl8{{j6G-ug;8J0{$GL*Ijm_{B0H!z;dEj<|YQndv%NV>zXPwrjzvn&hN@ zta#PhxzQ*PPbt~Z0b9^2r(O-2&y;RHsHqYaTlR&Yu_%kC3<7>jbG0l#HM;nm^_Q~k z?3g4`^T;YT(dKCy%J83W2)P_)6^(w#j1Bxc^_+U-MP5ZpiprG4+fuz15n~I)BWFX` zi&xp~&HhQ^5o|5K8QQ$IFdVWROi@G=i<&y*XC3RLdVQzFCrWQ?8;p|Ls zU+#zw~-`+ch; z&m5VvxKVo;I!%4xdT(MqFQpD)iCcc{pNrz%@OUM)?)zh-9=SxDS=qc8Vdv+-2Di-T z`StzYPm`_Y~ zPQ}(_{sNyRJ^+9Pi3z;z0MOtPl+LHa@8dsOJU{4JNqin~d){+xmt+9U3rgf|`s~1I zlMWLG6)kQb(Qfwf^P9h?>}dI~3Atw;GFjOltfbGKys3H2UC!E3?W1Ww{Bt8~QggPB zrQ5Ks>HIg$fK55sbVMGh*{Bb%Eig|fYzw$+lcfp7J;et?JqPfMPmyE_g~H}ZjKgN9 zqMwSzPL$LxamTkG-vwf_j!VO?$*C}Dusli>742of@fNK@n=JPbqhlhJ5T(&e#yq$+2Seu#!R(uUB z(Eo2z?Pp5+422_<1-Aygt>72$GvKG?93T1imy6ulEECq~$G@(umN}FH0!HKelJr!b3tvDMV6n z$iJ4S$>BMIn75ghEj(4O!Fo@tHJ?Lf)(sCZ^W`?xgv_6Nbel>tL$sCgs~rwK)6!&1 zFN4jNIe$+pO{?w*4PkFM)nVzZirjdR>CfIA?u?kOZA+Xexu=GMIWk@k-MfbzCiv*zk{!Y8_MA-{m^ij0sAI$*)^(EW1?nVTUFo0)aF%zUK+Y(t2ZT0y^DOl=!Y~ z^1%HIHRL_tBZ<$)$GYykYW9@^Q|)kCl%4XgxCaZbhI$xzvrL=Q2*$-e!%gd$*8J{! z0;#dTSNlm7`e^9+#dHiu{t{Sl4-BhoL09_e7+L3q`=Zz)r)~3}s8-^l_F*WTL(eR~ x0w`Cv`z?m@#aQQpmyoP^iIZt5$MJ$oH|PmlU9hmRR~U74VzD^f>LnA1XJvq4Z4L?(KrkvTHO zDIh};I1sQZD8cfuP#(?*GQgG=FjJsRkhWl{$nm;zbaz#=B{P>??(+NoAHUD{`~UyC zJD6#0xy%v(V9g2)2mydXd;)>F8Sx&jt|bd*2ieR3U?88u24NNerlqWauS0*z)Al#T zIqq=$Wnw0l>S$pR`_gXRs@#=bVw3Y*>_3CopEqx}-m^fx9O9R~X48$r8%gKnembXY zg*Yf<)mDmg`s-PjaohOzyS$W+zC0BSW&X&loDs*gi0YFTz9Dx3njaQElBU}_WW5YjO#c(OAQE<9>RNyc+%@tT(so5?UM#Pgs zvbhg)RsztH%Po>PMJK+Us3}}eSiFoCYhess zjQZD7lo?eU=X|t7Hjv!!88-zV>{>`i3~c$aw_+;-!P?hp!IYyN>1_GHkbiz&qpVG1 zrS*j*gBE?}Tht06a+~gD`oKv8vvj)}j}C>(b(sa6#__WRQVabNZfVt~M4FRpQ)TM5 z9Q1xX&30@)jVR6ONxR&d+;pMq4?|us_7vt?m>bblFQl$4?PLl$O0n_?)kAkmO?EF= z*#VDUZJf!|(<=x$nuY#F0WDtrqB99zojWGmqNF#4j2!;4qrP}N_8Newp%_q1-&&Gw zQz}|yJx+@u$qWMG{sZqHLokTQnY{DH(Zzk=P41Y&Cr6)wfBx}^gCJxB-y zm2I@aSL0)@f%fQatfk}ip5lBy^4$^o{-2~2WOf57qvr|y8L%;T)64ws&kZX? zvNUvwh|Zom^+{MsY8kr@*Z4-y@KY2JJDP!Z3M!AsHCZeG6sfV{T8Y50kv0*zTB7*OR_QyaanpfPV=sCimu zdk^E1tp2%LT0{;mpNzW}GE%G%>iWpIlSkzvSj#mHe;!mBRW`2RvD6qAf}#uG7$scR zG4b+UIc_rfRo`SAftfB=;?`Eh^a^&d``WZQZmN4hB4ke_NrdYA%p|KX_O{aNdWN=< zAiH%U;FDp-9J2A%9CsuP=8YzKn!5ZisAbLXDgXCqllx8XToV=viETS>2_u3GJ;(R? zLfCOV3B09i0kKI0=4^2#_x5i4D94m{1ANd-`JEBHuUeG7~S(ERISps+U9aN zjJOZ?!s!0D-3c%F=UlD!(1+qxob>dQ~^5%Js*Nqe6?NS lEEzWM8UM|#7Z79F5Rv8mGae*8{esLDYe#Uvz3q`_{{iN>|C9g# literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_security_idle.png b/assets/spritesheets/gw/enemy_security_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..cb985e2175b478a067ca23be35f3e0f27c3db98a GIT binary patch literal 1019 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lNlJ8H+Z@@ zhE&XXJ9neMaH2$eed{7w867TW<-&tUdQaZ9*lBGk!P`B#zC*bCqJ_myV@b7gHnp2p zRu>|U%m@fxz*nxgMRV`HufN~D`a4g3=N6VKf6uzw{dL#(ofN~XZml=a$ru{J$4@cd;WiGldIF`J#XHhQooUF!`{g<=6_|R{~Y|I!}#n;9FvOY z<5Z2sI;`yV2KJ%{=G>{iR#sh{B7e*JrN^YO+p~rL|9i4TxFo*Ee$9NY1U^QCc7_?w z3}+M>o(V7%b2M1){JvuCwOc3bw%mVz?B5^hdKZu(N%L8K7Ur#=u7UmtZ>z~AaxW?$^*=d(i|yXT zEz|Dxefn`w*|g;UtAFqQ9c(%Nf8rJ2{O$((P4?NGH)d!|U$Xab->>H2uk6cjS-F4)Zd)`d@r}H8FnZNddPuVX&MHWS~{#gBK zGs}$0dCdBDF;f?K9f+T5&*`w~U5$2h9qYeSphyt8x4f@>VW04BZLxX@VDJG03N4(w z&a@S)`=!?U_|EVF=-muT0p)82=5Md1EDv*)WGm}78XGGuXGr8&s% zXUsD|k;d}>-T|MU>W|_V;~iN)ygeH4V(;Bx`Bb0r*xn!AFZAshz;rsNK|9D;tp-bQ z{31IW9G*1{#rB^W&-?|2s4*~r06eV9IyNk{vsXd+WFdzp!7C_Kj9rP$l>X)=zZk+@5{6o+s6u4 zJ^9%FHJA~RFkuc-|1MX$N8h$g-say9kV6lqvs`^E8dQ!J(4a7x5Aq8r0A>R1`Om&J XGR$&8!|f-)?8V^e>gTe~DWM4f)-c&B literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_security_run.png b/assets/spritesheets/gw/enemy_security_run.png new file mode 100644 index 0000000000000000000000000000000000000000..9538fc8a82d7840d29a3eb19d037a4238b56b360 GIT binary patch literal 1765 zcmY+F3se(V8pm%)dCIF@6==YSSQTj@V67EbrYHrnwuGX#K5C)RO)MBAg~YVDFLp_4tHK`ksV1fa1^f2Q@C1+)uYA5#I*f$rN z5<6c0!|F(C*|E>mdm`oZe3^dg)a-EUDQlpnCuoP3m2~dwQ;hiLlCF&3EVJq2*)z_L z<0k7se0>gqf9VDQ{`9T$?r_wph5y=Shx+@Ej=w@g%H4QxxZ~o8WnlN3PDay0?+8A@+?)ZK%QEBCc(P4G|~>A)&CTc$(Qu0 z$}sAoRHcIQO%Rzp2MGsLn}>KW%>23O_N@T4{38!MNt+q&eW)+2^34UH)I0+=L>9mM z5)YXa&(K^!n!g9&f4T{qq0UfMWAEh^B)6t#Wqr+T&)n$cfS(Bz3r`8ae?z19^@D>+ zG{J_#%lBC(wUXQWtH>LuDE&byjplaAaC%JXzAcF}0|H+4FLna}o=+FI0{WZCq#CB_ zmR4%|oR8kF-79T4@{o*%L#$nYKKx+*Ck>&W*DZXxx67+gA(t3q(3J8ydjvE&DBMl; zD|dXAyV(%eRX`i3#@I%D%Jlg!n<~Vu&-1<#KyYHo@ziD>JYrbILs`^>U$fjsgfs`= z#tczahqb(BFw2S6*B*2jv@3RU^ZPQA>u; zvE~HHS4Gk6^r+Gue=F6b)|W_miG(xyqKgWjW_Jt-^3^r=00Qt7_PVW=JUCzHXA%^; zWE(p53P33yG&-U8kd|ovnJovhS<+f#YR)vBbS#487!7k2bDGXK+Z$alFl65RfY;{( z9yz1kj1JQOmovvwLj;ufw1g+z-b)`sm)dxH%`ZA97_pdM2^wiM|1wK_KH}$R{&;$k z79r;q6AWLkWTh2kG35w7gK@Y`NnXQ47A;Z_)g(FmaM`BimBqKjlberL2TP0IV#~G$ zSa<+2i?Q!p zle;;OP^+-s7*EQFqOl+K+m&_TW2K0*y;LVi!h&VDu}FkFdRlW}%XGp<5y!G)TzZeA zdYrkci?j#PZeWyO+q3XZ=KH(WVsoxftc_PHN4ax+4q|Tq3HtGL=uiaX!V27id>tRB z`h$Vqe7UU%a)fj2yFFBMhh*98`-4Uo^jpKg?{?#dX^wt$*cVpE6gT9Wtl^kvV1){L z1La2ZUuMXtGxQcE=SQBY_V+q)qXAvk&G7X@GDNYIKkBf(_@bKw9v{J7RcRIxDNX0A zIhL9V@(rR)u{;!w2>DZ|)nt^5gscP#MYm=nFVhygKdQz)5j-G3k;3PWUT3U~CrW<) zJ1)=RHoU5y&Y06yVk)k;1@fbm?FvtLSg#)Mz>JB@y=38v>X5sAxPTS2I*)he7dtf@ z^N{rT;GHuZ#AH5g}{4e*Ba4ip5T%#jJ)%sOhvj9b!`Dea|!I_jB_6 zk%QMX<>ETFq>uL4IE8KwYOX>#RjzR+HAFk0J|ZM;n~?JfFCB{!kxqyp)giK3T? z2oAVrMnC$&fL<~rMEeCToNcd#- z`-Lq|e@eeeO2B-S>Wbc5>OMGXOR8yhx^`6kJKX2i!T&HBhn{2o$=+}q3c`9``6Rfy zs;#HgA2CbG>=(Gs7uc>RzPJmAY0laFQ(D(H7Gvk6SeJZddTuV?#R zue+J_U??ApQGqnM<6GiwbgAQO3xajaT4Qj3rX*t=yfI#X5onD#(T{D+9csCLxmc+4 Y+YcqHa--ID~-K4lXyV8pO2gAa7<^TWy literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/enemy_security_walk.png b/assets/spritesheets/gw/enemy_security_walk.png new file mode 100644 index 0000000000000000000000000000000000000000..27509a31370ab01f8061f624413fd6b806316773 GIT binary patch literal 1327 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 literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/fx_pickup.png b/assets/spritesheets/gw/fx_pickup.png new file mode 100644 index 0000000000000000000000000000000000000000..e5aed81dc20a00938fb473976505df4cc4ab6cd3 GIT binary patch literal 1336 zcmV-81;_e{P)+U4;V)2MXn;iPl6f5TuqE6GET` zH5d=Z!bw|6Of)gN7d;rm#fvLOE|7w>MFWW;Xo8%e!E)e+wqCr|>=y9=OFPfQ4DAB5 zZkd*u&d&Q>I`ivv->)xkf8CjRQ!vJ)mc%^)6Hc*PGx;35)J502oPFt{%%&;6SsqT@ z6ENXqa}*VZaX2~M#MfzyZhY+Txq#(H!>#l1hu3q0Bx2a-5b!ayQEO zqFhp8KY$9qMj3l0#J}3DnW>zY|IRX}pZ_h|{5J|)0KzKK54;CJ85cMiW%$)CymPC< zc?Yzkg^?&@uY~xMYv>n0|9@no&wrz^1t2`P#&#rL{YmZs$D@wBQsRp&vrHzcI$7i(b|)y{uhv&%>nCiC*nG(VOi0OZF*% zGk^Q(_n2p5QYbT*{Q67w0#M<{xTj#!Yp%)a&lrA3yH+#GL;|lIT+a)z6=VHWfKsTDI3LYK9X12+9 zVz*}2Wa$${Hr-@oIXea)NBu=D5zhkX72TraI-ujaVSY@H}+sXeWD6hJZo;wI7ntu}g(F5Y_?xw<>;% zaZTE{xUmJRGwf67Ls%zpVA^5VN{L@>GEcuKgN`ti%`H9u*&KTuVMrVXC-cGiuV<`B zx18Fc1H(J(*Wd6?-EeA$4vh7LtiOmQVgZ=vqW2HXE#jCZ&|0rG7clOIj;jyM*`eO= zAOYVG8mk>cWnn+=__a7Sj|rLofO1)kivP8xQosK09aDMeJ1bKnP66ZvxdGg`Z%huC zRF52oe-J6me*}{k$|wb`iq!d1PsZ$2-WHr;GJvHUj%Ib0Q5C~=p@|! zGTMuP@x>?R{2OD8iJMO7dY#bqanHk~({Qh@AMQ0c9gLji7fzOm+#TT~D? zaIfdwwB7rY!T0s-_&q=J&TgCL*GJa1YQH~0q21I)X1>&EE_bBWz->j43q$a z2uFC1X4+)Rd7hHi6-0C|DjUGh2l*ZRgT!~8cb)~H^l&A3ji775n?Up|3E9t$oj09l zDQ{iE9lst=wgJT;H$dAdzSYLrebdhKyx6>oDQ_?6+X&ABzaid1`s;pmo&}(+^&Na| zNL>I_3xV^%s(>LeM2_V&)Cal+C`=xWQ_DEYk${EjHVM}Akql+Ie-*Gau$G{gC47le zJ*TGpOsCZT=l<2Y4v+kKoqO$E?{mBLQe_vn0j5&_CT6ms^_=HqEIhr-;Y42aejR`Am|Rh5o6ow&(NkVGqKx zIca>haXt1^)_Z0WZQBZd3xJna`ZQ$n12mx;$$h#c4?#H)xJ!X$0E;{a&T=awTUBdFgrdzAhqc{9VvLLi#EU}*}-Pj0h=X~wMCC%pQYGu-C! zr{4%K>Pn(3o_Chz&Ywk~D>LL->nsbvKM!8dSl5KxJej{6C9FOiw2^?tuhlV`$V&fo(UyzAnvm*s;yXri(l;S$4{tg+s z2a!bX6Q*bk*$a#UhnyzqkShosfiwzDEL0}^JR$wzC$K3`6 zYNZ>Gjldb;E--|0ln51z@)~fII+Wc&FK{2|Lug0NYua&O5S4Z`Qt9*#H>*IlqtbxV2i!;LMRYgCx9Xf{`Kx{yUn+p3 zs0;yjQ8|Mz8;Qrl7OLDCh#g1S46-<{i;XeH7-Nhv#u#IaF~%5Uj4{R-V~jDz7-Nhv d#u)R&{spUPG}j;8E8GA8002ovPDHLkV1m#EDe?dS literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/fx_slasharc.png b/assets/spritesheets/gw/fx_slasharc.png new file mode 100644 index 0000000000000000000000000000000000000000..92cc719bdd7a305a82c88a85faad15412179a223 GIT binary patch literal 2534 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 literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/miniboss_vp_attack.png b/assets/spritesheets/gw/miniboss_vp_attack.png new file mode 100644 index 0000000000000000000000000000000000000000..34aaf1486970c059f407a7881ba2fe1f2bc95b8e GIT binary patch literal 1616 zcmZ`)2~bm46n%s!1OiNf7LX+}%A!JXXHYRz*+Lkw1+@q?RN0h*h%ADVAHii>(I8lX zLRe}nq5@K>8w60asX7v5Qz#HhLLr1LV3JSrll1>!JGL{OKlji3_r3Suz2}~D-?w{$ z{EQ4%7ytl_DE{7G0HA{o0YiT|`WF6jADdWykm~0RG}u$gsV+nv%P8KTg`OyzW;GlQ z-)nQ0S!f=AHuT7VG0VysN2nJmA^t98OD&o=3Q`qxh#x668WQ1B?xL)C|*TokI_{$oS!`G0LzB9f7MS zOiIDFmz;_p`60O^vf7z`6@XuRzQXwzY@Nx|cy56u0_JEO4y^x4Rz7yt@cwd{J*lqV zzhL0Pwcwx~S&gP?G;`=vb)jl1OW6kt6eR%Ut=XZ69@o&{m|uSz%M# zVW75}+oS_5cY`GhIbmGc8)la&ONL#d*Uq_%nLe+_om+1iX*MH)SRBKvc4o}vo)%`! z3%NC?bPdpm1xoA)LX$-l@u91 zOen4Lit`K<)HCXB``5Sk%kpHEagl(GDV+`uI1bGzEQxTY@iqHd5 zfnEp3dYP9O3pv@8o+KLBg`UTP@g+Q>h&a;}}N@FGw)ZySM9gs$>O?bLUbUYx`ae73Yl7=R;UAaNKX2 zH0c|klZ9~UygV4!;YQ&m9#%(EXiv>Ubv49AYXF64Y4Og9QGJW&oA293-mT_Il<-NN z&hU(3s{M_|*vF_Vp_gW1h+JF@!vRaPvW@Mo>~?mN&od@TBcwY5a7h1u?B>i~b!$a) zbE!)rmL%*XD_Z7tjGVcpOL|SfWkLs`e$&ba70oL|iq{y?8=w{;fC451vZ|i&jgLEv zs@N=byeSUdYNilJ)DNbTJ8=6rsf^#EMZ|>G`rzH354fPRf3%{FQ{e zfFX<0cx4!Q(aS>dDiXOXVm_N2e;b*9kJlkm$y*B3)yTdTNap|+G|iERgnsa5Vk?Wm%*+8$O;m9<2u9uhp&_R!a0wb+R?v5T}2 z2U|=1x<960`nhRfF1TGA=7=UHMf9(fu(bYbfxVm;-zc?dqWH?tJS5wdFRy}rIg0Y^ zl$+Rw*Fr*>6bG@y-% zUQ3)f03Y%;-!9OCrNh8oU}uQC#hbl zqcVMDV+z$Dfse~RY*YWVD=9JN-h0?^E0s%98;XG2cj{OX~ OFepAj-gUd8a{dBRHXM8a literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/miniboss_vp_idle.png b/assets/spritesheets/gw/miniboss_vp_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..e9bcfb97f247b74c04d5c5631b08ce33427eb6f3 GIT binary patch literal 1077 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 literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/miniboss_vp_walk.png b/assets/spritesheets/gw/miniboss_vp_walk.png new file mode 100644 index 0000000000000000000000000000000000000000..cd7d64e8643604b00036ba12480344333c27d243 GIT binary patch literal 1404 zcma)6Yfuwc6uvwPf?zu0h}NlC4MIB>td7+RHdJt8q$X5b>I;@YjaCHIsv(5kL_3I% zGscpkGGllZAGK^b*wzWbf; z+;fkm@wwrlZ-fE>!g*^`HUQwqxIjK7i1`m_8hr~v*{R$V;Prhqt>={hy!IY1<)cpv zRl~hl!Dk0%-5M1*YmZdK#)jRVmYtnFUwQoa&&PW8*JBs)J#Xe01JBoR6pCwadFq_r5Y{pY&`rj1@(n$-C-+N!x(5DBr~fNvm=*u)Pgc_jRm7 zoh#=lL7)w?GmSd}-Q@m?^a3(L;;|dsBGMoTLv;~gh6p4HZ*?O#cGLF`dEsIAqwQ4+ zoz4^L>g9tc@daL~2~RfSIC++w4nlL`kdy4q-iLi?={Xd&q*_9Ja|YXhKDA{e*{nsD z@%BA!_i$8AQpYaTvBqw=(_=Gk4bgB4ymie(`;~lam>gGl(&|ZIq3&B@&Nh&S@SZusv{( z#XYmzgNGU=k#~R0z~|}jz8P~ghBueg23ZM;%S5?9T)eE(!c8ov2PvxDWex@<2P)Ey z-3m1dX~{rPG8?3AA~;i)XeKu>CAerVRWpRvTB5-W({O>mx+todDbGAO2E<-6uIj8z z=wNjV%#Qs1FiayZK1k~tHvkb-%|Frl&2CzyQRJiU&4UD?xK~{bP9SB8+9rB$7)4Pz z&ocazgkuln3aq#&aCQlUI*T6mtA~3>`+w*cSbZVl5Qd>npcSWDGm{JQe#dc0_kw4I z-vr(Nn0Jd%8|KoV7AwPBqB59tt%wm6jw804VU2%}quYLRDC0#`R>zBE)&j;KT!SP-^Z?`c+Yeo^y62>Bygw-v%&1iQ<+96@A~7lZ zNN6&rt$ZOHtpW?L#%Dm-h6&ZE=~+-j_bEo>3qI}#nsZ@AM@X~;%G=XrA!&t^Llgls%s17jtc!~CtEs=^c>DYnCMRs4uLG8Xn#BRH znyt?=AARAdBZ$vOmWRvrBp1igo`UAU3OBMJraS0!mHkS~L_U_sbVm*ugELL0wa}3> zMHUrL6lI8deDM-ocyTOeq7q~xK%U#}_cf=?>&muW6E7e=&d%`w^-hlOI@sttWWWl? zo(1O{MxOj;qE*tSyLRD9rf(sgMYv^sF0%`Hq!atE_I09(QXJ;zO-{YsPnXHfBR%V@ zj?e?Mv$zZ}BJ*+hdlg$>Ude|=NZ?()z`axk1KBtKSjMd>+oM>E8flk literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/player_gw_attack.png b/assets/spritesheets/gw/player_gw_attack.png new file mode 100644 index 0000000000000000000000000000000000000000..cf5a1d5889d596565ae690ee8d218151a9ca8d05 GIT binary patch literal 1548 zcmZ9M3s4hR6oxO40D@rE7A;Uh%OInos1%e}f)zH)Teqvokw;|GW3jIp6uu`8|+A zGB>p{1pt_nclquGKo9){EE6O2JyczTZ5T!PlYD^|dx~rMR{+2@kbSoYrQJ}z6~-6( z*)&g4BUatcG+Y;OK4*#l`l={>qb$2MA&rfJm(z}pJ`D#e%=Q&{T=;ECb>x~33%`gT zc@(+t&Mc#KyDyvUwsLu079o8({VbIrBTN*0>9EIISoGmnwHKvs1r`ZNxYr7q8ChH1 zm}McuxnwQ@@j{x)xXW3ImvCTH*SyI+#++h9%W-F=PK;LTjL!|26bLbm2PqPV55kT)yu8vu6l585w0 zPL%fr!1NIbnRs>ZTJ=CF(HJ|t*%H*RHUmeT(#-9Wh*k37mIos;W%CM{aEB?#)|`YD z07N!?b4?XTI6a?3>S*w=R!h#Y8R?>H6~+|j|wvIn-~ zMN{U7Dt>N7N$nGknj~y*56$bhVe~bY@Q4n`X81327?L|Gwx;LrO;s%YE}5dV%W?4L zZadrPp~ViJ#-l~5pY5h^2|PO8CYPp;Pw)28L1MovhUC`jP$h`=URH!=N`r0mKxBnx z&ESkO`;#OSm0Tt;;?;A#L#}*jBPW1LWC+E58Sn?FM-Payx`EMvGx_aUd)r;hI7Rc) z%(zhY+q=a?BGR7?hp$qS+a;a&!-k4-|K;%d9!nVP&h!SoE_HS24{ zORrCK!=u<_gi1q0T@=^xdZyU@b&13m7R9`DIVAT~x$6Vbqs_Lwg(ZgV;Ng3_-0?+q zB<&D0rEqQ-dauIdGupXi;=Yj1Mv9G@`awh8^lqh1(9b zNVy}%t60aJXO4_-@ZiBA01lp%tC-!++pv7`g@qYrgWHV}3e8%@p@BefDY(neP;ZiAo zqED93()Ia)X?vdqM`IpcWP_?>_n%W6IeV!8pB%UtgRHo%izY{`fSIeY(Rq2nLREvV ztX6;1!mx8EFERU>PQlZ1xlA{9aH-(im!6)HTt4S4Mff+fcc74uuaQ`w&P+27jEYr? zU-v|J5lcp-{BR*AFJ^|_o?IDd>8W!Jvr|8Co}L6lMVJr&k?HcPyzU;hAZqnUQC(Z6 SI(s#k-N=3v-@7}GocR}t@)3Ff literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/player_gw_idle.png b/assets/spritesheets/gw/player_gw_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..3e42c883b8b2bbd948753a1f9f3d6ba9dced0a7b GIT binary patch literal 1021 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lNlJ8H+i}^ zhE&XXJ9oc-aH2@t{ZG!aGCf?(%DWOC9edJKSY+zQ=ayJl^fAAnFp06Zd2(T@(S{wD zTRhbyWfg=B)snbk+T)~eJLJEA`~B|vPj>#7w)noN_4@Q}&bLFBQ-L-fnCNzsJ*E59 zFS&xPe+)k^|J={}x97qBHij9&`&e_|N-s@NdCCFVTd$%+Sx?tJClG^ZqNS zi)ygk!cc54dSK3_%(=B6m*z87->j@uexc1&9|07VVM^d*G-zj-;mmMGk>QyDL$TT^ zyM%2w-|X7I@uR}4nfiYU|AsIWdxbYBiHX^j%w4(aw`kM;IrF(twDJ7nD-F7|^iNUX zr5W??&b{`znqSp(z1_a+pMI@dBJ8Pw9apO46&jQ?WzVbhY8e|F8bHqT$Z z@b%o=r(e%rZu4*XlD&U+as5#K-5qt{%*rCqsN1(LCcbuPU(38U_wARTtZ7^_KZJh) zC6_G8p0w`C_R|+8eTlua{ZE-dfN3N&D*{!=d~PBr{vd~p5|e^!I#m!zjTreASBf9x^; z`{hhCF4yr-*gJQUTAru-{Hqmv!hdf*F#pW_@P?1eFP;4Rt(5D-@=uqU&YZMoliUAp z$^w-K{!jDS7u+qkyQ=%X!G7j^u>`-T=U46xUa|Mcyso42$AC5*4_p7}e6(*$Vx;W~!m`UzYG^PWAu`v(~BO*QEkDrZeE{~XMCCeglO zCotapKD_7EIZ`23FY=dDtKq%QKaF3RjL)vzXX;7+=zcN2o&ikza~rh(Wq4Mn1#%@? zBH18+;11C0VtbIiZ`cjKZw3m)|K%6ExjR#{dXoIJUa9^vZF%l`qyGl-%+Hs+$@;x$ zr($2T{lfYg3_0Gtf4{ljc9vnUcLE!La5!>u4F1J?dco$G^_;fK{q}3nk{d9U0z+@9 zdCM8I*|Fb~&mVl;{~8!y!Zq#z@1J$;idXz``sYe;Vg?5?$oa@l1-bpdd_Q~cg<### R=fK>>;OXk;vd$@?2>>0c-wFT# literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/player_gw_run.png b/assets/spritesheets/gw/player_gw_run.png new file mode 100644 index 0000000000000000000000000000000000000000..27aa3b0155474adb584ae399d660a81b2fe80e9b GIT binary patch literal 1766 zcmb7Fdo)ye9RC?fp`<7ZqasC8o0YsqjG0E|RZ&!wO|^+yGs&a5R;4p4HhS2tF)I!^ zn^e-&c-(2Nq+*y&QW$ooX;cj3HN%}dd+%)RIlF)Do_o&k-1EEN^ZR|jpVwst2U2Gl zEHnTB%%W{1hXSC3y@K=^)3H@j#l=5N-?xcM1{(bNxwbS9+qgy}Z`gL?`T!eFu-tA+ zfmv2Q-(}3Py^<>|Su>aI=tEe%)FFcGZ}NS2aNE$j;=+KKc_G1zLrZ*V^Jcn72Apx+ z6>9tIl9_WU$7@VI^1Jt{W90}_Ua-`ETxy3(UBV|?S|($&&bO6N3P<9oJCnkH_fm?9 z?%c_!nJp$08v0@0Cdmy9>c(y0XOS zk+qd3o>8g~9c2~+z0z;RYb{WvqX{&q1KdhN_4!7bkc{!6SQ4ZUdd(B{SD&`H6@+y_ zjzj4HWETS9mPr7;`Lcp(E3cKgx-#<%9!J18;vW+=t&iF{vjKli8v`^LBx%sbQ+3bZ zxG2RW74J653Z%!pu;M@K>3MlL!OR>&>{;E~>I)*>Xi7b#_!_MrFVzJ{H`C>WOWR)- zhIjFLb0GG}l7C#A{Qk_j+&#}UHOu=m>XgwtqnJvTZU09i+)Qx0N#7xm-4>ut9OnPq=ci7hELJ564gv4B?0IndYBzdBJb??0D z8_F!m5&1HkKsztz7dBg(Nn2G#Tf7X_MRC-tZ(lSLHJ1=4V**=JNp4RrS!JIX%VnHY ziaFOw3AzNgWxU2^oyIwk%o4f=t15wCS5A)|u8EvxjtP$E$%Vle<@*j3kl_S_RGp1+ zB%Z|=N}~(HDb;U_T8)GaTk`)vt40pSI4?q#r4oS`rlV~xL6$SSNlu;HZ%vHuFe}iAEH(r*2Vs zw_1jiG=SVA97UN5)xiXkJJw8;2OKxe4I-)1?sJK3?5YYj9IVhS2v|r<*_#bTN_Gef zi$#i8#h)p@GBG!=D<{7B3m0~eh_$}ns5%`oL~CZvzyxhw`VGkwElfm?pi%+BXfG+{ z;;M-TF~*ChD@4IvIdzCn3w_fbriTnyWYq%O2gGh8v@a2<=H*gW3mhxseK)t*+#R5D zF=sZw=Q=s5*pP=L+Sv>zjSP`bu4UA+5~B#(3-v33V=_3I{k z=%6aZduF~c{(%E#fvu>Q>EHX^3qa%Nk{UzIh5=UpAK0crsy!!7pxUozqr$`wgx7=)NmL*eA># zuV}ZZbT~yq+on2_O;1EU>p|sH*-w)y%bj8;RnJbWjEH1Lr8sNou}RgP7*r|HR6M_6 zqDb(j+4ZtW5$}o&8%wEDL0kX~ww9z|Z>C?G+dspZ2)=4vlAr_`B<=W(9-PTeCm+z5&xwf{fqsL)2stlT2txdUwus;8MrbcoYIXi&MJzv(NxBQoz oeiaWHSV+3R_y3pB4gV`28e?~V$iobQJn`Qc%|DQQ+c!GnPiCWgA^-pY literal 0 HcmV?d00001 diff --git a/assets/spritesheets/gw/player_gw_walk.png b/assets/spritesheets/gw/player_gw_walk.png new file mode 100644 index 0000000000000000000000000000000000000000..548777201cb126484e273b6d373e92656c181eb9 GIT binary patch literal 1339 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 V`NXq;D8(<|J{K?N=Z-;_{sX`KL>&MC literal 0 HcmV?d00001 diff --git a/assets/spritesheets/rw/player_rw_idle.png b/assets/spritesheets/rw/player_rw_idle.png new file mode 100644 index 0000000000000000000000000000000000000000..8ddd6655cbd90603585ba5f0988584cfd9f08e28 GIT binary patch literal 2920 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 literal 0 HcmV?d00001 diff --git a/assets/spritesheets/rw/player_rw_run.png b/assets/spritesheets/rw/player_rw_run.png new file mode 100644 index 0000000000000000000000000000000000000000..ad5966ed9d5a45ae2f5fa6a3e893f0550cb6b0bd GIT binary patch literal 3585 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 H&pF~B= 20.9.0" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.89.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.89.0.tgz", + "integrity": "sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8b1e5b8 --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "name": "that-one-game", + "version": "1.0.0", + "description": "That One Game – Phaser 3 placeholder asset pack generator and loader helpers", + "scripts": { + "generate": "node tools/generate-assets.js" + }, + "dependencies": { + "canvas": "^3.2.3" + } +} diff --git a/src/AnimationHelper.js b/src/AnimationHelper.js new file mode 100644 index 0000000..1cb1678 --- /dev/null +++ b/src/AnimationHelper.js @@ -0,0 +1,197 @@ +/** + * AnimationHelper.js + * + * Phaser 3 helper – creates all character and FX animations based on the + * sprite-sheet layout defined in the asset spec. + * + * Sprite-sheet layout (all characters): + * Row 0 = down | Row 1 = left | Row 2 = right | Row 3 = up + * Columns = animation frames (4 for idle, 8 for walk/run/attack) + * + * Phaser frame indices are left-to-right, top-to-bottom, so: + * idle (4 cols): down 0-3, left 4-7, right 8-11, up 12-15 + * others (8 cols): down 0-7, left 8-15, right 16-23, up 24-31 + * + * FX sheets are a single row of 8 frames (no direction). + * + * Animation key convention: + * Characters : "//" e.g. "player_rw/idle/down" + * FX : "" e.g. "fx_hitspark" + * + * Usage (plain ES module): + * + * import { createAllAnimations } from './AnimationHelper.js'; + * + * // Inside a Phaser.Scene subclass: + * create() { + * createAllAnimations(this); + * } + */ + +'use strict'; + +// ─── SPEC (mirrors tools/generate-assets.js) ───────────────────────────────── + +/** Direction rows, in order. */ +const DIR_ROWS = ['down', 'left', 'right', 'up']; + +/** Animation name → number of frames per direction. */ +const ANIMS = { idle: 4, walk: 8, run: 8, attack: 8 }; + +/** Suggested frame-rates per animation. */ +const FRAME_RATES = { + idle: 6, + walk: 12, + run: 18, + attack:14, +}; + +/** repeat: -1 = loop, 0 = play once */ +const ANIM_REPEAT = { + idle: -1, + walk: -1, + run: -1, + attack: 0, +}; + +/** All character spritesheet base IDs. */ +const CHAR_IDS = [ + 'player_rw', + 'player_gw', + 'enemy_intern', + 'enemy_hr', + 'enemy_dev', + 'enemy_security', + 'enemy_accountant', + 'miniboss_vp', + 'boss_ceo', +]; + +/** FX spritesheet IDs (single-row, 8 frames, no direction). */ +const FX_IDS = [ + 'fx_hitspark', + 'fx_slasharc', + 'fx_projectile', + 'fx_pickup', +]; + +// ─── HELPERS ───────────────────────────────────────────────────────────────── + +/** + * Create 4-directional animations for one character + one animation. + * + * @param {Phaser.Scene} scene + * @param {string} charId – e.g. "player_gw" + * @param {string} animName – e.g. "walk" + * @param {number} numFrames – frames per direction (4 or 8) + */ +function make4DirAnim(scene, charId, animName, numFrames) { + const sheetKey = `${charId}_${animName}`; + const frameRate = FRAME_RATES[animName] || 8; + const repeat = ANIM_REPEAT[animName] !== undefined ? ANIM_REPEAT[animName] : -1; + + DIR_ROWS.forEach(function (dir, rowIdx) { + const key = `${charId}/${animName}/${dir}`; + const start = rowIdx * numFrames; + const end = start + numFrames - 1; + + if (scene.anims.exists(key)) return; // idempotent + + scene.anims.create({ + key, + frames: scene.anims.generateFrameNumbers(sheetKey, { start, end }), + frameRate, + repeat, + }); + }); +} + +/** + * Create a single-row FX animation. + * + * @param {Phaser.Scene} scene + * @param {string} fxId – e.g. "fx_hitspark" + */ +function makeFxAnim(scene, fxId) { + const key = fxId; + if (scene.anims.exists(key)) return; + + scene.anims.create({ + key, + frames: scene.anims.generateFrameNumbers(fxId, { start: 0, end: 7 }), + frameRate: 16, + repeat: 0, + }); +} + +// ─── PUBLIC API ────────────────────────────────────────────────────────────── + +/** + * Create every animation defined by the asset spec. + * Safe to call multiple times (existing keys are skipped). + * + * @param {Phaser.Scene} scene + */ +function createAllAnimations(scene) { + // Character animations + CHAR_IDS.forEach(function (charId) { + Object.entries(ANIMS).forEach(function ([animName, numFrames]) { + make4DirAnim(scene, charId, animName, numFrames); + }); + }); + + // FX animations + FX_IDS.forEach(function (fxId) { + makeFxAnim(scene, fxId); + }); +} + +/** + * Create animations for a single character. + * Useful when loading characters lazily. + * + * @param {Phaser.Scene} scene + * @param {string} charId + */ +function createCharAnimations(scene, charId) { + Object.entries(ANIMS).forEach(function ([animName, numFrames]) { + make4DirAnim(scene, charId, animName, numFrames); + }); +} + +/** + * Return the animation key for a character, animation, and direction. + * Convenience wrapper to avoid typos in game code. + * + * @param {string} charId – e.g. "player_gw" + * @param {string} animName – "idle" | "walk" | "run" | "attack" + * @param {string} dir – "down" | "left" | "right" | "up" + * @returns {string} + */ +function animKey(charId, animName, dir) { + return `${charId}/${animName}/${dir}`; +} + +// ─── EXPORTS ───────────────────────────────────────────────────────────────── + +if (typeof module !== 'undefined' && module.exports) { + module.exports = { + createAllAnimations, + createCharAnimations, + animKey, + CHAR_IDS, + FX_IDS, + ANIMS, + DIR_ROWS, + }; +} else if (typeof window !== 'undefined') { + window.AnimationHelper = { + createAllAnimations, + createCharAnimations, + animKey, + CHAR_IDS, + FX_IDS, + ANIMS, + DIR_ROWS, + }; +} diff --git a/src/AssetLoader.js b/src/AssetLoader.js new file mode 100644 index 0000000..f3f581d --- /dev/null +++ b/src/AssetLoader.js @@ -0,0 +1,90 @@ +/** + * AssetLoader.js + * + * Phaser 3 helper – reads assets/asset-manifest.json and loads all + * sprite-sheets and atlases in a scene's preload() method. + * + * Usage (plain ES module): + * + * import { preloadAssets } from './AssetLoader.js'; + * + * // Inside a Phaser.Scene subclass: + * preload() { + * preloadAssets(this); + * } + * + * The manifest path can be overridden via the second argument. + */ + +'use strict'; + +/** Default path to the asset manifest, relative to the Phaser base URL. */ +const DEFAULT_MANIFEST_PATH = 'assets/asset-manifest.json'; + +/** + * Loads all assets declared in asset-manifest.json. + * + * @param {Phaser.Scene} scene – The Phaser scene (provides this.load). + * @param {string} [manifestPath] – Optional override for the manifest URL. + */ +function preloadAssets(scene, manifestPath) { + const url = manifestPath || DEFAULT_MANIFEST_PATH; + + // Use Phaser's built-in JSON loader so the manifest is fetched + // asynchronously alongside other assets. + scene.load.json('__asset_manifest__', url); + + // Once the manifest arrives we kick off the real asset loads. + scene.load.once('filecomplete-json-__asset_manifest__', function (key, type, data) { + _loadFromManifest(scene, data); + }); +} + +/** + * Loads all assets described in a manifest object. + * Can be called directly if you have the manifest data already. + * + * @param {Phaser.Scene} scene + * @param {object} manifest – { spritesheets: [...], atlases: [...] } + */ +function loadFromManifest(scene, manifest) { + _loadFromManifest(scene, manifest); +} + +// ─── INTERNAL ──────────────────────────────────────────────────────────────── + +function _loadFromManifest(scene, manifest) { + const loader = scene.load; + + // Sprite-sheets + for (const ss of (manifest.spritesheets || [])) { + if (!loader.textureManager.exists(ss.key)) { + loader.spritesheet(ss.key, ss.path, { + frameWidth: ss.frameWidth, + frameHeight: ss.frameHeight, + }); + } + } + + // Atlases (TexturePacker hash format) + for (const atlas of (manifest.atlases || [])) { + if (!loader.textureManager.exists(atlas.key)) { + loader.atlas(atlas.key, atlas.png, atlas.json); + } + } + + // Restart the loader if it is not already running so the new entries + // are fetched immediately (necessary when called from filecomplete). + if (!loader.isLoading()) { + loader.start(); + } +} + +// ─── EXPORTS ───────────────────────────────────────────────────────────────── + +// Support both CommonJS (Node / bundler) and plain browser ES modules. +if (typeof module !== 'undefined' && module.exports) { + module.exports = { preloadAssets, loadFromManifest }; +} else if (typeof window !== 'undefined') { + window.AssetLoader = { preloadAssets, loadFromManifest }; +} diff --git a/tools/generate-assets.js b/tools/generate-assets.js new file mode 100644 index 0000000..f23cf10 --- /dev/null +++ b/tools/generate-assets.js @@ -0,0 +1,1024 @@ +#!/usr/bin/env node +'use strict'; + +/** + * generate-assets.js + * + * Generates all placeholder PNG sprite-sheets, atlas PNGs + JSONs, and + * assets/asset-manifest.json for "That One Game". + * + * Run: node tools/generate-assets.js + * + * Outputs (deterministic, safe to re-run): + * assets/spritesheets/rw/*.png + * assets/spritesheets/gw/*.png + * assets/atlas/rw/atlas_rw_world.{png,json} + * assets/atlas/rw/atlas_rw_ui.{png,json} + * assets/atlas/gw/atlas_gw_world.{png,json} + * assets/atlas/gw/atlas_gw_ui.{png,json} + * assets/asset-manifest.json + */ + +const { createCanvas } = require('canvas'); +const fs = require('fs'); +const path = require('path'); + +// ─── PATHS ──────────────────────────────────────────────────────────────────── +const ROOT = path.join(__dirname, '..'); +const ASSETS_DIR = path.join(ROOT, 'assets'); +const SS_RW = path.join(ASSETS_DIR, 'spritesheets', 'rw'); +const SS_GW = path.join(ASSETS_DIR, 'spritesheets', 'gw'); +const ATLAS_RW = path.join(ASSETS_DIR, 'atlas', 'rw'); +const ATLAS_GW = path.join(ASSETS_DIR, 'atlas', 'gw'); + +// ─── SPRITE-SHEET SPEC ─────────────────────────────────────────────────────── +const DIR_ROWS = ['down', 'left', 'right', 'up']; // Row 0-3 +const ANIMS = { idle: 4, walk: 8, run: 8, attack: 8 }; +const FX_FRAMES = 8; + +// ─── CHARACTER DEFINITIONS ─────────────────────────────────────────────────── +/** + * Each character definition: + * world – 'rw' | 'gw' (determines output subdir and style) + * style – 'cartoon' | 'pixel' + * frameSize – 32 | 64 + * body – torso / suit colour + * head – skin colour + * hair – hair colour (also used as accent) + * eyes – eye colour (red for enemies) + * legs – leg / trouser colour + * tie – tie / detail colour (optional) + * boss – true if boss-tier (gets a slightly different silhouette) + */ +const CHARS = { + // ── Player ──────────────────────────────────────────────────────────────── + player_rw: { + world: 'rw', style: 'cartoon', frameSize: 32, + body: '#2277DD', head: '#FFCC99', hair: '#FF6600', + eyes: '#333333', legs: '#4444AA', tie: null, + }, + player_gw: { + world: 'gw', style: 'pixel', frameSize: 32, + body: '#2277DD', head: '#FFCC99', hair: '#FF6600', + eyes: '#333333', legs: '#4444AA', tie: null, + }, + // ── Regular enemies ─────────────────────────────────────────────────────── + enemy_intern: { + world: 'gw', style: 'pixel', frameSize: 32, + body: '#AAAAAA', head: '#FFCC99', hair: '#555555', + eyes: '#FF0000', legs: '#888888', tie: '#CC0000', + }, + enemy_hr: { + world: 'gw', style: 'pixel', frameSize: 32, + body: '#CC4488', head: '#FFCC99', hair: '#881133', + eyes: '#FF0000', legs: '#AA2266', tie: '#FF88BB', + }, + enemy_dev: { + world: 'gw', style: 'pixel', frameSize: 32, + body: '#33AA33', head: '#FFCC99', hair: '#115511', + eyes: '#FF0000', legs: '#226622', tie: '#88FF44', + }, + enemy_security: { + world: 'gw', style: 'pixel', frameSize: 32, + body: '#111122', head: '#FFCC99', hair: '#000000', + eyes: '#FF0000', legs: '#080815', tie: '#FF0000', + }, + enemy_accountant: { + world: 'gw', style: 'pixel', frameSize: 32, + body: '#774400', head: '#FFCC99', hair: '#442200', + eyes: '#FF0000', legs: '#553300', tie: '#FFCC00', + }, + // ── Mini-boss VP (32×32) ────────────────────────────────────────────────── + miniboss_vp: { + world: 'gw', style: 'pixel', frameSize: 32, + body: '#111166', head: '#FFCC99', hair: '#000033', + eyes: '#FF0000', legs: '#0A0A44', tie: '#FFCC00', boss: true, + }, + // ── Boss CEO (64×64) ────────────────────────────────────────────────────── + boss_ceo: { + world: 'gw', style: 'pixel', frameSize: 64, + body: '#0A0A0A', head: '#CCAA88', hair: '#000000', + eyes: '#FF0000', legs: '#050505', tie: '#CC0000', boss: true, + }, +}; + +// ─── FX DEFINITIONS ────────────────────────────────────────────────────────── +const FX_DEFS = { + fx_hitspark: { colors: ['#FFFF44','#FFAA00','#FF4400','#CC0000'], shape: 'spark' }, + fx_slasharc: { colors: ['#FFFFFF','#CCDDFF','#88AAFF','#4466DD'], shape: 'arc' }, + fx_projectile: { colors: ['#00FFFF','#00AAFF','#0055FF','#002299'], shape: 'orb' }, + fx_pickup: { colors: ['#FFFF88','#FFCCFF','#FF88FF','#AA44FF'], shape: 'sparkle' }, +}; + +// ─── ATLAS FRAME DEFINITIONS ───────────────────────────────────────────────── +// Each entry: { name, w, h, color, shape, detail } +// shape – hint for the placeholder drawing routine +// detail – accent / line colour + +const ATLAS_RW_WORLD_FRAMES = [ + // Buildings + { name: 'building_office', w: 64, h: 96, color: '#CCE0FF', shape: 'building', detail: '#3366AA' }, + { name: 'building_shop', w: 64, h: 80, color: '#FFEEDD', shape: 'building', detail: '#CC6633' }, + { name: 'building_house', w: 64, h: 64, color: '#EEDDCC', shape: 'building', detail: '#885533' }, + { name: 'building_apartment', w: 48, h: 96, color: '#DDEECC', shape: 'building', detail: '#447733' }, + // Props + { name: 'prop_desk', w: 48, h: 32, color: '#AA7755', shape: 'rect', detail: '#774433' }, + { name: 'prop_chair', w: 32, h: 32, color: '#3355AA', shape: 'rect', detail: '#112266' }, + { name: 'prop_computer', w: 32, h: 32, color: '#222244', shape: 'rect', detail: '#00AAFF' }, + { name: 'prop_plant', w: 32, h: 48, color: '#33AA33', shape: 'rect', detail: '#226622' }, + { name: 'prop_filing_cabinet', w: 32, h: 48, color: '#AAAACC', shape: 'rect', detail: '#666688' }, + { name: 'prop_coffee_machine', w: 32, h: 48, color: '#333333', shape: 'rect', detail: '#FF6600' }, + { name: 'prop_water_cooler', w: 24, h: 48, color: '#AADDFF', shape: 'rect', detail: '#3399FF' }, + { name: 'prop_printer', w: 48, h: 32, color: '#CCCCCC', shape: 'rect', detail: '#666666' }, + // Tiles + { name: 'tile_floor_office', w: 32, h: 32, color: '#EEEEFF', shape: 'tile', detail: '#CCCCEE' }, + { name: 'tile_floor_carpet', w: 32, h: 32, color: '#5566AA', shape: 'tile', detail: '#3344AA' }, + { name: 'tile_wall_office', w: 32, h: 32, color: '#DDDDEE', shape: 'tile', detail: '#BBBBCC' }, + { name: 'tile_floor_sidewalk', w: 32, h: 32, color: '#CCCCBB', shape: 'tile', detail: '#AAAAAA' }, + { name: 'tile_floor_road', w: 32, h: 32, color: '#444444', shape: 'tile', detail: '#666666' }, + { name: 'tile_grass', w: 32, h: 32, color: '#44AA44', shape: 'tile', detail: '#338833' }, + // Environmental + { name: 'env_tree', w: 48, h: 64, color: '#226622', shape: 'tree', detail: '#774422' }, + { name: 'env_streetlight', w: 16, h: 64, color: '#888866', shape: 'rect', detail: '#FFFF88' }, + { name: 'env_bench', w: 48, h: 32, color: '#AA7744', shape: 'rect', detail: '#774422' }, + { name: 'env_trash_can', w: 24, h: 32, color: '#555555', shape: 'rect', detail: '#333333' }, + { name: 'env_mailbox', w: 24, h: 32, color: '#1133AA', shape: 'rect', detail: '#0022AA' }, +]; + +const ATLAS_RW_UI_FRAMES = [ + { name: 'ui_button_normal', w: 120, h: 40, color: '#4477FF', shape: 'button', detail: '#FFFFFF' }, + { name: 'ui_button_hover', w: 120, h: 40, color: '#5599FF', shape: 'button', detail: '#FFFFFF' }, + { name: 'ui_button_pressed', w: 120, h: 40, color: '#2255CC', shape: 'button', detail: '#DDDDFF' }, + { name: 'ui_panel', w: 200, h: 150, color: '#1A2244', shape: 'panel', detail: '#3355AA' }, + { name: 'ui_panel_header', w: 200, h: 40, color: '#223366', shape: 'panel', detail: '#4477CC' }, + { name: 'ui_health_bar_bg', w: 100, h: 16, color: '#442222', shape: 'bar', detail: '#661111' }, + { name: 'ui_health_bar_fill', w: 100, h: 16, color: '#FF3333', shape: 'bar', detail: '#FF6666' }, + { name: 'ui_icon_health', w: 24, h: 24, color: '#FF3333', shape: 'icon', detail: '#FF6666' }, + { name: 'ui_icon_stamina', w: 24, h: 24, color: '#33FF33', shape: 'icon', detail: '#66FF66' }, + { name: 'ui_icon_coin', w: 24, h: 24, color: '#FFCC00', shape: 'icon', detail: '#FFEE88' }, + { name: 'ui_icon_key', w: 24, h: 24, color: '#FFAA44', shape: 'icon', detail: '#FFCC88' }, + { name: 'ui_dialog_box', w: 300, h: 80, color: '#1A2244', shape: 'panel', detail: '#3355AA' }, + { name: 'ui_cursor', w: 32, h: 32, color: '#FFFFFF', shape: 'cursor', detail: '#4477FF' }, + { name: 'ui_minimap_bg', w: 128, h: 128, color: '#0A1122', shape: 'panel', detail: '#1A2244' }, + { name: 'ui_minimap_player', w: 8, h: 8, color: '#00FF88', shape: 'rect', detail: '#00FF88' }, +]; + +const ATLAS_GW_WORLD_FRAMES = [ + // Buildings (pixel, game world) + { name: 'gw_building_server', w: 64, h: 96, color: '#112233', shape: 'building', detail: '#00AAFF' }, + { name: 'gw_building_arena', w: 96, h: 96, color: '#221133', shape: 'building', detail: '#AA00FF' }, + { name: 'gw_building_portal', w: 48, h: 64, color: '#003322', shape: 'building', detail: '#00FF88' }, + // Props + { name: 'gw_prop_terminal', w: 32, h: 48, color: '#112244', shape: 'rect', detail: '#00AAFF' }, + { name: 'gw_prop_chest', w: 32, h: 32, color: '#885500', shape: 'rect', detail: '#FFCC00' }, + { name: 'gw_prop_barrel', w: 24, h: 32, color: '#553300', shape: 'rect', detail: '#886644' }, + { name: 'gw_prop_crate', w: 32, h: 32, color: '#665533', shape: 'rect', detail: '#998866' }, + { name: 'gw_prop_crystal', w: 24, h: 32, color: '#8800FF', shape: 'diamond', detail: '#CC88FF' }, + // Items + { name: 'item_sword', w: 16, h: 32, color: '#AAAAAA', shape: 'sword', detail: '#CCCCCC' }, + { name: 'item_shield', w: 24, h: 24, color: '#3355AA', shape: 'shield', detail: '#6688CC' }, + { name: 'item_potion_red', w: 16, h: 24, color: '#FF3333', shape: 'potion', detail: '#FF6666' }, + { name: 'item_potion_blue', w: 16, h: 24, color: '#3333FF', shape: 'potion', detail: '#6666FF' }, + { name: 'item_coin', w: 16, h: 16, color: '#FFCC00', shape: 'circle', detail: '#FFEE88' }, + { name: 'item_key', w: 16, h: 24, color: '#FFAA44', shape: 'rect', detail: '#FFCC88' }, + { name: 'item_badge', w: 24, h: 24, color: '#334455', shape: 'rect', detail: '#FF0000' }, + { name: 'item_power_chip', w: 16, h: 16, color: '#001133', shape: 'rect', detail: '#00AAFF' }, + // Tiles + { name: 'gw_tile_floor_dungeon', w: 32, h: 32, color: '#221122', shape: 'tile', detail: '#332233' }, + { name: 'gw_tile_floor_circuit', w: 32, h: 32, color: '#001122', shape: 'tile', detail: '#002244' }, + { name: 'gw_tile_wall_dungeon', w: 32, h: 32, color: '#332233', shape: 'tile', detail: '#443344' }, + { name: 'gw_tile_wall_circuit', w: 32, h: 32, color: '#112233', shape: 'tile', detail: '#223355' }, + { name: 'gw_tile_floor_boss', w: 32, h: 32, color: '#110011', shape: 'tile', detail: '#330022' }, + // Environmental + { name: 'gw_env_pillar', w: 32, h: 48, color: '#334455', shape: 'rect', detail: '#556677' }, + { name: 'gw_env_spike', w: 32, h: 32, color: '#AA2222', shape: 'diamond', detail: '#FF3333' }, + { name: 'gw_env_portal_ring', w: 48, h: 48, color: '#8800FF', shape: 'ring', detail: '#CC88FF' }, + { name: 'gw_env_data_stream', w: 16, h: 64, color: '#00FF88', shape: 'rect', detail: '#00FFCC' }, +]; + +const ATLAS_GW_UI_FRAMES = [ + { name: 'gw_ui_button_normal', w: 120, h: 40, color: '#220033', shape: 'button', detail: '#AA00FF' }, + { name: 'gw_ui_button_hover', w: 120, h: 40, color: '#330044', shape: 'button', detail: '#CC44FF' }, + { name: 'gw_ui_button_pressed', w: 120, h: 40, color: '#110022', shape: 'button', detail: '#8800DD' }, + { name: 'gw_ui_panel', w: 200, h: 150, color: '#0A0022', shape: 'panel', detail: '#220055' }, + { name: 'gw_ui_health_bar_bg', w: 100, h: 16, color: '#330000', shape: 'bar', detail: '#440000' }, + { name: 'gw_ui_health_bar_fill', w: 100, h: 16, color: '#FF0033', shape: 'bar', detail: '#FF4466' }, + { name: 'gw_ui_energy_bar_bg', w: 100, h: 16, color: '#001133', shape: 'bar', detail: '#002244' }, + { name: 'gw_ui_energy_bar_fill', w: 100, h: 16, color: '#0099FF', shape: 'bar', detail: '#44BBFF' }, + { name: 'gw_ui_icon_hp', w: 24, h: 24, color: '#FF0033', shape: 'icon', detail: '#FF4466' }, + { name: 'gw_ui_icon_mp', w: 24, h: 24, color: '#0099FF', shape: 'icon', detail: '#44BBFF' }, + { name: 'gw_ui_icon_exp', w: 24, h: 24, color: '#FFCC00', shape: 'icon', detail: '#FFEE88' }, + { name: 'gw_ui_icon_gold', w: 24, h: 24, color: '#FFAA00', shape: 'icon', detail: '#FFCC44' }, + { name: 'gw_ui_dialog_box', w: 300, h: 80, color: '#0A0022', shape: 'panel', detail: '#220055' }, + { name: 'gw_ui_cursor', w: 32, h: 32, color: '#AA00FF', shape: 'cursor', detail: '#CC88FF' }, + { name: 'gw_ui_minimap_bg', w: 128, h: 128, color: '#050011', shape: 'panel', detail: '#110033' }, + { name: 'gw_ui_hud_frame', w: 256, h: 64, color: '#0A0022', shape: 'panel', detail: '#330066' }, + { name: 'gw_ui_level_up_banner', w: 200, h: 48, color: '#220044', shape: 'panel', detail: '#FF44FF' }, +]; + +// ─── UTILITY ───────────────────────────────────────────────────────────────── + +function ensureDir(p) { + fs.mkdirSync(p, { recursive: true }); +} + +function nextPow2(n) { + let p = 1; + while (p < n) p <<= 1; + return p; +} + +function savePNG(canvas, filePath) { + const buf = canvas.toBuffer('image/png'); + fs.writeFileSync(filePath, buf); + console.log(' wrote', path.relative(path.join(__dirname, '..'), filePath)); +} + +// ─── CHARACTER DRAWING ─────────────────────────────────────────────────────── + +/** + * Compute per-frame animation offsets. + * Returns { bodyDY, legToggle, strikePhase } + */ +function animOffsets(animName, frameIdx, p) { + const pat4 = [0, -p * 0.25, -p * 0.5, -p * 0.25]; + if (animName === 'idle') { + return { bodyDY: pat4[frameIdx % 4], legToggle: false, strikePhase: false }; + } + if (animName === 'walk') { + return { bodyDY: (frameIdx % 2) * (-p * 0.5), legToggle: frameIdx % 2 === 1, strikePhase: false }; + } + if (animName === 'run') { + return { bodyDY: (frameIdx % 2) * (-p), legToggle: frameIdx % 2 === 1, strikePhase: false }; + } + if (animName === 'attack') { + const strike = frameIdx >= 4; + return { bodyDY: strike ? -p * 0.25 : 0, legToggle: false, strikePhase: strike }; + } + return { bodyDY: 0, legToggle: false, strikePhase: false }; +} + +/** + * Draw one pixel-art character frame at canvas pixel offset (ox, oy). + * sz = frameSize (32 or 64). + */ +function drawPixelChar(ctx, char, dir, animName, frameIdx, ox, oy, sz) { + const p = sz >= 64 ? 8 : 4; // one "logical pixel" in actual pixels + const { bodyDY, legToggle, strikePhase } = animOffsets(animName, frameIdx, p); + const snap = (v) => Math.round(v / p) * p; + const bdy = snap(bodyDY); + + // Layout (in actual pixels within the sz×sz frame) + const headW = 2 * p, headH = 2 * p; + const bodyW = 3 * p, bodyH = 2 * p; + const legW = p, legH = 2 * p; + + const headX = snap((sz - headW) / 2); + const headY = p + bdy; + const bodyX = snap((sz - bodyW) / 2); + const bodyY = headY + headH; + const legY = bodyY + bodyH; + + const fill = (x, y, w, h, color) => { + if (w <= 0 || h <= 0) return; + ctx.fillStyle = color; + ctx.fillRect(ox + Math.round(x), oy + Math.round(y), + Math.max(1, Math.round(w)), Math.max(1, Math.round(h))); + }; + + // Shadow + ctx.save(); + ctx.fillStyle = 'rgba(0,0,0,0.18)'; + ctx.beginPath(); + ctx.ellipse(ox + sz / 2, oy + sz - p * 0.4, sz * 0.28, p * 0.55, 0, 0, Math.PI * 2); + ctx.fill(); + ctx.restore(); + + // Legs + if (dir === 'left' || dir === 'right') { + fill(bodyX + p * 0.5, legY, bodyW - p, legH, char.legs); + } else { + const l1DY = legToggle ? p * 0.5 : 0; + const l2DY = legToggle ? 0 : p * 0.5; + fill(bodyX, legY + l1DY, legW, legH - l1DY, char.legs); + fill(bodyX + bodyW - legW, legY + l2DY, legW, legH - l2DY, char.legs); + } + + // Body + if (dir === 'left' || dir === 'right') { + fill(bodyX + p * 0.25, bodyY, bodyW - p * 0.5, bodyH, char.body); + } else { + fill(bodyX, bodyY, bodyW, bodyH, char.body); + } + // Tie stripe + if (char.tie) { + fill(bodyX + snap(bodyW * 0.38), bodyY, p * 0.5, bodyH, char.tie); + } + + // Boss crown / aura indicator (extra decoration for boss-tier characters) + if (char.boss && sz >= 32) { + const crownW = p, crownH = p * 0.5; + fill(headX + headW * 0.25, headY - crownH, crownW, crownH, char.tie || char.hair); + fill(headX + headW * 0.75 - crownW * 0.5, headY - crownH, crownW, crownH, char.tie || char.hair); + } + + // Attack arm + if (animName === 'attack') { + const armW = p * 1.5, armH = p; + const armY = bodyY + p * 0.5; + if (strikePhase) { + let armX; + if (dir === 'left') armX = bodyX - armW; + else if (dir === 'right') armX = bodyX + bodyW; + else armX = bodyX + bodyW; // down / up + fill(armX, armY, armW, armH, char.head); + // Weapon tip (bright accent) + const wpX = dir === 'left' ? armX - p * 0.5 : armX + armW; + fill(wpX, armY - p * 0.5, p * 0.5, armH * 2, char.hair); + } else { + // Wind-up: arm on opposite side + let armX; + if (dir === 'left') armX = bodyX + bodyW; + else armX = bodyX - p * 1.5; + fill(armX, armY, armW, armH, char.head); + } + } + + // Head + fill(headX, headY, headW, headH, char.head); + // Hair (top half) + fill(headX, headY, headW, Math.max(p * 0.5, Math.round(headH * 0.4)), char.hair); + + // Eyes + const eyeSize = Math.max(1, Math.round(p * 0.5)); + const eyeY = headY + Math.round(headH * 0.55); + if (dir === 'down') { + fill(headX + Math.round(p * 0.3), eyeY, eyeSize, eyeSize, char.eyes); + fill(headX + headW - Math.round(p * 0.3) - eyeSize, eyeY, eyeSize, eyeSize, char.eyes); + } else if (dir === 'left') { + fill(headX + Math.round(p * 0.3), eyeY, eyeSize, eyeSize, char.eyes); + } else if (dir === 'right') { + fill(headX + headW - Math.round(p * 0.3) - eyeSize, eyeY, eyeSize, eyeSize, char.eyes); + } + // dir === 'up': no eyes visible + + // Direction indicator: small teal dot at edge of frame + ctx.save(); + ctx.fillStyle = 'rgba(0,255,160,0.55)'; + ctx.beginPath(); + const dr = Math.max(1.5, p * 0.35); + let dx = ox + sz * 0.5, dy = oy + sz * 0.5; + if (dir === 'down') dy = oy + sz - dr - 1; + if (dir === 'up') dy = oy + dr + 1; + if (dir === 'left') dx = ox + dr + 1; + if (dir === 'right') dx = ox + sz - dr - 1; + ctx.arc(dx, dy, dr, 0, Math.PI * 2); + ctx.fill(); + ctx.restore(); +} + +/** + * Draw one cartoon-style character frame at (ox, oy). + * Uses smooth arcs instead of pixel blocks. + */ +function drawCartoonChar(ctx, char, dir, animName, frameIdx, ox, oy, sz) { + const u = sz / 32; + const p = 4 * u; + const { bodyDY, legToggle, strikePhase } = animOffsets(animName, frameIdx, p); + + const bodyW = 12 * u, bodyH = 10 * u; + const bodyX = (sz - bodyW) / 2; + const bodyY = sz * 0.45 + bodyDY; + const headR = 6.5 * u; + const headCX = sz * 0.5; + const headCY = bodyY - headR; + const legW = 4.5 * u, legH = 8 * u; + const legY = bodyY + bodyH; + + const fillRect = (x, y, w, h, color) => { + if (w <= 0 || h <= 0) return; + ctx.fillStyle = color; + ctx.fillRect(ox + x, oy + y, w, h); + }; + const fillCircle = (cx, cy, r, color) => { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(ox + cx, oy + cy, r, 0, Math.PI * 2); + ctx.fill(); + }; + + // Shadow + ctx.save(); + ctx.fillStyle = 'rgba(0,0,0,0.15)'; + ctx.beginPath(); + ctx.ellipse(ox + sz * 0.5, oy + sz - 2 * u, sz * 0.28, 2.5 * u, 0, 0, Math.PI * 2); + ctx.fill(); + ctx.restore(); + + // Legs + if (dir === 'left' || dir === 'right') { + fillRect(bodyX + legW * 0.5, legY, bodyW - legW, legH, char.legs); + } else { + const l1DY = legToggle ? p * 0.5 : 0; + const l2DY = legToggle ? 0 : p * 0.5; + fillRect(bodyX + u, legY + l1DY, legW, legH - l1DY, char.legs); + fillRect(bodyX + bodyW - legW - u, legY + l2DY, legW, legH - l2DY, char.legs); + } + + // Body (rounded rect approximated as rect) + fillRect(bodyX, bodyY, bodyW, bodyH, char.body); + // Tie + if (char.tie) { + fillRect(bodyX + bodyW * 0.42, bodyY, 2 * u, bodyH, char.tie); + } + + // Attack arm + if (animName === 'attack') { + const armW = 9 * u, armH = 4 * u; + const armY = bodyY + bodyH * 0.2; + if (strikePhase) { + let armX = dir === 'left' ? bodyX - armW : bodyX + bodyW; + fillRect(armX, armY, armW, armH, char.head); + const wpX = dir === 'left' ? armX - p * 0.5 : armX + armW; + fillRect(wpX, armY - p * 0.4, p * 0.4, armH * 2, char.hair); + } else { + let armX = dir === 'left' ? bodyX + bodyW : bodyX - 9 * u; + fillRect(armX, armY, armW, armH, char.head); + } + } + + // Head + fillCircle(headCX, headCY, headR, char.head); + // Hair (upper half arc) + ctx.save(); + ctx.fillStyle = char.hair; + ctx.beginPath(); + ctx.arc(ox + headCX, oy + headCY, headR, Math.PI, 2 * Math.PI); + ctx.fill(); + ctx.restore(); + + // Eyes + if (dir !== 'up') { + const eyeR = Math.max(1.5, 1.5 * u); + const eyeY = headCY + headR * 0.35; + if (dir === 'down') { + fillCircle(headCX - headR * 0.38, eyeY, eyeR, char.eyes); + fillCircle(headCX + headR * 0.38, eyeY, eyeR, char.eyes); + } else if (dir === 'left') { + fillCircle(headCX - headR * 0.3, eyeY, eyeR, char.eyes); + } else { + fillCircle(headCX + headR * 0.3, eyeY, eyeR, char.eyes); + } + } + + // Direction dot + ctx.save(); + ctx.fillStyle = 'rgba(0,255,160,0.55)'; + ctx.beginPath(); + const dr = Math.max(1.5, 2 * u); + let dx = ox + sz * 0.5, dy = oy + sz * 0.5; + if (dir === 'down') dy = oy + sz - dr - 1; + if (dir === 'up') dy = oy + dr + 1; + if (dir === 'left') dx = ox + dr + 1; + if (dir === 'right') dx = ox + sz - dr - 1; + ctx.arc(dx, dy, dr, 0, Math.PI * 2); + ctx.fill(); + ctx.restore(); +} + +/** + * Draw one character frame – dispatches to pixel or cartoon renderer. + */ +function drawCharFrame(ctx, char, dir, animName, frameIdx, ox, oy, sz) { + if (char.style === 'pixel') { + drawPixelChar(ctx, char, dir, animName, frameIdx, ox, oy, sz); + } else { + drawCartoonChar(ctx, char, dir, animName, frameIdx, ox, oy, sz); + } +} + +// ─── FX DRAWING ────────────────────────────────────────────────────────────── + +/** + * Draw one FX frame at (ox, oy) on a 32×32 cell. + * frame 0 = start, 7 = end. + */ +function drawFxFrame(ctx, fxDef, frameIdx, ox, oy) { + const sz = 32; + const t = frameIdx / (FX_FRAMES - 1); // 0..1 + const tinv = 1 - t; + const cx = ox + sz * 0.5, cy = oy + sz * 0.5; + const col = fxDef.colors[Math.min(frameIdx, fxDef.colors.length - 1)]; + + ctx.save(); + + switch (fxDef.shape) { + case 'spark': { + // Expanding burst of lines + const numRays = 6; + const maxR = sz * 0.45 * t; + ctx.strokeStyle = col; + ctx.lineWidth = Math.max(1, 2 * tinv); + ctx.globalAlpha = tinv * 0.9 + 0.1; + for (let i = 0; i < numRays; i++) { + const angle = (i / numRays) * Math.PI * 2; + const r0 = maxR * 0.2; + ctx.beginPath(); + ctx.moveTo(cx + Math.cos(angle) * r0, cy + Math.sin(angle) * r0); + ctx.lineTo(cx + Math.cos(angle) * maxR, cy + Math.sin(angle) * maxR); + ctx.stroke(); + } + // Center flash + ctx.fillStyle = fxDef.colors[0]; + ctx.globalAlpha = tinv * 0.8; + ctx.beginPath(); + ctx.arc(cx, cy, sz * 0.12 * tinv, 0, Math.PI * 2); + ctx.fill(); + break; + } + case 'arc': { + // Growing + fading slash arc + const maxR = sz * 0.4; + const r = maxR * Math.min(1, t * 2); + ctx.strokeStyle = col; + ctx.lineWidth = Math.max(1, 4 * tinv); + ctx.globalAlpha = tinv; + ctx.beginPath(); + ctx.arc(cx, cy, r, -Math.PI * 0.75, Math.PI * 0.25); + ctx.stroke(); + break; + } + case 'orb': { + // Glowing projectile with trail + const posX = ox + sz * 0.1 + sz * 0.8 * t; + ctx.globalAlpha = 0.9; + // Trail + ctx.fillStyle = fxDef.colors[2]; + ctx.globalAlpha = tinv * 0.5; + ctx.fillRect(ox + sz * 0.1, cy - 3, sz * 0.8 * t, 4); + // Core + ctx.globalAlpha = 0.95; + ctx.fillStyle = col; + ctx.beginPath(); + ctx.arc(posX + 4, cy, 4, 0, Math.PI * 2); + ctx.fill(); + break; + } + case 'sparkle': { + // Growing / fading star points + const numPts = 4; + const maxR = sz * 0.4 * Math.sin(t * Math.PI); + ctx.fillStyle = col; + ctx.globalAlpha = Math.sin(t * Math.PI); + for (let i = 0; i < numPts; i++) { + const a = (i / numPts) * Math.PI * 2; + const px = cx + Math.cos(a) * maxR; + const py = cy + Math.sin(a) * maxR; + ctx.beginPath(); + ctx.arc(px, py, Math.max(1, 2 * Math.sin(t * Math.PI)), 0, Math.PI * 2); + ctx.fill(); + } + // Center + ctx.fillStyle = fxDef.colors[0]; + ctx.beginPath(); + ctx.arc(cx, cy, Math.max(1, 3 * Math.sin(t * Math.PI)), 0, Math.PI * 2); + ctx.fill(); + break; + } + default: + ctx.fillStyle = col; + ctx.globalAlpha = tinv; + ctx.fillRect(ox + 4, oy + 4, sz - 8, sz - 8); + } + + ctx.restore(); +} + +// ─── ATLAS FRAME DRAWING ───────────────────────────────────────────────────── + +/** + * Draw one atlas placeholder frame at (ox, oy) with given w × h dimensions. + */ +function drawAtlasFrame(ctx, frame, ox, oy) { + const { w, h, color, detail, shape, name } = frame; + + ctx.save(); + + switch (shape) { + case 'building': { + // Main structure + ctx.fillStyle = color; + ctx.fillRect(ox + 2, oy + h * 0.25, w - 4, h * 0.75 - 2); + // Roof + ctx.fillStyle = detail; + ctx.fillRect(ox + 2, oy + 2, w - 4, h * 0.25); + // Windows (2×2 grid) + const winColor = detail + 'CC'; + const cols = 2, rows = 2; + const winW = Math.max(4, Math.floor((w - 8) / (cols * 1.5))); + const winH = Math.max(4, Math.floor((h * 0.5) / (rows * 1.5))); + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const wx = ox + 4 + c * (winW + 4); + const wy = oy + h * 0.35 + r * (winH + 4); + ctx.fillStyle = winColor; + ctx.fillRect(wx, wy, winW, winH); + } + } + break; + } + case 'tile': { + ctx.fillStyle = color; + ctx.fillRect(ox, oy, w, h); + ctx.strokeStyle = detail; + ctx.lineWidth = 1; + ctx.strokeRect(ox + 1, oy + 1, w - 2, h - 2); + // Cross lines + ctx.beginPath(); + ctx.moveTo(ox + w * 0.5, oy); + ctx.lineTo(ox + w * 0.5, oy + h); + ctx.moveTo(ox, oy + h * 0.5); + ctx.lineTo(ox + w, oy + h * 0.5); + ctx.stroke(); + break; + } + case 'tree': { + // Trunk + ctx.fillStyle = detail; + ctx.fillRect(ox + w * 0.38, oy + h * 0.6, w * 0.24, h * 0.4); + // Canopy (layered circles) + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(ox + w * 0.5, oy + h * 0.55, w * 0.4, 0, Math.PI * 2); + ctx.fill(); + ctx.beginPath(); + ctx.arc(ox + w * 0.5, oy + h * 0.38, w * 0.35, 0, Math.PI * 2); + ctx.fill(); + break; + } + case 'button': { + // Background fill + ctx.fillStyle = color; + ctx.fillRect(ox + 2, oy + 2, w - 4, h - 4); + // Border + ctx.strokeStyle = detail; + ctx.lineWidth = 2; + ctx.strokeRect(ox + 2, oy + 2, w - 4, h - 4); + // Highlight line + ctx.strokeStyle = detail + '88'; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(ox + 4, oy + 4); + ctx.lineTo(ox + w - 4, oy + 4); + ctx.stroke(); + break; + } + case 'panel': { + ctx.fillStyle = color; + ctx.fillRect(ox + 1, oy + 1, w - 2, h - 2); + ctx.strokeStyle = detail; + ctx.lineWidth = 2; + ctx.strokeRect(ox + 1, oy + 1, w - 2, h - 2); + // Inner border + ctx.strokeStyle = detail + '66'; + ctx.lineWidth = 1; + ctx.strokeRect(ox + 4, oy + 4, w - 8, h - 8); + break; + } + case 'bar': { + ctx.fillStyle = color; + ctx.fillRect(ox, oy, w, h); + ctx.fillStyle = detail; + ctx.fillRect(ox, oy, w * 0.7, h); + ctx.strokeStyle = detail; + ctx.lineWidth = 1; + ctx.strokeRect(ox + 0.5, oy + 0.5, w - 1, h - 1); + break; + } + case 'icon': { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(ox + w * 0.5, oy + h * 0.5, Math.min(w, h) * 0.42, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = detail; + ctx.lineWidth = 1.5; + ctx.stroke(); + break; + } + case 'cursor': { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.moveTo(ox + 4, oy + 4); + ctx.lineTo(ox + 4, oy + h - 4); + ctx.lineTo(ox + w * 0.5, oy + h * 0.65); + ctx.lineTo(ox + w - 4, oy + h - 4); + ctx.lineTo(ox + w * 0.6, oy + h * 0.6); + ctx.lineTo(ox + w - 4, oy + 4); + ctx.closePath(); + ctx.fill(); + ctx.strokeStyle = detail; + ctx.lineWidth = 1; + ctx.stroke(); + break; + } + case 'diamond': { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.moveTo(ox + w * 0.5, oy + 2); + ctx.lineTo(ox + w - 2, oy + h * 0.5); + ctx.lineTo(ox + w * 0.5, oy + h - 2); + ctx.lineTo(ox + 2, oy + h * 0.5); + ctx.closePath(); + ctx.fill(); + ctx.strokeStyle = detail; + ctx.lineWidth = 1; + ctx.stroke(); + break; + } + case 'ring': { + ctx.strokeStyle = color; + ctx.lineWidth = 5; + ctx.beginPath(); + ctx.arc(ox + w * 0.5, oy + h * 0.5, Math.min(w, h) * 0.4, 0, Math.PI * 2); + ctx.stroke(); + ctx.strokeStyle = detail; + ctx.lineWidth = 2; + ctx.stroke(); + break; + } + case 'sword': { + // Blade + ctx.fillStyle = color; + ctx.fillRect(ox + w * 0.38, oy + 2, w * 0.24, h * 0.75); + // Guard + ctx.fillStyle = detail; + ctx.fillRect(ox + 2, oy + h * 0.7, w - 4, h * 0.08); + // Handle + ctx.fillStyle = '#AA7744'; + ctx.fillRect(ox + w * 0.38, oy + h * 0.78, w * 0.24, h * 0.2); + break; + } + case 'shield': { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.moveTo(ox + w * 0.5, oy + 2); + ctx.lineTo(ox + w - 2, oy + h * 0.45); + ctx.quadraticCurveTo(ox + w - 2, oy + h - 2, ox + w * 0.5, oy + h - 2); + ctx.quadraticCurveTo(ox + 2, oy + h - 2, ox + 2, oy + h * 0.45); + ctx.closePath(); + ctx.fill(); + ctx.strokeStyle = detail; + ctx.lineWidth = 1.5; + ctx.stroke(); + break; + } + case 'potion': { + // Bottle body + ctx.fillStyle = color + 'CC'; + ctx.beginPath(); + ctx.arc(ox + w * 0.5, oy + h * 0.65, w * 0.38, 0, Math.PI * 2); + ctx.fill(); + // Neck + ctx.fillStyle = detail + '99'; + ctx.fillRect(ox + w * 0.3, oy + h * 0.1, w * 0.4, h * 0.3); + // Cork + ctx.fillStyle = '#AA8844'; + ctx.fillRect(ox + w * 0.3, oy + 2, w * 0.4, h * 0.12); + // Shine + ctx.fillStyle = 'rgba(255,255,255,0.4)'; + ctx.beginPath(); + ctx.arc(ox + w * 0.38, oy + h * 0.55, w * 0.12, 0, Math.PI * 2); + ctx.fill(); + break; + } + case 'circle': { + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(ox + w * 0.5, oy + h * 0.5, Math.min(w, h) * 0.45, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = detail; + ctx.lineWidth = 1.5; + ctx.stroke(); + break; + } + default: { // 'rect' and fallback + ctx.fillStyle = color; + ctx.fillRect(ox + 1, oy + 1, w - 2, h - 2); + ctx.strokeStyle = detail; + ctx.lineWidth = 1; + ctx.strokeRect(ox + 1, oy + 1, w - 2, h - 2); + break; + } + } + + ctx.restore(); +} + +// ─── SPRITESHEET GENERATION ────────────────────────────────────────────────── + +/** + * Generate one spritesheet PNG for a given character + animation combo. + * Returns { key, path, frameWidth, frameHeight, cols, rows } + */ +function generateCharSheet(charId, char, animName, numFrames, outputDir) { + const sz = char.frameSize; + const cols = numFrames; + const rows = DIR_ROWS.length; + const canvas = createCanvas(cols * sz, rows * sz); + const ctx = canvas.getContext('2d'); + + // Transparent background (default for canvas) + ctx.clearRect(0, 0, canvas.width, canvas.height); + // Optional: light checkerboard to confirm transparency visually (skip for real output) + + for (let rowIdx = 0; rowIdx < rows; rowIdx++) { + const dir = DIR_ROWS[rowIdx]; + for (let frameIdx = 0; frameIdx < numFrames; frameIdx++) { + const ox = frameIdx * sz; + const oy = rowIdx * sz; + drawCharFrame(ctx, char, dir, animName, frameIdx, ox, oy, sz); + } + } + + const key = `${charId}_${animName}`; + const fileName = `${key}.png`; + const filePath = path.join(outputDir, fileName); + savePNG(canvas, filePath); + + return { + key, + path: `assets/spritesheets/${char.world}/${fileName}`, + frameWidth: sz, + frameHeight: sz, + }; +} + +/** + * Generate one FX spritesheet (single row, 8 frames, 32×32 each). + */ +function generateFxSheet(fxId, fxDef, outputDir) { + const sz = 32; + const canvas = createCanvas(FX_FRAMES * sz, sz); + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + + for (let f = 0; f < FX_FRAMES; f++) { + drawFxFrame(ctx, fxDef, f, f * sz, 0); + } + + const fileName = `${fxId}.png`; + const filePath = path.join(outputDir, fileName); + savePNG(canvas, filePath); + + return { + key: fxId, + path: `assets/spritesheets/gw/${fileName}`, + frameWidth: sz, + frameHeight: sz, + }; +} + +// ─── ATLAS GENERATION ──────────────────────────────────────────────────────── + +const ATLAS_PADDING = 2; + +/** + * Simple greedy row packer. + * Returns array of { name, w, h, x, y } and atlas { width, height }. + */ +function packFrames(frames, maxWidth) { + let x = ATLAS_PADDING, y = ATLAS_PADDING, rowH = 0; + const packed = []; + + for (const f of frames) { + if (x + f.w + ATLAS_PADDING > maxWidth && x > ATLAS_PADDING) { + x = ATLAS_PADDING; + y += rowH + ATLAS_PADDING; + rowH = 0; + } + packed.push({ ...f, x, y }); + x += f.w + ATLAS_PADDING; + rowH = Math.max(rowH, f.h); + } + + const totalH = y + rowH + ATLAS_PADDING; + return { + frames: packed, + atlasWidth: nextPow2(maxWidth), + atlasHeight: nextPow2(totalH), + }; +} + +/** + * Build Phaser-compatible TexturePacker "hash" JSON for an atlas. + */ +function buildAtlasJson(packedFrames, atlasWidth, atlasHeight, imageName) { + const frames = {}; + for (const f of packedFrames) { + frames[f.name] = { + frame: { x: f.x, y: f.y, w: f.w, h: f.h }, + rotated: false, + trimmed: false, + spriteSourceSize:{ x: 0, y: 0, w: f.w, h: f.h }, + sourceSize: { w: f.w, h: f.h }, + }; + } + return { + frames, + meta: { + app: 'asset-generator', + version: '1.0', + image: imageName, + format: 'RGBA8888', + size: { w: atlasWidth, h: atlasHeight }, + scale: '1', + }, + }; +} + +/** + * Generate one atlas (PNG + JSON) and return the manifest entry. + */ +function generateAtlas(atlasId, framesDefs, outputDir, relDir) { + const maxWidth = 512; + const { frames: packed, atlasWidth, atlasHeight } = packFrames(framesDefs, maxWidth); + + const canvas = createCanvas(atlasWidth, atlasHeight); + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, atlasWidth, atlasHeight); + + for (const f of packed) { + drawAtlasFrame(ctx, f, f.x, f.y); + } + + const pngFile = `${atlasId}.png`; + const jsonFile = `${atlasId}.json`; + const pngPath = path.join(outputDir, pngFile); + const jsonPath = path.join(outputDir, jsonFile); + + savePNG(canvas, pngPath); + + const json = buildAtlasJson(packed, atlasWidth, atlasHeight, pngFile); + fs.writeFileSync(jsonPath, JSON.stringify(json, null, 2)); + console.log(' wrote', path.relative(path.join(__dirname, '..'), jsonPath)); + + return { + key: atlasId, + png: `assets/atlas/${relDir}/${pngFile}`, + json: `assets/atlas/${relDir}/${jsonFile}`, + }; +} + +// ─── ASSET MANIFEST ────────────────────────────────────────────────────────── + +function buildManifest(spritesheets, atlases) { + return { spritesheets, atlases }; +} + +// ─── MAIN ──────────────────────────────────────────────────────────────────── + +function main() { + console.log('=== That One Game – Asset Generator ===\n'); + + ensureDir(SS_RW); + ensureDir(SS_GW); + ensureDir(ATLAS_RW); + ensureDir(ATLAS_GW); + + const spritesheets = []; + + // ── Character sprite-sheets ────────────────────────────────────────────── + console.log('Generating character sprite-sheets…'); + for (const [charId, char] of Object.entries(CHARS)) { + const outputDir = char.world === 'rw' ? SS_RW : SS_GW; + for (const [animName, numFrames] of Object.entries(ANIMS)) { + const entry = generateCharSheet(charId, char, animName, numFrames, outputDir); + spritesheets.push(entry); + } + } + + // ── FX sprite-sheets ───────────────────────────────────────────────────── + console.log('\nGenerating FX sprite-sheets…'); + for (const [fxId, fxDef] of Object.entries(FX_DEFS)) { + const entry = generateFxSheet(fxId, fxDef, SS_GW); + spritesheets.push(entry); + } + + // ── Atlases ────────────────────────────────────────────────────────────── + console.log('\nGenerating atlases…'); + const atlases = []; + atlases.push(generateAtlas('atlas_rw_world', ATLAS_RW_WORLD_FRAMES, ATLAS_RW, 'rw')); + atlases.push(generateAtlas('atlas_rw_ui', ATLAS_RW_UI_FRAMES, ATLAS_RW, 'rw')); + atlases.push(generateAtlas('atlas_gw_world', ATLAS_GW_WORLD_FRAMES, ATLAS_GW, 'gw')); + atlases.push(generateAtlas('atlas_gw_ui', ATLAS_GW_UI_FRAMES, ATLAS_GW, 'gw')); + + // ── Asset manifest ─────────────────────────────────────────────────────── + const manifest = buildManifest(spritesheets, atlases); + const manifestPath = path.join(ASSETS_DIR, 'asset-manifest.json'); + fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2)); + console.log('\n wrote', path.relative(path.join(__dirname, '..'), manifestPath)); + + console.log('\n✓ Done – generated', spritesheets.length, 'sprite-sheets and', atlases.length, 'atlases.'); +} + +main(); From e87b83505ed6a1eed529eb346805e78160533e99 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 03:07:16 +0000 Subject: [PATCH 3/3] feat: add index.html + src/main.js for GitHub Spark upload-ready package Agent-Logs-Url: https://github.com/paulcombs56-ops/That-One-Game/sessions/9baecddb-4a21-4a81-9767-20f767bbef18 Co-authored-by: paulcombs56-ops <263761623+paulcombs56-ops@users.noreply.github.com> --- index.html | 63 +++++++++++++++++ src/main.js | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 index.html create mode 100644 src/main.js diff --git a/index.html b/index.html new file mode 100644 index 0000000..a91f0b7 --- /dev/null +++ b/index.html @@ -0,0 +1,63 @@ + + + + + + That One Game + + + +

That One Game

+ + +
+ +
Arrows / WASD · SHIFT run · SPACE attack · X swap world
+ + + + + + + + + + + + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..97d49c2 --- /dev/null +++ b/src/main.js @@ -0,0 +1,193 @@ +/** + * main.js – That One Game – GitHub Spark entry point + * + * Scenes: + * BootScene – tiny loading screen while the asset manifest is fetched + * PreloadScene – loads every spritesheet and atlas via AssetLoader + * GameScene – registers all animations and shows a playable demo + * + * Keyboard controls (GameScene demo): + * Arrow keys / WASD – move the player + * SHIFT – hold to run + * SPACE – attack + * X key – toggle Real-World ↔ Game-World skin + */ + +'use strict'; + +// ─── CONSTANTS ──────────────────────────────────────────────────────────────── + +const TILE = 32; // px per logical tile +const SPEED = {walk: 80, run: 150}; + +// ─── BOOT SCENE ────────────────────────────────────────────────────────────── + +class BootScene extends Phaser.Scene { + constructor() { super('BootScene'); } + + preload() { + // Show a simple loading bar while the manifest JSON is fetched + const W = this.scale.width; + const H = this.scale.height; + + this.add.text(W / 2, H / 2 - 20, 'Loading…', { + fontFamily: 'monospace', fontSize: '20px', color: '#ffffff', + }).setOrigin(0.5); + + const bar = this.add.rectangle(W / 2, H / 2 + 10, 0, 10, 0x44ff88).setOrigin(0, 0.5); + const bg = this.add.rectangle(W / 2 - 150, H / 2 + 10, 300, 10, 0x336633).setOrigin(0, 0.5); + bg.setDepth(0); bar.setDepth(1); + + this.load.on('progress', (v) => { bar.width = 300 * v; }); + + // Hand off to AssetLoader (attached to window by AssetLoader.js) + window.AssetLoader.preloadAssets(this); + } + + create() { + this.scene.start('GameScene'); + } +} + +// ─── GAME SCENE ────────────────────────────────────────────────────────────── + +class GameScene extends Phaser.Scene { + constructor() { super('GameScene'); } + + create() { + const { width: W, height: H } = this.scale; + const AH = window.AnimationHelper; + + // Register all animations (idempotent) + AH.createAllAnimations(this); + + // ── Background ──────────────────────────────────────────────────────────── + this.add.rectangle(0, 0, W, H, 0x1a1a2e).setOrigin(0); + + // Draw a simple tiled floor from the atlas + this._drawFloor(W, H); + + // ── Player sprite ───────────────────────────────────────────────────────── + this._world = 'rw'; // 'rw' or 'gw' + this._dir = 'down'; + this._moving = false; + this._running = false; + this._attacking = false; + + this.player = this.add.sprite(W / 2, H / 2, 'player_rw_idle') + .setScale(3); + + this.player.play(AH.animKey('player_rw', 'idle', 'down')); + + // ── Input ───────────────────────────────────────────────────────────────── + this.cursors = this.input.keyboard.createCursorKeys(); + this.wasd = this.input.keyboard.addKeys('W,A,S,D'); + this.shiftKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT); + this.spaceKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); + this.swapKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.X); + + // Attack fires once per keydown + this.input.keyboard.on('keydown-SPACE', () => this._startAttack()); + + // Swap world skin + this.input.keyboard.on('keydown-X', () => this._swapWorld()); + + // ── HUD ─────────────────────────────────────────────────────────────────── + this.worldLabel = this.add.text(10, 10, + 'World: Real | X = swap world | Arrows/WASD = move | SHIFT = run | SPACE = attack', { + fontFamily: 'monospace', fontSize: '11px', color: '#aaffaa', + }); + } + + update() { + if (this._attacking) return; // lock movement during attack + + const left = this.cursors.left.isDown || this.wasd.A.isDown; + const right = this.cursors.right.isDown || this.wasd.D.isDown; + const up = this.cursors.up.isDown || this.wasd.W.isDown; + const down = this.cursors.down.isDown || this.wasd.S.isDown; + const run = this.shiftKey.isDown; + + const moving = left || right || up || down; + const speed = run ? SPEED.run : SPEED.walk; + const animName = moving ? (run ? 'run' : 'walk') : 'idle'; + const AH = window.AnimationHelper; + + // Direction + if (left) this._dir = 'left'; + else if (right) this._dir = 'right'; + else if (up) this._dir = 'up'; + else if (down) this._dir = 'down'; + + // Position + const dt = this.game.loop.delta / 1000; + if (left) this.player.x -= speed * dt; + if (right) this.player.x += speed * dt; + if (up) this.player.y -= speed * dt; + if (down) this.player.y += speed * dt; + + // Clamp to screen + this.player.x = Phaser.Math.Clamp(this.player.x, 16, this.scale.width - 16); + this.player.y = Phaser.Math.Clamp(this.player.y, 16, this.scale.height - 16); + + // Play animation only when it changes + const newKey = AH.animKey(`player_${this._world}`, animName, this._dir); + if (this.player.anims.currentAnim?.key !== newKey) { + this.player.play(newKey); + } + } + + // ── Private helpers ────────────────────────────────────────────────────── + + _drawFloor(W, H) { + // Draw a checkerboard pattern as a stand-in for tiles + const cols = Math.ceil(W / TILE) + 1; + const rows = Math.ceil(H / TILE) + 1; + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const col = (r + c) % 2 === 0 ? 0x111122 : 0x0d0d1a; + this.add.rectangle(c * TILE, r * TILE, TILE, TILE, col) + .setOrigin(0).setAlpha(0.8); + } + } + } + + _startAttack() { + if (this._attacking) return; + this._attacking = true; + const key = window.AnimationHelper.animKey(`player_${this._world}`, 'attack', this._dir); + this.player.play(key); + this.player.once('animationcomplete', () => { + this._attacking = false; + }); + } + + _swapWorld() { + this._world = this._world === 'rw' ? 'gw' : 'rw'; + const label = this._world === 'rw' ? 'Real' : 'Game'; + this.worldLabel.setText( + `World: ${label} | X = swap world | Arrows/WASD = move | SHIFT = run | SPACE = attack` + ); + // Reset to idle so the new texture loads cleanly + const key = window.AnimationHelper.animKey(`player_${this._world}`, 'idle', this._dir); + this.player.play(key); + this._attacking = false; + } +} + +// ─── PHASER CONFIG ──────────────────────────────────────────────────────────── + +window.addEventListener('load', function () { + new Phaser.Game({ + type: Phaser.AUTO, + width: 800, + height: 500, + backgroundColor: '#1a1a2e', + scene: [BootScene, GameScene], + parent: 'game-container', + scale: { + mode: Phaser.Scale.FIT, + autoCenter: Phaser.Scale.CENTER_BOTH, + }, + }); +});