123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package h2d;
- /**
- Displays an animated sequence of bitmap Tiles on the screen.
- Anim does not provide animation sequence management and it's up to user on how to implement it.
- Another limitation is framerate. Anim runs at a fixed framerate dictated by `Anim.speed`.
- Switching animations can be done through `Anim.play` method.
- Note that animation playback happens regardless of Anim visibility and only can be paused by `Anim.pause` flag.
- Anim should be added to an active `h2d.Scene` in order to function.
- **/
- class Anim extends Drawable {
- /**
- The current animation, as a list of tile frames to display.
- If the frames are empty or if a tile is frames is null, a pink 5x5 bitmap will be displayed instead.
- **/
- public var frames(default,null) : Array<Tile>;
- /**
- The current frame the animation is currently playing. Always in `[0,frames.length]` range.
- Use `Std.int(anim.currentFrame)` in order to obtain current frame index.
- Fractional value represents the progress of current frame and increases according to `Anim.speed` value.
- Setting frame to a negative value will wrap it around from the end of the animation. Setting negative value smaller than `-frames.length` lead to undefined behavior.
- Setting frame to a value greater than `frames.length` would cause to wrap around.
- **/
- public var currentFrame(get,set) : Float;
- /**
- The speed (in frames per second) at which the animation is playing.
- Settings speed to a negative value is not supported and leads to undefined behavior.
- **/
- public var speed : Float;
- /**
- Setting pause will suspend the animation, preventing automatic accumulation of `Anim.currentFrame` over time.
- **/
- public var pause : Bool = false;
- /**
- Disabling loop will stop the animation at the last frame.
- **/
- public var loop : Bool = true;
- /**
- When enabled, fading will draw two consecutive frames with alpha transition between
- them instead of directly switching from one to another when it reaches the next frame.
- This can be used to have smoother animation on some effects.
- **/
- public var fading : Bool = false;
- var curFrame : Float;
- /**
- Create a new animation with the specified frames, speed and parent object.
- @param frames An optional array of Tiles as an initial `Anim.frames` value.
- @param speed The Anim playback speed in frames per second.
- @param parent An optional parent `h2d.Object` instance to which Anim adds itself if set.
- **/
- public function new( ?frames : Array<Tile>, speed : Float = 15, ?parent : h2d.Object ) {
- super(parent);
- this.frames = frames == null ? [] : frames;
- this.curFrame = 0;
- this.speed = speed;
- }
- inline function get_currentFrame() {
- return curFrame;
- }
- /**
- Change the currently playing animation and unset the pause if it was set.
- @param frames The list of frames to play.
- @param atFrame Optional starting frame of the new animation.
- **/
- public function play( frames : Array<Tile>, atFrame = 0. ) {
- this.frames = frames == null ? [] : frames;
- currentFrame = atFrame;
- pause = false;
- }
- /**
- Sent each time the animation reaches past the last frame.
- If `loop` is enabled, callback is sent every time the animation loops.
- During the call, `currentFrame` is already wrapped around and represent new frame position so it's safe to modify it.
- If `loop` is disabled, callback is sent only once when the animation reaches `currentFrame == frames.length`.
- During the call, `currentFrame` is always equals to `frames.length`.
- **/
- public dynamic function onAnimEnd() {
- }
- function set_currentFrame( frame : Float ) {
- curFrame = frames.length == 0 ? 0 : frame % frames.length;
- if( curFrame < 0 ) curFrame += frames.length;
- return curFrame;
- }
- override function getBoundsRec( relativeTo : Object, out : h2d.col.Bounds, forSize : Bool ) {
- super.getBoundsRec(relativeTo, out, forSize);
- var tile = getFrame();
- if( tile != null ) addBounds(relativeTo, out, tile.dx, tile.dy, tile.width, tile.height);
- }
- override function sync( ctx : RenderContext ) {
- super.sync(ctx);
- var prev = curFrame;
- if (!pause)
- curFrame += speed * ctx.elapsedTime;
- if( curFrame < frames.length )
- return;
- if( loop ) {
- if( frames.length == 0 )
- curFrame = 0;
- else
- curFrame %= frames.length;
- onAnimEnd();
- } else if( curFrame >= frames.length ) {
- curFrame = frames.length;
- if( curFrame != prev ) onAnimEnd();
- }
- }
- /**
- Returns the Tile at current frame.
- **/
- public function getFrame() : Tile {
- var i = Std.int(curFrame);
- if( i == frames.length ) i--;
- return frames[i];
- }
- override function draw( ctx : RenderContext ) {
- var t = getFrame();
- if( fading ) {
- var i = Std.int(curFrame) + 1;
- if( i >= frames.length ) {
- if( !loop ) return;
- i = 0;
- }
- var t2 = frames[i];
- var old = ctx.globalAlpha;
- var alpha = curFrame - Std.int(curFrame);
- ctx.globalAlpha *= 1 - alpha;
- emitTile(ctx, t);
- ctx.globalAlpha = old * alpha;
- emitTile(ctx, t2);
- ctx.globalAlpha = old;
- } else {
- emitTile(ctx,t);
- }
- }
- }
|