Come effettuare l’importazione e comandarli

I modelli MD2 sono dei particolari files introdotti dalla Id Software nel gioco Quake 2 nel novembre 1997. E’ un formato di semplice comprensione contenente dei modelli poligonali e le relative animazioni frame by frame. Per chi volesse saperne di più segnalo questo link contenente tutte le spiegazioni tecniche.

Come sempre ecco qui il risultato finale:


Il nostro modello importato viene visualizzato nel filmato. I comandi attivi si limitano a richiamare le varie animazioni contenute nel file MD2, per semplicità non ho aggiunto la possibilità di muoversi nello spazio 3D. Premete i tasti numerici sulla vostra tastiera per vedere il personaggio compiere varie animazioni.

Questo invece è il codice sorgente


  package {
    import flash.display.*; 
    import flash.events.*;
    import flash.net.*;
    import flash.utils.*;
    import flash.ui.*;
    
    import sandy.util.*;
    import sandy.core.Scene3D;
    import sandy.core.data.*;
    import sandy.core.scenegraph.*;
    import sandy.materials.*;
    import sandy.materials.attributes.*;
    import sandy.primitive.*;
    import sandy.events.*;
    
    import caurina.transitions.Tweener;
    
    public class SandyMain extends Sprite {
      private var scene:Scene3D;
      private var camera:Camera3D;
      private var queue:LoaderQueue;
      private var queueSkin:LoaderQueue;
      private var player:MD2;
    
      public function SandyMain() { 
        queue = new LoaderQueue();
        queue.add( "ogre", new URLRequest("md2/ogre.md2"), "BIN" );
        queue.add( "ogreSkin", new URLRequest("md2/Ogrobase.jpg"), "IMG" ); 
        queue.addEventListener(SandyEvent.QUEUE_COMPLETE, loadMD2Complete );
        queue.start();
      }

      private function loadMD2Complete(event:Event):void {
        stage.frameRate = 24;
        camera = new Camera3D( 600, 600 );
        scene = new Scene3D( "scene", this, camera, new Group() );
        player = new MD2 ( "ogre", queue.data["ogre"], 2 ); 
        player.appearance = new Appearance (new BitmapMaterial( queue.data["ogreSkin"].bitmapData ));
        player.x = 0;
        player.y = 0;
        player.rotateY = 270;
        scene.root.addChild(player);
        standAction();
        stage.addEventListener( Event.ENTER_FRAME, enterFrameListener );
        stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownListener );
        stage.addEventListener(KeyboardEvent.KEY_UP, keyUpListener );        
      }
      
      private function keyDownListener( event : KeyboardEvent ):void {
        var char : String = String.fromCharCode(event.charCode);
        if (char == '1') {
          standAction();
        } 
        if (char == '2') {
          waveAltAction();
        } 
        if (char == '3') {
          attackAction();
        } 
        if (char == '4') {
          deathTwoAction();
        } 
        if (char == '5') {
          sniffSniffAction();
        } 
        if (char == '6') {
          cWalkAction();
        } 
        if (char == '7') {
          bumFlopAction();
        } 
        if (char == '8') {
          flipAction();
        } 
        if (char == '9') {
          saluteAction();
        } 
        if (char == '0') {
          jumpAction();
        } 
      }
        
      private function keyUpListener( event : KeyboardEvent ):void { 
        var char : String = String.fromCharCode(event.charCode);
        if (event.keyCode == Keyboard.ENTER) {
          player.x = 0;
          player.y = 0;
          player.z = 100;
        }
      }
      
      private function enterFrameListener( event : Event ) : void {
        scene.render();
      }
      
      /*
      standAction()
      runAction()
      attackAction()
      painOneAction()
      painTwoAction()
      painThreeAction()
      jumpAction()
      flipAction()
      saluteAction()
      bumFlopAction()
      waveAltAction()
      sniffSniffAction
      cStandAction
      cWalkAction
      crAttachAction
      crPainAction
      crDeathAction
      deathOneAction
      deathTwoAction
      deathThreeAction()
      boomAction()
      */
      
      private function standAction():void {
        player.frame = 0;
        Tweener.addTween (player, { frame: 39, time: 8, onComplete: standAction });
      }
      
      private function runAction():void {
        player.frame = 40;
        Tweener.addTween (player, { frame: 45, time: 0.3, onComplete: runAction  });
      }
      
      private function attackAction():void {
        player.frame = 46;
        Tweener.addTween (player, { frame: 53, time: 1});
      }
      
      private function painOneAction():void {
        player.frame = 54;
        Tweener.addTween (player, { frame: 57, time: 1});
      }
      
      private function painTwoAction():void {
        player.frame = 58;
        Tweener.addTween (player, { frame: 61, time: 1});
      }
      
      private function painThreeAction():void {
        player.frame = 62;
        Tweener.addTween (player, { frame: 65, time: 1});
      }
      
      private function jumpAction():void {
        player.frame = 66;
        Tweener.addTween (player, { frame: 71, time: 1});
      }
      
      private function flipAction():void {
        player.frame = 72;
        Tweener.addTween (player, { frame: 83, time: 1});
      }
      
      private function saluteAction():void {
        player.frame = 84;
        Tweener.addTween (player, { frame: 94, time: 1});
      }
      
      private function bumFlopAction():void {
        player.frame = 95;
        Tweener.addTween (player, { frame: 111, time: 1});
      }
      
      private function waveAltAction():void {
        player.frame = 112;
        Tweener.addTween (player, { frame: 122, time: 1});
      }
      
      private function sniffSniffAction():void {
        player.frame = 123;
        Tweener.addTween (player, { frame: 134, time: 1});
      }
      
      private function cStandAction():void {
        player.frame = 135;
        Tweener.addTween (player, { frame: 153, time: 1});
      }
      
      private function cWalkAction():void {
        player.frame = 154;
        Tweener.addTween (player, { frame: 159, time: 1});
      }
      
      private function crAttachAction():void {
        player.frame = 160;
        Tweener.addTween (player, { frame: 168, time: 1});
      }
      
      private function crPainAction():void {
        player.frame = 169;
        Tweener.addTween (player, { frame: 172, time: 1});
      }
      
      private function crDeathAction():void {
        player.frame = 173;
        Tweener.addTween (player, { frame: 177, time: 1});
      }
      
      private function deathOneAction():void {
        player.frame = 178;
        Tweener.addTween (player, { frame: 183, time: 1});
      }
      
      private function deathTwoAction():void {
        player.frame = 184;
        Tweener.addTween (player, { frame: 189, time: 1});
      }
      
      private function deathThreeAction():void {
        player.frame = 190;
        Tweener.addTween (player, { frame: 197, time: 1});
      }
      
      private function boomAction():void {
        player.frame = 198;
      }
      
    }
  }

