Our flash game designer tools let you create your own online game in a flash!    TEST IT…

Create an Animated Sprite using a Sprite Sheet

The goal of this Tutorial is to show how a simple animated sprite can be created using a sprite sheet with the open source flash Push Button Engine.

Did you know that using the makeyourflashgame.com website you can easily create an animation’s spritesheet from a number of frames? Read it in this post

Download tutorial code file – AnimatedSprite01 (rar) PBE 1.0 code!

To run this example properly, in addition to making a development project with the AnimatedSprite01.as file, you need to put the spritesheet into the folder where your compiled swf is located.

See example of this tutorial in action

What is Sprite?

In computer graphics, a sprite is a two-dimensional/three-dimensional image or animation that is integrated into a larger scene.
http://en.wikipedia.org/wiki/Sprite_(computer_graphics)

What is Sprite Sheet?

A sprite sheet is a depiction of various sprites arranged in one image, detailing the exact frames of animation for each character or object by way of layout. These are either procured from still images of a game or created originally for use in sprite cartoons or video games. Sprite sheets are also used to store tiles for tile based video games.
http://en.wikipedia.org/wiki/Sprite_sheet

Create the Sprite Sheet…

The 3D rendered sprites for the spritesheet in this tutorial in this example were created using ZBrush for the star model and Blender 2.49a for the animation.

- Download sprite sheet star-green.png
- Download blender file + model (rar)
( render RGBA, premul on , to PNG separate files )

The 71 separate rendered single sprites where merged into a sprite sheet using a little (buggy but workable) application named SpriteStripComposer
( create an empty text file {filename}.png name before saving sheet over it and uncheck ‘open after save option’ )

Initialization of the tutorial application

In the application constructor the PBE is initialized, a scene is created and an animated sprite is added to the scene. We add an event listener to listen for mouse movement because we want the animated sprite rotate towards the mouse cursor.

The code for setting up a PBE scene was taken from the PushButton Engine Lesson #2: Adding a Simple Shape on the website of the Pushbutton Engine en is not covered in this tutorial.

         // Start up PBE
         PBE.startup(this);

         // Set up a simple PBE scene
		 PBE.initializeScene(new SceneView());

         // Create an animated sprite
         createAnimatedSprite("green", 0,0,"star-green.png",25,3,0,71,1);

         // lets add a MouseEvent.MOUSE_MOVE handler  so that we can rotate the animating sprite when the mouse moves
         PBE.mainStage.addEventListener(MouseEvent.MOUSE_MOVE, MainStageMouseMove);

         // create TextField for info display purposes
         txt = new TextField();
         txt.x = 10; txt.y = 10; txt.width = 350;

         // add TextField to main stage
         PBE.mainStage.addChild(txt);

function CreateAnimatedSprite(..)

We will create a function that will add an animated sprite to the Scene

/**
 * create an animated sprite providing spritesheet information
 *
 * params :
 *
 *   name:String		  		name of the IEnitity
 *   x:Number			  		x position of the animated sprite
 *   y:Number			  		y position of the animated sprite
 *   sheetname:String	  		filename/url to the spritesheet
 *   cellXCount:int				number of columns in the spritesheet
 *   cellYCount:int 			number of rows in the spritesheet
 *   startFrame:int				start frame of this animation
 *   targetFrame:int 			end frame of this animation
 *   animationSpeed:Number		animation speed in seconds
*/
private function CreateAnimatedSprite(name:String, x:Number, y:Number, sheetname:String, cellXCount:int, cellYCount:int, startFrame:int, targetFrame:int, animationSpeed:Number):void
{
    ....
}

We first need an IEntity that will hold several components that we need for rotating/moving (spatial) and rendering and animating

	       // Allocate an entity for our animated sprite
	       var animatedSprite01:IEntity = allocateEntity();
	       // Register the entity with PBE
	       animatedSprite01.initialize(name);

Now we need to setup the spritesheet. We need a SpriteSheetComponent and a CellCountDivider to provide the sprite sheet with the information about the sprite sheet’s matrix.

The Pushbutton Engine also has support of a FixedSizeDivider that divides the sprite sheet using a fixed width and height of each frame.

	 	   // Create the SpriteSheet
	       var animatedSpriteSheet:SpriteSheetComponent = new SpriteSheetComponent();

	       // By assigning the SpriteSheetComponent.ImageFilename, the image will be automaticly loaded
	       animatedSpriteSheet.imageFilename = sheetname;

	       // Create a CellCountDivider to specify the number of columns and rows of our spritesheet
	       var spriteSheetDivider:CellCountDivider= new CellCountDivider();
	       spriteSheetDivider.xCount = cellXCount;
	       spriteSheetDivider.yCount = cellYCount;

	       // Hook up the SpriteSheetDivider
	       animatedSpriteSheet.divider = spriteSheetDivider;

