From 3750a3feda17c18adbab8cb86a146d58f7177f6c Mon Sep 17 00:00:00 2001 From: Mel-Raeven Date: Thu, 11 Dec 2025 11:30:10 +0100 Subject: [PATCH] removed legacy files and updated nix script to work with macos --- assets/sprites/equipment/diamond_armor.png | Bin 120 -> 0 bytes assets/sprites/equipment/diamond_helmet.png | Bin 248 -> 0 bytes assets/sprites/equipment/dragon_armor.png | Bin 145 -> 0 bytes assets/sprites/equipment/dragon_crown.png | Bin 203 -> 0 bytes assets/sprites/equipment/dragon_saddle.png | Bin 169 -> 0 bytes assets/sprites/equipment/enchanted_saddle.png | Bin 207 -> 0 bytes assets/sprites/equipment/gold_armor.png | Bin 120 -> 0 bytes assets/sprites/equipment/gold_helmet.png | Bin 246 -> 0 bytes assets/sprites/equipment/iron_armor.png | Bin 120 -> 0 bytes assets/sprites/equipment/iron_helmet.png | Bin 248 -> 0 bytes assets/sprites/equipment/leather_saddle.png | Bin 175 -> 0 bytes assets/sprites/equipment/padded_saddle.png | Bin 204 -> 0 bytes assets/sprites/equipment/royal_saddle.png | Bin 205 -> 0 bytes assets/sprites/equipment/steel_armor.png | Bin 120 -> 0 bytes assets/sprites/equipment/steel_helmet.png | Bin 246 -> 0 bytes demo_save_protection.py | 155 ----------- DEPLOYMENT.md => docs/DEPLOYMENT.md | 0 .../REWARD_CONSTANTS.md | 0 flake.nix | 172 ++++++++----- generate_all_sprites.sh | 142 ---------- generate_sounds.py | 243 ------------------ run.sh | 19 -- ...ert_existing_sprites.sh => spritefusion.sh | 0 verify_sprites.py | 43 ---- 24 files changed, 114 insertions(+), 660 deletions(-) delete mode 100644 assets/sprites/equipment/diamond_armor.png delete mode 100644 assets/sprites/equipment/diamond_helmet.png delete mode 100644 assets/sprites/equipment/dragon_armor.png delete mode 100644 assets/sprites/equipment/dragon_crown.png delete mode 100644 assets/sprites/equipment/dragon_saddle.png delete mode 100644 assets/sprites/equipment/enchanted_saddle.png delete mode 100644 assets/sprites/equipment/gold_armor.png delete mode 100644 assets/sprites/equipment/gold_helmet.png delete mode 100644 assets/sprites/equipment/iron_armor.png delete mode 100644 assets/sprites/equipment/iron_helmet.png delete mode 100644 assets/sprites/equipment/leather_saddle.png delete mode 100644 assets/sprites/equipment/padded_saddle.png delete mode 100644 assets/sprites/equipment/royal_saddle.png delete mode 100644 assets/sprites/equipment/steel_armor.png delete mode 100644 assets/sprites/equipment/steel_helmet.png delete mode 100644 demo_save_protection.py rename DEPLOYMENT.md => docs/DEPLOYMENT.md (100%) rename REWARD_CONSTANTS.md => docs/REWARD_CONSTANTS.md (100%) delete mode 100755 generate_all_sprites.sh delete mode 100644 generate_sounds.py delete mode 100755 run.sh rename convert_existing_sprites.sh => spritefusion.sh (100%) delete mode 100644 verify_sprites.py diff --git a/assets/sprites/equipment/diamond_armor.png b/assets/sprites/equipment/diamond_armor.png deleted file mode 100644 index 61d560955f6324b7ff1fbab477239495ff7a344a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y-!3HF~bz9kil)a~mV@L%fqY1<5|3EGpn3l2y cA&SC*DeOGU8m;_VSQ*6kboFyt=akR{00mhS761SM diff --git a/assets/sprites/equipment/diamond_helmet.png b/assets/sprites/equipment/diamond_helmet.png deleted file mode 100644 index c057609423609ecbb3405b67bf2748ab89c89a09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRY!3HGPMlP2IQu{q!978G?-yUFIpb|Ol*vJ3n z?|M(1SzhFwye{|lHYm#MnK#XA{X8RMrFTEewr5o>Yq!q6y8hE4Mgg1Y`8EINo1bTM z_`vY~|EBrb4d3f;o;M9=5U{!Yd;go~zf$ABr7~9BoL(C_kF(*y%(!o<@zdCU9sB;j zl9?eS&VoUU|HJh9pVMu`8MMxS0kQVHIlWKk`|s2H|9CSnG^PLgw*QaM->32aR2hJh o^(VLgf11w4;IO9vtoxrJ>uK5F!E1Mj0KLNC>FVdQ&MBb@00>iZ-~a#s diff --git a/assets/sprites/equipment/dragon_armor.png b/assets/sprites/equipment/dragon_armor.png deleted file mode 100644 index 5eabd78b832b14879787ce33cacb6365461a3a2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y}!3HGH?)<(INJV(MIEGX(zCFOaKqYe8v5)`D z-}Rn2v%JVVd0p=9ZBUfiGjE#L`gumiO7DJ_ZO^J&)^44Bb$t;l1LFsA`vyjq2gj3b n*+SPbEC32U;$qMWXZX;c6v5gSm>}5&w1dIZ)z4*}Q$iB}WqUP2 diff --git a/assets/sprites/equipment/dragon_crown.png b/assets/sprites/equipment/dragon_crown.png deleted file mode 100644 index 2b2552c6c8de7d2196140920451b33cdcd12cad7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^96-#?!3HFqW}i_7QjYq!q6y8hE4L7N8o{z^ZV^Iyd6 z8yNpRVmCP7R-tAu_t~e4=Mfjv1N}ON&kXe+nP+IPu#wmQz3EQ>DdWFS<3IgTn0K=O yxXom_<{eEBW`2=i`7piyB(q|ig_gd|e-7VPv6|SM>92sUWAJqKb6Mw<&;$TV2vpYq diff --git a/assets/sprites/equipment/dragon_saddle.png b/assets/sprites/equipment/dragon_saddle.png deleted file mode 100644 index e2c8649e604861e56c1bc8e914a8bd9100e212f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)L!3HEN&baUbsRB^*=1ucjKhMZm>D|w=?O9dJ+O4y%uK)ChF`)7v!wQ>vhLCyo z3{C03y5$el+57{N3=C7Bf7+za&A{;JC-VX%g@2SK@;K}-woC;oVPNod^>bP0l+XkK Dj-Er{ diff --git a/assets/sprites/equipment/enchanted_saddle.png b/assets/sprites/equipment/enchanted_saddle.png deleted file mode 100644 index 8ca9a19005fdf6454fdb3889c86e2ff06692e87d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207 zcmeAS@N?(olHy`uVBq!ia0vp@K+MI#1|;*}T{!}zrg^$JhEy=VJ;1y`C34!akN?Zx z^`1DhyvRFwUGD8|P?Xs-Z<^Qoc}B)c?|znT&#GG1Zk>H~{ipTJ4o~CR8&2)#W0+bm z%b>;o;h+BRopm>-*G9^{(EtBQ|L3>;e|!pA8Kyq}G`;@kbejv?|36KC^*8=o@!z-g sKW8#Atgtx%66zA?1Do;)YTADebu+=F*CJQX0bR)8>FVdQ&MBb@092)3L;wH) diff --git a/assets/sprites/equipment/gold_armor.png b/assets/sprites/equipment/gold_armor.png deleted file mode 100644 index a02001bf09a7ebdfe85f9bbe30b9e26a3a6e5235..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y-!3HF~bz9kil)a~mV@L%fqY1<5|3EGpaBDh& c5Jlm@6gHh_mG}4APz~aHy85}Sb4q9e0QYq!q6y8hE4Mgg1Y=6~+ko1JHK z_`tCI{x50Xf?sR*UyNaN_}~NL{@tYidlSQ+H>daMoM!=w0eSkTnfE??{%<2AgOd<^MWc13kjv>FVdQ&MBb@0Hr5z-2eap diff --git a/assets/sprites/equipment/iron_armor.png b/assets/sprites/equipment/iron_armor.png deleted file mode 100644 index 31929bbcfaec0915d1b9eb8658d0b08a10c0b192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y-!3HF~bz9kil)a~mV@L%fqY1<5|3EGpSh;c~ cLKKAqQ#kV%>(@W)oF9Ssp00i_>zopr07kDC5&!@I diff --git a/assets/sprites/equipment/iron_helmet.png b/assets/sprites/equipment/iron_helmet.png deleted file mode 100644 index 51e200789002c99ed69cc836c86eb6bf180a81ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRY!3HGPMlP2IQu{q!978G?-yUFIpb|Ol*vJ3n z?|M(1SzhFwye{|lHYm#MnK#XA{X8RMrFTEewr5o>Yq!q6y8hE4Mgg1Y@;@ia8=hx# z_`op#i|7252LE46{EfmH0xFk*Sf5VsdvluU!zTUTn{0#`4jS)$b9$c+{}*NZPs(fz zEA|vHgvdS6|Nlw9QjZ~I-b*m+=JeXgci*Si|D4Xiz;gbJYWyeFU#Iu~@n-n_E)L!3HEN&baUbsWML&$B+ufw+EOPs6^*=1ucjKhMZm>D|w=?O9dJ+O4y%uK)ChF`)7v!wQ>vhLCyo z3{C03miYft`G2DSPlx@>$#y3h7^Xh|v`PQ>CI*I%=ll()KC?SK{mHxlsO>|)X&^@p U`?OPcfi7V1boFyt=akR{0Pjaiy8r+H diff --git a/assets/sprites/equipment/padded_saddle.png b/assets/sprites/equipment/padded_saddle.png deleted file mode 100644 index babaca7d7431bdb1048e08821e3418c3c033ecbc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmeAS@N?(olHy`uVBq!ia0vp@K+MI#1|;*}T{!}zCVRR#hEy=VJ;1y`C34!akN?Zx z^`1DhyvRFwUGD8|P?Xs-Z<^Qoc}B)c?|znT&#GG1Zk>H~{ipTJ4o~CR8&2)#W0+bm z%b>+yaQgTCN7HL>PJi0?@00%jNw@d?H7jIgnEL$F^!lIEZ7$^AubZ7$`9Hem_V)W~ r3=OB4?|gf^y;GbIY{Vm|QU5s}eG&?KSZk66bRL7JtDnm{r-UW|F4SD7 diff --git a/assets/sprites/equipment/royal_saddle.png b/assets/sprites/equipment/royal_saddle.png deleted file mode 100644 index b273e559d77d8edd3fc1d1a61cda2ded3153db17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp@K+MI#1|;*}T{!}zrg*wIhEy=VJ;1y`C34!akN?Zx z^`1DhyvRFwUGD8|P?Xs-Z<^Qoc}B)c?|znT&#GG1Zk>H~{ipTJ4o~CR8&2)#W0+bm z%b>+y@N4b7Qo)`!xQa>hro^&PPQVLgt;0|MxWhlLLrf3Q_}NurdTxHWb_c pUHGV#c>&O@h9B1%LG%H8rm#PP^L!OAdjZ|Y;OXk;vd$@?2>>GyTqghk diff --git a/assets/sprites/equipment/steel_armor.png b/assets/sprites/equipment/steel_armor.png deleted file mode 100644 index 86aec59a6816b05c20ace1e55a5224a7af22f5aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^%s|Y-!3HF~bz9kil)a~mV@L%fqY1<5|3EGp2$&Xt c5Jlm@6c!q?WM9l)FAd^*y85}Sb4q9e0ND5vLjV8( diff --git a/assets/sprites/equipment/steel_helmet.png b/assets/sprites/equipment/steel_helmet.png deleted file mode 100644 index d5684985979bca2be74a7a8d4a883fd84af6798a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRY!3HGPMlP2IQhPmJ978G?-yUFIpb|Ol*vJ3n z?|M(1SzhFwye{|lHYm#MnK#XA{X8RMrFTEewr5o>Yq!q6y8hE4Mgg1Y+y5QgZg!r{ z;RD0=J^yvtc0B!?Zy3%XU~^gbeSLTQx72vChUv98r$3#^z%lP-Do~(u0ay!z!_!vg z1)mt|e@?GIS;vIlZ5SL7`&V?R|gE{yvTWrwUP*d%tcr1H%z+ ec97-=@{DsQ$V@I^suTr!gu&C*&t;ucLK6U{rEmoR diff --git a/demo_save_protection.py b/demo_save_protection.py deleted file mode 100644 index d9dcc16..0000000 --- a/demo_save_protection.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python3 -""" -Demo script showing save file integrity protection. -Demonstrates how the save system prevents tampering. -""" -import json -import os -from src.save_system import SaveSystem - - -def print_header(text): - """Print a formatted header.""" - print(f"\n{'='*60}") - print(f" {text}") - print(f"{'='*60}\n") - - -def main(): - """Run demo of save protection system.""" - demo_save_file = "demo_protected_save.json" - - print_header("Dragon Riders - Save File Protection Demo") - - # Clean up any existing demo file - if os.path.exists(demo_save_file): - os.remove(demo_save_file) - - save_system = SaveSystem(demo_save_file) - - # Step 1: Create a legitimate save - print_header("Step 1: Creating Legitimate Save") - - game_data = { - "coins": 100, - "dragons": [ - {"name": "Ember", "type": "fire", "level": 5}, - {"name": "Frost", "type": "ice", "level": 3} - ], - "inventory": [ - {"id": "ruby_shard", "quantity": 5}, - {"id": "sapphire_shard", "quantity": 3} - ] - } - - print("Original game data:") - print(json.dumps(game_data, indent=2)) - - if save_system.save(game_data): - print(f"\n[OK] Save created successfully at: {demo_save_file}") - - # Show the saved file structure (encrypted) - print("\nSaved file structure (ENCRYPTED):") - with open(demo_save_file, 'r') as f: - saved_content = json.load(f) - print(json.dumps(saved_content, indent=2)) - print("\n[!] Notice: The data is encrypted and cannot be read or edited!") - - # Step 2: Load the legitimate save - print_header("Step 2: Loading Legitimate Save") - - loaded_data = save_system.load() - if loaded_data: - print(f"[OK] Save loaded successfully from: {demo_save_file}") - print(f"Coins: {loaded_data['coins']}") - print(f"Dragons: {len(loaded_data['dragons'])}") - - # Step 3: Attempt to tamper with the save - print_header("Step 3: Attempting to Tamper with Save") - - print("Simulating cheater trying to decrypt/edit save file...") - print("Corrupting the encrypted data...") - - # Read the save file - with open(demo_save_file, 'r') as f: - tampered_content = json.load(f) - - # Tamper with encrypted data (simulating someone trying to hack it) - # Corrupt the encrypted string - tampered_content["_encrypted"] = tampered_content["_encrypted"][:-20] + "HACKED_DATA_HERE==" - - # Write back - with open(demo_save_file, 'w') as f: - json.dump(tampered_content, f, indent=2) - - print("[!] Save file has been tampered with!") - - # Step 4: Try to load tampered save - print_header("Step 4: Loading Tampered Save") - - loaded_tampered = save_system.load() - if loaded_tampered is None: - print("[OK] Tampering detected! Save rejected!") - print("The integrity check failed.") - print("Player cannot cheat by editing the save file!") - else: - print("[!] WARNING: Tampering not detected (this shouldn't happen)") - - # Step 5: Test legacy save migration - print_header("Step 5: Testing Legacy Save Migration") - - legacy_save_file = "demo_legacy_save.json" - - # Create old format save (no hash protection) - legacy_data = { - "coins": 50, - "dragons": [{"name": "OldDragon", "type": "storm", "level": 2}] - } - - print("Creating old format save (no protection):") - print(json.dumps(legacy_data, indent=2)) - - with open(legacy_save_file, 'w') as f: - json.dump(legacy_data, f, indent=2) - - # Load with new system - legacy_system = SaveSystem(legacy_save_file) - print("\nLoading legacy save with new system...") - migrated_data = legacy_system.load() - - if migrated_data: - print("[OK] Legacy save migrated successfully!") - print("Old saves are automatically upgraded to protected format.") - - # Verify migration - with open(legacy_save_file, 'r') as f: - migrated_file = json.load(f) - - if "_hash" in migrated_file and "_encrypted" in migrated_file: - print("[OK] Migration complete - save now has encryption + integrity protection!") - print("[!] Save data is now encrypted and unreadable!") - - # Cleanup - print_header("Cleanup") - for f in [demo_save_file, legacy_save_file]: - if os.path.exists(f): - os.remove(f) - print(f"Removed: {f}") - - # Summary - print_header("Summary") - print("Save File Protection Features:") - print(" [+] AES-128 encryption (Fernet)") - print(" [+] HMAC-SHA256 hash verification") - print(" [+] Data compression (zlib)") - print(" [+] Detects any unauthorized changes") - print(" [+] Automatic migration of old saves") - print(" [+] Secret key makes tampering difficult") - print(" [+] Time-safe hash comparison (prevents timing attacks)") - print("\nPlayers cannot cheat by editing save files!") - print("The save data is encrypted and completely unreadable.") - print("The game will reject any tampered or corrupted saves.\n") - - -if __name__ == "__main__": - main() diff --git a/DEPLOYMENT.md b/docs/DEPLOYMENT.md similarity index 100% rename from DEPLOYMENT.md rename to docs/DEPLOYMENT.md diff --git a/REWARD_CONSTANTS.md b/docs/REWARD_CONSTANTS.md similarity index 100% rename from REWARD_CONSTANTS.md rename to docs/REWARD_CONSTANTS.md diff --git a/flake.nix b/flake.nix index f46ee09..e2219e6 100644 --- a/flake.nix +++ b/flake.nix @@ -7,66 +7,122 @@ outputs = { self, nixpkgs, ... }: let - system = "x86_64-linux"; - pkgs = nixpkgs.legacyPackages.${system}; + # Support multiple systems + systems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + + # Helper function to generate an attribute set for all systems + forAllSystems = nixpkgs.lib.genAttrs systems; + + # Helper to get nixpkgs for a system + nixpkgsFor = forAllSystems (system: import nixpkgs { + inherit system; + }); in { - devShells.${system}.default = pkgs.mkShell { - packages = [ - pkgs.uv - pkgs.python312 # uv respects this and uses it - ]; + devShells = forAllSystems (system: + let + pkgs = nixpkgsFor.${system}; + isDarwin = pkgs.stdenv.isDarwin; + isLinux = pkgs.stdenv.isLinux; + + # Base packages available on all systems + basePackages = [ + pkgs.uv + pkgs.python312 + ]; + + # System libraries for pygame - platform specific + linuxBuildInputs = with pkgs; [ + stdenv.cc.cc.lib + zlib + glib + SDL2 + SDL2_image + SDL2_mixer + SDL2_ttf + libpng + libjpeg + portmidi + freetype + alsa-lib + # X11 and graphics libraries + xorg.libX11 + xorg.libXext + xorg.libXcursor + xorg.libXrandr + xorg.libXi + xorg.libXinerama + xorg.libXxf86vm + libGL + libGLU + ]; + + darwinBuildInputs = with pkgs; [ + zlib + SDL2 + SDL2_image + SDL2_mixer + SDL2_ttf + libpng + libjpeg + portmidi + freetype + ] ++ (with pkgs.darwin.apple_sdk.frameworks; [ + Cocoa + CoreAudio + CoreVideo + IOKit + ForceFeedback + Carbon + AppKit + OpenGL + ]); + + buildInputs = if isDarwin then darwinBuildInputs else linuxBuildInputs; - # System libraries required by pygame - buildInputs = with pkgs; [ - stdenv.cc.cc.lib - zlib - glib - SDL2 - SDL2_image - SDL2_mixer - SDL2_ttf - libpng - libjpeg - portmidi - freetype - alsa-lib - # X11 and graphics libraries - xorg.libX11 - xorg.libXext - xorg.libXcursor - xorg.libXrandr - xorg.libXi - xorg.libXinerama - xorg.libXxf86vm - libGL - libGLU - ]; + # Library path for Linux + linuxLibraryPath = pkgs.lib.makeLibraryPath [ + pkgs.stdenv.cc.cc.lib + pkgs.zlib + pkgs.glib + pkgs.SDL2 + pkgs.SDL2_image + pkgs.SDL2_mixer + pkgs.SDL2_ttf + pkgs.libpng + pkgs.libjpeg + pkgs.portmidi + pkgs.freetype + pkgs.alsa-lib + pkgs.xorg.libX11 + pkgs.xorg.libXext + pkgs.xorg.libXcursor + pkgs.xorg.libXrandr + pkgs.xorg.libXi + pkgs.xorg.libXinerama + pkgs.xorg.libXxf86vm + pkgs.libGL + pkgs.libGLU + ]; + in { + default = pkgs.mkShell { + packages = basePackages; + buildInputs = buildInputs; - # Set up library path for dynamic linking - LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ - pkgs.stdenv.cc.cc.lib - pkgs.zlib - pkgs.glib - pkgs.SDL2 - pkgs.SDL2_image - pkgs.SDL2_mixer - pkgs.SDL2_ttf - pkgs.libpng - pkgs.libjpeg - pkgs.portmidi - pkgs.freetype - pkgs.alsa-lib - # X11 and graphics libraries - pkgs.xorg.libX11 - pkgs.xorg.libXext - pkgs.xorg.libXcursor - pkgs.xorg.libXrandr - pkgs.xorg.libXi - pkgs.xorg.libXinerama - pkgs.xorg.libXxf86vm - pkgs.libGL - pkgs.libGLU - ]; - }; + # Set up library path for dynamic linking (Linux only) + shellHook = if isLinux then '' + export LD_LIBRARY_PATH="${linuxLibraryPath}:$LD_LIBRARY_PATH" + '' else '' + # macOS uses DYLD_LIBRARY_PATH, but it's generally not needed + # as the Nix store paths are already handled correctly + export DYLD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath buildInputs}:$DYLD_LIBRARY_PATH" + ''; + }; + } + ); }; } diff --git a/generate_all_sprites.sh b/generate_all_sprites.sh deleted file mode 100755 index 3266968..0000000 --- a/generate_all_sprites.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -# Master script for complete sprite generation pipeline -# 1. Generates raw sprites using Python -# 2. Converts them to pixelmapped sprites using spritefusion -# 3. Outputs final game-ready sprites to assets folder - -set -e # Exit on error - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color - -# Directories -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SPRITEFUSION_DIR="$SCRIPT_DIR/spritefusion" -RAW_SPRITES_DIR="$SCRIPT_DIR/assets/sprites_raw" -FINAL_SPRITES_DIR="$SCRIPT_DIR/assets/sprites" - -echo -e "${CYAN}╔════════════════════════════════════════════╗${NC}" -echo -e "${CYAN}║ Dragon Game - Sprite Generation Pipeline ║${NC}" -echo -e "${CYAN}╚════════════════════════════════════════════╝${NC}" -echo "" - -# Step 1: Generate raw sprites with Python -echo -e "${BLUE}[1/3] Generating raw sprites...${NC}" -echo "" - -# Create raw sprites directory -mkdir -p "$RAW_SPRITES_DIR/dragons" -mkdir -p "$RAW_SPRITES_DIR/equipment" - -# Generate dragon sprites -echo -e "${YELLOW} → Generating dragon sprites...${NC}" -python -m src.dragon_sprite_generator -if [ $? -ne 0 ]; then - echo -e "${RED}Error: Failed to generate dragon sprites${NC}" - exit 1 -fi -echo -e "${GREEN} ✓ Dragon sprites generated${NC}" -echo "" - -# Generate equipment sprites -echo -e "${YELLOW} → Generating equipment sprites...${NC}" -python -m src.equipment_sprite_generator -if [ $? -ne 0 ]; then - echo -e "${RED}Error: Failed to generate equipment sprites${NC}" - exit 1 -fi -echo -e "${GREEN} ✓ Equipment sprites generated${NC}" -echo "" - -echo -e "${GREEN}✓ Step 1 Complete: Raw sprites generated${NC}" -echo " Location: $RAW_SPRITES_DIR" -echo "" - -# Step 2: Build spritefusion -echo -e "${BLUE}[2/3] Building spritefusion...${NC}" -echo "" - -if [ ! -d "$SPRITEFUSION_DIR" ]; then - echo -e "${RED}Error: spritefusion directory not found at $SPRITEFUSION_DIR${NC}" - exit 1 -fi - -cd "$SPRITEFUSION_DIR" -cargo build --release --quiet -if [ $? -ne 0 ]; then - echo -e "${RED}Error: Failed to build spritefusion${NC}" - exit 1 -fi -echo -e "${GREEN}✓ Step 2 Complete: spritefusion built${NC}" -echo "" - -# Step 3: Convert sprites -echo -e "${BLUE}[3/3] Converting sprites to pixelmapped format...${NC}" -echo "" - -# Create final sprites directories -mkdir -p "$FINAL_SPRITES_DIR/dragons" -mkdir -p "$FINAL_SPRITES_DIR/equipment" - -# Convert dragon sprites -echo -e "${YELLOW} → Converting dragon sprites...${NC}" -dragon_count=0 -for input_file in "$RAW_SPRITES_DIR/dragons"/*.png; do - if [ -f "$input_file" ]; then - filename=$(basename "$input_file") - output_file="$FINAL_SPRITES_DIR/dragons/$filename" - - cargo run --release --quiet -- "$input_file" "$output_file" 2>/dev/null - if [ $? -eq 0 ]; then - ((dragon_count++)) - else - echo -e " ${RED}✗ Failed: $filename${NC}" - fi - fi -done -echo -e "${GREEN} ✓ Converted $dragon_count dragon sprites${NC}" -echo "" - -# Convert equipment sprites -echo -e "${YELLOW} → Converting equipment sprites...${NC}" -equipment_count=0 -for input_file in "$RAW_SPRITES_DIR/equipment"/*.png; do - if [ -f "$input_file" ]; then - filename=$(basename "$input_file") - output_file="$FINAL_SPRITES_DIR/equipment/$filename" - - cargo run --release --quiet -- "$input_file" "$output_file" 2>/dev/null - if [ $? -eq 0 ]; then - ((equipment_count++)) - else - echo -e " ${RED}✗ Failed: $filename${NC}" - fi - fi -done -echo -e "${GREEN} ✓ Converted $equipment_count equipment sprites${NC}" -echo "" - -echo -e "${GREEN}✓ Step 3 Complete: Sprites converted${NC}" -echo "" - -# Summary -echo -e "${CYAN}╔════════════════════════════════════════════╗${NC}" -echo -e "${CYAN}║ Pipeline Complete! ✓ ║${NC}" -echo -e "${CYAN}╚════════════════════════════════════════════╝${NC}" -echo "" -echo -e "${GREEN}Summary:${NC}" -echo " • Dragon sprites: $dragon_count" -echo " • Equipment sprites: $equipment_count" -echo " • Total: $((dragon_count + equipment_count))" -echo "" -echo -e "${YELLOW}Directories:${NC}" -echo " • Raw sprites: $RAW_SPRITES_DIR" -echo " • Final sprites: $FINAL_SPRITES_DIR" -echo "" -echo -e "${GREEN}Game-ready sprites are in: assets/sprites/${NC}" diff --git a/generate_sounds.py b/generate_sounds.py deleted file mode 100644 index 46972e1..0000000 --- a/generate_sounds.py +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env python3 -"""Generate 8-bit style sound effects for the game.""" - -import numpy as np -import os -from scipy.io import wavfile - -def generate_sine_wave(frequency, duration, sample_rate=44100, amplitude=0.3): - """Generate a sine wave.""" - t = np.linspace(0, duration, int(sample_rate * duration), False) - wave = amplitude * np.sin(2 * np.pi * frequency * t) - return wave - -def generate_square_wave(frequency, duration, sample_rate=44100, amplitude=0.3): - """Generate a square wave (more 8-bit style).""" - t = np.linspace(0, duration, int(sample_rate * duration), False) - wave = amplitude * np.sign(np.sin(2 * np.pi * frequency * t)) - return wave - -def generate_triangle_wave(frequency, duration, sample_rate=44100, amplitude=0.3): - """Generate a triangle wave.""" - t = np.linspace(0, duration, int(sample_rate * duration), False) - wave = amplitude * (2 * np.abs(2 * ((frequency * t) % 1) - 1) - 1) - return wave - -def apply_envelope(wave, attack=0.01, decay=0.05, sustain=0.7, release=0.1): - """Apply ADSR envelope to wave.""" - length = len(wave) - envelope = np.ones(length) - - sample_rate = 44100 - attack_samples = int(attack * sample_rate) - decay_samples = int(decay * sample_rate) - release_samples = int(release * sample_rate) - - # Attack - if attack_samples > 0: - envelope[:attack_samples] = np.linspace(0, 1, attack_samples) - - # Decay - if decay_samples > 0: - envelope[attack_samples:attack_samples + decay_samples] = np.linspace(1, sustain, decay_samples) - - # Sustain - envelope[attack_samples + decay_samples:length - release_samples] = sustain - - # Release - if release_samples > 0: - envelope[length - release_samples:] = np.linspace(sustain, 0, release_samples) - - return wave * envelope - -def generate_egg_click(): - """Generate a tap/knock sound for egg clicking.""" - duration = 0.08 - sample_rate = 44100 - - t = np.linspace(0, duration, int(sample_rate * duration), False) - - # Mix of low frequency tone and noise for realistic tap - # Low thump component - low_freq = 200 - thump = 0.4 * np.sin(2 * np.pi * low_freq * t) - - # Higher frequency for initial attack - high_freq = 800 - click = 0.3 * np.sin(2 * np.pi * high_freq * t) - - # Noise component for texture - noise = np.random.uniform(-0.15, 0.15, len(t)) - - # Combine with different envelopes - thump_env = np.exp(-t * 20) - click_env = np.exp(-t * 50) # Quick attack/decay - noise_env = np.exp(-t * 40) - - wave = (thump * thump_env + click * click_env + noise * noise_env) - - # Very sharp envelope for percussive sound - master_env = np.exp(-t * 25) - wave = wave * master_env - - return (wave * 32767).astype(np.int16) - -def generate_egg_crack(): - """Generate a cracking sound for egg progress.""" - duration = 0.2 - sample_rate = 44100 - - # Noise with pitch - t = np.linspace(0, duration, int(sample_rate * duration), False) - - # Mix of noise and tone - noise = np.random.uniform(-0.2, 0.2, len(t)) - tone = 0.2 * np.sign(np.sin(2 * np.pi * 400 * t)) - - wave = noise + tone - - # Sharp attack and decay - envelope = np.exp(-t * 12) - wave = wave * envelope - - return (wave * 32767).astype(np.int16) - -def generate_egg_hatch(): - """Generate a hatching success sound.""" - duration = 0.5 - sample_rate = 44100 - - # Rising pitch arpeggio - notes = [523, 659, 784, 1047] # C5, E5, G5, C6 - note_duration = duration / len(notes) - - wave = np.array([]) - for freq in notes: - t = np.linspace(0, note_duration, int(sample_rate * note_duration), False) - note = 0.3 * np.sign(np.sin(2 * np.pi * freq * t)) - - # Envelope for each note - envelope = np.exp(-t * 8) - note = note * envelope - wave = np.concatenate([wave, note]) - - return (wave * 32767).astype(np.int16) - -def generate_button_click(): - """Generate a UI button click sound.""" - duration = 0.08 - sample_rate = 44100 - - t = np.linspace(0, duration, int(sample_rate * duration), False) - - # High pitched blip - wave = 0.25 * np.sign(np.sin(2 * np.pi * 1200 * t)) - - # Very short envelope - envelope = np.exp(-t * 30) - wave = wave * envelope - - return (wave * 32767).astype(np.int16) - -def generate_coin_collect(): - """Generate a coin/gold collection sound.""" - duration = 0.3 - sample_rate = 44100 - - # Two-tone beep - t1 = np.linspace(0, 0.1, int(sample_rate * 0.1), False) - wave1 = 0.3 * np.sign(np.sin(2 * np.pi * 800 * t1)) - - t2 = np.linspace(0, 0.2, int(sample_rate * 0.2), False) - wave2 = 0.3 * np.sign(np.sin(2 * np.pi * 1200 * t2)) - - # Envelopes - env1 = np.exp(-t1 * 15) - env2 = np.exp(-t2 * 10) - - wave = np.concatenate([wave1 * env1, wave2 * env2]) - - return (wave * 32767).astype(np.int16) - -def generate_purchase(): - """Generate a purchase/buy sound.""" - duration = 0.4 - sample_rate = 44100 - - # Happy three-note arpeggio - notes = [659, 784, 988] # E5, G5, B5 - note_duration = duration / len(notes) - - wave = np.array([]) - for freq in notes: - t = np.linspace(0, note_duration, int(sample_rate * note_duration), False) - note = 0.25 * np.sign(np.sin(2 * np.pi * freq * t)) - envelope = np.exp(-t * 6) - wave = np.concatenate([wave, note * envelope]) - - return (wave * 32767).astype(np.int16) - -def generate_error(): - """Generate an error/cannot do sound.""" - duration = 0.3 - sample_rate = 44100 - - # Low buzzing sound - t = np.linspace(0, duration, int(sample_rate * duration), False) - wave = 0.3 * np.sign(np.sin(2 * np.pi * 150 * t)) - - # Pulsing effect - pulse = 0.5 + 0.5 * np.sin(2 * np.pi * 15 * t) - wave = wave * pulse - - envelope = np.exp(-t * 5) - wave = wave * envelope - - return (wave * 32767).astype(np.int16) - -def generate_dragon_chirp(): - """Generate a cute dragon chirp sound.""" - duration = 0.25 - sample_rate = 44100 - - # Quick frequency sweep upward - t = np.linspace(0, duration, int(sample_rate * duration), False) - freq_start = 600 - freq_end = 1000 - frequency = np.linspace(freq_start, freq_end, len(t)) - - wave = 0.25 * np.sign(np.sin(2 * np.pi * frequency * t)) - - envelope = np.exp(-t * 10) - wave = wave * envelope - - return (wave * 32767).astype(np.int16) - -def main(): - """Generate all sound effects.""" - output_dir = "assets/sounds" - os.makedirs(output_dir, exist_ok=True) - - sample_rate = 44100 - - sounds = { - "egg_click": generate_egg_click(), - "egg_crack": generate_egg_crack(), - "egg_hatch": generate_egg_hatch(), - "button_click": generate_button_click(), - "coin_collect": generate_coin_collect(), - "purchase": generate_purchase(), - "error": generate_error(), - "dragon_chirp": generate_dragon_chirp(), - } - - print("Generating 8-bit sound effects...") - for name, wave in sounds.items(): - filepath = os.path.join(output_dir, f"{name}.wav") - wavfile.write(filepath, sample_rate, wave) - print(f"✓ Generated: {filepath}") - - print(f"\n✓ Successfully generated {len(sounds)} sound effects!") - -if __name__ == "__main__": - main() diff --git a/run.sh b/run.sh deleted file mode 100755 index 76574a1..0000000 --- a/run.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -# Run DragonRider game in Nix development environment - -cd "$(dirname "$0")" - -echo "🐉 Starting DragonRider..." - -# Ensure display environment variables are available -export DISPLAY="${DISPLAY:-:0}" - -# Run the game with all necessary environment variables -nix develop --command bash -c " - export DISPLAY='$DISPLAY' - export XDG_SESSION_TYPE='$XDG_SESSION_TYPE' - export XAUTHORITY='$XAUTHORITY' - source .venv/bin/activate - python run_game.py -" diff --git a/convert_existing_sprites.sh b/spritefusion.sh similarity index 100% rename from convert_existing_sprites.sh rename to spritefusion.sh diff --git a/verify_sprites.py b/verify_sprites.py deleted file mode 100644 index 59841d4..0000000 --- a/verify_sprites.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Verify that dragon and equipment sprites are loaded correctly.""" -import pygame - -pygame.init() -pygame.display.set_mode((1, 1)) # Minimal display for testing - -from src.sprite_manager import SpriteManager - -print("=" * 60) -print("SPRITE VERIFICATION") -print("=" * 60) - -sm = SpriteManager() - -print("\n🐉 DRAGON SPRITES:") -print("-" * 60) -dragon_types = ['fire', 'ice', 'forest', 'storm', 'shadow'] -stages = ['egg', 'hatchling', 'juvenile', 'adult', 'elder'] - -for dtype in dragon_types: - print(f"\n{dtype.upper()} Dragons:") - for stage in stages: - sprite = sm.get_sprite(dtype, stage) - print(f" ✓ {stage:12s} - {sprite.get_size()}") - -print("\n" + "=" * 60) -print("⚔️ EQUIPMENT SPRITES:") -print("-" * 60) - -equipment_count = len(sm.equipment_cache) -print(f"\nTotal equipment items: {equipment_count}") - -if equipment_count > 0: - print("\nLoaded items:") - for item_id in sorted(sm.equipment_cache.keys()): - sprite = sm.get_equipment_sprite(item_id) - print(f" ✓ {item_id:20s} - {sprite.get_size()}") -else: - print(" ⚠ No equipment sprites found!") - -print("\n" + "=" * 60) -print("VERIFICATION COMPLETE") -print("=" * 60) \ No newline at end of file