E adesso addentriamoci nelle dovute spiegazioni. Come detto nel titolo di questo articolo utilizzeremo nel nostro codice la classe Tweener della libreria caurina. Quindi il primo consiglio è scaricare le librerie necessarie, a questo scopo vi consiglio di utilizzare un client svn ed inserire la seguente url di checkuot: http://tweener.googlecode.com/svn/trunk. Scaricherete nella cartella selezionata le librerie aggiornate. Tra le varie sottodirectories che compongono il contenuto del vostro download sarà presente una directory chiamata ‘as3′, che aggiungerete alle librerie di flash ( Modifica -> Preferenze -> Actionscript -> Impostazioni Actionscript 3.0 ).

La classe Tweener

Tweener (caurina.transitions.Tweener) è una classe usata per creare tweenings e altre transizioni via codice ActionScript piuttosto che usando la timeline di flash. Questo comporta una maggiore semplicità nella gestione del codice. L’utilizzo che ne faremo in questo articolo si limita a questo genere di chiamata

      private function attackAction():void {
        player.frame = 46;
        Tweener.addTween (player, { frame: 53, time: 1});
      }

ovvero diciamo alla classe Tweener di arrivare al frame 53 dell’oggetto player ( che è il nostro MD2 che contiene, come abbiamo detto, una moltitudine di frames di animazione ). Il frame di partenza lo settiamo giusto 1 istante prima di questa chiamata in modo da ottenere la visualizzazione dell’animazione desiderata.

Viene naturale porsi una domanda, come faccio a sapere una certa animazione da quale frame parte e a quale frame arriva? La risposta a questa domanda è utilizzando un model editor. Più esattamente io ho utilizzato un programma chiamato Quake Model Editor. Questo programma è inizialmente sviluppato da Philip Martin, purtroppo il sito di riferimento è stato sostituito con altro, quindi lo metto in download da questo link.

Questo leggerissimo applicativo assomiglia vagamente a 3DStudio Max e vi da la possibilità di visualizzare i files MD2 e vedere le animazioni frame per frame.

Importazione del file MD2

Un oggetto MD2 in Sandy 3D Engine è gestito dall’omonima class, MD2 appunto. Tralasciando quindi il costruttore che utilizzeremo per caricare tutti i files necessari, arriviamo al metodo loadMD2Complete dove istanziamo un oggetto MD2, passando al costruttore il nome dell’oggetto, l’oggetto MD2 caricato e il fattore di scala. Quindi lo aggiungiamo nello stage.

I controlli

Potete controllare un oggetto MD2 come un qualsiasi altro componente di Sandy3D, quindi modificando le proprietà x, y, z ecc.. In questo tutorial tuttavia non mi addentrerò più di tanto nei controlli del personaggio nello spazio 3D, in ogni caso nel codice sono comprese tutte le animazioni del contenute nel file MD2, ognuna di esse è un metodo della classe. Il codice attuale mostra 10 delle 21 animazioni presenti ( una per tasto numerico ) per provare a vedere le altre non vi resta che modificare il codice. Se un’animazione viene visualizzata troppo velocemente o lentamente il consiglio è di modificare il valore per la proprietà ‘time’.

Cliccando su questo link potete scaricare il codice sorgente comprensivo del file MD2.

Prima di concludere voglio segnalarvi un link interessante per recuperare dei modelli MD2, polycount.com.

Si conclude qui il tutorial, comment, rate and share!

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>