Next step is to create a SpriteSheetRenderer and link that to the sprite sheet.

The SpriteSheetRenderer has a spriteIndex property that can be used to set which frame from the linked sprite sheet must be displayed. It defaults to 0 – the first frame of the sprite sheet.

In this tutorial we will use an AnimatorComponent to control that spriteIndex property through an ‘Idle’ animation.

	       // Create a sprite render component to display our animation
	       var spriteRender:SpriteSheetRenderer = new SpriteSheetRenderer();         

	       // assign the scene so this animatied sprite will we drawn.
	       spriteRender.scene = PBE.scene; 

	       // Assign the spritesheet to the sprite
	       spriteRender.spriteSheet = animatedSpriteSheet;

	       // Add our render component to the Animated Sprite Entity
	       animatedSprite01.addComponent( spriteRender, "render" );

An AnimatorComponent holds all possible animations from a specific IEntity (defaults to ‘Idle’) . Each animation is created by an Animator object.

An animation progresses from a startframe number to and endframe number in a specific time and with a specific AnimatorType.

By setting a reference from the AnimatorComponent to the SpriteRenderComponent’s property spriteIndex the AnimatorComponent has control over what frame of the linked sprite sheet is displayed.

	       // Create the animator component that will hold all animations for the sprite
	       var spriteAnimator:AnimatorComponent = new AnimatorComponent();

	       // Create the Animation Dictionary because it defaults to null
	       spriteAnimator.animations = new Dictionary();

	       // Create an Animator object for the Idle animation
	       // The animation will loop forever
	       var idleAnimation:Animator = new Animator();

	       // set the animation speed
	       idleAnimation.duration = animationSpeed;

	       // keep repeating
	       idleAnimation.repeatCount = -1;							

	       // This animation will be of the loop kind.
	       idleAnimation.animationType = AnimatorType.LOOP_ANIMATION;

	       // set start and endframe of this animation
	       idleAnimation.startValue = startFrame;
	       idleAnimation.targetValue = targetFrame;							

	       // Add the 'Idle' Animator
	       spriteAnimator.animations["Idle"] = idleAnimation;

	       // Add our Animator Component to the Animated Sprite Entity
	       animatedSprite01.addComponent( spriteAnimator,"animator");

The AnimatorComponent needs a reference to the the spriteIndex property of the SpriteRenderComponent so it will adjust the spriteIndex , a frame on the spritesheet, as the animation progresses.

       // Add Property Reference to the SpriteIndex of the Sprite Render Component
       spriteAnimator.reference = new PropertyReference("@render.spriteIndex");

Rotating the animating sprite towards the mouse cursor.

In our MouseMove event handler we want to capture the screen mouse coordinates and map these to the PBE Scene world, calculate the angle towards the mouse cursor and adjust the rotation of the animated sprite render component.

We can map screen to world coordinates using the PBE.scene:IScene2D property. IMPORTANT! The PBE.scene property is only usable if we created our scene using the function PBE.initializeScene(vw:SceneView)

We can set the rotation of the Animated Sprite IEntity by setting the rotation of the SpriteSheetRenderer. We can find the renderer using the PBE.nameManager class.

	       // transform screen mouse coordinates to world coordinates
	       var worldPoint:Point = PBE.scene.transformScreenToWorld(new Point(event.stageX,event.stageY));

	       // calculate the angle between the mouse world coordinates and the horizontal axes
	       var rotationAngle:Number = Math.round((Math.atan2( worldPoint.y, worldPoint.x) * 180 ) / Math.PI);

	       // display status label
		   txt.text = "PBE : mouse world coords " + Math.round(worldPoint.x)+","+Math.round(worldPoint.y) + " ( angle "+rotationAngle+" degrees )";	    			

	       // lookup the animated sprite render component
	       var render:SpriteSheetRenderer = PBE.nameManager.lookupComponentByName("green", "render") as SpriteSheetRenderer;

	       // set animated sprite rotation angle on the render component
	       render.rotation = rotationAngle;

Download tutorial code file – AnimatedSprite01 (rar) PBE 1.0 code!

To run this example properly, in addition to making a development project with the AnimatedSprite01.as file, you need to put the spritesheet into the folder where your compiled swf is located.

See example of this tutorial in action

The level based approach

As some people pointed out to me, there is another approach to accomplish the above. The pushbutton engine supports deserialized component creation by providing a level description file and one or more level files.

The level description file provides information about the levels available to the game application and is xml based. Each level can consist of a level file and a group name. When a specific level is started,
the level file is loaded and the group’s entities are deserialized.

<LevelDescriptions>
   <level index="1" name="level1">
      <file filename="AnimatedSprite02.pbelevel"/>
      <group name="animatedSprite02"/>
   </level>
