From 81453cdae5cc9a8d4ad2186df393bd32230f67d7 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sat, 1 Nov 2014 22:43:48 +0100 Subject: [PATCH] Enable different ways of rendering frames: * Traditionally, with a single bitmapData for every frame * By drawing a rect from one single bitmap data * Using tilesheets For this render targets are introduced, which render into a "graphics" object. For now the graphics object is the "graphics" member of the AnimatedSprite. Also: Introduced flag for rendering with "ADD" blendMode. Due to some issue, rendering with blendmode "Add" works only using tilesheets on C++ targets and by setting "blendMode" of the sprite on flash target. --- spritesheet/AnimatedSprite.hx | 45 +++++++++---- spritesheet/Spritesheet.hx | 67 ++++++++++++++----- spritesheet/data/SpritesheetFrame.hx | 1 + spritesheet/render/IRenderTarget.hx | 10 +++ .../render/RenderBitmapRectToGraphics.hx | 31 +++++++++ .../render/RenderTilesheetToGraphics.hx | 32 +++++++++ .../render/RenderWholeBitmapToGraphics.hx | 30 +++++++++ 7 files changed, 188 insertions(+), 28 deletions(-) create mode 100644 spritesheet/render/IRenderTarget.hx create mode 100644 spritesheet/render/RenderBitmapRectToGraphics.hx create mode 100644 spritesheet/render/RenderTilesheetToGraphics.hx create mode 100644 spritesheet/render/RenderWholeBitmapToGraphics.hx diff --git a/spritesheet/AnimatedSprite.hx b/spritesheet/AnimatedSprite.hx index db34cc0..fc53850 100644 --- a/spritesheet/AnimatedSprite.hx +++ b/spritesheet/AnimatedSprite.hx @@ -1,18 +1,22 @@ package spritesheet; -import flash.display.Bitmap; +import spritesheet.render.IRenderTarget; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.Lib; import spritesheet.data.BehaviorData; +enum Flag { + BLEND_ADD; +} +@:access(spritesheet.Spritesheet) class AnimatedSprite extends Sprite { - public var bitmap:Bitmap; + public var renderTarget:IRenderTarget; public var currentBehavior:BehaviorData; public var currentFrameIndex:Int; public var smoothing:Bool; @@ -23,6 +27,8 @@ class AnimatedSprite extends Sprite { private var behavior:BehaviorData; private var loopTime:Int; private var timeElapsed:Int; + + private var isAFrameShown : Bool = false; //Inidicates if any frame has been drawn at all public function new (sheet:Spritesheet, smoothing:Bool = false) { @@ -33,9 +39,16 @@ class AnimatedSprite extends Sprite { this.spritesheet = sheet; behaviorQueue = new Array (); - bitmap = new Bitmap (); - addChild (bitmap); - + renderTarget = switch(sheet.imageData) { + case BITMAP_DATA(_,_): + if (sheet.useSingleBitmapData) { + new spritesheet.render.RenderBitmapRectToGraphics (this); + } else { + new spritesheet.render.RenderWholeBitmapToGraphics (this); + } + case TILESHEET(ts): + new spritesheet.render.RenderTilesheetToGraphics(this, ts); + } } @@ -156,12 +169,9 @@ class AnimatedSprite extends Sprite { var frame = spritesheet.getFrame (currentBehavior.frames [currentFrameIndex]); - - bitmap.bitmapData = frame.bitmapData; - bitmap.smoothing = smoothing; - bitmap.x = frame.offsetX - currentBehavior.originX; - bitmap.y = frame.offsetY - currentBehavior.originY; - + isAFrameShown = true; + renderTarget.drawFrame(frame, -currentBehavior.originX, -currentBehavior.originY, smoothing); + if (behaviorComplete) { if (behaviorQueue.length > 0) { @@ -193,7 +203,7 @@ class AnimatedSprite extends Sprite { loopTime = Std.int ((behavior.frames.length / behavior.frameRate) * 1000); - if (bitmap.bitmapData == null) { + if (!isAFrameShown) { update (0); @@ -203,7 +213,7 @@ class AnimatedSprite extends Sprite { } else { - bitmap.bitmapData = null; + isAFrameShown = false; currentBehavior = null; currentFrameIndex = -1; behaviorComplete = true; @@ -212,5 +222,14 @@ class AnimatedSprite extends Sprite { } + public function setFlag(flag : Flag) { + renderTarget.enableFlag(flag); + update(0); + } + + public function unsetFlag(flag : Flag) { + renderTarget.disableFlag(flag); + update(0); + } } \ No newline at end of file diff --git a/spritesheet/Spritesheet.hx b/spritesheet/Spritesheet.hx index 52b269a..be06f9f 100644 --- a/spritesheet/Spritesheet.hx +++ b/spritesheet/Spritesheet.hx @@ -2,11 +2,22 @@ package spritesheet; import flash.display.BitmapData; +import openfl.display.Tilesheet; import flash.geom.Point; import flash.geom.Rectangle; import spritesheet.data.BehaviorData; import spritesheet.data.SpritesheetFrame; +private enum ImageData { + BITMAP_DATA(sourceImage : BitmapData, sourceImageAlpha : BitmapData); + TILESHEET(sheet : openfl.display.Tilesheet); +} + +enum StorageType { + INDIVIDUAL_BITMAPS;// Store every frame in its own BITMAP_DATA + SINGLE_BITMAP; // Store all frames in onw single bitmap + TILESHEET; // Store using openfl.display.Tilesheet +} class Spritesheet { @@ -16,14 +27,29 @@ class Spritesheet { public var totalFrames:Int; private var frames:Array ; + private var imageData : ImageData; private var sourceImage:BitmapData; private var sourceImageAlpha:BitmapData; + public var useSingleBitmapData(default,null):Bool; - - public function new (image:BitmapData = null, frames:Array = null, behaviors:Map = null, imageAlpha:BitmapData = null) { - - this.sourceImage = image; - this.sourceImageAlpha = imageAlpha; + public function new (image:BitmapData = null, frames:Array = null, behaviors:Map = null, + imageAlpha:BitmapData = null, storageType : StorageType = null) { + + if (storageType == null) { + #if flash + storageType = INDIVIDUAL_BITMAPS; //Tilesheet does not work with blendmode = ADD on flash + #else + storageType = TILESHEET; //Only tilesheets work for blendmode = ADD on other targets + #end + } + + if (storageType == TILESHEET) { + this.imageData = TILESHEET(new Tilesheet(image)); + this.useSingleBitmapData = true; + } else { + this.imageData = BITMAP_DATA(image, imageAlpha); + this.useSingleBitmapData = storageType == SINGLE_BITMAP; + } if (frames == null) { @@ -46,6 +72,12 @@ class Spritesheet { this.behaviors = behaviors; } + + if (useSingleBitmapData && imageAlpha != null) { + var targetRect = new Rectangle(0,0,image.width,image.height); + var targetPoint = new Point(); + image.copyChannel (imageAlpha, targetRect, targetPoint, 2, 8); + } } @@ -80,20 +112,25 @@ class Spritesheet { var frame = frames[index]; - var bitmapData = new BitmapData (frame.width, frame.height, true); var sourceRectangle = new Rectangle (frame.x, frame.y, frame.width, frame.height); var targetPoint = new Point (); - bitmapData.copyPixels (sourceImage, sourceRectangle, targetPoint); - - if (sourceImageAlpha != null) { - - bitmapData.copyChannel (sourceImageAlpha, sourceRectangle, targetPoint, 2, 8); - + switch(imageData) { + case BITMAP_DATA(sourceImage, sourceImageAlpha): + if (useSingleBitmapData) { + frame.bitmapData = sourceImage; + } else { + var bitmapData = new BitmapData (frame.width, frame.height, true); + bitmapData.copyPixels (sourceImage, sourceRectangle, targetPoint); + + if (sourceImageAlpha != null) { + bitmapData.copyChannel (sourceImageAlpha, sourceRectangle, targetPoint, 2, 8); + } + frame.bitmapData = bitmapData; + } + case TILESHEET(sheet): + frame.tilesheetIndex = sheet.addTileRect(sourceRectangle, new Point(0,0)); } - - frame.bitmapData = bitmapData; - } diff --git a/spritesheet/data/SpritesheetFrame.hx b/spritesheet/data/SpritesheetFrame.hx index 2ef199c..6d13708 100644 --- a/spritesheet/data/SpritesheetFrame.hx +++ b/spritesheet/data/SpritesheetFrame.hx @@ -8,6 +8,7 @@ class SpritesheetFrame { public var name:String; + public var tilesheetIndex:Int;//Used when drawing this frame from a tilesheet public var bitmapData:BitmapData; public var height:Int; public var offsetX:Int; diff --git a/spritesheet/render/IRenderTarget.hx b/spritesheet/render/IRenderTarget.hx new file mode 100644 index 0000000..88757b0 --- /dev/null +++ b/spritesheet/render/IRenderTarget.hx @@ -0,0 +1,10 @@ +package spritesheet.render; + +import spritesheet.data.SpritesheetFrame; +import spritesheet.AnimatedSprite; + +interface IRenderTarget { + function drawFrame(frame : SpritesheetFrame, offsetX : Float, offsetY : Float, smoothing : Bool) : Void; + function enableFlag(flag : Flag) : Void; + function disableFlag(flag : Flag) : Void; +} \ No newline at end of file diff --git a/spritesheet/render/RenderBitmapRectToGraphics.hx b/spritesheet/render/RenderBitmapRectToGraphics.hx new file mode 100644 index 0000000..5807d5c --- /dev/null +++ b/spritesheet/render/RenderBitmapRectToGraphics.hx @@ -0,0 +1,31 @@ +package spritesheet.render; + +import spritesheet.data.SpritesheetFrame; +import flash.display.Sprite; +import flash.display.BlendMode; +import spritesheet.AnimatedSprite; + +class RenderBitmapRectToGraphics implements IRenderTarget { + private var sprite : Sprite; + public function new(o : Sprite) {this.sprite = o;} + public function drawFrame(frame : SpritesheetFrame, offsetX : Float, offsetY : Float, smoothing : Bool) { + var m = new flash.geom.Matrix(); + m.translate(offsetX + frame.offsetX - frame.x, offsetY + frame.offsetY - frame.y); + sprite.graphics.clear(); + sprite.graphics.beginBitmapFill(frame.bitmapData, m, false, smoothing); + sprite.graphics.drawRect(offsetX + frame.offsetX,offsetY + frame.offsetY,frame.width, frame.height); + sprite.graphics.endFill(); + } + public function enableFlag(flag : Flag) { + switch(flag) { + case BLEND_ADD: + sprite.blendMode = BlendMode.ADD; + } + } + public function disableFlag(flag : Flag) { + switch(flag) { + case BLEND_ADD: + sprite.blendMode = BlendMode.NORMAL; + } + } +} \ No newline at end of file diff --git a/spritesheet/render/RenderTilesheetToGraphics.hx b/spritesheet/render/RenderTilesheetToGraphics.hx new file mode 100644 index 0000000..13fbec6 --- /dev/null +++ b/spritesheet/render/RenderTilesheetToGraphics.hx @@ -0,0 +1,32 @@ +package spritesheet.render; + +import openfl.display.Tilesheet; +import spritesheet.data.SpritesheetFrame; +import flash.display.Sprite; +import spritesheet.AnimatedSprite; + + class RenderTilesheetToGraphics implements IRenderTarget { + private var sprite : Sprite; + private var tilesheet : Tilesheet; + private var flags : Int = 0; + public function new(o : Sprite, tilesheet : Tilesheet) { + this.sprite = o; + this.tilesheet = tilesheet; + } + public function drawFrame(frame : SpritesheetFrame, offsetX : Float , offsetY : Float, smoothing : Bool) { + sprite.graphics.clear(); + tilesheet.drawTiles(sprite.graphics, [offsetX + frame.offsetX,offsetY + frame.offsetY, frame.tilesheetIndex], smoothing, flags); + } + public function enableFlag(flag : Flag) { + switch(flag) { + case BLEND_ADD: + flags = flags | Tilesheet.TILE_BLEND_ADD; + } + } + public function disableFlag(flag : Flag) { + switch(flag) { + case BLEND_ADD: + flags &= 0xFFFFFFF - Tilesheet.TILE_BLEND_ADD; + } + } +} \ No newline at end of file diff --git a/spritesheet/render/RenderWholeBitmapToGraphics.hx b/spritesheet/render/RenderWholeBitmapToGraphics.hx new file mode 100644 index 0000000..90ab39e --- /dev/null +++ b/spritesheet/render/RenderWholeBitmapToGraphics.hx @@ -0,0 +1,30 @@ +package spritesheet.render; + +import flash.display.Sprite; +import flash.display.BlendMode; +import spritesheet.AnimatedSprite; + +class RenderWholeBitmapToGraphics implements IRenderTarget { + private var sprite : Sprite; + public function new(o : Sprite) {this.sprite = o;} + public function drawFrame(frame : spritesheet.data.SpritesheetFrame, offsetX : Float, offsetY : Float, smoothing : Bool) { + var m = new flash.geom.Matrix(); + m.translate(offsetX + frame.offsetX, offsetY + frame.offsetY); + sprite.graphics.clear(); + sprite.graphics.beginBitmapFill(frame.bitmapData, m, false, smoothing); + sprite.graphics.drawRect(offsetX + frame.offsetX, offsetY + frame.offsetY ,frame.width, frame.height); + sprite.graphics.endFill(); + } + public function enableFlag(flag : Flag) { + switch(flag) { + case BLEND_ADD: + sprite.blendMode = BlendMode.ADD; + } + } + public function disableFlag(flag : Flag) { + switch(flag) { + case BLEND_ADD: + sprite.blendMode = BlendMode.NORMAL; + } + } +} \ No newline at end of file