Sestavte si ukázku Street Fighter pomocí CSS animací a JavaScriptu

Nedávno jsem se naučil skvělou techniku ​​od Simurai o tom, jak animovat sprity PNG pomocí animací CSS3 steps() vlastnictví. Hlavní myšlenkou této techniky je „znovu vytvořit“ nějaký druh animovaného GIFu, ale s dlaždicemi skřítka PNG.

Jako všichni, které znám, jsem v dětství hrál v Street Fighter, a když jsem viděl tohle... hádejte, co se mi vyrojilo v hlavě?

Check out this Pen!

Pokud se pero výše nevykresluje, klikněte sem a uvidíte jej v akci.

Pojďme vytvořit první přesun CSS

Začneme punčem (viz ve spritu níže je třetí). Nejprve musíme otevřít Photoshop a vytvořit sprite. Udělejte všechny obrázky stejně velké (tyto mají šířku 70 pixelů a výšku 80 pixelů). Existuje dobrá aplikace s názvem Texture Packer, která může pomoci při vytváření herních skřítků. Zkuste najít rozměry největšího z vašich rámů a použijte tyto rozměry pro vaši mřížku. Na konci dostanete něco takového:

Potom musíme nastavit DIV pro Kena, který obdrží náš tah úderem (a všechny naše další budoucí tahy):

/* html */
<div class="ken"></div>
/* css */
.ken { 
    width:70px; height:80px; /* exactly the size of an image in our sprite */
    background-image:url('../images/sprite.png'); 
}

Předpokládejme, že předpony dodavatele implicitně fungují. Nyní můžeme deklarovat animaci děrování takto:

/* css */
.punch { 
    animation: punch steps(4) 0.15s infinite; 
}
@keyframes punch {
    from { background-position:0px -160px; }
    to { background-position:-280px -160px; }
}

Právě jsme použili animaci (děrování) na název třídy (.punch ), který v podstatě animuje background-position od 0px-280px (na ose x). Tato animace bude rozdělena na 4 části (kroky(4), které odpovídají 4 obrázkům razníku) a její provedení bude trvat 0,15 sekundy; pak to začne donekonečna znovu.

Nakonec potřebujeme způsob, jak přidat/odebrat .punch název třídy na DIV.ken po stisknutí jiné klávesy.

/* javascript */
$(document).on('keydown', function(e) {
    if (e.keyCode === 68) { // 68 is the letter D on the keyboard
        $('.ken').addClass('punch');
        setTimeout(function() { $ken.removeClass('punch'); }, 150);
    }
});

Použili jsme jQuery až addClass('punch') pokud stisknete písmeno "D" a poté jej odstraňte po setTimeout (zpoždění) 150 ms (pamatujte, že naše css animace trvá přesně 0,15 s, což je stejné jako 150 ms). To je v podstatě vše, co potřebujete vědět, abyste vytvořili mnohem více tahů.

Posuňte se na další úroveň pomocí SASS

Pokud budete věnovat pozornost tomu, co děláme, všimnete si, že máme některé hodnoty, které se nikdy nemění (šířka/výška obrázku ve spritu), a poté, co vytvoříte nějaké další pohyby, zjistíte, že mnoho duplikací kódu, které bude v budoucnu obtížné číst a udržovat. SASS nám může pomoci vyschnout všechen ten nepořádek!

Nejprve potřebujeme základní @mixins jako animation() a keyframes() :

@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 }
}

Potřebujeme uložit hodnoty šířky / výšky obrázku a proměnné SASS existují z tohoto důvodu:

$spriteWidth:70px;
$spriteHeight:80px;

A nakonec je můžeme smíchat dohromady, abychom vytvořili komplikovaný nový mixin, který bude deklarovat pohyby a zpracuje správný výpočet pozic na pozadí za nás:

@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)); }
    }
}

Nyní můžete vytvořit nový tah pomocí jediného řádku kódu:

$spriteWidth:70px;
$spriteHeight:80px;

/* punch */
@include anim($animName:punch, $steps:3, $animNbr:3, $animParams:.15s infinite);
/* kick */
@include anim($animName:kick, $steps:5, $animNbr:7, $animParams:.5s infinite);
/* hadoken */
@include anim($animName:hadoken, $steps:4, $animNbr:1, $animParams:.5s infinite);
...

$animNbr je velmi důležité:výpočet je založen na tomto čísle. Ve skutečnosti se ve spritu počítají jen pohyby. Náš první příklad byl punč, že? A v našem spritu je to tah číslo 3. Kop je číslo 7 atd.

Přidat detekci kolize pro Fireball

Potřebujeme velmi rychlou smyčku pro detekci kolize. Bude testovat pozici ohnivé koule (offset) každých 50 milisekund, porovnat ji s něčím jiným (zde testujeme konec obrazovky). Pokud je levá poloha ohnivé koule větší než šířka okna, znamená to, že ohnivá koule předstihla obrazovku, takže okamžitě použijeme .explode třída.

Zde je návod, jak jsem to udělal; není to dokonalé, ale funguje to velmi dobře:

var $fireball = $('<div/>', { class:'fireball' });
$fireball.appendTo($ken);

var isFireballColision = function(){ 
    return $fireballPos.left + 75 > $(window).width();
};

var explodeIfColision = setInterval(function(){
    $fireballPos = $fireball.offset();
    if (isFireballColision()) {
        $fireball.addClass('explode'); 
        clearInterval(explodeIfColision);
        setTimeout(function() { $fireball.remove(); }, 500); 
    }
}, 50);

Co bude dál?

Mohli bychom snadno přidat nějaké zvukové efekty, hudbu na pozadí, sprite další postavu, smíchat to s webovým RTC, abychom umožnili více počítačům ovládat postavy (nevím něco o NodeJS a Socket.io nebo možná o skvělém novém frameworku Meteor); to je to, co miluji na vývoji webu:je téměř neomezený.