</LevelDescriptions>

Our example uses one level file named AnimtedSprite02.pbelevel and uses the group AnimatedSprite02.

The level file for our example is a serialized (xml based) document describing all components, objects and properties that need to be created. This file replaces the CreateScene and CreateAnimatedSprite functions of the AnimatedSprite01 source example.

<things version="1">
  <entity name="scene">
	<component type="com.pblabs.rendering2D.DisplayObjectScene" name="scene">
	  <sceneView type="com.pblabs.rendering2D.ui.SceneView" >
		  <width>400</width>
		  <height>300</height>
	  </sceneView>
	  <position>
		<x>0</x>
		<y>0</y>
	  </position>
	</component>
  </entity>
  <entity name="animatedSprite">
    <component type="com.pblabs.animation.AnimatorComponent" name="spriteAnimations">
      <animations childType="com.pblabs.animation.Animator">
        <idle type="">
          <animationType>LOOP_ANIMATION</animationType>
          <duration>1</duration>
          <repeatCount>-1</repeatCount>
          <startValue type="int">0</startValue>
          <targetValue type="int">71</targetValue>
        </idle>
      </animations>
      <defaultAnimation>idle</defaultAnimation>
      <reference>@render.spriteIndex</reference>
    </component>
    <component type="com.pblabs.rendering2D.spritesheet.SpriteSheetComponent" name="animatedSpriteSheet">
      <divider type="com.pblabs.rendering2D.spritesheet.CellCountDivider">
        <xCount>25</xCount>
        <yCount>3</yCount>
      </divider>
      <image filename="star-green.png"/>
    </component>
	<component type="com.pblabs.rendering2D.SpriteSheetRenderer" name="render" >
	  <spriteSheet componentName="animatedSpriteSheet" />
      <scene entityName="scene" componentName="scene"/>
	  <spriteIndex>0</spriteIndex>
	</component>
  </entity>
  <group name="animatedSprite02">
	<objectReference name="scene"/>
	<objectReference name="animatedSprite"/>
  </group>
</things>

By telling the Levelmanager to load and start the level in the application constructor, we don’t need to create a scene or add an animated sprite. The engine does it all automaticly for us.

// Deserialize scene and animated sprite from level file.
     PBE.levelManager.load("levelDescriptions.xml",1);

Because the information about components that need to be created is external, it is important to reference the used component classes and objects so that they are available when deserialization takes place.

This can be done by using a References.mxml file like you can see working in the PushButton PBEngineDemo if you would download it. However .. because I create Flexless ( read Actionscript Only ) appplications I can not use mxml so I need to code the references. Creating a function that creates local variables of the needed Component Classes will do the trick.

private function References()
{
			var _refScene2DComponent:IScene2D;
			var _refSceneView:SceneView;
			var _refAnimatorComponent:AnimatorComponent;
			var _refCellCountDivider:CellCountDivider;
}

To transform the coordinates in this example we have to get the scene using a lookup instead of using PBE.scene because we didn’t use the PBE.initializeScene function.

	       // lookup the Scene2D component
	       var Scene2D:IScene2D = PBE.lookupComponentByName("scene", "scene") as IScene2D;

	       // transform screen mouse coordinates to world coordinates
	       var worldPoint:Point = Scene2D.transformScreenToWorld(new Point(event.stageX,event.stageY));

Download tutorial code file AnimatedSprite02 – using level files (rar) PBE 1.0 code!

To run this example properly, in addition to making a development project with the AnimatedSprite01.as file, you need to put the spritesheet into the folder where your compiled swf is located.

Download Level files for the AnimatedSprite02 example (rar)
( place level files into the same folder as the .swf )

See example of this tutorial in action

Did you know that using the makeyourflashgame.com website you can easily create an animation’s spritesheet from a number of frames? Read it in this post

Tags: ,

5 Responses to “Create an Animated Sprite using a Sprite Sheet”

  1. Jos says:

    Nice tutorial. The only gripe I can come up with is the use of capitals at the begining of var names. But that’s a pretty minor stylistic issue ;) .

  2. Phil Peron says:

    Great job! I wasn’t sure where to comment so I did so in the PBE forums. :)

  3. shi503 says:

    in order to run these in the rev 888 and higher, you must change the code.

    NameManager.instance.lookupComponentByName(“green”, “Spatial”) has been depreciated and is now relpaced with.

    PBE.lookupComponentByName(“green”, “Spatial”)

  4. mas says:

    True,

    I didn’t get to refactor all the samples , but I will do so when we hit version 1.0 with
    PBE and make a new post for it with revised code for the different samples.

  5. This is awesome, I cant wait to see what else the engine can do.

Leave a Reply

Spam Protection by WP-SpamFree