Skip to content

Instantly share code, notes, and snippets.

@jacksonfdam
Created February 12, 2013 05:44
Show Gist options
  • Save jacksonfdam/4760514 to your computer and use it in GitHub Desktop.
Save jacksonfdam/4760514 to your computer and use it in GitHub Desktop.
Ken Street Fighter CSS Sprite ANimation
<div class="stage">
<div class="ken stance"></div>
</div>
<div class="commands">
<h1>Control Ken's moves with ur keyboard</h1>
Punch: <button id="a">a</button><br>
Kick: <button id="z">z</button><br>
Reverse kick: <button id="e">e</button><br>
<br>
Tatsumaki: <button id="q">q</button><br>
Hadoken: <button id="s">s</button><br>
Shoryuken: <button id="d">d</button><br>
<br>
Jump: &nbsp;&nbsp;&nbsp;<button id="up">▲</button><br>
Walk: <button id="left">◀</button><button id="right">►</button><br>
Kneel: &nbsp;&nbsp;<button id="down">▼</button>
</div>
/* a little more explanations on how it works on my blog : http://front-back.com/2013/01/animate-png-sprites-with-css3-animations */
/*
* mixins
*/
@mixin transform($params) {
-webkit-transform:$params;
-moz-transform:$params;
-ms-transform:$params;
transform:$params;
}
@mixin transition($params) {
-webkit-transition:$params;
-moz-transition:$params;
-ms-transition:$params;
transition:$params;
}
@mixin animation($params) {
-webkit-animation:$params;
-moz-animation:$params;
-ms-animation:$params;
animation:$params;
}
@mixin keyframes($name) {
@-webkit-keyframes $name { @content }
@-moz-keyframes $name { @content }
@-ms-keyframes $name { @content }
@keyframes $name { @content }
}
@mixin anim($animName, $steps, $animNbr, $animParams){
.#{$animName} {
@content;
@include animation($animName steps($steps) $animParams);
}
@include keyframes($animName) {
from { background-position:0px (-$spriteHeight * ($animNbr - 1)); }
to { background-position:-($spriteWidth * $steps) (-$spriteHeight * ($animNbr - 1)); }
}
}
/* element who's going to receive this class will be mirrored */
.flip { @include transform(scaleX(-1)); }
/* sprite tile dimensions */
$spriteWidth:70px;
$spriteHeight:80px;
/* ken */
.ken {
position:absolute; bottom:112px; margin-left:150px;
width:$spriteWidth; height:$spriteHeight;
background-image:url('http://front-back.com/wp-content/uploads/2013/01/ken.png');
/* other sprites preloading */
&:before {
content:'';
background: url('http://front-back.com/wp-content/uploads/2013/01/ken-tatsumaki-senpuu-kyaku.png') no-repeat;
}
&:after {
content:'';
background: url('http://front-back.com/wp-content/uploads/2013/01/ken-shoryuken.png') no-repeat;
}
}
/* ken's fireball */
@include anim($animName:fireball, $steps:2, $animNbr:5, $animParams:.15s infinite) {
@extend .ken;
position:absolute; left:100%; bottom:0px;
margin-left:0; /* default margin-left */
background-position:140px 320px; /* default background position */
@include transition(margin 8s linear);
&:before { left:25px; right:25px; }
&.moving { margin-left:4000px; } /* triggering the movement with this class */
}
/* ken's fireball impact explosion */
@include anim($animName:explode, $steps:4, $animNbr:6, $animParams:.5s 1);
/* stance */
@include anim($animName:stance, $steps:4, $animNbr:2, $animParams:.5s infinite);
/* hadoken - must be declared AFTER .stance */
@include anim($animName:hadoken, $steps:4, $animNbr:1, $animParams:.5s infinite);
/* punch */
@include anim($animName:punch, $steps:3, $animNbr:3, $animParams:.15s infinite);
/* walking */
@include anim($animName:walk, $steps:5, $animNbr:4, $animParams:.5s infinite);
/* kick */
@include anim($animName:kick, $steps:5, $animNbr:7, $animParams:.5s infinite);
/* reverse kick */
@include anim($animName:reversekick, $steps:5, $animNbr:8, $animParams:.5s infinite);
/* kneel down */
@include anim($animName:kneel, $steps:1, $animNbr:10, $animParams:.2s infinite);
/* jump */
@include anim($animName:jump, $steps:7, $animNbr:9, $animParams:1s infinite) {
@include transition(bottom .5s cubic-bezier(0.990, 0.005, 0.000, 0.420));
bottom:225px;
&.down { bottom:112px; }
}
/* shoryuken */
@include anim($animName:shoryuken, $steps:7, $animNbr:1, $animParams:1s infinite) {
height:110px;
background-image:url('http://front-back.com/wp-content/uploads/2013/01/ken-shoryuken.png');
@include transition(bottom .5s cubic-bezier(0.990, 0.005, 0.000, 0.420));
bottom:225px;
&.down { bottom:112px; }
}
/* tatsumaki senpuu kyaku */
@include anim($animName:tatsumaki, $steps:13, $animNbr:1, $animParams:2s infinite) {
height:110px;
background-image:url('http://front-back.com/wp-content/uploads/2013/01/ken-tatsumaki-senpuu-kyaku.png');
@include transition(bottom .2s cubic-bezier(0.990, 0.005, 0.000, 0.420));
bottom:132px;
&.down { bottom:112px; }
}
.commands {
h1 { margin-top:0; font-size:14px; }
margin-left:450px;
font-size:12px; padding:15px;
i { padding:0px 4px; font-style:normal; font-weight:bold; outline:1px solid pink; }
button + button { white-space:nowrap; }
}
.stage {
position:absolute; top:0; width:450px; height:330px;
background:url('http://front-back.com/wp-content/uploads/2013/01/sf2-bg.jpg') no-repeat 0px -100px;
background-size:contain;
float:left; margin-right:20px;
}
body { margin:0px; padding:0; }
var $ken = $('.ken');
var $kenPos, $fireballPos;
var punch = function(){
$ken.addClass('punch');
setTimeout(function() { $ken.removeClass('punch'); }, 150);
return false;q
};
var kick = function(){
$ken.addClass('kick');
setTimeout(function() { $ken.removeClass('kick'); }, 500);
return false;
};
var rkick = function(){
$ken.addClass('reversekick');
setTimeout(function() { $ken.removeClass('reversekick'); }, 500);
return false;
};
var tatsumaki = function(){
$ken.addClass('tatsumaki');
setTimeout(function() { $ken.addClass('down'); }, 1500);
setTimeout(function() { $ken.removeClass('tatsumaki down'); }, 2000);
return false;
};
var hadoken = function(){
$ken.addClass('hadoken');
setTimeout(function() { $ken.removeClass('hadoken'); }, 500);
setTimeout(function() {
var $fireball = $('<div/>', { class:'fireball' });
$fireball.appendTo($ken);
var isFireballColision = function(){
return $fireballPos.left + 75 > $(window).width() ? true : false;
};
var explodeIfColision = setInterval(function(){
$fireballPos = $fireball.offset();
//console.log('fireballInterval:',$fireballPos.left);
if (isFireballColision()) {
$fireball.addClass('explode').removeClass('moving').css('marginLeft','+=22px');
clearInterval(explodeIfColision);
setTimeout(function() { $fireball.remove(); }, 500);
}
}, 50);
setTimeout(function() { $fireball.addClass('moving'); }, 20);
setTimeout(function() {
$fireball.remove();
clearInterval(explodeIfColision);
}, 3020);
}, (250));
return false;
};
var shoryuken = function(){
$ken.addClass('shoryuken');
setTimeout(function() { $ken.addClass('down'); }, 500);
setTimeout(function() { $ken.removeClass('shoryuken down'); }, 1000);
return false;
};
var jump = function(){
$ken.addClass('jump');
setTimeout(function() { $ken.addClass('down'); }, 500);
setTimeout(function() { $ken.removeClass('jump down'); }, 1000);
return false;
};
var kneel = function(){
$ken.addClass('kneel');
return false;
};
var walkLeft = function(){
$ken.addClass('walk').css({ marginLeft:'-=10px' });
return false;
};
var walkRight = function(){
$ken.addClass('walk').css({ marginLeft:'+=10px' });
return false;
};
// on click events
$('#a').click(punch);
$('#z').click(kick);
$('#e').click(rkick);
$('#q').click(tatsumaki);
$('#s').click(hadoken);
$('#d').click(shoryuken);
$('#up').click(jump);
$('#down').on('mousedown mouseup', function(e){
if (e.type == 'mousedown') { kneel(); }
else { $ken.removeClass('kneel'); }
});
$('#left').on('mousedown mouseup', function(e){
if (e.type == 'mousedown') { walkLeft(); }
else { $ken.removeClass('walk'); }
});
$('#right').on('mousedown mouseup', function(e){
if (e.type == 'mousedown') { walkRight(); }
else { $ken.removeClass('walk'); }
});
// on keydown events
$(document).on('keydown keyup', function(e) {
if (e.type == 'keydown') {
// s - hadoken
if (e.keyCode == 83
&& !$ken.hasClass('tatsumaki')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('punch')
&& !$ken.hasClass('kick')
&& !$ken.hasClass('reversekick')
) {
hadoken();
}
// d - shoryuken
if (e.keyCode == 68
&& !$ken.hasClass('tatsumaki')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('punch')
&& !$ken.hasClass('kick')
&& !$ken.hasClass('reversekick')
&& !$ken.hasClass('jump')
) {
shoryuken();
}
// q - tatsumaki senpuu kyaku
if (e.keyCode == 81
&& !$ken.hasClass('tatsumaki')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('punch')
&& !$ken.hasClass('kick')
&& !$ken.hasClass('reversekick')
&& !$ken.hasClass('jump')
) {
tatsumaki();
}
// a - punch
if (e.keyCode == 65
&& !$ken.hasClass('punch')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('tatsumaki')
) {
punch();
}
// e - kick
if (e.keyCode == 90
&& !$ken.hasClass('kick')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('tatsumaki')
) {
kick();
}
// r - reverse kick
if (e.keyCode == 69
&& !$ken.hasClass('reversekick')
&& !$ken.hasClass('kick')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('tatsumaki')
) {
rkick();
}
// up - jump
if (e.keyCode == 38
&& !$ken.hasClass('jump')
&& !$ken.hasClass('reversekick')
&& !$ken.hasClass('kick')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('tatsumaki')
) {
jump();
}
// down - kneel
if (e.keyCode == 40
&& !$ken.hasClass('kneel')
&& !$ken.hasClass('jump')
&& !$ken.hasClass('reversekick')
&& !$ken.hasClass('kick')
&& !$ken.hasClass('hadoken')
&& !$ken.hasClass('shoryuken')
&& !$ken.hasClass('tatsumaki')
) {
kneel();
}
// ← flip
//if (e.keyCode == 37) $ken.addClass('flip');
// → unflip
//if (e.keyCode == 39) $ken.removeClass('flip');
// ←← →→ walking
if (e.keyCode == 37) { walkLeft(); }
if (e.keyCode == 39) { walkRight(); }
}
else { // keyup
$ken.removeClass('walk kneel');
}
//console.log(e.keyCode);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment