A Flash Developer Resource Site

Page 1 of 2 12 LastLast
Results 1 to 20 of 24

Thread: [as3] Sprites, sprite sheets, animations, displays

  1. #1
    SaphuA SaphuA's Avatar
    Join Date
    Oct 2002
    Location
    The Netherlands
    Posts
    2,182

    [as3] Sprites, sprite sheets, animations, displays

    Hi there,

    Has anyone been working on some decent as3 projects containing classes for support sprites, sprite sheets, animations or displays. Or ever thought about creating them?

    How would you handle these things or how are you handling them at the moment? I'm working on a simple version of this but might expand it a little depending on the information I'll get

    Just something I thought of one day, will see where it gets

  2. #2
    FK founder & general loiterer Flashkit's Avatar
    Join Date
    Feb 2000
    Location
    Sydney
    Posts
    1,149
    i use a mc -> bitmapdata array class

    Code:
    package com.markfennell.display
    {
    	
    	import flash.display.*;
    	import flash.geom.Rectangle;
    	import flash.geom.Point;
    	import flash.geom.Matrix;
    	
    	public class BitmapSprite extends Sprite
    	{
    		private var BitmapDataTile:BitmapData
    		private var BitmapDataArray:Array
    		
    		private var copyRectangle:Rectangle
    		private var copyPoint:Point
    		private var transformMatrix:Matrix
    		
    		private var _w:Number
    		private var _h:Number
    		private var _frames:Number
    		private var xScale:Number
    		private var yScale:Number
    		private var rotScale:Number
    		
    		
    		
    		private var stepX:Number
    		private var stepY:Number
    		private var stepRot:Number
    		
    		
    	
    		public function BitmapSprite(mc:MovieClip, w, h, x0, x1, y0, y1, rot0, rot1, frames)
    		{
    			/*  	
    			
    				mc : source movie clip
    				
    				for rotation must be centered on point of rotation
    				
    				w - bitmap Sprite Width
    				h - bitmap sprite Height 				
    				
    				x0 - startScaleX: pixels
    				x1 - endScaleX: pixels 
    				y0 - startScaleY: pixels
    				y1 - endScaleY: pixels
    				rot0 - startRot: degrees
    				rot1 - endRot: degrees
    				
    				frames = frames: Number
    				
    			*/
    			
    			_frames = frames
    			_w = w
    			_h = h
    			BitmapDataArray = []
    			
    			// percentage of original size
    			xScale = x0
    			yScale = y0
    			rotScale = rot0
    		
    			stepX = (x1-x0)/frames
    			stepY = (y1-y0)/frames		
    			stepRot = (rot1-rot0)/frames		
    			
    			copyRectangle = new Rectangle(0,0,_w,_h)
    		
    			
    			for (var i=0; i<frames; i++)
    			{
    				BitmapDataTile = new BitmapData(w, h, true, 0x00FFFFFF);
    				transformMatrix = new Matrix()
    					
    				
    				transformMatrix.scale(xScale,yScale)
    				
    				transformMatrix.rotate(rotScale)
    				transformMatrix.tx = w / 2 
    				transformMatrix.ty = h / 2
    					
    
    				BitmapDataTile.draw(mc, transformMatrix);
    				BitmapDataArray.push(BitmapDataTile)
    		
    					
    				xScale += stepX
    				yScale += stepY
    				rotScale += stepRot
    				
    				}
    		
    		}
    		
    		public function getFrames():int
    		{
    			return _frames
    		}
    		
    		public function getBitmap(position:Number)
    		{
    			if (position < 0) position = 0
    			if (position >= BitmapDataArray.length) position = BitmapDataArray.length-1
    			
    			return BitmapDataArray[position]
    
    		}
    		
    		public function getWidth():Number
    		{
    			return _w
    		}
    		public function getHeight():Number
    		{
    			return _h
    		}
    		
    		public function draw(target:BitmapData, x:Number, y:Number, position:int)
    		{
    			if (position < 0) position = 0
    			if (position >= BitmapDataArray.length) position = BitmapDataArray.length-1
    			
    			copyPoint = new Point(x-_w/2, y-_h/2)
    			target.copyPixels(getBitmap(position), copyRectangle, copyPoint, null, null, true);
    			return
    		}
    		
    	}
    }
    basically I generate from a mc an array of bitmap data objects, it also has a draw function in there to draw it to what ever bitmap data object I am using.

    It aint genius, but it works and plays nice (I used it on vector www.markfennell.com/flash/vector )
    Regards Mark Fennell - Flash Kit Founder, general loiterer
    -------------------------------
    I Hate Zombies - iPhone Game | markfennell.com

  3. #3
    SaphuA SaphuA's Avatar
    Join Date
    Oct 2002
    Location
    The Netherlands
    Posts
    2,182
    Ah kewl, that's basicly how I have it now:


    Result:


    Source:
    http://www.saphua.com/temp/game.rar

    What I'm trying to do now is get some decent animation. I can't realy decide how to do work this out, making it time or frame based and where to handle the changing of frames.

    [Ps. Please note that this was build with VengeanceMX's CopyPixels source in mind]
    Last edited by SaphuA; 12-13-2007 at 10:34 AM.

  4. #4
    n00b LeechmasterB's Avatar
    Join Date
    May 2004
    Location
    Switzerland
    Posts
    1,067
    Out of curiosity, what tool did you use to create the class diagram in the first screenshot?
    I do stuff that does stuff...

    J-Force

  5. #5
    SaphuA SaphuA's Avatar
    Join Date
    Oct 2002
    Location
    The Netherlands
    Posts
    2,182
    Visual Studio 2005

  6. #6
    n00b LeechmasterB's Avatar
    Join Date
    May 2004
    Location
    Switzerland
    Posts
    1,067
    Thanks
    I do stuff that does stuff...

    J-Force

  7. #7
    SaphuA SaphuA's Avatar
    Join Date
    Oct 2002
    Location
    The Netherlands
    Posts
    2,182
    So anyone got some idea's?

    There are quite some flaws and missing things with the current systen:
    - Animations:
    How the hell am I going to handle this? Should a Sprite handle it's animations? Does this mean that every sprite should keep track of it's own timer to calculate what frame to show?
    - SpriteSheets:
    Should I make one SpriteSheet for each animation, or should there be several animations within each SpriteSheet?
    Last edited by SaphuA; 12-14-2007 at 08:25 AM.

  8. #8
    Professional Flash Developer
    Join Date
    Aug 2007
    Location
    California
    Posts
    105
    This is one of my favorite subjects, so here is a brief rundown of my latest version. I am always working to improve my engine, but here is how I currently handle animation with Bitmapdata.

    1. My basicGameSprite class contains a generic object called bitmapStateObject which is used as an associative array of STATES for the sprite. For instance, in my latest game, the player can move up, down, right and left. Those 4 states are added to the object and each contains an array of BitmapData that represents the frames of animation for that state.

    2. aSpriteBitmapData is a reference to the above state array of BitmapData for which ever current state the player is in.

    3. spriteBitmapDataIndex is an int that holds the index of the current frame of animation

    4. animationFrameDelay holds is an int the holds the number of frames to wait between each frame (before moving on to the next frame)

    5. animationFrameCount is a count of frames between animation changes, so when it == animationFrameDelay, I increase spriteBitmapDataIndex by 1 or loop back to 0 if it is == aSpriteBitmapData.length

    6. My screen is one bitmapData object called gameScreenBD. On each frame, first the background draws itself to the gameScreenBD, then the tiles are drawn to it.

    7. My main GamePlay class then dispatches an event called UPDATE. Each basicGameSprite listens for this event and updates the animationFrameCount and related varaibles described above.

    8. My main GamePlay class next dispatches an event called RENDER. Each basicGameSprite listens for this event, and then draws itself to the gameScreenBD.

    Those are the basics, but it seems to work very fast.

    Jeff Fulton
    www.8bitrocket.com

  9. #9
    M.D. mr_malee's Avatar
    Join Date
    Dec 2002
    Location
    Shelter
    Posts
    4,139
    8bitjeff, that sounds like a really nice way to handle it. I like it all except for the listeners thing, how many sprites have you tested this with?
    lather yourself up with soap - soap arcade

  10. #10
    Professional Flash Developer
    Join Date
    Aug 2007
    Location
    California
    Posts
    105
    Good question. Before I put AI, dynamic BitmapData color transformation filters, and collision detection, I had 1000 of my enemy running around the maze and animating easily at 40FPS. With all of those things added, I easily have 200+ running at 40 FPS now.
    I completely understand the why you would not like the listener approach, so it can easily be replaced with a loop through each array of objects. The main GamePlay class already maintains arrays of instances of enemies, explosions, animated tiles, etc. You could just as easily loop through them and call the update() and render() functions.

    I was not going to use an event based model in my new game at all, but I experimented with it and found that it runs nicely in a synchronous manner, and doesn't add any overhead beyond what the loops through arrays already do. In fact, the event dispatchers need to loop through arrays anyway, but they seem to do it a little faster than the normal iteration of a loop. Maybe the EventDispatcher class uses ByteArrays and optimized iterating structures. In any case, the event model makes it really easy to pause the game because I just set the game into a state when the render function isn't called.

    Without events, the exact same thing can be accomplished by just not calling the function that loops through all of the arrays of objects (so update() and render() are not called) in a PAUSED state.

    Anyway, I hope that helps.

    -Jeff
    www.8bitrocket.com

  11. #11
    hippie hater Cimmerian's Avatar
    Join Date
    Oct 2006
    Location
    over there
    Posts
    599
    Update with EventDispatcher faster than with function calls?How are you testing that?
    I mean, there is a listener function for each object that will be updated?
    Last edited by Cimmerian; 12-15-2007 at 12:42 AM.

  12. #12
    Professional Flash Developer
    Join Date
    Aug 2007
    Location
    California
    Posts
    105
    There are some code profilers out there that can test is down to the millisecond (Squize has one in his blog I think - at www.gamingyourway.com), but I just used my frame rate counter and pumped up the number of objects on the screen with each until I got a noticeable slowdown. It wasn't scientific, but it showed me that the event driven version of my engine was not fundamentally slower than the function call version. Both basically were doing the same thing, looping through arrays and calling functions. The extra overhead of the listeners certainly adds memory to the application through.

    Now, the vector rendered and GAS version of my game's engine WAS very much slower than the BitmapData / Sprite Array version. Since I was trying to get as much performance from the animation engine as possible, I focused on that instead.

    I'm not saying this would be the case with every game, but when I started to optimize my current game's engine, I didn't find it affected adversely by the event driven model.

    I am sure if I ran a code profiler I would see the actual event model eating up more cycles per frame, but since I was able to maintain my frame rate through an optimized rendering engine I didn't notice it w/o one. I was still able to pump put the necessary Bitmaps in the time needed to get the game running smoothly on the screen.

    Now, I did find some big problems with the Event model and garbage collection until I recreated all of my listeners with weak references.

    Anyhow, I hope to get more ideas from you guys about how to optimize. Has anyone run a code profiler on an event model v. a method call model to see the difference in execution time?

  13. #13
    hippie hater Cimmerian's Avatar
    Join Date
    Oct 2006
    Location
    over there
    Posts
    599
    About animations, this is how i handle for now (not such a great code,there is a lot of things to improve but you can get the main idea)
    I have an array of bitmapDatas, a class mainObject with a frameD property and another class that each frame will get the frameD and copy pixels from the bitmapData wich index is the same as the frameD to the main bitmap
    The array of BitmapDatas is made looping in a movieClip and drawing each frame to a bitmapData
    The mainObject class has some methods like

    addInFrameGoToAndPlay(frame:int, to:int)
    wich means when frameD is equal to frame it will jump to frame to and keep going, so its like a workaround to put your gotoAndStops and gotoAndPlays but without a timeline and have all the animations in the same array of bitmapDatas
    This is the code(dont expect an amazing piece of art, its just to get the idea)
    /*
    frameD is the var that tells what bmdt to copy pixels
    frameD is the current frame

    the frame that have a goto... is not shown

    */


    package{

    public class mmc{

    public var isActive:Boolean;
    public var x,y:Number;

    public var frameD:int;

    var stoped:Boolean;
    var totalFrames:int;

    var frameInfo:Array;

    public var depth:Number;

    public function mmc(tt:int){
    isActive = false;
    frameD = 0;
    stoped = true;
    totalFrames = tt;
    frameInfo = new Array();
    //create frameData for all frames
    for(var i:int = 1; i<= totalFrames ; i++){
    frameInfo[i] = new frameData();
    }
    }

    public function oef(){
    if(stoped == false){
    //update frame
    frameD++;
    if(frameD > totalFrames){
    frameD = 1;
    }

    //see if this frame has stop, gotoAndPlay or gotoAndStop
    if(frameInfo[frameD].hasStop){
    stoped = true;
    }
    if(frameInfo[frameD].hasGoToAndPlay){
    frameD = frameInfo[frameD].frameToGoAndPlay;
    stoped = false;
    }
    if(frameInfo[frameD].hasGoToAndStop){
    frameD = frameInfo[frameD].frameToGoAndStop;
    stoped = true;
    }


    }
    }

    public function activate(obj:Object){
    isActive = true;
    }

    public function unActivate(){
    isActive = false;
    }

    public function addInFrameGoToAndPlay(frame:int, to:int){
    if(to <0 ){
    trace("cant send to frame "+to);
    }
    if(to>totalFrames){
    trace("cant send to frame "+to);
    }
    frameInfo[frame].hasGoToAndPlay = true;
    frameInfo[frame].frameToGoAndPlay = to;
    }

    public function addInFrameGoToAndStop(frame:int, to:int){
    if(to <0 ){
    trace("cant send to frame "+to);
    }
    if(to>totalFrames){
    trace("cant send to frame "+to);
    }
    frameInfo[frame].hasGoToAndStop = true;
    frameInfo[frame].frameToGoAndStop = to;
    }

    public function removeInFrameGoToAndPlay(frame:int){
    frameInfo[frame].hasGoToAndPlay = false;
    frameInfo[frame].frameToGoAndPlay = -1;
    }

    public function removeInFrameGoToAndStop(frame:int){
    frameInfo[frame].hasGoToAndStop = false;
    frameInfo[frame].frameToGoAndStop = -1;
    }

    public function goToAndPlay(to:int){
    frameD = to;
    stoped = false;
    }

    public function goToAndStop(to:int){
    frameD = to;
    stoped = true;
    }

    public function putStop(to:int){
    frameInfo[to].hasStop = true;
    }

    public function removeStop(to:int){
    frameInfo[to].hasStop = false;
    }

    public function stop(){
    stoped = true;
    }

    public function play(){
    stoped = false;
    }





    }

    }

    class frameData{
    public var hasStop:Boolean = false;
    public var hasGoToAndPlay:Boolean = false;
    public var hasGoToAndStop:Boolean = false;
    public var frameToGoAndPlay:int = -1;
    public var frameToGoAndStop:int = -1;
    }
    Last edited by Cimmerian; 12-15-2007 at 06:56 AM.

  14. #14
    Heli Attack! iopred's Avatar
    Join Date
    Jun 2003
    Location
    Sydney, Australia
    Posts
    923
    Running a function call is much faster than EventDriving something.

    As for my way, I have an Animation class that handles a single animation, frame numbers, and time (in ms) until the next frame, and a loop count.

    Animation.as
    Code:
    /**
    * ...
    * @author iopred
    * @version 0.1
    */
    
    package com.iopred.sol.display 
    {
    
    	public class Animation 
    	{
    		public static var INFINITE:int = -1;		
    		
    		protected var name:String;
    		protected var loops:int;
    		protected var frames:Array;		
    		
    		public function Animation(name:String, loops:int = 0)
    		{
    			this.name = name;
    			this.loops = loops;
    			this.frames = new Array();
    		}
    		
    		public function clone():Animation
    		{
    			var a:Animation = new Animation(this.name, this.loops);
    			
    			for(var i:int = 0; i < this.frames.length; i++)
    			{
    				a.addFrame(this.frames[i].frame, this.frames[i].time);
    			}
    			
    			return a;
    		}
    		
    		public function addFrame(frame:int, time:int = -1):void
    		{
    			this.frames.push(new Frame(frame, time));
    		}
    		
    		public function getFrames():int
    		{
    			return this.frames.length;
    		}
    		
    		public function getFrame(frame:int):int
    		{
    			return this.frames[frame].frame;
    		}
    		
    		public function getTime(frame:int):int
    		{
    			return this.frames[frame].time;
    		}
    		
    		public function getLoops():int
    		{
    			return this.loops;
    		}
    		
    		public function getName():String
    		{
    			return this.name;
    		}
    		
    		public static function fromXML(xml:XML):Animation
    		{
    			var animation:Animation = new Animation(xml.@name, parseInt(xml.@loops));
    			
    			var frameList:XMLList = xml..frame;
    			
    			for(var i:int = 0; i< frameList.length(); i++)
    			{
    				var frame:XML = frameList[i];
    				animation.addFrame(parseInt(frame.@frame), parseInt(frame.@time));
    			}
    			
    			return animation;
    		}
    	}
    }
    
    class Frame
    {
    	public var frame:int;
    	public var time:int;
    	
    	public function Frame(frame:int, time:int)
    	{
    		this.frame = frame;
    		this.time = time;
    	}
    }
    My classes that are animated implement IAnimatable, which looks like this:

    IAnimatable.as
    Code:
    package com.iopred.sol.display 
    {
    
    	public interface IAnimatable extends IDrawable
    	{
    		function animate(ms:int):void;
    		
    		//The following functions operate on the current animation only, and are affected by loop counts
    		function play():void;
    		function stop():void;
    		function nextFrame():void;
    		function prevFrame():void;
    		
    		function isFinished():Boolean;
    		
    		//The following functions operate on the current animation AND in the current loop only
    		function goto(frame:int):void;
    		function gotoAndStop(frame:int):void
    		function gotoAndPlay(frame:int):void
    		
    		//The following functions change the 'timeline' to a different animation			
    		function setAnimation(name:String):void;
    		function getCurrentAnimation():Animation;
    		
    		function getAnimation(name:String):Animation;
    		function addAnimation(animation:Animation):void;
    		function removeAnimation(name:String):void;
    	}
    	
    }
    The game I'm working on at the moment is 100% bitmapData, so my Tilesheet class (which implemenst IAnimatable) simply uses the frame info from the Animation class to set the Rectangle to copyPixels from.
    Last edited by iopred; 12-15-2007 at 06:56 AM.
    Christopher Rhodes
    squarecircleco.

  15. #15
    SaphuA SaphuA's Avatar
    Join Date
    Oct 2002
    Location
    The Netherlands
    Posts
    2,182
    Ah thanks for the replies guys, I was already wondering where ya'll were waiting for

    I like the idea of adding multiple animations to a sprite, and then be able switch between them. Kind lika working with framelabels.

    You guys feel anything for a FKG framework?

    Iopred, mind sharing a class diagram? You seem to have worked out quite something there.
    Last edited by SaphuA; 12-15-2007 at 10:31 AM.

  16. #16
    Professional Flash Developer
    Join Date
    Aug 2007
    Location
    California
    Posts
    105
    I spent a few hours trying to build an as3 code profiler using the new Timer class and failed miserably. It seems that the code executes before the timer even has a chance to fire off an event and count.

    I simply wrote a class that creates 10000 objects and then counts the number Timer.TimerEvents events fired to call a render() event on those 10000 and broadcast an event to do the same thing. They both came out at 0, which is completely odd. After digging deeper, I saw that the Timer.TimerEvent didn't get one call until AFTER all of the processing was complete, even though I set it to start and stop between each process and deliver its currentCount property as a trace.

    I then investigated an as3 code profiler from Manuel’s Coding blog (http://manuel.bit-fire.com/2007/10/17/an-as3-profiler/ ) but couldn’t get it to work in the Flash CS3 IDE.

    Anyway, if someone knows of a good AS3 profiler, or can get the above one to work in the IDE, I’d love to test it out.

  17. #17
    Manic
    Join Date
    Jan 2004
    Location
    Denmark
    Posts
    154
    Quote Originally Posted by Flashkit
    i use a mc -> bitmapdata array class

    Code:
    ....
    basically I generate from a mc an array of bitmap data objects, it also has a draw function in there to draw it to what ever bitmap data object I am using.

    It aint genius, but it works and plays nice (I used it on vector www.markfennell.com/flash/vector )
    Ohh pretty nice game.
    I wrote a very simple sprite class that works a lot like this.

    The only real difference is that I copy the graphics out of movieclips instead of a larger bitmap.

    A demo running 15.000 sprites at once can be found here http://chrisbenjaminsen.com/stuff/SpriteTest.swf
    Source
    http://chrisbenjaminsen.com/stuff/SpriteTest.fla

  18. #18
    Developer
    Join Date
    Apr 2007
    Location
    UK
    Posts
    324
    I have a 3 year old computer at work and that runs quite slowly. Looks nice though.

  19. #19
    Anyone else have some insite on how they handle these sort of things? Trying to get into building an AS3 game and would be interested in seeing what others are doing...

    pred your classes look very well stuctured and thought out

  20. #20
    Professional Flash Developer
    Join Date
    Aug 2007
    Location
    California
    Posts
    105
    Over the last week I took some time to write an app that will do speed test calculations on both FPS and execution times for rendering engines. I posted the full results at my site: http://www.8bitrocket.com/newsdispla...?newspage=7496.

    Basically, I got the BEST performance in a 15000 object test with an array of Bitmapdata objects each blitting to a single output objects using a loop through an array to call the update. I was able to get 8FPS doing this, but Mike Gundvig says he can get 17FPS, so my machine must be a little lacking.

    Also, a close second was my test replacing the array of BitmapData objects with a spriteSheet. I change the rectangle property of the copyPixels() method on the sheet to output the animation. I think this is similar to the scrollrect versions people have been talking about.

    I did find that a loop through an array of objects is faster and uses less memory than an EVENT, but the speed difference may not be great enough to completely abandon the advantages of an event model.

    One interesting note it the single display object uses much more execution time than the individual display objects. The caveat is that the single display object can actually pump out more than 10,000 objects to the screen while the individual display object engines seem to start failing at anything other 10,000. For a limited number of on screen objects (1-1000), the use of individual display objects might prove useful because the execution time savings will allow for more collision detection, and AI.

    -Jeff

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center