|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Pokemon Sprite Expression Animator</title> |
|
<style> |
|
* { |
|
margin: 0; |
|
padding: 0; |
|
box-sizing: border-box; |
|
} |
|
|
|
body { |
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
min-height: 100vh; |
|
padding: 20px; |
|
} |
|
|
|
.container { |
|
max-width: 1400px; |
|
margin: 0 auto; |
|
background: rgba(255, 255, 255, 0.95); |
|
border-radius: 20px; |
|
padding: 30px; |
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
h1 { |
|
text-align: center; |
|
color: #333; |
|
font-size: 2.5em; |
|
margin-bottom: 10px; |
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); |
|
} |
|
|
|
.subtitle { |
|
text-align: center; |
|
color: #666; |
|
margin-bottom: 30px; |
|
font-size: 1.1em; |
|
} |
|
|
|
.upload-section { |
|
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); |
|
padding: 25px; |
|
border-radius: 15px; |
|
margin-bottom: 30px; |
|
text-align: center; |
|
border: 3px dashed #ff6b35; |
|
} |
|
|
|
.file-input { |
|
margin: 15px 0; |
|
} |
|
|
|
.file-input input[type="file"] { |
|
display: none; |
|
} |
|
|
|
.file-label { |
|
display: inline-block; |
|
padding: 12px 25px; |
|
background: #ff6b35; |
|
color: white; |
|
border-radius: 25px; |
|
cursor: pointer; |
|
transition: all 0.3s ease; |
|
font-weight: bold; |
|
} |
|
|
|
.file-label:hover { |
|
background: #e55a2b; |
|
transform: translateY(-2px); |
|
box-shadow: 0 5px 15px rgba(229, 90, 43, 0.3); |
|
} |
|
|
|
.animation-grid { |
|
display: grid; |
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
|
gap: 25px; |
|
margin-top: 30px; |
|
} |
|
|
|
.animation-card { |
|
background: white; |
|
border-radius: 15px; |
|
padding: 20px; |
|
text-align: center; |
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); |
|
transition: all 0.3s ease; |
|
border: 2px solid transparent; |
|
} |
|
|
|
.animation-card:hover { |
|
transform: translateY(-5px); |
|
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.15); |
|
border-color: #667eea; |
|
} |
|
|
|
.animation-title { |
|
font-size: 1.2em; |
|
color: #333; |
|
margin-bottom: 15px; |
|
font-weight: bold; |
|
} |
|
|
|
.sprite-container { |
|
width: 120px; |
|
height: 120px; |
|
margin: 0 auto 20px; |
|
background: #f0f0f0; |
|
border-radius: 10px; |
|
display: flex; |
|
align-items: center; |
|
justify-content: center; |
|
overflow: visible; |
|
border: 2px solid #ddd; |
|
position: relative; |
|
} |
|
|
|
.sprite { |
|
max-width: 100%; |
|
max-height: 100%; |
|
image-rendering: pixelated; |
|
} |
|
|
|
.demo-sprite { |
|
width: 80px; |
|
height: 80px; |
|
background: linear-gradient(45deg, #ff6b6b, #4ecdc4); |
|
border-radius: 50%; |
|
position: relative; |
|
} |
|
|
|
.demo-sprite::before { |
|
content: '🎮'; |
|
position: absolute; |
|
top: 50%; |
|
left: 50%; |
|
transform: translate(-50%, -50%); |
|
font-size: 2em; |
|
} |
|
|
|
.apply-btn { |
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
|
color: white; |
|
border: none; |
|
padding: 10px 20px; |
|
border-radius: 25px; |
|
cursor: pointer; |
|
font-weight: bold; |
|
transition: all 0.3s ease; |
|
width: 100%; |
|
} |
|
|
|
.apply-btn:hover { |
|
transform: translateY(-2px); |
|
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3); |
|
} |
|
|
|
.apply-btn:disabled { |
|
background: #ccc; |
|
cursor: not-allowed; |
|
transform: none; |
|
box-shadow: none; |
|
} |
|
|
|
|
|
.idle-bounce { |
|
animation: idleBounce 2s ease-in-out infinite; |
|
} |
|
|
|
.happy-bounce { |
|
animation: happyBounce 0.6s ease-in-out infinite; |
|
} |
|
|
|
.excited-shake { |
|
animation: excitedShake 0.5s ease-in-out infinite; |
|
} |
|
|
|
.sad-droop { |
|
animation: sadDroop 3s ease-in-out infinite; |
|
} |
|
|
|
.angry-shake { |
|
animation: angryShake 0.3s ease-in-out infinite; |
|
} |
|
|
|
.confused-tilt { |
|
animation: confusedTilt 2s ease-in-out infinite; |
|
} |
|
|
|
.sleepy-sway { |
|
animation: sleepySway 4s ease-in-out infinite; |
|
} |
|
|
|
.alert-pulse { |
|
animation: alertPulse 1s ease-in-out infinite; |
|
} |
|
|
|
.hurt-flash { |
|
animation: hurtFlash 0.8s ease-in-out infinite; |
|
} |
|
|
|
.victory-spin { |
|
animation: victorySpin 1.5s ease-in-out infinite; |
|
} |
|
|
|
.charging-glow { |
|
animation: chargingGlow 1.2s ease-in-out infinite; |
|
} |
|
|
|
.dizzy-wobble { |
|
animation: dizzyWobble 1s ease-in-out infinite; |
|
} |
|
|
|
.attack-lunge { |
|
animation: attackLunge 1.5s ease-in-out infinite; |
|
} |
|
|
|
.defend-crouch { |
|
animation: defendCrouch 2s ease-in-out infinite; |
|
} |
|
|
|
.love-hearts { |
|
animation: loveHearts 2s ease-in-out infinite; |
|
} |
|
|
|
.fear-tremble { |
|
animation: fearTremble 0.4s ease-in-out infinite; |
|
} |
|
|
|
.evolving-glow { |
|
animation: evolvingGlow 2s ease-in-out infinite; |
|
} |
|
|
|
.fainting-fall { |
|
animation: faintingFall 3s ease-in-out infinite; |
|
} |
|
|
|
.turn-left { |
|
animation: turnLeft 2s ease-in-out infinite; |
|
} |
|
|
|
.turn-right { |
|
animation: turnRight 2s ease-in-out infinite; |
|
} |
|
|
|
.look-around { |
|
animation: lookAround 4s ease-in-out infinite; |
|
} |
|
|
|
.confetti-effect { |
|
animation: confettiSpin 2s ease-in-out infinite; |
|
} |
|
|
|
.hearts-float { |
|
animation: heartsFloat 3s ease-in-out infinite; |
|
} |
|
|
|
.lightning-strike { |
|
animation: lightningStrike 1.5s ease-in-out infinite; |
|
} |
|
|
|
.sparkle-magic { |
|
animation: sparkleMagic 2s ease-in-out infinite; |
|
} |
|
|
|
.fire-burst { |
|
animation: fireBurst 1.8s ease-in-out infinite; |
|
} |
|
|
|
.ice-crystals { |
|
animation: iceCrystals 2.5s ease-in-out infinite; |
|
} |
|
|
|
.poison-bubbles { |
|
animation: poisonBubbles 3s ease-in-out infinite; |
|
} |
|
|
|
.healing-aura { |
|
animation: healingAura 2.8s ease-in-out infinite; |
|
} |
|
|
|
|
|
.particles { |
|
position: absolute; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
pointer-events: none; |
|
overflow: visible; |
|
} |
|
|
|
.particle { |
|
position: absolute; |
|
border-radius: 50%; |
|
} |
|
|
|
.confetti-particle { |
|
width: 6px; |
|
height: 6px; |
|
animation: confettifall 2s linear infinite; |
|
} |
|
|
|
.heart-particle { |
|
width: 12px; |
|
height: 12px; |
|
animation: heartFloat 3s ease-in-out infinite; |
|
color: #ff69b4; |
|
} |
|
|
|
.heart-particle::before { |
|
content: '💖'; |
|
font-size: 12px; |
|
} |
|
|
|
.lightning-particle { |
|
width: 2px; |
|
height: 20px; |
|
background: linear-gradient(to bottom, #ffff00, #4169e1); |
|
animation: lightningFlash 0.3s ease-in-out infinite; |
|
border-radius: 1px; |
|
} |
|
|
|
.sparkle-particle { |
|
width: 4px; |
|
height: 4px; |
|
background: #ffd700; |
|
animation: sparkleShine 1.5s ease-in-out infinite; |
|
box-shadow: 0 0 6px #ffd700; |
|
} |
|
|
|
.fire-particle { |
|
width: 8px; |
|
height: 8px; |
|
background: radial-gradient(circle, #ff4500, #ff8c00); |
|
animation: fireRise 1.8s ease-out infinite; |
|
} |
|
|
|
.ice-particle { |
|
width: 6px; |
|
height: 6px; |
|
background: linear-gradient(45deg, #00bfff, #87ceeb); |
|
animation: iceFall 2.5s linear infinite; |
|
transform: rotate(45deg); |
|
} |
|
|
|
.poison-particle { |
|
width: 10px; |
|
height: 10px; |
|
background: radial-gradient(circle, #9932cc, #8b008b); |
|
animation: poisonBubble 3s ease-in-out infinite; |
|
} |
|
|
|
.heal-particle { |
|
width: 5px; |
|
height: 5px; |
|
background: radial-gradient(circle, #32cd32, #90ee90); |
|
animation: healFloat 2.8s ease-in-out infinite; |
|
box-shadow: 0 0 8px #32cd32; |
|
} |
|
|
|
|
|
@keyframes idleBounce { |
|
0%, 100% { transform: translateY(0px); } |
|
50% { transform: translateY(-8px); } |
|
} |
|
|
|
@keyframes happyBounce { |
|
0%, 100% { transform: translateY(0px) scale(1); } |
|
50% { transform: translateY(-15px) scale(1.1); } |
|
} |
|
|
|
@keyframes excitedShake { |
|
0%, 100% { transform: translateX(0px); } |
|
25% { transform: translateX(-5px) rotate(-2deg); } |
|
75% { transform: translateX(5px) rotate(2deg); } |
|
} |
|
|
|
@keyframes sadDroop { |
|
0%, 100% { transform: translateY(0px) scaleY(1); } |
|
50% { transform: translateY(10px) scaleY(0.9); } |
|
} |
|
|
|
@keyframes angryShake { |
|
0%, 100% { transform: translateX(0px); } |
|
10%, 30%, 50%, 70%, 90% { transform: translateX(-3px); } |
|
20%, 40%, 60%, 80% { transform: translateX(3px); } |
|
} |
|
|
|
@keyframes confusedTilt { |
|
0%, 100% { transform: rotate(0deg); } |
|
25% { transform: rotate(-10deg); } |
|
75% { transform: rotate(10deg); } |
|
} |
|
|
|
@keyframes sleepySway { |
|
0%, 100% { transform: rotate(0deg) translateY(0px); } |
|
25% { transform: rotate(-5deg) translateY(5px); } |
|
75% { transform: rotate(5deg) translateY(5px); } |
|
} |
|
|
|
@keyframes alertPulse { |
|
0%, 100% { transform: scale(1); } |
|
50% { transform: scale(1.15); } |
|
} |
|
|
|
@keyframes hurtFlash { |
|
0%, 100% { opacity: 1; filter: brightness(1); } |
|
50% { opacity: 0.7; filter: brightness(1.5) hue-rotate(0deg); } |
|
} |
|
|
|
@keyframes victorySpin { |
|
0% { transform: rotate(0deg) scale(1); } |
|
50% { transform: rotate(180deg) scale(1.2); } |
|
100% { transform: rotate(360deg) scale(1); } |
|
} |
|
|
|
@keyframes chargingGlow { |
|
0%, 100% { filter: brightness(1) saturate(1); transform: scale(1); } |
|
50% { filter: brightness(1.3) saturate(1.5); transform: scale(1.05); } |
|
} |
|
|
|
@keyframes dizzyWobble { |
|
0%, 100% { transform: rotate(0deg); } |
|
25% { transform: rotate(-15deg) translateX(-5px); } |
|
50% { transform: rotate(0deg) translateX(0px); } |
|
75% { transform: rotate(15deg) translateX(5px); } |
|
} |
|
|
|
@keyframes attackLunge { |
|
0%, 100% { transform: translateX(0px) scaleX(1); } |
|
30% { transform: translateX(-10px) scaleX(0.9); } |
|
60% { transform: translateX(15px) scaleX(1.1); } |
|
} |
|
|
|
@keyframes defendCrouch { |
|
0%, 100% { transform: scaleY(1) translateY(0px); } |
|
50% { transform: scaleY(0.8) translateY(10px); } |
|
} |
|
|
|
@keyframes loveHearts { |
|
0%, 100% { transform: scale(1); filter: hue-rotate(0deg); } |
|
50% { transform: scale(1.1); filter: hue-rotate(20deg); } |
|
} |
|
|
|
@keyframes fearTremble { |
|
0%, 100% { transform: translateX(0px) translateY(0px); } |
|
10%, 30%, 50%, 70%, 90% { transform: translateX(-2px) translateY(-1px); } |
|
20%, 40%, 60%, 80% { transform: translateX(2px) translateY(1px); } |
|
} |
|
|
|
@keyframes evolvingGlow { |
|
0%, 100% { |
|
filter: brightness(1) contrast(1); |
|
transform: scale(1); |
|
} |
|
50% { |
|
filter: brightness(1.5) contrast(1.2); |
|
transform: scale(1.1); |
|
} |
|
} |
|
|
|
@keyframes faintingFall { |
|
0%, 70% { transform: rotate(0deg) translateY(0px); opacity: 1; } |
|
100% { transform: rotate(90deg) translateY(20px); opacity: 0.3; } |
|
} |
|
|
|
|
|
@keyframes turnLeft { |
|
0%, 100% { transform: scaleX(1); } |
|
50% { transform: scaleX(-1); } |
|
} |
|
|
|
@keyframes turnRight { |
|
0%, 100% { transform: scaleX(-1); } |
|
50% { transform: scaleX(1); } |
|
} |
|
|
|
@keyframes lookAround { |
|
0%, 100% { transform: scaleX(1); } |
|
25% { transform: scaleX(-1); } |
|
50% { transform: scaleX(1); } |
|
75% { transform: scaleX(-1); } |
|
} |
|
|
|
|
|
@keyframes confettiSpin { |
|
0%, 100% { transform: translateY(0px) rotate(0deg) scale(1); } |
|
50% { transform: translateY(-10px) rotate(180deg) scale(1.1); } |
|
} |
|
|
|
@keyframes heartsFloat { |
|
0%, 100% { transform: translateY(0px) scale(1); } |
|
50% { transform: translateY(-8px) scale(1.05); } |
|
} |
|
|
|
@keyframes lightningStrike { |
|
0%, 90%, 100% { filter: brightness(1) contrast(1); } |
|
10%, 20%, 30% { filter: brightness(2) contrast(1.5) hue-rotate(60deg); } |
|
} |
|
|
|
@keyframes sparkleMagic { |
|
0%, 100% { transform: rotate(0deg) scale(1); filter: brightness(1); } |
|
50% { transform: rotate(180deg) scale(1.1); filter: brightness(1.3); } |
|
} |
|
|
|
@keyframes fireBurst { |
|
0%, 100% { transform: scale(1); filter: hue-rotate(0deg) brightness(1); } |
|
50% { transform: scale(1.1); filter: hue-rotate(30deg) brightness(1.2); } |
|
} |
|
|
|
@keyframes iceCrystals { |
|
0%, 100% { transform: rotate(0deg) scale(1); filter: brightness(1) saturate(1); } |
|
50% { transform: rotate(180deg) scale(1.05); filter: brightness(1.2) saturate(1.3); } |
|
} |
|
|
|
@keyframes poisonBubbles { |
|
0%, 100% { transform: translateY(0px) scale(1); filter: hue-rotate(0deg); } |
|
50% { transform: translateY(-5px) scale(1.03); filter: hue-rotate(30deg); } |
|
} |
|
|
|
@keyframes healingAura { |
|
0%, 100% { transform: scale(1); filter: brightness(1) saturate(1); } |
|
50% { transform: scale(1.05); filter: brightness(1.2) saturate(1.4); } |
|
} |
|
|
|
|
|
@keyframes confettifall { |
|
0% { |
|
transform: translateY(-20px) rotate(0deg); |
|
opacity: 1; |
|
} |
|
100% { |
|
transform: translateY(140px) rotate(360deg); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
@keyframes heartFloat { |
|
0% { |
|
transform: translateY(20px) scale(0.5); |
|
opacity: 0; |
|
} |
|
50% { |
|
opacity: 1; |
|
transform: translateY(-10px) scale(1); |
|
} |
|
100% { |
|
transform: translateY(-40px) scale(0.8); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
@keyframes lightningFlash { |
|
0%, 100% { opacity: 0; } |
|
50% { opacity: 1; } |
|
} |
|
|
|
@keyframes sparkleShine { |
|
0%, 100% { |
|
transform: scale(0.5) rotate(0deg); |
|
opacity: 0.5; |
|
} |
|
50% { |
|
transform: scale(1.2) rotate(180deg); |
|
opacity: 1; |
|
} |
|
} |
|
|
|
@keyframes fireRise { |
|
0% { |
|
transform: translateY(20px) scale(1); |
|
opacity: 1; |
|
} |
|
100% { |
|
transform: translateY(-30px) scale(0.3); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
@keyframes iceFall { |
|
0% { |
|
transform: translateY(-20px) rotate(45deg) scale(1); |
|
opacity: 1; |
|
} |
|
100% { |
|
transform: translateY(140px) rotate(405deg) scale(0.5); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
@keyframes poisonBubble { |
|
0% { |
|
transform: translateY(20px) scale(0.5); |
|
opacity: 0.7; |
|
} |
|
50% { |
|
transform: translateY(0px) scale(1); |
|
opacity: 1; |
|
} |
|
100% { |
|
transform: translateY(-20px) scale(0.3); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
@keyframes healFloat { |
|
0% { |
|
transform: translateY(10px) scale(0.5); |
|
opacity: 0.5; |
|
} |
|
50% { |
|
transform: translateY(-5px) scale(1); |
|
opacity: 1; |
|
} |
|
100% { |
|
transform: translateY(-20px) scale(0.7); |
|
opacity: 0; |
|
} |
|
} |
|
|
|
.description { |
|
font-size: 0.9em; |
|
color: #666; |
|
margin-bottom: 15px; |
|
line-height: 1.4; |
|
} |
|
|
|
.controls { |
|
display: flex; |
|
gap: 10px; |
|
margin-top: 15px; |
|
} |
|
|
|
.speed-control { |
|
flex: 1; |
|
} |
|
|
|
.speed-control select { |
|
width: 100%; |
|
padding: 5px; |
|
border: 1px solid #ddd; |
|
border-radius: 5px; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1>🎮 Pokemon Sprite Expression Animator</h1> |
|
<p class="subtitle">Upload your sprite and test various Pokemon-style animations</p> |
|
|
|
<div class="upload-section"> |
|
<h3>Upload Your Sprite</h3> |
|
<div class="file-input"> |
|
<label for="sprite-upload" class="file-label">Choose Sprite Image</label> |
|
<input type="file" id="sprite-upload" accept="image/*"> |
|
</div> |
|
<p>Supports PNG, JPG, GIF - Best results with square sprites (64x64 to 256x256px)</p> |
|
</div> |
|
|
|
<div class="animation-grid" id="animationGrid"> |
|
|
|
</div> |
|
</div> |
|
|
|
<script> |
|
const animations = [ |
|
{ |
|
name: 'Idle Bounce', |
|
class: 'idle-bounce', |
|
description: 'Gentle up-down bounce for idle state' |
|
}, |
|
{ |
|
name: 'Happy Bounce', |
|
class: 'happy-bounce', |
|
description: 'Excited bouncing with slight scaling' |
|
}, |
|
{ |
|
name: 'Excited Shake', |
|
class: 'excited-shake', |
|
description: 'Side-to-side shake with rotation' |
|
}, |
|
{ |
|
name: 'Sad Droop', |
|
class: 'sad-droop', |
|
description: 'Slow drooping motion with vertical squash' |
|
}, |
|
{ |
|
name: 'Angry Shake', |
|
class: 'angry-shake', |
|
description: 'Rapid horizontal shaking' |
|
}, |
|
{ |
|
name: 'Confused Tilt', |
|
class: 'confused-tilt', |
|
description: 'Side-to-side head tilting motion' |
|
}, |
|
{ |
|
name: 'Sleepy Sway', |
|
class: 'sleepy-sway', |
|
description: 'Slow swaying with slight rotation' |
|
}, |
|
{ |
|
name: 'Alert Pulse', |
|
class: 'alert-pulse', |
|
description: 'Quick scaling pulse for attention' |
|
}, |
|
{ |
|
name: 'Hurt Flash', |
|
class: 'hurt-flash', |
|
description: 'Opacity and brightness flashing' |
|
}, |
|
{ |
|
name: 'Victory Spin', |
|
class: 'victory-spin', |
|
description: 'Full rotation with scaling' |
|
}, |
|
{ |
|
name: 'Charging Glow', |
|
class: 'charging-glow', |
|
description: 'Brightness and saturation increase' |
|
}, |
|
{ |
|
name: 'Dizzy Wobble', |
|
class: 'dizzy-wobble', |
|
description: 'Unsteady wobbling motion' |
|
}, |
|
{ |
|
name: 'Attack Lunge', |
|
class: 'attack-lunge', |
|
description: 'Forward lunge motion with stretch' |
|
}, |
|
{ |
|
name: 'Defend Crouch', |
|
class: 'defend-crouch', |
|
description: 'Defensive crouching animation' |
|
}, |
|
{ |
|
name: 'Love Hearts', |
|
class: 'love-hearts', |
|
description: 'Gentle scaling with color shift' |
|
}, |
|
{ |
|
name: 'Fear Tremble', |
|
class: 'fear-tremble', |
|
description: 'Rapid small trembling motion' |
|
}, |
|
{ |
|
name: 'Evolving Glow', |
|
class: 'evolving-glow', |
|
description: 'Mystical glowing evolution effect' |
|
}, |
|
{ |
|
name: 'Fainting Fall', |
|
class: 'fainting-fall', |
|
description: 'Rotation and fade for fainting' |
|
}, |
|
{ |
|
name: 'Turn Left', |
|
class: 'turn-left', |
|
description: 'Smooth horizontal flip to face left' |
|
}, |
|
{ |
|
name: 'Turn Right', |
|
class: 'turn-right', |
|
description: 'Smooth horizontal flip to face right' |
|
}, |
|
{ |
|
name: 'Look Around', |
|
class: 'look-around', |
|
description: 'Turn left and right alternately' |
|
}, |
|
{ |
|
name: 'Confetti Celebration', |
|
class: 'confetti-effect', |
|
description: 'Victory with colorful confetti particles', |
|
hasParticles: true |
|
}, |
|
{ |
|
name: 'Love Hearts Float', |
|
class: 'hearts-float', |
|
description: 'Floating heart particles around sprite', |
|
hasParticles: true |
|
}, |
|
{ |
|
name: 'Lightning Strike', |
|
class: 'lightning-strike', |
|
description: 'Electric attack with lightning effects', |
|
hasParticles: true |
|
}, |
|
{ |
|
name: 'Sparkle Magic', |
|
class: 'sparkle-magic', |
|
description: 'Magical sparkles surrounding sprite', |
|
hasParticles: true |
|
}, |
|
{ |
|
name: 'Fire Burst', |
|
class: 'fire-burst', |
|
description: 'Fire attack with flame particles', |
|
hasParticles: true |
|
}, |
|
{ |
|
name: 'Ice Crystals', |
|
class: 'ice-crystals', |
|
description: 'Ice attack with crystal particles', |
|
hasParticles: true |
|
}, |
|
{ |
|
name: 'Poison Bubbles', |
|
class: 'poison-bubbles', |
|
description: 'Toxic bubbles floating around', |
|
hasParticles: true |
|
}, |
|
{ |
|
name: 'Healing Aura', |
|
class: 'healing-aura', |
|
description: 'Gentle healing particles', |
|
hasParticles: true |
|
} |
|
]; |
|
|
|
let uploadedImage = null; |
|
|
|
function createAnimationCard(animation) { |
|
const particleHTML = animation.hasParticles ? '<div class="particles" id="particles-' + animation.class + '"></div>' : ''; |
|
|
|
return ` |
|
<div class="animation-card"> |
|
<div class="animation-title">${animation.name}</div> |
|
<div class="sprite-container"> |
|
${uploadedImage |
|
? `<img src="${uploadedImage}" class="sprite ${animation.class}" alt="Animated sprite">` |
|
: `<div class="demo-sprite ${animation.class}"></div>` |
|
} |
|
${particleHTML} |
|
</div> |
|
<div class="description">${animation.description}</div> |
|
<div class="controls"> |
|
<div class="speed-control"> |
|
<select onchange="changeSpeed(this, '${animation.class}')"> |
|
<option value="0.5">2x Speed</option> |
|
<option value="1" selected>Normal</option> |
|
<option value="1.5">0.75x Speed</option> |
|
<option value="2">0.5x Speed</option> |
|
</select> |
|
</div> |
|
</div> |
|
<button class="apply-btn" onclick="copyCSS('${animation.class}')"> |
|
Copy CSS |
|
</button> |
|
</div> |
|
`; |
|
} |
|
|
|
function renderAnimations() { |
|
const grid = document.getElementById('animationGrid'); |
|
grid.innerHTML = animations.map(createAnimationCard).join(''); |
|
|
|
|
|
animations.forEach(animation => { |
|
if (animation.hasParticles) { |
|
initializeParticles(animation.class); |
|
} |
|
}); |
|
} |
|
|
|
function initializeParticles(animationClass) { |
|
const particleContainer = document.getElementById(`particles-${animationClass}`); |
|
if (!particleContainer) return; |
|
|
|
|
|
particleContainer.innerHTML = ''; |
|
|
|
const particleConfigs = { |
|
'confetti-effect': { |
|
count: 8, |
|
type: 'confetti', |
|
colors: ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#ffeaa7', '#dda0dd'] |
|
}, |
|
'hearts-float': { |
|
count: 6, |
|
type: 'heart' |
|
}, |
|
'lightning-strike': { |
|
count: 5, |
|
type: 'lightning' |
|
}, |
|
'sparkle-magic': { |
|
count: 12, |
|
type: 'sparkle' |
|
}, |
|
'fire-burst': { |
|
count: 8, |
|
type: 'fire' |
|
}, |
|
'ice-crystals': { |
|
count: 10, |
|
type: 'ice' |
|
}, |
|
'poison-bubbles': { |
|
count: 6, |
|
type: 'poison' |
|
}, |
|
'healing-aura': { |
|
count: 8, |
|
type: 'heal' |
|
} |
|
}; |
|
|
|
const config = particleConfigs[animationClass]; |
|
if (!config) return; |
|
|
|
for (let i = 0; i < config.count; i++) { |
|
const particle = document.createElement('div'); |
|
particle.className = `particle ${config.type}-particle`; |
|
|
|
|
|
const angle = (360 / config.count) * i + Math.random() * 45; |
|
const radius = 40 + Math.random() * 20; |
|
const x = 50 + Math.cos(angle * Math.PI / 180) * radius; |
|
const y = 50 + Math.sin(angle * Math.PI / 180) * radius; |
|
|
|
particle.style.left = x + '%'; |
|
particle.style.top = y + '%'; |
|
|
|
|
|
particle.style.animationDelay = Math.random() * 2 + 's'; |
|
|
|
|
|
if (config.type === 'confetti' && config.colors) { |
|
particle.style.backgroundColor = config.colors[Math.floor(Math.random() * config.colors.length)]; |
|
} |
|
|
|
particleContainer.appendChild(particle); |
|
} |
|
} |
|
|
|
function changeSpeed(select, animationClass) { |
|
const multiplier = parseFloat(select.value); |
|
const elements = document.querySelectorAll(`.${animationClass}`); |
|
elements.forEach(el => { |
|
el.style.animationDuration = `${getOriginalDuration(animationClass) * multiplier}s`; |
|
}); |
|
} |
|
|
|
function getOriginalDuration(animationClass) { |
|
const durations = { |
|
'idle-bounce': 2, |
|
'happy-bounce': 0.6, |
|
'excited-shake': 0.5, |
|
'sad-droop': 3, |
|
'angry-shake': 0.3, |
|
'confused-tilt': 2, |
|
'sleepy-sway': 4, |
|
'alert-pulse': 1, |
|
'hurt-flash': 0.8, |
|
'victory-spin': 1.5, |
|
'charging-glow': 1.2, |
|
'dizzy-wobble': 1, |
|
'attack-lunge': 1.5, |
|
'defend-crouch': 2, |
|
'love-hearts': 2, |
|
'fear-tremble': 0.4, |
|
'evolving-glow': 2, |
|
'fainting-fall': 3, |
|
'turn-left': 2, |
|
'turn-right': 2, |
|
'look-around': 4, |
|
'confetti-effect': 2, |
|
'hearts-float': 3, |
|
'lightning-strike': 1.5, |
|
'sparkle-magic': 2, |
|
'fire-burst': 1.8, |
|
'ice-crystals': 2.5, |
|
'poison-bubbles': 3, |
|
'healing-aura': 2.8 |
|
}; |
|
return durations[animationClass] || 1; |
|
} |
|
|
|
function copyCSS(animationClass) { |
|
const cssMap = { |
|
'idle-bounce': `.idle-bounce { |
|
animation: idleBounce 2s ease-in-out infinite; |
|
} |
|
|
|
@keyframes idleBounce { |
|
0%, 100% { transform: translateY(0px); } |
|
50% { transform: translateY(-8px); } |
|
}`, |
|
'happy-bounce': `.happy-bounce { |
|
animation: happyBounce 0.6s ease-in-out infinite; |
|
} |
|
|
|
@keyframes happyBounce { |
|
0%, 100% { transform: translateY(0px) scale(1); } |
|
50% { transform: translateY(-15px) scale(1.1); } |
|
}`, |
|
'excited-shake': `.excited-shake { |
|
animation: excitedShake 0.5s ease-in-out infinite; |
|
} |
|
|
|
@keyframes excitedShake { |
|
0%, 100% { transform: translateX(0px); } |
|
25% { transform: translateX(-5px) rotate(-2deg); } |
|
75% { transform: translateX(5px) rotate(2deg); } |
|
}`, |
|
'sad-droop': `.sad-droop { |
|
animation: sadDroop 3s ease-in-out infinite; |
|
} |
|
|
|
@keyframes sadDroop { |
|
0%, 100% { transform: translateY(0px) scaleY(1); } |
|
50% { transform: translateY(10px) scaleY(0.9); } |
|
}`, |
|
'angry-shake': `.angry-shake { |
|
animation: angryShake 0.3s ease-in-out infinite; |
|
} |
|
|
|
@keyframes angryShake { |
|
0%, 100% { transform: translateX(0px); } |
|
10%, 30%, 50%, 70%, 90% { transform: translateX(-3px); } |
|
20%, 40%, 60%, 80% { transform: translateX(3px); } |
|
}`, |
|
'confused-tilt': `.confused-tilt { |
|
animation: confusedTilt 2s ease-in-out infinite; |
|
} |
|
|
|
@keyframes confusedTilt { |
|
0%, 100% { transform: rotate(0deg); } |
|
25% { transform: rotate(-10deg); } |
|
75% { transform: rotate(10deg); } |
|
}`, |
|
'sleepy-sway': `.sleepy-sway { |
|
animation: sleepySway 4s ease-in-out infinite; |
|
} |
|
|
|
@keyframes sleepySway { |
|
0%, 100% { transform: rotate(0deg) translateY(0px); } |
|
25% { transform: rotate(-5deg) translateY(5px); } |
|
75% { transform: rotate(5deg) translateY(5px); } |
|
}`, |
|
'alert-pulse': `.alert-pulse { |
|
animation: alertPulse 1s ease-in-out infinite; |
|
} |
|
|
|
@keyframes alertPulse { |
|
0%, 100% { transform: scale(1); } |
|
50% { transform: scale(1.15); } |
|
}`, |
|
'hurt-flash': `.hurt-flash { |
|
animation: hurtFlash 0.8s ease-in-out infinite; |
|
} |
|
|
|
@keyframes hurtFlash { |
|
0%, 100% { opacity: 1; filter: brightness(1); } |
|
50% { opacity: 0.7; filter: brightness(1.5); } |
|
}`, |
|
'victory-spin': `.victory-spin { |
|
animation: victorySpin 1.5s ease-in-out infinite; |
|
} |
|
|
|
@keyframes victorySpin { |
|
0% { transform: rotate(0deg) scale(1); } |
|
50% { transform: rotate(180deg) scale(1.2); } |
|
100% { transform: rotate(360deg) scale(1); } |
|
}`, |
|
'charging-glow': `.charging-glow { |
|
animation: chargingGlow 1.2s ease-in-out infinite; |
|
} |
|
|
|
@keyframes chargingGlow { |
|
0%, 100% { filter: brightness(1) saturate(1); transform: scale(1); } |
|
50% { filter: brightness(1.3) saturate(1.5); transform: scale(1.05); } |
|
}`, |
|
'dizzy-wobble': `.dizzy-wobble { |
|
animation: dizzyWobble 1s ease-in-out infinite; |
|
} |
|
|
|
@keyframes dizzyWobble { |
|
0%, 100% { transform: rotate(0deg); } |
|
25% { transform: rotate(-15deg) translateX(-5px); } |
|
50% { transform: rotate(0deg) translateX(0px); } |
|
75% { transform: rotate(15deg) translateX(5px); } |
|
}`, |
|
'attack-lunge': `.attack-lunge { |
|
animation: attackLunge 1.5s ease-in-out infinite; |
|
} |
|
|
|
@keyframes attackLunge { |
|
0%, 100% { transform: translateX(0px) scaleX(1); } |
|
30% { transform: translateX(-10px) scaleX(0.9); } |
|
60% { transform: translateX(15px) scaleX(1.1); } |
|
}`, |
|
'defend-crouch': `.defend-crouch { |
|
animation: defendCrouch 2s ease-in-out infinite; |
|
} |
|
|
|
@keyframes defendCrouch { |
|
0%, 100% { transform: scaleY(1) translateY(0px); } |
|
50% { transform: scaleY(0.8) translateY(10px); } |
|
}`, |
|
'love-hearts': `.love-hearts { |
|
animation: loveHearts 2s ease-in-out infinite; |
|
} |
|
|
|
@keyframes loveHearts { |
|
0%, 100% { transform: scale(1); filter: hue-rotate(0deg); } |
|
50% { transform: scale(1.1); filter: hue-rotate(20deg); } |
|
}`, |
|
'fear-tremble': `.fear-tremble { |
|
animation: fearTremble 0.4s ease-in-out infinite; |
|
} |
|
|
|
@keyframes fearTremble { |
|
0%, 100% { transform: translateX(0px) translateY(0px); } |
|
10%, 30%, 50%, 70%, 90% { transform: translateX(-2px) translateY(-1px); } |
|
20%, 40%, 60%, 80% { transform: translateX(2px) translateY(1px); } |
|
}`, |
|
'evolving-glow': `.evolving-glow { |
|
animation: evolvingGlow 2s ease-in-out infinite; |
|
} |
|
|
|
@keyframes evolvingGlow { |
|
0%, 100% { |
|
filter: brightness(1) contrast(1); |
|
transform: scale(1); |
|
} |
|
50% { |
|
filter: brightness(1.5) contrast(1.2); |
|
transform: scale(1.1); |
|
} |
|
}`, |
|
'fainting-fall': `.fainting-fall { |
|
animation: faintingFall 3s ease-in-out infinite; |
|
} |
|
|
|
@keyframes faintingFall { |
|
0%, 70% { transform: rotate(0deg) translateY(0px); opacity: 1; } |
|
100% { transform: rotate(90deg) translateY(20px); opacity: 0.3; } |
|
}` |
|
}; |
|
|
|
const css = cssMap[animationClass]; |
|
if (css) { |
|
navigator.clipboard.writeText(css).then(() => { |
|
alert('CSS copied to clipboard!'); |
|
}).catch(() => { |
|
const textArea = document.createElement('textarea'); |
|
textArea.value = css; |
|
document.body.appendChild(textArea); |
|
textArea.select(); |
|
document.execCommand('copy'); |
|
document.body.removeChild(textArea); |
|
alert('CSS copied to clipboard!'); |
|
}); |
|
} |
|
} |
|
|
|
|
|
document.getElementById('sprite-upload').addEventListener('change', function(e) { |
|
const file = e.target.files[0]; |
|
if (file) { |
|
const reader = new FileReader(); |
|
reader.onload = function(e) { |
|
uploadedImage = e.target.result; |
|
renderAnimations(); |
|
}; |
|
reader.readAsDataURL(file); |
|
} |
|
}); |
|
|
|
|
|
renderAnimations(); |
|
</script> |
|
</body> |
|
</html> |