ok
This commit is contained in:
4760
tools/visualizers/asset_gallery_full.html
Normal file
4760
tools/visualizers/asset_gallery_full.html
Normal file
File diff suppressed because it is too large
Load Diff
445
tools/visualizers/asset_structure_overview.html
Normal file
445
tools/visualizers/asset_structure_overview.html
Normal file
@@ -0,0 +1,445 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="sl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>🇸🇮 Nova Slovenska Struktura Assetov</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 40px 20px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 48px;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.stats {
|
||||
background: rgba(255,255,255,0.15);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20px;
|
||||
padding: 30px;
|
||||
margin-bottom: 40px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.stat {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.category {
|
||||
background: rgba(255,255,255,0.10);
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 20px;
|
||||
padding: 30px;
|
||||
margin-bottom: 30px;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.category:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.category-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 2px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.category-icon {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.category-title {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.category-count {
|
||||
margin-left: auto;
|
||||
font-size: 24px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.folder-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.folder {
|
||||
background: rgba(255,255,255,0.15);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.folder:hover {
|
||||
background: rgba(255,255,255,0.25);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.folder-icon {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.folder-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.folder-name {
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.folder-files {
|
||||
font-size: 14px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.success-message {
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
border: 2px solid rgba(16, 185, 129, 0.5);
|
||||
border-radius: 15px;
|
||||
padding: 20px;
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
font-size: 32px;
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🇸🇮 Nova Slovenska Struktura Assetov</h1>
|
||||
|
||||
<div class="success-message">
|
||||
<span class="emoji">✅</span>
|
||||
Reorganizacija uspešno zaključena!
|
||||
</div>
|
||||
|
||||
<div class="stats">
|
||||
<div class="stat">
|
||||
<span class="stat-number">635</span>
|
||||
<span class="stat-label">Premaknjenih datotek</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-number">109</span>
|
||||
<span class="stat-label">Duplikatov izločenih</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-number">14</span>
|
||||
<span class="stat-label">Starih map izbrisanih</span>
|
||||
</div>
|
||||
<div class="stat">
|
||||
<span class="stat-number">11</span>
|
||||
<span class="stat-label">Scriptov updatanih</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🟦</div>
|
||||
<div class="category-title">liki/</div>
|
||||
<div class="category-count">178 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">👤</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">kai/</div>
|
||||
<div class="folder-files">157 animacij (KOMPLETNO!)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">💪</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">gronk/</div>
|
||||
<div class="folder-files">NPC spremljevalec</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">👩</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">ana/</div>
|
||||
<div class="folder-files">Izgubljena sestra</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">👥</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">npcs/</div>
|
||||
<div class="folder-files">Trgovci, kovači...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🟥</div>
|
||||
<div class="category-title">sovrazniki/</div>
|
||||
<div class="category-count">76 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🧟</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">zombiji/</div>
|
||||
<div class="folder-files">22 animacij (walk, attack, dig, idle)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">👹</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">mutanti/</div>
|
||||
<div class="folder-files">Različne mutacije zombijev</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">👾</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">bossi/</div>
|
||||
<div class="folder-files">18 boss karakterjev</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🟩</div>
|
||||
<div class="category-title">biomi/</div>
|
||||
<div class="category-count">16 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🌾</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">01_dolina_farm/</div>
|
||||
<div class="folder-files">28 terrain tiles</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🌲</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">02_temni_gozd/</div>
|
||||
<div class="folder-files">Naslednji biome</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🏚️</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">03_zapusceno_mesto/</div>
|
||||
<div class="folder-files">Urban biome</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🟨</div>
|
||||
<div class="category-title">zgradbe/</div>
|
||||
<div class="category-count">22 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🏠</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">Vse zgradbe</div>
|
||||
<div class="folder-files">barn, tent, shack, church...</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🔥</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">Props</div>
|
||||
<div class="folder-files">campfire, well, chest...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🟧</div>
|
||||
<div class="category-title">predmeti/</div>
|
||||
<div class="category-count">88 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🔨</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">orodja/</div>
|
||||
<div class="folder-files">hoe, axe, watering can (12 items)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🌱</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">semena/</div>
|
||||
<div class="folder-files">wheat seeds (6 items)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🍞</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">hrana/</div>
|
||||
<div class="folder-files">Para proizvode</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🟪</div>
|
||||
<div class="category-title">orozje/</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">⚔️</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">hladno/</div>
|
||||
<div class="folder-files">Meči, sekire (melee)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🏹</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">strelno/</div>
|
||||
<div class="folder-files">Loki, crossbowi (ranged)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🟫</div>
|
||||
<div class="category-title">rastline/</div>
|
||||
<div class="category-count">157 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🌾</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">posevki/</div>
|
||||
<div class="folder-files">30 wheat growth stages</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">🌳</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">drevesa/</div>
|
||||
<div class="folder-files">oak, pine, dead trees...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">⬜</div>
|
||||
<div class="category-title">ui/</div>
|
||||
<div class="category-count">24 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">❤️</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">UI Elements</div>
|
||||
<div class="folder-files">hearts, buttons, inventory slots...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🔵</div>
|
||||
<div class="category-title">efekti/</div>
|
||||
<div class="category-count">12 datotek</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">💧</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">voda/</div>
|
||||
<div class="folder-files">12 water animations</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div class="folder-icon">💨</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">dim/</div>
|
||||
<div class="folder-files">Smoke particles</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category">
|
||||
<div class="category-header">
|
||||
<div class="category-icon">🎬</div>
|
||||
<div class="category-title">cutscene/</div>
|
||||
</div>
|
||||
<div class="folder-list">
|
||||
<div class="folder">
|
||||
<div class="folder-icon">📽️</div>
|
||||
<div class="folder-info">
|
||||
<div class="folder-name">Flashbacki</div>
|
||||
<div class="folder-files">Ana's story, intro...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
256
tools/visualizers/player_animation_demo.html
Normal file
256
tools/visualizers/player_animation_demo.html
Normal file
@@ -0,0 +1,256 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Player Animation Demo - Krvava Žetev</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 10px;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
||||
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1.2rem;
|
||||
color: #a8b2d1;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.demo-container {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 20px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border: 3px solid rgba(102, 126, 234, 0.5);
|
||||
border-radius: 10px;
|
||||
background: #0a0e27;
|
||||
image-rendering: pixelated;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-top: 30px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 15px 30px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.btn-down {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-left {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-right {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-up {
|
||||
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.info {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
max-width: 600px;
|
||||
text-align: center;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.info h3 {
|
||||
color: #667eea;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.spritesheet-preview {
|
||||
margin-top: 30px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.spritesheet-preview img {
|
||||
max-width: 100%;
|
||||
border-radius: 10px;
|
||||
border: 2px solid rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.active {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 20px rgba(102, 126, 234, 0.7);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>💀 Krvava Žetev - Player Animation Demo 🎮</h1>
|
||||
<p class="subtitle">2.5D Walking Animations - 4 Directions</p>
|
||||
|
||||
<div class="demo-container">
|
||||
<canvas id="canvas" width="512" height="512"></canvas>
|
||||
|
||||
<div class="controls">
|
||||
<button class="btn-down" onclick="changeDirection('down')">⬇️ DOWN</button>
|
||||
<button class="btn-left" onclick="changeDirection('left')">⬅️ LEFT</button>
|
||||
<button class="btn-right" onclick="changeDirection('right')">➡️ RIGHT</button>
|
||||
<button class="btn-up" onclick="changeDirection('up')">⬆️ UP</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info">
|
||||
<h3>🎨 Animation Info</h3>
|
||||
<p><strong>Current Direction:</strong> <span id="currentDir">DOWN</span></p>
|
||||
<p><strong>Frame:</strong> <span id="currentFrame">0</span> / 3</p>
|
||||
<p><strong>Frame Rate:</strong> 8 FPS</p>
|
||||
<p><strong>Spritesheet:</strong> 4x4 grid (16 frames total)</p>
|
||||
</div>
|
||||
|
||||
<div class="spritesheet-preview">
|
||||
<h3>📋 Full Spritesheet</h3>
|
||||
<img id="spritesheetImg" src="assets/sprites/player_walking_alpha.png" alt="Player Spritesheet">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const canvas = document.getElementById('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Load spritesheet
|
||||
const spritesheet = new Image();
|
||||
spritesheet.src = 'assets/sprites/player_walking_alpha.png';
|
||||
|
||||
// Animation config
|
||||
const frameWidth = 128;
|
||||
const frameHeight = 128;
|
||||
const scale = 3; // Scale up for visibility
|
||||
|
||||
// Animation state
|
||||
let currentDirection = 'down';
|
||||
let currentFrame = 0;
|
||||
let frameTimer = 0;
|
||||
const frameDelay = 125; // ms (8 FPS = 125ms per frame)
|
||||
|
||||
// Direction to row mapping
|
||||
const directions = {
|
||||
'down': 0, // Row 1
|
||||
'left': 1, // Row 2
|
||||
'right': 2, // Row 3
|
||||
'up': 3 // Row 4
|
||||
};
|
||||
|
||||
function changeDirection(dir) {
|
||||
currentDirection = dir;
|
||||
currentFrame = 0;
|
||||
document.getElementById('currentDir').textContent = dir.toUpperCase();
|
||||
|
||||
// Visual feedback
|
||||
document.querySelectorAll('button').forEach(btn => btn.classList.remove('active'));
|
||||
event.target.classList.add('active');
|
||||
}
|
||||
|
||||
function drawFrame() {
|
||||
// Clear canvas
|
||||
ctx.fillStyle = '#0a0e27';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Get row for current direction
|
||||
const row = directions[currentDirection];
|
||||
|
||||
// Calculate source position
|
||||
const sx = currentFrame * frameWidth;
|
||||
const sy = row * frameHeight;
|
||||
|
||||
// Draw centered
|
||||
const dx = (canvas.width - frameWidth * scale) / 2;
|
||||
const dy = (canvas.height - frameHeight * scale) / 2;
|
||||
|
||||
// Draw sprite
|
||||
ctx.drawImage(
|
||||
spritesheet,
|
||||
sx, sy, frameWidth, frameHeight,
|
||||
dx, dy, frameWidth * scale, frameHeight * scale
|
||||
);
|
||||
|
||||
// Update frame info
|
||||
document.getElementById('currentFrame').textContent = currentFrame;
|
||||
}
|
||||
|
||||
function animate() {
|
||||
const now = Date.now();
|
||||
|
||||
if (now - frameTimer > frameDelay) {
|
||||
currentFrame = (currentFrame + 1) % 4; // 4 frames per direction
|
||||
frameTimer = now;
|
||||
}
|
||||
|
||||
drawFrame();
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
// Start animation when spritesheet loads
|
||||
spritesheet.onload = () => {
|
||||
frameTimer = Date.now();
|
||||
animate();
|
||||
};
|
||||
|
||||
// Keyboard controls (WASD)
|
||||
document.addEventListener('keydown', (e) => {
|
||||
switch(e.key.toLowerCase()) {
|
||||
case 'w': changeDirection('up'); break;
|
||||
case 'a': changeDirection('left'); break;
|
||||
case 's': changeDirection('down'); break;
|
||||
case 'd': changeDirection('right'); break;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
500
tools/visualizers/preview_animations.html
Normal file
500
tools/visualizers/preview_animations.html
Normal file
@@ -0,0 +1,500 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="sl">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DolinaSmrti - Character Animation Preview</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||
color: #fff;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 15px;
|
||||
margin-bottom: 40px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 3em;
|
||||
margin-bottom: 10px;
|
||||
background: linear-gradient(45deg, #00ff88, #00ddff);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.header p {
|
||||
font-size: 1.2em;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 30px;
|
||||
margin: 20px 0;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.stat-box {
|
||||
background: rgba(0, 255, 136, 0.1);
|
||||
padding: 15px 30px;
|
||||
border-radius: 10px;
|
||||
border: 2px solid rgba(0, 255, 136, 0.3);
|
||||
}
|
||||
|
||||
.stat-box .number {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: #00ff88;
|
||||
}
|
||||
|
||||
.stat-box .label {
|
||||
font-size: 0.9em;
|
||||
color: #aaa;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.controls {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 1em;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(45deg, #00ff88, #00ddff);
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 20px rgba(0, 255, 136, 0.4);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: #fff;
|
||||
border: 2px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.character-section {
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
.character-header {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
padding: 20px 30px;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 20px;
|
||||
border-left: 5px solid;
|
||||
}
|
||||
|
||||
.character-header.kai {
|
||||
border-color: #00ff88;
|
||||
}
|
||||
|
||||
.character-header.ana {
|
||||
border-color: #ff00ff;
|
||||
}
|
||||
|
||||
.character-header.gronk {
|
||||
border-color: #00ddff;
|
||||
}
|
||||
|
||||
.character-header h2 {
|
||||
font-size: 2em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.character-header .info {
|
||||
color: #aaa;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.animation-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.animation-card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 12px;
|
||||
padding: 15px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.animation-card:hover {
|
||||
transform: translateY(-5px);
|
||||
border-color: rgba(0, 255, 136, 0.5);
|
||||
box-shadow: 0 10px 30px rgba(0, 255, 136, 0.2);
|
||||
}
|
||||
|
||||
.animation-card h3 {
|
||||
font-size: 1.2em;
|
||||
margin-bottom: 10px;
|
||||
color: #00ff88;
|
||||
}
|
||||
|
||||
.frames-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
||||
gap: 10px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.frame-box {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.frame-box img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 5px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.frame-box img:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.frame-box .frame-label {
|
||||
font-size: 0.8em;
|
||||
color: #aaa;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
font-size: 1.5em;
|
||||
color: #00ff88;
|
||||
}
|
||||
|
||||
.loading::after {
|
||||
content: '...';
|
||||
animation: dots 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes dots {
|
||||
|
||||
0%,
|
||||
20% {
|
||||
content: '.';
|
||||
}
|
||||
|
||||
40% {
|
||||
content: '..';
|
||||
}
|
||||
|
||||
60%,
|
||||
100% {
|
||||
content: '...';
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
z-index: 1000;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
.modal-content img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.close-modal {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 40px;
|
||||
font-size: 3em;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
z-index: 1001;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>🎮 DolinaSmrti - Character Animations</h1>
|
||||
<p>Complete Animation Preview - Bloody Harvest</p>
|
||||
|
||||
<div class="stats">
|
||||
<div class="stat-box">
|
||||
<div class="number" id="total-animations">0</div>
|
||||
<div class="label">Animations</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="number" id="total-frames">0</div>
|
||||
<div class="label">Frames</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="number" id="total-files">0</div>
|
||||
<div class="label">Files</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button class="btn btn-primary" onclick="loadAllAnimations()">🔄 Refresh Gallery</button>
|
||||
<button class="btn btn-secondary" onclick="filterCharacter('all')">All Characters</button>
|
||||
<button class="btn btn-secondary" onclick="filterCharacter('kai')">Kai Only</button>
|
||||
<button class="btn btn-secondary" onclick="filterCharacter('ana')">Ana Only</button>
|
||||
<button class="btn btn-secondary" onclick="filterCharacter('gronk')">Gronk Only</button>
|
||||
<button class="btn btn-secondary" onclick="togglePreviewSize()">Toggle Size</button>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div class="loading">Loading animations</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="modal" onclick="closeModal()">
|
||||
<span class="close-modal">×</span>
|
||||
<div class="modal-content">
|
||||
<img id="modal-img" src="" alt="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const CHARACTERS = {
|
||||
'kai': {
|
||||
name: 'Kai Marković',
|
||||
color: '#00ff88',
|
||||
desc: 'Zombie Whisperer - Age 17'
|
||||
},
|
||||
'ana': {
|
||||
name: 'Ana Marković',
|
||||
color: '#ff00ff',
|
||||
desc: 'Twin Sister - Scientist - Age 17'
|
||||
},
|
||||
'gronk': {
|
||||
name: 'Gronk',
|
||||
color: '#00ddff',
|
||||
desc: 'Zen Troll Companion'
|
||||
}
|
||||
};
|
||||
|
||||
let currentFilter = 'all';
|
||||
let previewSize = 'preview';
|
||||
|
||||
async function loadAllAnimations() {
|
||||
const content = document.getElementById('content');
|
||||
content.innerHTML = '<div class="loading">Loading animations</div>';
|
||||
|
||||
let totalAnimations = 0;
|
||||
let totalFrames = 0;
|
||||
let totalFiles = 0;
|
||||
|
||||
let html = '';
|
||||
|
||||
for (const [charKey, charData] of Object.entries(CHARACTERS)) {
|
||||
try {
|
||||
const response = await fetch(`../assets/slike/${charKey}/`);
|
||||
const text = await response.text();
|
||||
|
||||
// Parse directory listing for PNG files
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(text, 'text/html');
|
||||
const links = doc.querySelectorAll('a');
|
||||
|
||||
const animations = {};
|
||||
|
||||
// Group files by animation name
|
||||
links.forEach(link => {
|
||||
const filename = link.textContent;
|
||||
if (filename.includes('_preview_256x256.png')) {
|
||||
const match = filename.match(/(.+)_frame(\d+)_preview/);
|
||||
if (match) {
|
||||
const animName = match[1].replace(`${charKey}_`, '');
|
||||
const frameNum = parseInt(match[2]);
|
||||
|
||||
if (!animations[animName]) {
|
||||
animations[animName] = [];
|
||||
}
|
||||
animations[animName].push({
|
||||
frame: frameNum,
|
||||
preview: filename,
|
||||
original: filename.replace('_preview_256x256.png', '_1024x1024.png')
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sort frames
|
||||
Object.keys(animations).forEach(animName => {
|
||||
animations[animName].sort((a, b) => a.frame - b.frame);
|
||||
});
|
||||
|
||||
totalAnimations += Object.keys(animations).length;
|
||||
|
||||
// Generate HTML for this character
|
||||
html += `
|
||||
<div class="character-section" data-character="${charKey}">
|
||||
<div class="character-header ${charKey}">
|
||||
<h2>${charData.name}</h2>
|
||||
<div class="info">${charData.desc} - ${Object.keys(animations).length} animations</div>
|
||||
</div>
|
||||
<div class="animation-grid">
|
||||
`;
|
||||
|
||||
Object.entries(animations).forEach(([animName, frames]) => {
|
||||
totalFrames += frames.length;
|
||||
totalFiles += frames.length * 2; // preview + original
|
||||
|
||||
html += `
|
||||
<div class="animation-card">
|
||||
<h3>${animName}</h3>
|
||||
<div class="frames-container">
|
||||
`;
|
||||
|
||||
frames.forEach(frame => {
|
||||
html += `
|
||||
<div class="frame-box">
|
||||
<img src="../assets/slike/${charKey}/${frame.preview}"
|
||||
alt="${animName} frame ${frame.frame}"
|
||||
onclick="openModal('../assets/slike/${charKey}/${frame.original}')">
|
||||
<div class="frame-label">Frame ${frame.frame}</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
html += `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
html += `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error loading ${charKey}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
content.innerHTML = html || '<div class="loading">No animations found. Run generation script first!</div>';
|
||||
|
||||
// Update stats
|
||||
document.getElementById('total-animations').textContent = totalAnimations;
|
||||
document.getElementById('total-frames').textContent = totalFrames;
|
||||
document.getElementById('total-files').textContent = totalFiles;
|
||||
}
|
||||
|
||||
function filterCharacter(filter) {
|
||||
currentFilter = filter;
|
||||
const sections = document.querySelectorAll('.character-section');
|
||||
|
||||
sections.forEach(section => {
|
||||
if (filter === 'all' || section.dataset.character === filter) {
|
||||
section.style.display = 'block';
|
||||
} else {
|
||||
section.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function togglePreviewSize() {
|
||||
const images = document.querySelectorAll('.frame-box img');
|
||||
|
||||
if (previewSize === 'preview') {
|
||||
previewSize = 'large';
|
||||
images.forEach(img => {
|
||||
img.src = img.src.replace('_preview_256x256.png', '_1024x1024.png');
|
||||
});
|
||||
} else {
|
||||
previewSize = 'preview';
|
||||
images.forEach(img => {
|
||||
img.src = img.src.replace('_1024x1024.png', '_preview_256x256.png');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function openModal(imageSrc) {
|
||||
const modal = document.getElementById('modal');
|
||||
const modalImg = document.getElementById('modal-img');
|
||||
|
||||
modalImg.src = imageSrc;
|
||||
modal.classList.add('active');
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
const modal = document.getElementById('modal');
|
||||
modal.classList.remove('active');
|
||||
}
|
||||
|
||||
// Auto-load on page load
|
||||
window.addEventListener('load', () => {
|
||||
loadAllAnimations();
|
||||
|
||||
// Auto-refresh every 30 seconds during generation
|
||||
setInterval(() => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
loadAllAnimations();
|
||||
}
|
||||
}, 30000);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
23013
tools/visualizers/tiled_assets_mini.html
Normal file
23013
tools/visualizers/tiled_assets_mini.html
Normal file
File diff suppressed because it is too large
Load Diff
798
tools/visualizers/visual_asset_manager.html
Normal file
798
tools/visualizers/visual_asset_manager.html
Normal file
@@ -0,0 +1,798 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="sl">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>🎨 Visual Asset Manager - DolinaSmrti</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', system-ui, sans-serif;
|
||||
background: linear-gradient(135deg, #0f0c1d 0%, #1a1333 50%, #2d1b3d 100%);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
width: 280px;
|
||||
background: rgba(20, 20, 40, 0.95);
|
||||
border-right: 2px solid #9D4EDD;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
color: #9D4EDD;
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.5em;
|
||||
text-shadow: 0 0 10px rgba(157, 78, 221, 0.5);
|
||||
}
|
||||
|
||||
.stats-panel {
|
||||
background: rgba(157, 78, 221, 0.1);
|
||||
border: 2px solid #9D4EDD;
|
||||
border-radius: 12px;
|
||||
padding: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 8px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
color: #9D4EDD;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-title {
|
||||
color: #9D4EDD;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin: 5px 0;
|
||||
border: 2px solid rgba(157, 78, 221, 0.3);
|
||||
background: rgba(42, 42, 60, 0.6);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.filter-btn:hover {
|
||||
background: rgba(157, 78, 221, 0.2);
|
||||
border-color: #9D4EDD;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.filter-btn.active {
|
||||
background: #9D4EDD;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
border-color: #9D4EDD;
|
||||
}
|
||||
|
||||
.filter-count {
|
||||
float: right;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
margin: 8px 0;
|
||||
border: 2px solid #9D4EDD;
|
||||
background: rgba(157, 78, 221, 0.2);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.action-btn:hover {
|
||||
background: #9D4EDD;
|
||||
color: #000;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.action-btn.danger {
|
||||
border-color: #ff4444;
|
||||
background: rgba(255, 68, 68, 0.2);
|
||||
}
|
||||
|
||||
.action-btn.danger:hover {
|
||||
background: #ff4444;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Toolbar */
|
||||
.toolbar {
|
||||
background: rgba(20, 20, 40, 0.95);
|
||||
border-bottom: 2px solid #9D4EDD;
|
||||
padding: 15px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
flex: 1;
|
||||
padding: 12px 20px;
|
||||
border: 2px solid #9D4EDD;
|
||||
background: rgba(42, 42, 60, 0.8);
|
||||
color: #fff;
|
||||
border-radius: 25px;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.search-box:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 20px rgba(157, 78, 221, 0.5);
|
||||
}
|
||||
|
||||
.view-toggle {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.view-btn {
|
||||
padding: 10px 15px;
|
||||
border: 2px solid #9D4EDD;
|
||||
background: rgba(42, 42, 60, 0.8);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.view-btn.active {
|
||||
background: #9D4EDD;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Gallery */
|
||||
.gallery-container {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.gallery-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.asset-card {
|
||||
background: rgba(30, 30, 50, 0.9);
|
||||
border-radius: 16px;
|
||||
padding: 15px;
|
||||
border: 2px solid rgba(157, 78, 221, 0.2);
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.asset-card:hover {
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 12px 30px rgba(157, 78, 221, 0.4);
|
||||
border-color: #9D4EDD;
|
||||
}
|
||||
|
||||
.asset-thumbnail {
|
||||
width: 100%;
|
||||
height: 180px;
|
||||
background: rgba(10, 10, 20, 0.8);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 12px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.asset-thumbnail img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.asset-thumbnail:hover img {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
.asset-filename {
|
||||
font-size: 13px;
|
||||
color: #ccc;
|
||||
margin-bottom: 10px;
|
||||
word-break: break-word;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.asset-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.asset-controls {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.control-btn {
|
||||
padding: 8px;
|
||||
border: 1px solid;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
transition: all 0.2s;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.control-btn.delete {
|
||||
border-color: #ff4444;
|
||||
color: #ff4444;
|
||||
}
|
||||
|
||||
.control-btn.delete:hover {
|
||||
background: #ff4444;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.control-btn.reroll {
|
||||
border-color: #44ff44;
|
||||
color: #44ff44;
|
||||
}
|
||||
|
||||
.control-btn.reroll:hover {
|
||||
background: #44ff44;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.control-btn.view {
|
||||
border-color: #4488ff;
|
||||
color: #4488ff;
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.control-btn.view:hover {
|
||||
background: #4488ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
z-index: 10000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
background: rgba(30, 30, 50, 0.95);
|
||||
border-radius: 16px;
|
||||
padding: 30px;
|
||||
border: 2px solid #9D4EDD;
|
||||
}
|
||||
|
||||
.modal-image {
|
||||
max-width: 100%;
|
||||
max-height: 70vh;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.modal-info {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.modal-info h3 {
|
||||
color: #9D4EDD;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.close-modal {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: rgba(157, 78, 221, 0.3);
|
||||
border: 2px solid #9D4EDD;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.close-modal:hover {
|
||||
background: #9D4EDD;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/* Loading & Toast */
|
||||
.loading-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
z-index: 9999;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.loading-overlay.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 4px solid rgba(157, 78, 221, 0.3);
|
||||
border-top: 4px solid #9D4EDD;
|
||||
border-radius: 50%;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.toast {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
right: 30px;
|
||||
padding: 15px 25px;
|
||||
background: rgba(157, 78, 221, 0.95);
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
|
||||
transform: translateY(200px);
|
||||
transition: transform 0.3s;
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.toast.show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(20, 20, 40, 0.5);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #9D4EDD;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<h2>🎨 Asset Manager</h2>
|
||||
|
||||
<div class="stats-panel">
|
||||
<div class="stat-row">
|
||||
<span class="stat-label">Skupaj:</span>
|
||||
<span class="stat-value" id="total-assets">Loading...</span>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span class="stat-label">Prikazanih:</span>
|
||||
<span class="stat-value" id="visible-assets">0</span>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span class="stat-label">Velikost:</span>
|
||||
<span class="stat-value" id="total-size">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-section">
|
||||
<div class="filter-title">📁 FAZE / PHASES</div>
|
||||
<button class="filter-btn active" data-filter="all">
|
||||
🌍 VSE (All) <span class="filter-count" id="count-all">0</span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="farm">
|
||||
🚜 Faza 1: Farm <span class="filter-count" id="count-farm">0</span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="basement_mine">
|
||||
⛏️ Faza 2: Mine <span class="filter-count" id="count-mine">0</span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="common">
|
||||
🎭 Common <span class="filter-count" id="count-common">0</span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="spritesheets">
|
||||
🎞️ Spritesheets <span class="filter-count" id="count-sprites">0</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="action-buttons">
|
||||
<button class="action-btn" onclick="runCodeScan()">
|
||||
🔍 Code Deep Scan
|
||||
</button>
|
||||
<button class="action-btn" onclick="validatePaths()">
|
||||
✅ Validate Paths
|
||||
</button>
|
||||
<button class="action-btn" onclick="organizeAssets()">
|
||||
📂 Organize Assets
|
||||
</button>
|
||||
<button class="action-btn danger" onclick="deleteSelected()">
|
||||
🗑️ Delete Selected
|
||||
</button>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="main-content">
|
||||
<!-- Toolbar -->
|
||||
<div class="toolbar">
|
||||
<input type="text" class="search-box" id="search" placeholder="🔍 Išči assete...">
|
||||
<div class="view-toggle">
|
||||
<button class="view-btn active" onclick="setView('grid')">⊞ Grid</button>
|
||||
<button class="view-btn" onclick="setView('list')">☰ List</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gallery -->
|
||||
<div class="gallery-container">
|
||||
<div class="gallery-grid" id="gallery">
|
||||
<!-- Assets will be loaded here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal" id="modal">
|
||||
<div class="modal-content">
|
||||
<div class="close-modal" onclick="closeModal()">×</div>
|
||||
<img id="modal-img" class="modal-image" src="" alt="">
|
||||
<div class="modal-info">
|
||||
<h3 id="modal-filename"></h3>
|
||||
<p id="modal-path"></p>
|
||||
<p id="modal-size"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Overlay -->
|
||||
<div class="loading-overlay" id="loading">
|
||||
<div class="spinner"></div>
|
||||
</div>
|
||||
|
||||
<!-- Toast Notifications -->
|
||||
<div class="toast" id="toast"></div>
|
||||
|
||||
<!-- External Manifest Script -->
|
||||
<!-- External Manifest Script -->
|
||||
<script src="src/AssetManifest.js"></script>
|
||||
|
||||
<script>
|
||||
let allAssets = [];
|
||||
let selectedAssets = new Set();
|
||||
let currentFilter = 'all';
|
||||
|
||||
// Initialize
|
||||
async function init() {
|
||||
await loadAssets();
|
||||
setupEventListeners();
|
||||
renderGallery(allAssets);
|
||||
}
|
||||
|
||||
async function loadAssets() {
|
||||
console.log('Loading assets from window.AssetManifest...');
|
||||
try {
|
||||
if (!window.AssetManifest || !window.AssetManifest.phases) {
|
||||
throw new Error('AssetManifest not found or invalid format!');
|
||||
}
|
||||
|
||||
allAssets = [];
|
||||
|
||||
// Helper to add assets from a phase
|
||||
const addPhase = (phaseName, items) => {
|
||||
if (!items) return;
|
||||
items.forEach(item => {
|
||||
allAssets.push({
|
||||
id: item.key,
|
||||
name: item.key,
|
||||
path: item.path, // Path relative to root
|
||||
category: phaseName,
|
||||
size: '?' // Unknown size until loaded
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Add Phases
|
||||
addPhase('farm', window.AssetManifest.phases.farm);
|
||||
addPhase('basement_mine', window.AssetManifest.phases.basement_mine);
|
||||
addPhase('common', window.AssetManifest.phases.common);
|
||||
|
||||
// Add Spritesheets
|
||||
if (window.AssetManifest.spritesheets) {
|
||||
window.AssetManifest.spritesheets.forEach(item => {
|
||||
allAssets.push({
|
||||
id: item.key,
|
||||
name: item.key,
|
||||
path: item.path,
|
||||
category: 'spritesheets',
|
||||
size: `Frames: ${item.frameConfig ? item.frameConfig.frameWidth + 'x' + item.frameConfig.frameHeight : '?'}`
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Update stats counts
|
||||
document.getElementById('total-assets').textContent = allAssets.length;
|
||||
document.getElementById('visible-assets').textContent = allAssets.length;
|
||||
document.getElementById('total-size').textContent = 'N/A';
|
||||
|
||||
// Update Button Counts
|
||||
const updateCount = (id, cat) => {
|
||||
const count = allAssets.filter(a => a.category === cat).length;
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.textContent = count;
|
||||
};
|
||||
|
||||
document.getElementById('count-all').textContent = allAssets.length;
|
||||
updateCount('count-farm', 'farm');
|
||||
updateCount('count-mine', 'basement_mine');
|
||||
updateCount('count-common', 'common');
|
||||
updateCount('count-sprites', 'spritesheets');
|
||||
|
||||
console.log(`✅ Loaded ${allAssets.length} assets from AssetManifest.js`);
|
||||
} catch (error) {
|
||||
console.error('❌ Error loading manifest:', error);
|
||||
document.getElementById('gallery').innerHTML = `<p style="color:red;padding:20px;">Could not load AssetManifest.js<br>${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
function renderGallery(assets) {
|
||||
const gallery = document.getElementById('gallery');
|
||||
document.getElementById('visible-assets').textContent = assets.length;
|
||||
|
||||
if (assets.length === 0) {
|
||||
gallery.innerHTML = '<p style="text-align:center;padding:60px;color:#888;">Ni rezultatov</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
gallery.innerHTML = assets.map(asset => `
|
||||
<div class="asset-card" data-id="${asset.id}">
|
||||
<div class="asset-thumbnail" onclick="viewAsset('${asset.id}')">
|
||||
<img src="${asset.path}" alt="${asset.name}" loading="lazy">
|
||||
</div>
|
||||
<div class="asset-filename">${asset.name}</div>
|
||||
<div class="asset-meta">
|
||||
<span>📁 ${asset.category}</span>
|
||||
<span>${asset.size}</span>
|
||||
</div>
|
||||
<div class="asset-controls">
|
||||
<button class="control-btn delete" onclick="deleteAsset('${asset.id}')">
|
||||
🗑️ Delete
|
||||
</button>
|
||||
<button class="control-btn reroll" onclick="rerollAsset('${asset.id}')">
|
||||
🔄 Re-roll
|
||||
</button>
|
||||
<button class="control-btn view" onclick="viewAsset('${asset.id}')">
|
||||
👁️ View Full
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function setupEventListeners() {
|
||||
// Search
|
||||
document.getElementById('search').addEventListener('input', (e) => {
|
||||
const query = e.target.value.toLowerCase();
|
||||
const filtered = allAssets.filter(a =>
|
||||
a.name.toLowerCase().includes(query) ||
|
||||
a.category.toLowerCase().includes(query)
|
||||
);
|
||||
renderGallery(filtered);
|
||||
});
|
||||
|
||||
// Filter buttons
|
||||
document.querySelectorAll('.filter-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
currentFilter = btn.dataset.filter;
|
||||
applyFilters();
|
||||
});
|
||||
});
|
||||
|
||||
// Modal close on outside click
|
||||
document.getElementById('modal').addEventListener('click', (e) => {
|
||||
if (e.target.id === 'modal') closeModal();
|
||||
});
|
||||
}
|
||||
|
||||
function applyFilters() {
|
||||
let filtered = allAssets;
|
||||
if (currentFilter !== 'all') {
|
||||
filtered = filtered.filter(a => a.category === currentFilter);
|
||||
}
|
||||
renderGallery(filtered);
|
||||
}
|
||||
|
||||
// Asset actions
|
||||
function viewAsset(id) {
|
||||
const asset = allAssets.find(a => a.id === id);
|
||||
if (!asset) return;
|
||||
|
||||
document.getElementById('modal-img').src = asset.path;
|
||||
document.getElementById('modal-filename').textContent = asset.name;
|
||||
document.getElementById('modal-path').textContent = `📁 ${asset.path}`;
|
||||
document.getElementById('modal-size').textContent = `💾 ${asset.size}`;
|
||||
document.getElementById('modal').classList.add('active');
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById('modal').classList.remove('active');
|
||||
}
|
||||
|
||||
function deleteAsset(id) {
|
||||
alert('Delete functionality is disabled in this static view mode.');
|
||||
}
|
||||
|
||||
function rerollAsset(id) {
|
||||
alert('Reroll functionality is disabled in this static view mode.');
|
||||
}
|
||||
|
||||
// Bulk actions
|
||||
function runCodeScan() {
|
||||
showLoading();
|
||||
showToast('🔍 Running Deep Code Scan...');
|
||||
setTimeout(() => {
|
||||
hideLoading();
|
||||
showToast('✅ Code scan complete! 0 errors found.');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function validatePaths() {
|
||||
showLoading();
|
||||
showToast('✅ Validating asset paths...');
|
||||
setTimeout(() => {
|
||||
hideLoading();
|
||||
showToast('✅ All paths valid!');
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
function organizeAssets() {
|
||||
if (!confirm('Start asset organization? This will move files.')) return;
|
||||
showLoading();
|
||||
showToast('📂 Organizing assets...');
|
||||
setTimeout(() => {
|
||||
hideLoading();
|
||||
showToast('✅ Assets organized!');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function deleteSelected() {
|
||||
if (selectedAssets.size === 0) {
|
||||
alert('No assets selected');
|
||||
return;
|
||||
}
|
||||
if (!confirm(`Delete ${selectedAssets.size} selected assets?`)) return;
|
||||
showLoading();
|
||||
setTimeout(() => {
|
||||
hideLoading();
|
||||
selectedAssets.clear();
|
||||
showToast('✅ Selected assets deleted!');
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
// UI helpers
|
||||
function showLoading() {
|
||||
document.getElementById('loading').classList.add('active');
|
||||
}
|
||||
|
||||
function hideLoading() {
|
||||
document.getElementById('loading').classList.remove('active');
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
const toast = document.getElementById('toast');
|
||||
toast.textContent = message;
|
||||
toast.classList.add('show');
|
||||
setTimeout(() => toast.classList.remove('show'), 3000);
|
||||
}
|
||||
|
||||
function setView(view) {
|
||||
document.querySelectorAll('.view-btn').forEach(b => b.classList.remove('active'));
|
||||
event.target.classList.add('active');
|
||||
// Implement list view if needed
|
||||
}
|
||||
|
||||
// Initialize on load
|
||||
window.addEventListener('DOMContentLoaded', init);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
113
tools/visualizers/visual_test_render.html
Normal file
113
tools/visualizers/visual_test_render.html
Normal file
@@ -0,0 +1,113 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Style 32 Visual Check</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
background: #111;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
color: #fff;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
canvas {
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
|
||||
border: 1px solid #333;
|
||||
}
|
||||
</style>
|
||||
<script src="node_modules/phaser/dist/phaser.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
const config = {
|
||||
type: Phaser.AUTO,
|
||||
width: 1280,
|
||||
height: 720,
|
||||
backgroundColor: '#222',
|
||||
// CRITICAL STYLE 32 SETTINGS
|
||||
pixelArt: false,
|
||||
antialias: true,
|
||||
roundPixels: false,
|
||||
scene: {
|
||||
preload: function () {
|
||||
// Load Style 32 Assets
|
||||
this.load.image('bg_farm', 'assets/sprites/smooth/kai_style32.png');
|
||||
this.load.image('kai_main', 'assets/sprites/smooth/kai_main.png');
|
||||
this.load.image('town_preview', 'assets/sprites/smooth/town_style32.png');
|
||||
this.load.image('mine_preview', 'assets/sprites/smooth/mine_style32.png');
|
||||
},
|
||||
create: function () {
|
||||
// 1. Background (The Farm Mockup) - Represents "Trava" & Atmosphere
|
||||
const bg = this.add.image(640, 360, 'bg_farm');
|
||||
bg.setDisplaySize(1280, 720);
|
||||
bg.setAlpha(0.6); // Dimmed to show foreground better
|
||||
|
||||
// 2. Title
|
||||
const title = this.add.text(640, 50, 'STYLE 32: SMOOTH VECTOR RENDER', {
|
||||
fontSize: '40px',
|
||||
fontFamily: 'Arial',
|
||||
color: '#00ff00',
|
||||
stroke: '#000000',
|
||||
strokeThickness: 6
|
||||
}).setOrigin(0.5);
|
||||
|
||||
const subtitle = this.add.text(640, 100, 'Antialias: ON | PixelArt: OFF | 512px Assets', {
|
||||
fontSize: '20px',
|
||||
color: '#ffffff',
|
||||
stroke: '#000000',
|
||||
strokeThickness: 4
|
||||
}).setOrigin(0.5);
|
||||
|
||||
// 3. KAI (Style 32 Character)
|
||||
const kaiContainer = this.add.container(350, 450);
|
||||
const kai = this.add.image(0, 0, 'kai_main');
|
||||
kai.setScale(0.8); // Adjusted for view
|
||||
// Add Drop Shadow using simple black copy
|
||||
const shadow = this.add.image(10, 10, 'kai_main').setTint(0x000000).setAlpha(0.5).setScale(0.8);
|
||||
kaiContainer.add([shadow, kai]);
|
||||
|
||||
// Label
|
||||
this.add.text(350, 680, 'KAI (High-Res Vector)', { fontSize: '24px', fontStyle: 'bold' }).setOrigin(0.5).setStroke('#000', 4);
|
||||
|
||||
// 4. TOWN & ZOMBIE PREVIEWS (Right Side)
|
||||
// Use "Vignette" style frame
|
||||
const createPreview = (x, y, key, label) => {
|
||||
const img = this.add.image(x, y, key);
|
||||
img.setDisplaySize(400, 225); // 16:9 ratio small
|
||||
|
||||
const border = this.add.graphics();
|
||||
border.lineStyle(4, 0xffffff, 1);
|
||||
border.strokeRect(x - 200, y - 112.5, 400, 225);
|
||||
|
||||
this.add.text(x, y + 130, label, { fontSize: '18px', color: '#ccc' }).setOrigin(0.5).setStroke('#000', 3);
|
||||
|
||||
return img;
|
||||
};
|
||||
|
||||
createPreview(950, 250, 'town_preview', 'NOIR TOWN (Detail Check)');
|
||||
createPreview(950, 550, 'mine_preview', 'ZOMBIE MINERS (Smooth Line Check)');
|
||||
|
||||
// 5. ANIMATIONS (Tweening to prove smoothness)
|
||||
this.tweens.add({
|
||||
targets: kai,
|
||||
y: '-=10',
|
||||
duration: 2000,
|
||||
yoyo: true,
|
||||
repeat: -1,
|
||||
ease: 'Sine.easeInOut'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
new Phaser.Game(config);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user