Files
novafarma/player_animation_demo.html
2025-12-14 12:21:17 +01:00

257 lines
7.9 KiB
HTML

<!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>