Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

11jan/120

Starling API – 17 – Création des éléments du décor avec BlockFactory, TerrainFactory et EnemyFactory

Dans le monde que l'on va créer, on va avoir des blocks, de plusieurs couleurs, de plusieurs tailles et plus ou moins résistants. Pour faire simple, j'ai repris les SpriteSheet d'un célèbre jeu par dessus laquelle j'ai "calqué" les formes. Les transparences (80/60/40%) représentent l'état de destruction du bloc:

Du coup, je peux profiter de leur Atlas de Texture. Sauf que dans leur cas, l'atlas est au format JSON et pas au format XML:

http://www.flex-tutorial.fr/wp-content/uploads/aquarium/r/blocks.json

Création d'un parser d'Atlas JSON

C'est pas grave, on va créer la classe TextureAtlasJSON, qui reprend les méthodes de TextureAtlas, adaptées pour du JSON:

package utils
{
  import flash.geom.Rectangle;
  import flash.utils.Dictionary;

  import starling.textures.Texture;

  public class TextureAtlasJSON
  {
    private var _atlasTexture:Texture;
    private var _textureRegions:Dictionary;
    private var _textureFrames:Dictionary;
    public function TextureAtlasJSON(texture:Texture, atlas:Object = null)
    {
      _textureRegions = new Dictionary();
      _textureFrames  = new Dictionary();
      _atlasTexture   = texture;

      if (atlas){
        parseAtlas(atlas);
      }
    }

    /** Disposes the atlas texture. */
    public function dispose():void
    {
      _atlasTexture.dispose();
    }

    private function parseAtlas(atlas:Object):void
    {
      for (var key:String in atlas){
        var subTexture:Object = atlas[key];
        if (subTexture.hasOwnProperty("id")){
          var name:String        = subTexture.id;
          var x:Number           = parseFloat(subTexture.x);
          var y:Number           = parseFloat(subTexture.y);
          var width:Number       = parseFloat(subTexture.width);
          var height:Number      = parseFloat(subTexture.height);
          var frameX:Number      = parseFloat(subTexture.frameX);
          var frameY:Number      = parseFloat(subTexture.frameY);
          var frameWidth:Number  = parseFloat(subTexture.frameWidth);
          var frameHeight:Number = parseFloat(subTexture.frameHeight);

          var region:Rectangle = new Rectangle(x, y, width, height);
          var frame:Rectangle  = frameWidth > 0 && frameHeight > 0 ?
            new Rectangle(frameX, frameY, frameWidth, frameHeight) : null;

          addRegion(name, region, frame);
        }
      }
    }
    /** Retrieves a subtexture by name. Returns <code>null</code> if it is not found. */
    public function getTexture(name:String):Texture
    {
      var region:Rectangle = _textureRegions[name];

      if (region == null) return null;
      else
      {
        var texture:Texture = Texture.fromTexture(_atlasTexture, region);
        texture.frame = _textureFrames[name];
        return texture;
      }
    }

    /** Returns all textures that start with a certain string, sorted alphabetically
     *  (especially useful for "MovieClip"). */
    public function getTextures(prefix:String=""):Vector.<Texture>
    {
      var textures:Vector.<Texture> = new <Texture>[];
      var names:Vector.<String> = new <String>[];
      var name:String;

      for (name in _textureRegions)
        if (name.indexOf(prefix) == 0)
          names.push(name);                

      names.sort(Array.CASEINSENSITIVE);

      for each (name in names)
      textures.push(getTexture(name)); 

      return textures;
    }

    /** Creates a region for a subtexture and gives it a name. */
    public function addRegion(name:String, region:Rectangle, frame:Rectangle=null):void
    {
      _textureRegions[name] = region;
      if (frame) _textureFrames[name] = frame;
    }

    /** Removes a region with a certain name. */
    public function removeRegion(name:String):void
    {
      delete _textureRegions[name];
    }
  }
}

Création de la BlockFactory

Vous avez l'habitude, on va maintenant, on va créer une Factory qui va nous retourner nos blocks. ceux-ci sont en fait des MovieClip à plusieurs Textures.

package com.fnicollet {
  import flash.display.Bitmap;

  import starling.display.Image;
  import starling.display.MovieClip;
  import starling.textures.Texture;

  import utils.TextureAtlasJSON;

  public class BlockFactory {

    [Embed(source = "/assets/atlas/blocks.json", mimeType = "application/octet-stream")]
    public static const SpriteSheet:Class;
    [Embed(source = "/assets/spritesheet/blocks.png")]
    private static const imageSpriteSheet:Class;
    private static var bitmap:Bitmap = Bitmap(new imageSpriteSheet());

    private static var _textureAtlas:TextureAtlasJSON = null;

    public function BlockFactory() {
    }

    public static function get(id:String):MovieClip {
      if (!_textureAtlas) {
        _textureAtlas = new TextureAtlasJSON(Texture.fromBitmap(bitmap), JSON.parse(new SpriteSheet()));
      }
      var textures:Vector.<Texture> = _textureAtlas.getTextures(id + "_");
      if (!textures || textures.length < 1) {
        return null;
      }
      var ret:MovieClip = new MovieClip(textures);
      ret.pivotX = ret.width >> 1;
      ret.pivotY = ret.height >> 1;
      ret.scaleX = ret.scaleY = 0.61;
      return ret;
    }
  }
}

Création de TerrainFactory

On va faire exactement la même chose avec TerrainFactory:

décrit pas la SpriteSheet suivante:

http://www.flex-tutorial.fr/wp-content/uploads/aquarium/r/terrain.json

Pour le code de la Factory, c'est le même que celui de la BlockFactory mais avec une spritesheet et un atlas différent, je ne vous le répète pas.

Création de la EnemyFactory

Rebelotte :)

avec:

http://www.flex-tutorial.fr/wp-content/uploads/aquarium/r/enemies.json

Conclusion

Bon, ce billet ne servait pas à grand chose, à part vérifier que vous avez bien suivi ce que l'on a dit plus tôt avec les Factory :) . Dans le prochain billet, on va construire automatiquement le niveau grâce à une description JSON de celui-ci. Vous verrez que grâce à nos Factory, le code sera très lisible.

Télécharger les sources

Remplis sous: Starling || Taggé comme: Laisser un commentaire

Articles similaires