Hi i am trying to make a simple character where different animations play depending on if the character is going left, right or idle. I have an animation class with a bunch of fields, an animation manager that makes use of said fields for the animation logic and draws it with spritebatch.Draw() and with the players position and I also have a player class.
The following is the Animation.cs file:
public class Animation
{
public float speed;
public Rectangle[] sourceRectangles;
public Texture2D texture;
public int currentframe;
public int frameCount;
int frameWidth;
int frameHeight;
public Animation(Texture2D spriteSheet, int frameCount)
{
texture = spriteSheet;
this.frameCount = frameCount;
speed = 0.1f;
frameWidth = texture.Width;
frameHeight = texture.Height / frameCount; //divide by framecount to get the height of each individual frame
sourceRectangles = new Rectangle[frameCount]; //intialize a new array of rectangles
for(int i = 0; i < frameCount;i++) //fill up the array with
{
sourceRectangles[i] = new Rectangle(0, (i) * frameHeight, frameWidth, frameHeight);
}
currentframe = 0; //start at the first frame of the animation
}
}
This is the AnimationManager.cs
public class AnimationManager
{
float timer;
Animation animation;
public AnimationManager(Animation Animation) //we send an animation to be played from outside the class
{
animation = Animation;
timer = 0;
}
public void Play(Animation currentAnimation) //the parameter is the animation that we want to play
{
if (animation == currentAnimation)
return;
animation = currentAnimation;
animation.currentframe = 0;
timer = 0f;
}
public void Stop()
{
timer = 0f;
animation.currentframe = 0;
}
public void Update(GameTime gameTime) //animation logic
{
timer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (timer > animation.speed)
{
if (animation.currentframe >= 4)
{
animation.currentframe = 0;
}
animation.currentframe++;
timer = 0f;
}
}
public void Draw(SpriteBatch spriteBatch, Vector2 position) //Vector2 position will be the players position
{
spriteBatch.Draw(animation.texture, position, animation.sourceRectangles[animation.currentframe], Color.White);
}
}
And here is the Player.cs file:
internal class Player1
{
public Vector2 position; //player position
Vector2 velocity; //players speed
bool hasJumped;
AnimationManager animationManager;
Dictionary<string, Animation> animations; //we use a dictionary to store the animations
public Player1(Dictionary<string, Animation> Animations) //we get the dictionary, which was created and initialized in game1.LoadContent
{
//startposition for player
this.position.X = 50;
this.position.Y = 50;
hasJumped = true; //a bool to check if we are mid jumpp or not
animations = Animations;
animationManager = new AnimationManager(animations.First().Value); //play the first animation, i.e Idle, by default
}
public void Update(GameTime gameTime, ContentManager content)
{
KeyboardState keyboardState = Keyboard.GetState();
animationManager.Update(gameTime);
position += velocity; //the players position is always dependent on the velocity which changes depending on input from the keyboard
if (keyboardState.IsKeyDown(Keys.Right)) //the horizontal speed changes when you press right or left keys
{
velocity.X = 5f;
animationManager.Play(animations["RunRight"]);
}
else if (keyboardState.IsKeyDown(Keys.Left))
{
velocity.X = -5f;
animationManager.Play(animations["RunLeft"]);
}
else
{
velocity.X = 0f;
animationManager.Play(animations["Idle"]);
}
Jump(keyboardState);
}
private void Jump(KeyboardState keyboardState)
{
if (keyboardState.IsKeyDown(Keys.Space) && hasJumped == false) //if you have pressed space and are not in the air the vertical speed and hasjumped change and the player is shot upwards
{
position.Y -= 15f;
velocity.Y = -20f;
hasJumped = true;
}
if (hasJumped == true) //this is the gravity code
{
velocity.Y += 2f; //since the speed was negativ when the player was shot up, it goes slowly back to a positiv value everytime player.Update() runs, ,
//and since the position is dependent on the velocity, the player is forced downward naturally
}
if (position.Y + 200 >= 450) //when you reach groundlevel, hasjumped becomes false and the gravity code above stops
hasJumped = false;
if (hasJumped == false) //but since we change the value of velocity.Y with gravity, the player will keep dropping down even when hasJumped is false
velocity.Y = 0f; //therefore we change velocity.Y back to 0 at groundlevel, so the player doesnt fall through the ground
}
public void Draw(SpriteBatch spriteBatch)
{
animationManager.Draw(spriteBatch, position); //we send the players position so that the animation follows the player
}
}
The problem I am having is that when I run the program and I hold down the left or the right key for a while, it crashes and i get an IndexOutOfRangeException in the AnimationManager.Draw() method, i think the position is out of bounds but I don’t understand why that is. Can anyone help? I apologize in advance for the sloppy code or unclear explanations, please say if something is unclear.