Created
February 6, 2013 16:56
-
-
Save jkneb/4723985 to your computer and use it in GitHub Desktop.
A CodePen by Julien Knebel. Ken's Street Fighter II with animated sprites - Make Ken walk / punch / kick / jump / etc. with your keyboard. I assigned portions of png sprites to css class names, then added some css animations in it and finally used simple JS events to add / remove them on Ken.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="stage"> | |
<div class="ken stance"></div> | |
</div> | |
<div class="commands"> | |
<h1>Control Ken's moves with keyboard</h1> | |
<strong>PRESS KEYS TO MOVE KEN</strong><br><br> | |
Punch: <i>a</i><br> | |
Kick: <i>z</i><br> | |
Reverse kick: <i>e</i><br> | |
<br> | |
Tatsumaki: <i>q</i><br> | |
Hadoken: <i>s</i><br> | |
Shoryuken: <i>d</i><br> | |
<br> | |
Jump: <i>▲</i><br> | |
Walk: <i>◀</i> <i>►</i><br> | |
Kneel: <i>▼</i> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var $ken = $('.ken'); | |
var $kenPos, $fireballPos; | |
$(document).on('click', function(){ | |
// todo: make buttons to trigger moves | |
}); | |
$(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') | |
) { | |
$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)); | |
} | |
// 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') | |
) { | |
$ken.addClass('shoryuken'); | |
setTimeout(function() { $ken.addClass('down'); }, 500); | |
setTimeout(function() { $ken.removeClass('shoryuken down'); }, 1000); | |
} | |
// 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') | |
) { | |
$ken.addClass('tatsumaki'); | |
setTimeout(function() { $ken.addClass('down'); }, 1500); | |
setTimeout(function() { $ken.removeClass('tatsumaki down'); }, 2000); | |
} | |
// a - punch | |
if (e.keyCode == 65 | |
&& !$ken.hasClass('punch') | |
&& !$ken.hasClass('hadoken') | |
&& !$ken.hasClass('shoryuken') | |
&& !$ken.hasClass('tatsumaki') | |
) { | |
$ken.addClass('punch'); | |
setTimeout(function() { $ken.removeClass('punch'); }, 150); | |
} | |
// e - kick | |
if (e.keyCode == 90 | |
&& !$ken.hasClass('kick') | |
&& !$ken.hasClass('hadoken') | |
&& !$ken.hasClass('shoryuken') | |
&& !$ken.hasClass('tatsumaki') | |
) { | |
$ken.addClass('kick'); | |
setTimeout(function() { $ken.removeClass('kick'); }, 500); | |
} | |
// r - reverse kick | |
if (e.keyCode == 69 | |
&& !$ken.hasClass('reversekick') | |
&& !$ken.hasClass('kick') | |
&& !$ken.hasClass('hadoken') | |
&& !$ken.hasClass('shoryuken') | |
&& !$ken.hasClass('tatsumaki') | |
) { | |
$ken.addClass('reversekick'); | |
setTimeout(function() { $ken.removeClass('reversekick'); }, 500); | |
} | |
// up - jump | |
if (e.keyCode == 38 | |
&& !$ken.hasClass('jump') | |
&& !$ken.hasClass('reversekick') | |
&& !$ken.hasClass('kick') | |
&& !$ken.hasClass('hadoken') | |
&& !$ken.hasClass('shoryuken') | |
&& !$ken.hasClass('tatsumaki') | |
) { | |
$ken.addClass('jump'); | |
setTimeout(function() { $ken.addClass('down'); }, 500); | |
setTimeout(function() { $ken.removeClass('jump down'); }, 1000); | |
} | |
// 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') | |
) { | |
$ken.addClass('kneel'); | |
} | |
// ← flip | |
//if (e.keyCode == 37) $ken.addClass('flip'); | |
// → unflip | |
//if (e.keyCode == 39) $ken.removeClass('flip'); | |
// ←← →→ walking | |
if (e.keyCode == 37) { | |
if ($ken.hasClass('flip')) | |
$ken.addClass('walk').css({ marginLeft:'-=10px' }); | |
else | |
$ken.addClass('walk').css({ marginLeft:'-=10px' }); | |
} | |
if (e.keyCode == 39) { | |
if ($ken.hasClass('flip')) | |
$ken.addClass('walk').css({ marginLeft:'+=10px' }); | |
else | |
$ken.addClass('walk').css({ marginLeft:'+=10px' }); | |
} | |
} | |
else { // keyup | |
$ken.removeClass('walk kneel'); | |
} | |
//console.log(e.keyCode); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import "compass"; | |
/* 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; } | |
} | |
.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; } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment