GrizzlyBear1010

In XNA GSE 1.0, I've been looking at a few how-to articles in the documentation. The first few I tried were quite good, but I'm having a problem with the "How To: Animate a Sprite" tutorial. I made a single texture with four frames in it, all the same size (I believe the texture is 255 X 92 pixels, or close to that). I typed in all the code exactly what it's like in the tutorial, but when I run the program, only the first three frames play. Then, they loop back and play again and again, as if only three frames were there. Does anyone know why

Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

easlern

Can you post the code that cycles the frames, please



Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

Darkside

Possibly just a simple thing, dont forget that array's start @ 0, or you are reseting the animateindex to soon.

If you have your animated class picking up the next frame make sure it knows this!!

Rgds Darkside






Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

Bill Reiss

This brings up a good question for the XNA team, is there any way you could make the source code for the samples available either as a download or at least a file-by-file source listing in the doc There have been a few instances where someone has followed the tutorials and received unexpected results and it's hard to track down the problem since there's no easy way to tell what was mistyped.

Bill






Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

wakawaka54

Well I have never looked at the tutorial before but I can post two classes I made that cycle through frames. These classes are from my half complete JumpCannonEngine which works with XNA. I created them during the XNA Beta 1 hoping to get some fame from it, but it turned out that making an engine isn't so easy. Anyways these classes are some of my completed ones.

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Graphics;

namespace JumpCannonEngine.Graphics

{

/// <summary>

/// A Size Structure to use for the JumpCannonEngine

/// </summary>

public struct Size2

{

/// <summary>

/// Gets or set the height

/// </summary>

public float Height;

/// <summary>

/// Gets or sets the width

/// </summary>

public float Width;

/// <summary>

/// Creates a new size

/// </summary>

/// <param name="height">Measure of top to bottom</param>

/// <param name="width">Measure of left to right</param>

public Size2(float width, float height)

{

Height = height;

Width = width;

}

/// <summary>

/// Gets the height in an integer data type

/// </summary>

/// <returns>Height</returns>

public int GetHeightInteger()

{

return (int)Height;

}

/// <summary>

/// Gets the width in an integer data type

/// </summary>

/// <returns>Width</returns>

public int GetWidthInteger()

{

return (int)Width;

}

/// <summary>

/// Converts this Size type to the System.Drawing.Size type

/// </summary>

/// <returns>System.Drawing.Size</returns>

public System.Drawing.Size ToSystemSize()

{

return new System.Drawing.Size((int)Width, (int)Height);

}

/// <summary>

/// Gets the Size3 repersentation of this class depth is 0

/// </summary>

/// <returns>Size3</returns>

public Size3 ToSize3()

{

return new Size3(Width, Height, 0);

}

public static Size2 Zero

{

get

{

return new Size2(0f, 0f);

}

}

}

/// <summary>

/// Repersents three different size measurements width, height, depth

/// </summary>

public struct Size3

{

/// <summary>

/// Gets or set the height

/// </summary>

public float Height;

/// <summary>

/// Gets or sets the width

/// </summary>

public float Width;

/// <summary>

/// Gets or sets the depth

/// </summary>

public float Depth;

/// <summary>

/// Creates a new size

/// </summary>

/// <param name="height">Differece between biggest x value - the smallest x value</param>

/// <param name="width">Differece between the biggest y value - the smallest y value </param>

/// <param name="depth">Differece between the biggest z value - the smallest z value</param>

public Size3(float width, float height, float depth)

{

Height = height;

Width = width;

Depth = depth;

}

/// <summary>

/// Gets the height in an integer data type

/// </summary>

/// <returns>Height</returns>

public int GetHeightInteger()

{

return (int)Height;

}

/// <summary>

/// Gets the width in an integer data type

/// </summary>

/// <returns>Width</returns>

public int GetWidthInteger()

{

return (int)Width;

}

/// <summary>

/// Gets the depth in an integar value

/// </summary>

/// <returns>Depth</returns>

public int GetDepthIntegar()

{

return (int) Depth;

}

/// <summary>

/// Converts this Size type to the System.Drawing.Size type DOES NOT INCLUDE DEPTH VALUE

/// </summary>

/// <returns>System.Drawing.Size</returns>

public System.Drawing.Size ToSystemSize()

{

return new System.Drawing.Size((int)Width, (int)Height);

}

/// <summary>

/// Gets a size2 repersentation of this size DOES NOT INCLUDE DEPTH VALUE

/// </summary>

/// <returns>Size2</returns>

public Size2 ToSize2()

{

return new Size2(Width, Height);

}

/// <summary>

/// Gets the zero value of this class

/// </summary>

public static Size3 Zero

{

get

{

return new Size3(0f, 0f, 0f);

}

}

}

/// <summary>

/// Repersents a frame of a tilesheet

/// </summary>

public struct Frame

{

/// <summary>

/// Gets or sets the x cooridate on the tilesheet

/// </summary>

public int X;

/// <summary>

/// Gets or sets the y cooridate on the tilesheet

/// </summary>

public int Y;

/// <summary>

/// Gets or sets the width of the frame

/// </summary>

public int Width;

/// <summary>

/// Gets or sets the height of the frame

/// </summary>

public int Height;

/// <summary>

/// Gets or sets the column the frame is on (ZERO-BASED)

/// </summary>

public int Column;

/// <summary>

/// Gets or sets the row the frame is on (ZERO-BASED)

/// </summary>

public int Row;

/// <summary>

/// Creates a new frame structure

/// </summary>

/// <param name="width">Width of the frame</param>

/// <param name="height">Height of the frame</param>param>

/// <param name="column">(Zero-Based) Column of were the frame is located

/// (EXAMPLE THE FIRST COLUMN WOULD BE COLUMN 0)</param>

/// <param name="row">(Zero-Based) Row of were the frame is located

/// (EXAMPLE THE FIRST ROW WOULD BE ROW 0)</param>

public Frame(int width, int height, int column, int row)

{

Width = width;

Height = height;

Column = column;

Row = row;

X = Column * Width;

Y = Row * Height;

}

public Frame(int width, int height, Vector2 startPosition, int column, int row)

{

Width = width;

Height = height;

Column = column;

Row = row;

X = (Column * Width) + Convert.ToInt32(startPosition.X);

Y = (Row * Height) + Convert.ToInt32(startPosition.Y);

}

/// <summary>

/// Gets the rectangle repersented by this structure

/// </summary>

/// <returns>A Rectangle</returns>

public Rectangle ToRectangle()

{

return new Rectangle(X, Y, Width, Height);

}

}

/// <summary>

/// Repersents a tilesheet

/// </summary>

public class TileSet : IDisposable

{

#region Pubic Properties

/// <summary>

/// Gets or sets the number of columns in the tilesheet (NOT ZERO BASED

/// MEANING THE FIRST COLUMN IS REFERED TO AS COLUMN 1)

/// </summary>

public int Columns;

/// <summary>

/// Gets or sets the number of rows in the tilesheet (NOT ZERO BASED

/// MEANING THE FIRST ROW IS REFERED TO AS ROW 1

/// </summary>

public int Rows;

/// <summary>

/// Gets or sets the size per frame

/// </summary>

public Size2 FrameSize;

/// <summary>

/// Gets or sets the current tilesheet

/// </summary>

public Texture2D TileSheet;

/// <summary>

/// Gets the current frame

/// </summary>

public Frame CurrentFrame;

/// <summary>

/// Gets or sets the start position

/// </summary>

public Vector2 StartPosition = new Vector2(0, 0);

public bool RepeatCycle = true;

#endregion

#region Constructor

/// <summary>

/// Constructor of the TileSet Class

/// </summary>

/// <param name="tileSheet">The texture(tilesheet)</param>

/// <param name="frameSize">The size of each frame</param>

/// <param name="columns">The number of columns on the tilesheet (NOT ZERO BASED)</param>

/// <param name="rows">The number of rows on the tilesheet (NOT ZERO BASED)</param>

public TileSet(Texture2D tileSheet, Size2 frameSize, int columns, int rows)

{

TileSheet = tileSheet;

FrameSize = frameSize;

Columns = columns;

Rows = rows;

CurrentFrame = new Frame(FrameSize.GetWidthInteger(),

FrameSize.GetHeightInteger(), 0, 0);

}

#endregion

#region Public Methods

public Frame GetNextFrame()

{

int column = CurrentFrame.Column + 1;

int row = CurrentFrame.Row;

if (column > Columns - 1)

{

column = 0;

row++;

}

if (row > Rows - 1)

{

if (RepeatCycle)

{

column = 0;

row = 0;

}

else

{

column = Columns - 1;

row = Rows - 1;

}

}

CurrentFrame = new Frame(FrameSize.GetWidthInteger(),

FrameSize.GetHeightInteger(), StartPosition, column, row);

return CurrentFrame;

}

public Frame ReturnNextFrame()

{

int column = CurrentFrame.Column + 1;

int row = CurrentFrame.Row;

if (column > Columns - 1)

{

column = 0;

row++;

}

if (row > Rows - 1)

{

if (RepeatCycle)

{

column = 0;

row = 0;

}

else

{

column = Columns - 1;

row = Rows - 1;

}

}

return new Frame(FrameSize.GetWidthInteger(),

FrameSize.GetHeightInteger(), StartPosition, column, row);

}

/// <summary>

/// Gets a frame but if you call GetNextFrame() it will go back to original position

/// </summary>

/// <param name="row">Row the frame is on (NOT ZERO-BASED)</param>

/// <param name="column">Column the frame is on (NOT ZERO-BASED)</param>

/// <returns></returns>

public Frame GetFrame(int row, int column)

{

if (row - 1 == Rows)

{

throw new Exception("Row out of range");

}

if (column - 1 == Columns)

{

throw new Exception("Column out of range");

}

return new Frame(FrameSize.GetWidthInteger(), FrameSize.GetHeightInteger(),

StartPosition ,column - 1, row - 1);

}

/// <summary>

/// Goes to the frame before the current frame

/// </summary>

/// <returns>Frame</returns>

///

public Frame GetLastFrame()

{

int column = CurrentFrame.Column - 1;

int row = CurrentFrame.Row;

if (column < 0)

{

column = Columns - 1;

row--;

}

if (row < 0)

{

if (RepeatCycle)

{

column = Columns - 1;

row = Rows - 1;

}

else

{

column = 0;

row = 0;

}

}

CurrentFrame = new Frame(FrameSize.GetWidthInteger(),

FrameSize.GetHeightInteger(), StartPosition, column, row);

return CurrentFrame;

}

/// <summary>

/// Goes to certain frame and if you call GetNextFrame() it will get the one after it

/// </summary>

/// <param name="row">Row the frame is on (NOT ZERO-BASED)</param>

/// <param name="column">Column the frame is on (NOT ZERO-BASED)</param>

/// <returns></returns>

public Frame GoToFrame(int row, int column)

{

if (row > Rows)

{

throw new Exception("Row out of range");

}

if (column > Columns)

{

throw new Exception("Column out of range");

}

CurrentFrame = new Frame(FrameSize.GetWidthInteger(), FrameSize.GetHeightInteger(),

StartPosition ,column - 1, row - 1);

return CurrentFrame;

}

#region IDisposable Members

public void Dispose()

{

TileSheet.Dispose();

}

#endregion

#endregion

}

}

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Graphics;

namespace JumpCannonEngine.Graphics

{

/// <summary>

/// Repersents an animated sprite inherits from two interfaces (IDisposable, IUpdateAble)

/// </summary>

public class AnimatedSprite : IDisposable, IUpdateAble

{

#region Public Varibles

public TileSet TileSet;

public GraphicsDevice Graphics;

public SpriteBatch Sprite;

public Vector2 Position;

public Vector2 Origin;

public Size2 Size;

public Color Tint;

public float Rotation;

public float Scale;

public float LayerDepth;

#endregion

#region Constructor

public AnimatedSprite(GraphicsDevice device, TileSet tileSet)

{

Graphics = device;

TileSet = tileSet;

Sprite = new SpriteBatch(Graphics);

Position = new Vector2(0f, 0f);

Origin = new Vector2(tileSet.FrameSize.Width / 2, tileSet.FrameSize.Height / 2);

Size = tileSet.FrameSize;

Tint = Color.White;

Rotation = 0.0f;

LayerDepth = 1.0f;

}

#endregion

#region Public Methods

public void Update()

{

}

public void Begin()

{

Sprite.Begin();

}

public void Begin(SpriteBlendMode blendMode, SpriteSortMode sortOptions,

SaveStateMode stateOptions)

{

Sprite.Begin(blendMode, sortOptions, stateOptions);

}

public void Draw(Frame frameToDraw, SpriteEffects effects)

{

Sprite.Draw(TileSet.TileSheet,

new Rectangle((int)Position.X, (int)Position.Y, Size.GetWidthInteger(), Size.GetHeightInteger()),

frameToDraw.ToRectangle(), Tint, Rotation, Origin, effects, LayerDepth);

}

public void Draw(Frame frameToDraw, SpriteEffects effects, Rectangle destinationRectangle)

{

Sprite.Draw(TileSet.TileSheet,

destinationRectangle, frameToDraw.ToRectangle(),

Tint, Rotation, Origin, effects, LayerDepth);

}

public void End()

{

Sprite.End();

}

#region IDisposable Members

public void Dispose()

{

try

{

Graphics.Dispose();

Sprite.Dispose();

}

catch { }

}

#endregion

#endregion

}

}

