diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Idle0.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Idle0.png new file mode 100644 index 0000000..367733f Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Idle0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run0.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run0.png new file mode 100644 index 0000000..f1df19a Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run1.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run1.png new file mode 100644 index 0000000..1ad16a3 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run1.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run2.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run2.png new file mode 100644 index 0000000..2a0c1c3 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run2.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run3.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run3.png new file mode 100644 index 0000000..561d9e8 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run3.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run4.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run4.png new file mode 100644 index 0000000..9af1511 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run4.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run5.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run5.png new file mode 100644 index 0000000..7808a21 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run5.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run6.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run6.png new file mode 100644 index 0000000..e484a9f Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run6.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run7.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run7.png new file mode 100644 index 0000000..974bd9a Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run7.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run8.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run8.png new file mode 100644 index 0000000..e0d1360 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run8.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run9.png b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run9.png new file mode 100644 index 0000000..9ab32f6 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male1/Male_1_Run9.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Idle0.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Idle0.png new file mode 100644 index 0000000..955eb9e Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Idle0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run0.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run0.png new file mode 100644 index 0000000..8704ba7 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run1.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run1.png new file mode 100644 index 0000000..dfed4f0 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run1.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run2.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run2.png new file mode 100644 index 0000000..db9a024 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run2.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run3.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run3.png new file mode 100644 index 0000000..dc40232 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run3.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run4.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run4.png new file mode 100644 index 0000000..681b4c1 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run4.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run5.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run5.png new file mode 100644 index 0000000..2639c69 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run5.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run6.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run6.png new file mode 100644 index 0000000..030a630 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run6.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run7.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run7.png new file mode 100644 index 0000000..e7a47fb Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run7.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run8.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run8.png new file mode 100644 index 0000000..fa7a55f Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run8.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run9.png b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run9.png new file mode 100644 index 0000000..61ab8f2 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male2/Male_2_Run9.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Idle0.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Idle0.png new file mode 100644 index 0000000..a089ebc Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Idle0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run0.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run0.png new file mode 100644 index 0000000..2352da1 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run1.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run1.png new file mode 100644 index 0000000..ce71eb5 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run1.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run2.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run2.png new file mode 100644 index 0000000..75727e5 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run2.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run3.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run3.png new file mode 100644 index 0000000..6572f25 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run3.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run4.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run4.png new file mode 100644 index 0000000..30a3331 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run4.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run5.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run5.png new file mode 100644 index 0000000..add7261 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run5.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run6.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run6.png new file mode 100644 index 0000000..1cda4c6 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run6.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run7.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run7.png new file mode 100644 index 0000000..0e3e5c6 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run7.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run8.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run8.png new file mode 100644 index 0000000..458a8c5 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run8.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run9.png b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run9.png new file mode 100644 index 0000000..fa6c903 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male3/Male_3_Run9.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Idle0.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Idle0.png new file mode 100644 index 0000000..e25a05c Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Idle0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run0.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run0.png new file mode 100644 index 0000000..6aca4a1 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run1.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run1.png new file mode 100644 index 0000000..77af251 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run1.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run2.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run2.png new file mode 100644 index 0000000..4c0793e Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run2.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run3.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run3.png new file mode 100644 index 0000000..47731a4 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run3.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run4.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run4.png new file mode 100644 index 0000000..71db17b Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run4.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run5.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run5.png new file mode 100644 index 0000000..9394ae4 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run5.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run6.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run6.png new file mode 100644 index 0000000..35b6023 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run6.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run7.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run7.png new file mode 100644 index 0000000..51661e5 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run7.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run8.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run8.png new file mode 100644 index 0000000..b3ace8b Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run8.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run9.png b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run9.png new file mode 100644 index 0000000..7e73cbb Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male4/Male_4_Run9.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Idle0.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Idle0.png new file mode 100644 index 0000000..b0d934f Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Idle0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run0.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run0.png new file mode 100644 index 0000000..00992e2 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run1.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run1.png new file mode 100644 index 0000000..387a1e9 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run1.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run2.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run2.png new file mode 100644 index 0000000..7ca2c1e Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run2.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run3.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run3.png new file mode 100644 index 0000000..e5edaea Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run3.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run4.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run4.png new file mode 100644 index 0000000..b7db454 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run4.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run5.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run5.png new file mode 100644 index 0000000..b06a8c1 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run5.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run6.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run6.png new file mode 100644 index 0000000..c95a889 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run6.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run7.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run7.png new file mode 100644 index 0000000..b90eaf6 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run7.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run8.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run8.png new file mode 100644 index 0000000..fc15715 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run8.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run9.png b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run9.png new file mode 100644 index 0000000..9c9130d Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male5/Male_5_Run9.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Idle0.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Idle0.png new file mode 100644 index 0000000..ea00932 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Idle0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run0.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run0.png new file mode 100644 index 0000000..1b35429 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run1.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run1.png new file mode 100644 index 0000000..5ca61d2 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run1.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run2.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run2.png new file mode 100644 index 0000000..bae055d Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run2.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run3.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run3.png new file mode 100644 index 0000000..42ef2d2 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run3.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run4.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run4.png new file mode 100644 index 0000000..ccc01d0 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run4.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run5.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run5.png new file mode 100644 index 0000000..5eb0044 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run5.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run6.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run6.png new file mode 100644 index 0000000..28c67aa Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run6.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run7.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run7.png new file mode 100644 index 0000000..c3b786c Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run7.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run8.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run8.png new file mode 100644 index 0000000..87c0eb1 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run8.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run9.png b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run9.png new file mode 100644 index 0000000..1ee63f2 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male6/Male_6_Run9.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Idle0.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Idle0.png new file mode 100644 index 0000000..9342287 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Idle0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run0.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run0.png new file mode 100644 index 0000000..aa1e7ee Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run0.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run1.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run1.png new file mode 100644 index 0000000..833597d Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run1.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run2.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run2.png new file mode 100644 index 0000000..cc730d8 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run2.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run3.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run3.png new file mode 100644 index 0000000..c2d3e67 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run3.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run4.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run4.png new file mode 100644 index 0000000..65209bb Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run4.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run5.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run5.png new file mode 100644 index 0000000..19a043e Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run5.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run6.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run6.png new file mode 100644 index 0000000..ac186b9 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run6.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run7.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run7.png new file mode 100644 index 0000000..2185a5e Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run7.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run8.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run8.png new file mode 100644 index 0000000..a0813ae Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run8.png differ diff --git a/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run9.png b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run9.png new file mode 100644 index 0000000..4d73d90 Binary files /dev/null and b/html/assets/kenney/iso-dungeon/characters/male7/Male_7_Run9.png differ diff --git a/html/js/render/assetPacks.js b/html/js/render/assetPacks.js index ae0a94e..a1a2118 100644 --- a/html/js/render/assetPacks.js +++ b/html/js/render/assetPacks.js @@ -189,32 +189,39 @@ return out; }; + function isoMale(n) { + var base = 'assets/kenney/iso-dungeon/characters/male' + n + '/Male_' + n + '_'; + var run = []; + for (var i = 0; i < 10; i++) run.push(base + 'Run' + i + '.png'); + return { + idle: base + 'Idle0.png', + run: run, + imageW: 48, + imageH: 92 + }; + } + RK.isoAssets = { pack: 'iso-dungeon', tile: { w: 84, h: 42, imageW: 92, imageH: 184 }, tiles: { floor: 'assets/kenney/iso-dungeon/tiles/planks_S.png', - wall: 'assets/kenney/iso-dungeon/tiles/stoneWall_S.png', + wall: 'assets/kenney/iso-dungeon/tiles/stoneWallHalf_S.png', bar: 'assets/kenney/iso-dungeon/tiles/barrelsStacked_S.png', table: 'assets/kenney/iso-dungeon/tiles/chestClosed_S.png', fallback: 'assets/kenney/iso-dungeon/tiles/planks_S.png' }, - character: { - idle: 'assets/kenney/iso-dungeon/characters/male0/Male_0_Idle0.png', - run: [ - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run0.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run1.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run2.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run3.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run4.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run5.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run6.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run7.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run8.png', - 'assets/kenney/iso-dungeon/characters/male0/Male_0_Run9.png' - ], - imageW: 74, - imageH: 148 + character: isoMale(0), + characters: { + fallback: isoMale(0), + 'char-villager': isoMale(0), + 'char-elder': isoMale(1), + 'char-barbarian': isoMale(2), + 'char-monk': isoMale(3), + 'char-ranger': isoMale(4), + 'char-bard': isoMale(5), + 'char-rogue': isoMale(6), + 'char-merchant': isoMale(7) } }; diff --git a/html/js/render/charCustomize.js b/html/js/render/charCustomize.js index 923e583..e282bb3 100644 --- a/html/js/render/charCustomize.js +++ b/html/js/render/charCustomize.js @@ -7,6 +7,8 @@ var DEFAULT_EQUIPMENT = { body: 'none', head: 'none', shield: 'none', weapon: 'none' }; var DEFAULT_COLORS = { base: 'none', skin: 'natural', hair: 'copper', body: 'none', head: 'none', shield: 'none', weapon: 'none' }; + var thumbImages = {}; + var thumbBounds = {}; function cloneEquipment(eq) { eq = eq || {}; @@ -110,8 +112,169 @@ } catch (_) { return null; } }; - function drawBaseThumb(ctx, a, draft, onReady) { + function projectionForMode(mode) { + if (mode === 'iso' || mode === '3d' || mode === 'ascii') return mode; + return 'topdown'; + } + + function hasIsoCharacter(a) { + return !!(a && a.kind === 'char' && RK.isoAssets && RK.isoAssets.characters && RK.isoAssets.characters[a.id]); + } + + function appearanceVisibleInProjection(a, projection) { + if (!a) return false; + if (a.kind === 'color') return true; + if (projection === 'topdown') return a.kind === 'char' || a.kind === 'skin'; + if (projection === 'iso') return hasIsoCharacter(a); + if (projection === '3d') return a.kind === 'model3d'; + return false; + } + + function loadThumbImage(url, onReady) { + if (!url) return null; + if (thumbImages[url]) return thumbImages[url]; + var rec = thumbImages[url] = { ready: false, error: false, img: new Image() }; + rec.img.onload = function () { rec.ready = true; if (onReady) onReady(); }; + rec.img.onerror = function () { rec.error = true; }; + rec.img.src = url; + return rec; + } + + function tintColorForThumb(a, draft) { + var source = {}; + var d = draft || {}; + for (var dk in d) source[dk] = d[dk]; + source.avatar = a.id; + if (a.kind === 'color') return a.color; + if (RK.avatarVisuals && RK.avatarVisuals.tintColorFor) return RK.avatarVisuals.tintColorFor(source, '#9aa4b2'); + return '#9aa4b2'; + } + + function isoCharacterForThumb(a, draft) { + var source = {}; + var d = draft || {}; + for (var dk in d) source[dk] = d[dk]; + source.avatar = a.id; + if (RK.avatarVisuals && RK.avatarVisuals.resolve) { + var visual = RK.avatarVisuals.resolve(source, { projection: 'iso', context: 'customizer' }); + if (visual && visual.character) return visual.character; + } + var chars = RK.isoAssets && RK.isoAssets.characters; + return (chars && (chars[a.id] || chars.fallback)) || (RK.isoAssets && RK.isoAssets.character) || null; + } + + function imageBounds(img) { + var key = img && img.src; + if (!img || !key) return null; + if (thumbBounds[key]) return thumbBounds[key]; + var w = img.naturalWidth || img.width; + var h = img.naturalHeight || img.height; + var cv = document.createElement('canvas'); + cv.width = w; + cv.height = h; + var ctx = cv.getContext('2d'); + ctx.drawImage(img, 0, 0); + var data = ctx.getImageData(0, 0, w, h).data; + var minX = w, minY = h, maxX = -1, maxY = -1; + for (var y = 0; y < h; y++) { + for (var x = 0; x < w; x++) { + if (data[(y * w + x) * 4 + 3] < 8) continue; + if (x < minX) minX = x; + if (y < minY) minY = y; + if (x > maxX) maxX = x; + if (y > maxY) maxY = y; + } + } + thumbBounds[key] = maxX < minX ? { x: 0, y: 0, w: w, h: h } : { x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1 }; + return thumbBounds[key]; + } + + function drawTintedImage(ctx, img, bounds, x, y, w, h, tint) { + bounds = bounds || { x: 0, y: 0, w: img.naturalWidth || img.width, h: img.naturalHeight || img.height }; + if (!tint) { + ctx.drawImage(img, bounds.x, bounds.y, bounds.w, bounds.h, x, y, w, h); + return; + } + var cv = document.createElement('canvas'); + cv.width = bounds.w; + cv.height = bounds.h; + var tctx = cv.getContext('2d'); + tctx.drawImage(img, bounds.x, bounds.y, bounds.w, bounds.h, 0, 0, bounds.w, bounds.h); + tctx.globalCompositeOperation = 'source-atop'; + tctx.globalAlpha = 0.42; + tctx.fillStyle = tint; + tctx.fillRect(0, 0, cv.width, cv.height); + tctx.globalAlpha = 1; + tctx.globalCompositeOperation = 'source-over'; + ctx.drawImage(cv, x, y, w, h); + } + + function drawProjectionThumb(ctx, a, draft, projection, onReady) { + var color = tintColorForThumb(a, draft); ctx.clearRect(0, 0, 72, 80); + if (projection === 'ascii') { + ctx.fillStyle = color || '#9aa4b2'; + ctx.font = '42px monospace'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText('@', 36, 43); + return; + } + if (projection === 'iso') { + ctx.imageSmoothingEnabled = true; + ctx.fillStyle = '#705842'; + ctx.beginPath(); + ctx.moveTo(36, 54); + ctx.lineTo(62, 42); + ctx.lineTo(36, 30); + ctx.lineTo(10, 42); + ctx.closePath(); + ctx.fill(); + ctx.strokeStyle = 'rgba(255,255,255,0.22)'; + ctx.stroke(); + var ch = isoCharacterForThumb(a, draft); + var rec = loadThumbImage(ch && ch.idle, onReady); + if (rec && rec.ready) { + var b = imageBounds(rec.img); + var dh = 52; + var dw = dh * (b.w / b.h); + drawTintedImage(ctx, rec.img, b, 36 - dw / 2, 74 - dh, dw, dh, color); + } else { + ctx.fillStyle = color || '#9aa4b2'; + ctx.beginPath(); + ctx.ellipse(36, 37, 8, 16, 0, 0, Math.PI * 2); + ctx.fill(); + ctx.fillStyle = '#0a0c0f'; + ctx.fillRect(32, 34, 8, 3); + } + return; + } + if (projection === '3d') { + ctx.imageSmoothingEnabled = true; + ctx.fillStyle = color || '#64748b'; + ctx.beginPath(); + ctx.ellipse(36, 45, 17, 24, 0, 0, Math.PI * 2); + ctx.fill(); + ctx.fillStyle = 'rgba(255,255,255,0.28)'; + ctx.beginPath(); + ctx.ellipse(29, 34, 6, 9, -0.5, 0, Math.PI * 2); + ctx.fill(); + if (a.kind === 'model3d') { + ctx.fillStyle = '#d7dbe0'; + ctx.font = '15px monospace'; + ctx.textAlign = 'center'; + ctx.fillText('3D', 36, 49); + } + return; + } + } + + function drawBaseThumb(ctx, a, draft, projection, onReady) { + ctx.clearRect(0, 0, 72, 80); + if (projection && projection !== 'topdown') { + drawProjectionThumb(ctx, a, draft, projection, onReady); + return; + } if (a.kind === 'color') { ctx.beginPath(); ctx.arc(36, 44, 21, 0, Math.PI * 2); ctx.fillStyle = a.color; ctx.fill(); @@ -163,7 +326,11 @@ cv.width = 72; cv.height = 80; cv.style.cssText = 'display:block;margin:0 auto;image-rendering:pixelated;'; var ctx = cv.getContext('2d'); - function draw() { drawBaseThumb(ctx, a, getDraft && getDraft(), draw); } + function draw() { + var d = getDraft && getDraft(); + var projection = (d && d.__projection) || 'topdown'; + drawBaseThumb(ctx, a, d, projection, draw); + } draw(); if (redraw) redraw.push(draw); return cv; @@ -266,8 +433,7 @@ } function activeProjection() { - if (selectedMode === 'iso' || selectedMode === '3d' || selectedMode === 'ascii') return selectedMode; - return 'topdown'; + return projectionForMode(selectedMode); } function ensureColorDraft() { @@ -455,7 +621,9 @@ selectedMode = mode.id; if (RK.saveMode) RK.saveMode(mode.id); markRenderMode(); + buildAvatarGrid(); renderEditor(); + redrawAll(); } function buildRenderModes() { @@ -567,26 +735,74 @@ redrawAll(); } - RK.appearances().forEach(function (a) { - var card = document.createElement('button'); - var locked = !!(RK.canUseAppearance && !RK.canUseAppearance(a)); - card.type = 'button'; - card.className = 'rk-option-card' + (locked ? ' is-locked' : ''); - if (locked) card.title = 'Premium pack - buy credits to unlock'; - card.appendChild(thumbCanvas(a, function () { return draft; }, redrawers)); - var lab = document.createElement('div'); - lab.className = 'rk-option-label'; - lab.textContent = a.label + (a.premium ? ' *' : ''); - card.appendChild(lab); - card.onclick = function () { selectAvatar(a); }; - grid.appendChild(card); - cards[a.id] = card; - }); + function visibleAppearances() { + var projection = activeProjection(); + return RK.appearances().filter(function (a) { + return appearanceVisibleInProjection(a, projection); + }); + } + + function appearanceForId(list, id) { + for (var i = 0; i < list.length; i++) if (list[i].id === id) return list[i]; + return null; + } + + function ensureVisibleAvatar() { + var list = visibleAppearances(); + if (appearanceForId(list, draft.avatar)) return; + if (!list.length) return; + draft.avatar = list[0].id; + if (RK.isChar && RK.isChar(draft.avatar)) ensureCharDraft(); + else if (draftKind() === 'model3d') { + ensureColorDraft(); + draft.equipment = cloneEquipment(DEFAULT_EQUIPMENT); + } else { + draft.tint = 'none'; + draft.equipment = cloneEquipment(DEFAULT_EQUIPMENT); + delete draft.colors; + } + } + + function buildAvatarGrid() { + ensureVisibleAvatar(); + grid.innerHTML = ''; + cards = {}; + redrawers = []; + visibleAppearances().forEach(function (a) { + var card = document.createElement('button'); + var locked = !!(RK.canUseAppearance && !RK.canUseAppearance(a)); + card.type = 'button'; + card.className = 'rk-option-card' + (locked ? ' is-locked' : ''); + if (locked) card.title = 'Premium pack - buy credits to unlock'; + card.appendChild(thumbCanvas(a, function () { + var d = {}; + for (var dk in draft) d[dk] = draft[dk]; + d.__projection = activeProjection(); + return d; + }, redrawers)); + var lab = document.createElement('div'); + lab.className = 'rk-option-label'; + lab.textContent = a.label + (a.premium ? ' *' : ''); + card.appendChild(lab); + card.onclick = function () { selectAvatar(a); }; + grid.appendChild(card); + cards[a.id] = card; + }); + mark(); + } function drawPreview() { pctx.clearRect(0, 0, preview.width, preview.height); var base = baseAppearance(draft.avatar); - if (base.kind === 'color') { + var projection = activeProjection(); + if (projection !== 'topdown') { + var temp = document.createElement('canvas'); + temp.width = 72; + temp.height = 80; + drawProjectionThumb(temp.getContext('2d'), base, draft, projection, redrawAll); + pctx.imageSmoothingEnabled = projection !== 'ascii'; + pctx.drawImage(temp, 0, 0, 72, 80, 21, 12, 108, 120); + } else if (base.kind === 'color') { pctx.beginPath(); pctx.arc(75, 86, 34, 0, Math.PI * 2); pctx.fillStyle = base.color; pctx.fill(); pctx.lineWidth = 3; pctx.strokeStyle = 'rgba(255,255,255,0.35)'; pctx.stroke(); @@ -610,10 +826,12 @@ pctx.drawImage(rec.img, 0, row * s.frameH, s.frameW, s.frameH, 75 - dw / 2, 158 - dh, dw, dh); } } else { - drawBaseThumb(pctx, base, draft, redrawAll); + drawBaseThumb(pctx, base, draft, 'topdown', redrawAll); } previewName.textContent = base.label || base.id; - previewMeta.textContent = base.premium ? 'Premium pack' : (base.kind === 'char' ? 'Customizable' : 'Free'); + previewMeta.textContent = projection !== 'topdown' + ? (projection.toUpperCase() + ' identity') + : (base.premium ? 'Premium pack' : (base.kind === 'char' ? 'Customizable' : 'Free')); } function redrawAll() { @@ -638,7 +856,7 @@ document.body.appendChild(wrap); buildRenderModes(); - mark(); + buildAvatarGrid(); renderEditor(); redrawAll(); }; diff --git a/html/js/render/isoRenderer.js b/html/js/render/isoRenderer.js index c9ce08f..2ac375e 100644 --- a/html/js/render/isoRenderer.js +++ b/html/js/render/isoRenderer.js @@ -17,6 +17,7 @@ this.ctx = this.canvas.getContext('2d'); this.cache = {}; this.tintCache = {}; + this.boundsCache = {}; this.last = {}; this.lastScene = null; this.enabled = !(root.RK && RK.canUsePack && this.assets.pack && !RK.canUsePack(this.assets.pack)); @@ -65,6 +66,40 @@ this.ctx.drawImage(img, cx - w / 2, baseY - h, w, h); }; + IsoRenderer.prototype._imageBounds = function (img) { + if (!img) return null; + var key = img.src || img._rkBoundsKey || null; + if (key && this.boundsCache[key]) return this.boundsCache[key]; + var w = img.naturalWidth || img.width; + var h = img.naturalHeight || img.height; + var cv = document.createElement('canvas'); + cv.width = w; + cv.height = h; + var ctx = cv.getContext('2d'); + ctx.drawImage(img, 0, 0); + var data = ctx.getImageData(0, 0, w, h).data; + var minX = w, minY = h, maxX = -1, maxY = -1; + for (var y = 0; y < h; y++) { + for (var x = 0; x < w; x++) { + if (data[(y * w + x) * 4 + 3] < 8) continue; + if (x < minX) minX = x; + if (y < minY) minY = y; + if (x > maxX) maxX = x; + if (y > maxY) maxY = y; + } + } + var bounds = maxX < minX ? { x: 0, y: 0, w: w, h: h } : { x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1 }; + if (key) this.boundsCache[key] = bounds; + return bounds; + }; + + IsoRenderer.prototype._drawSpriteImage = function (img, cx, baseY, h) { + var b = this._imageBounds(img); + if (!b) return; + var w = h * (b.w / b.h); + this.ctx.drawImage(img, b.x, b.y, b.w, b.h, cx - w / 2, baseY - h, w, h); + }; + IsoRenderer.prototype._tintedImage = function (img, tint) { if (!img || !tint) return img; var key = img.src + '|' + tint; @@ -80,6 +115,7 @@ ctx.fillRect(0, 0, cv.width, cv.height); ctx.globalAlpha = 1; ctx.globalCompositeOperation = 'source-over'; + cv._rkBoundsKey = key; this.tintCache[key] = cv; return cv; }; @@ -163,7 +199,7 @@ var tint = root.RK && RK.avatarVisuals && RK.avatarVisuals.tintColorFor ? RK.avatarVisuals.tintColorFor(frame.visual && frame.visual.appearance) : null; - this._drawImage(this._tintedImage(rec.img, tint), it.sx, it.sy + this.tileH * 0.95, ch.imageW || 74, ch.imageH || 148); + this._drawSpriteImage(this._tintedImage(rec.img, tint), it.sx, it.sy + this.tileH * 0.95, ch.imageH || 92); } else { ctx.beginPath(); ctx.arc(it.sx, it.sy, 8, 0, Math.PI * 2); @@ -195,6 +231,7 @@ this.ctx = null; this.cache = {}; this.tintCache = {}; + this.boundsCache = {}; this.last = {}; this.lastScene = null; }; diff --git a/html/js/render/sceneModel.js b/html/js/render/sceneModel.js index a08bd48..7beabea 100644 --- a/html/js/render/sceneModel.js +++ b/html/js/render/sceneModel.js @@ -23,6 +23,7 @@ function sceneFromTavern(state, youId) { state = state || {}; var layout = state.layout || []; + var walkable = state.walkable || null; var rows = state.rows || layout.length; var cols = state.cols || (layout[0] ? layout[0].length : 0); @@ -31,7 +32,9 @@ var srcRow = layout[y] || ''; var row = []; for (var x = 0; x < cols; x++) { - row.push(TAVERN_TILE_OF[srcRow[x]] || 'wall'); + if (layout[y]) row.push(TAVERN_TILE_OF[srcRow[x]] || 'wall'); + else if (walkable && walkable[y]) row.push(walkable[y][x] ? 'floor' : 'wall'); + else row.push('wall'); } grid.push(row); } diff --git a/html/tavern.html b/html/tavern.html index 62b50ad..6cf3c61 100644 --- a/html/tavern.html +++ b/html/tavern.html @@ -232,7 +232,11 @@ buildModebar(); setMode(RK.loadMode('tiles')); // Load the designed room (if the server is using one); re-render when ready. - if (state.roomUrl) RK.loadRoom(state.roomUrl, function () { draw(); }); + if (state.roomUrl) RK.loadRoom(state.roomUrl, function (room) { + if (room && room.desc && room.desc.walkable) state.walkable = room.desc.walkable; + rebuildScene(); + draw(); + }); setStatus('You are in the tavern.'); }); @@ -245,6 +249,7 @@ function applyFull(s) { state.layout = s.layout || []; + state.walkable = s.walkable || null; state.cols = s.cols || (state.layout[0] ? state.layout[0].length : 0); state.rows = s.rows || state.layout.length; state.occupants = s.occupants || []; diff --git a/src/multiplayer/Room.js b/src/multiplayer/Room.js index 880c3f4..4febcb7 100644 --- a/src/multiplayer/Room.js +++ b/src/multiplayer/Room.js @@ -201,6 +201,7 @@ class Room { cols: this.cols, rows: this.rows, layout: this.layout, + walkable: this.walkable, solidOccupants: this.solidOccupants, roomUrl: this.roomUrl || null }; diff --git a/src/multiplayer/appearance.js b/src/multiplayer/appearance.js index a0fe904..a6249d9 100644 --- a/src/multiplayer/appearance.js +++ b/src/multiplayer/appearance.js @@ -54,6 +54,10 @@ function isCharAvatar(id) { return includes(CHAR_AVATARS, id); } +function isModel3dAvatar(id) { + return includes(MODEL3D_AVATARS, id); +} + function isPremiumAvatar(id) { return !!AVATAR_PACKS[id]; } @@ -99,11 +103,20 @@ function normalizeAppearance(input = {}) { let avatar = input.avatar || input.id || 'default'; if (!isValidAvatar(avatar)) avatar = 'default'; - if (!isCharAvatar(avatar)) { + if (!isCharAvatar(avatar) && !isModel3dAvatar(avatar)) { return { avatar, tint: 'none', equipment: { ...DEFAULT_EQUIPMENT } }; } const colors = normalizeColors(input.colors, input.tint); + if (isModel3dAvatar(avatar)) { + return { + avatar, + tint: colors.base, + equipment: { ...DEFAULT_EQUIPMENT }, + colors + }; + } + return { avatar, tint: colors.base, @@ -129,6 +142,7 @@ module.exports = { avatarPack, isValidAvatar, isCharAvatar, + isModel3dAvatar, isPremiumAvatar, normalizeEquipment, normalizeColors, diff --git a/test/appearanceModel3d.test.js b/test/appearanceModel3d.test.js new file mode 100644 index 0000000..d3effe7 --- /dev/null +++ b/test/appearanceModel3d.test.js @@ -0,0 +1,19 @@ +const Appearance = require('../src/multiplayer/appearance'); + +describe('appearance normalization for 3D avatars', () => { + test('preserves base colors for model avatars', () => { + const ap = Appearance.normalizeAppearance({ + avatar: 'kenney-survivor-male', + tint: 'gold', + colors: { base: 'teal', skin: 'umber', hair: 'silver' }, + equipment: { body: 'mail', head: 'helm' } + }); + + expect(ap).toMatchObject({ + avatar: 'kenney-survivor-male', + tint: 'teal', + equipment: { body: 'none', head: 'none', shield: 'none', weapon: 'none' }, + colors: expect.objectContaining({ base: 'teal', skin: 'umber', hair: 'silver' }) + }); + }); +}); diff --git a/test/renderPackResolver.test.js b/test/renderPackResolver.test.js index 74f46c6..4c22709 100644 --- a/test/renderPackResolver.test.js +++ b/test/renderPackResolver.test.js @@ -82,7 +82,7 @@ describe('render pack visual resolver', () => { RK.setEntitlementSnapshot({ totalCreditsPurchased: 1 }); const iso = RK.avatarVisuals.resolve({ avatar: 'char-ranger' }, { projection: 'iso' }); expect(iso).toMatchObject({ projection: 'iso', kind: 'iso', pack: 'iso-dungeon', allowed: true }); - expect(iso.character.idle).toContain('Male_0_Idle0.png'); + expect(iso.character.idle).toContain('Male_4_Idle0.png'); const compat = RK.resolveAppearance( { appearance: { avatar: 'kenney-survivor-female' } }, @@ -95,6 +95,15 @@ describe('render pack visual resolver', () => { const RK = loadRenderKit(); expect(RK.isoAssets.tiles.floor).toContain('planks_S.png'); expect(RK.isoAssets.tiles.floor).not.toContain('stone_S.png'); + expect(RK.isoAssets.tiles.wall).toContain('stoneWallHalf_S.png'); + }); + + test('iso pack exposes only real imported character variants', () => { + const RK = loadRenderKit(); + expect(RK.isoAssets.characters['char-villager'].idle).toContain('Male_0_Idle0.png'); + expect(RK.isoAssets.characters['char-merchant'].idle).toContain('Male_7_Idle0.png'); + expect(RK.isoAssets.characters['char-wizard']).toBeUndefined(); + expect(RK.isoAssets.characters['char-goblin']).toBeUndefined(); }); test('projection visuals expose the saved base tint as a render color', () => { diff --git a/test/renderScene.test.js b/test/renderScene.test.js index 751bcc0..eabf450 100644 --- a/test/renderScene.test.js +++ b/test/renderScene.test.js @@ -35,4 +35,21 @@ describe('sceneFromTavern (render kit adapter)', () => { const s = scene.sceneFromTavern({ cols: 2, rows: 1, layout: ['?~'], occupants: [] }); expect(s.grid[0]).toEqual(['wall', 'wall']); }); + + test('uses walkability when a designed room has no ASCII layout', () => { + const s = scene.sceneFromTavern({ + cols: 3, + rows: 2, + layout: null, + walkable: [ + [true, false, true], + [false, true, true] + ], + occupants: [] + }); + expect(s.grid).toEqual([ + ['floor', 'wall', 'floor'], + ['wall', 'floor', 'floor'] + ]); + }); }); diff --git a/test/tavernRoom.test.js b/test/tavernRoom.test.js index 73e17d2..cb4d7d6 100644 --- a/test/tavernRoom.test.js +++ b/test/tavernRoom.test.js @@ -23,6 +23,20 @@ describe('Room — shared real-time engine (Tavern instance)', () => { expect(ids).toEqual(['alice', 'bob']); }); + test('full state includes walkability for designed rooms without ASCII layout', () => { + const room = new Room({ + id: 'designed', + roomData: { + cols: 2, + rows: 2, + walkable: [[true, false], [false, true]] + } + }); + const state = room.fullState(); + expect(state.layout).toBeNull(); + expect(state.walkable).toEqual([[true, false], [false, true]]); + }); + test('server-authoritative movement: a valid step moves and sets facing', () => { const room = new Room({ id: 'r' }); const occ = room.addOccupant('alice');