Just copy this code into a code file and it should built.

There are two class in that jumble of code up there an AnimatedSprite Class and a Tileset Class. The AnimatedSprite class works with the Tileset class the Tileset class is not to be used alone.

Below is an example of drawing an AnimatedSprite

Sprite.Begin();

Sprite.Draw(Sprite.Tileset.GetNextFrame(), SpriteEffects.None);

Sprite.End();

If you need any more help email me at

soue7@hotmail.com

wakawaka54!!!

The 13 year old genius...






Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

GrizzlyBear1010

Here's the code from the documentation for the AnimatedTexture class.

public class AnimatedTexture
{
  private int framecount;
  private Texture2D myTexture;
  private float TimePerFrame;
  private int Frame;
  private float TotalElapsed;
  private bool Paused;

  public void Load( GraphicsDevice device, ContentManager content, string asset, int FrameCount, int FramesPerSec )
  {
    framecount = FrameCount;
    //myTexture = Texture2D.FromFile( device, filename );
    myTexture = content.Load<Texture2D>( asset );
    TimePerFrame = (float)1 / FramesPerSec;
    Frame = 0;
    TotalElapsed = 0;
    Paused = false;
  }

  // class AnimatedTexture
  public void UpdateFrame( float elapsed )
  {
    if (Paused)
      return;
    TotalElapsed += elapsed;
    if (TotalElapsed > TimePerFrame)
    {
      Frame++;
      // Keep the Frame between 0 and the total frames, minus one
      Frame = Frame % (framecount - 1);
      TotalElapsed -= TimePerFrame;
    }
  }

  // class AnimatedTexture
  public void DrawFrame( SpriteBatch Batch, Vector2 screenpos )
  {
    DrawFrame( Batch, Frame, screenpos );
  }
  public void DrawFrame( SpriteBatch Batch, int Frame, Vector2 screenpos )
  {
    int FrameWidth = myTexture.Width / framecount;
    Rectangle sourcerect = new Rectangle( FrameWidth * Frame, 0,
      FrameWidth, myTexture.Height );
    Batch.Draw( myTexture, screenpos, sourcerect, Color.White );
  }

  public bool IsPaused
  {
    get { return Paused; }
  }
  public void Reset()
  {
    Frame = 0;
    TotalElapsed = 0f;
  }
  public void Stop()
  {
    Pause();
    Reset();
  }
  public void Play()
  {
    Paused = false;
  }
  public void Pause()
  {
    Paused = true;
  }

}

At first, I typed all this into the IDE by hand to learn it better, but when it didn't work, I copied and pasted it in over my typing in case of an error I made. However, it still didn't work right (it leaves off the fourth frame in the animation).





Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

ProfEclipse

The line:

    Frame = Frame % (framecount - 1);

Should be:

    Frame = Frame % framecount;

(the " - 1" isn't necessary as the mod operation will always return a value between 0 and framecount-1 by definition.)

 





Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

ProfEclipse

@wakawaka54:

Why are you calculating the Frame information every time a Get*Frame method is called That's probably not a very good idea. A better method would be to pre-calculate the frames and store them in a list. Then, when the client requests a frame, you just return the previously stored frame rather than recalculating the values over and over.





Re: XNA Game Studio Express Problem with "How To: Animate a Sprite" Tutorial

GrizzlyBear1010

ProfEclipse,

You are right!  I tried that and it fixed my problem.  I don't know why they said to do that in the documentation...  I thought it was weird, but I didn't argue (after all, I don't work at Microsoft!).  Thanks for the help.