Search code examples
c#xna

How to detect in which direction the sprite is moving?


I'm making a 2D tower defense game for learning purposes, and now i'm stuck in how to make the enemies to look in the right direction when moving.

Here's what i tried without success:

    // Class constructor
    public AnimatedSprite(Texture2D texture, int lines, int columns, Vector2 position)
        : base ( texture, position)
    {
        this.texture = texture;
        this.position = position;
        Lines = lines; // How many lines the sprite-sheet have
        Columns = columns; How many columns the sprite-sheet have
        totalFrames = Lines * Columns;
    }

Here's the update method, it's a 5x4 sprite sheet:

    public override void Update(GameTime gameTime)
    {

        // Depending on the direction the sprite is moving
        // it will use different parts of the sprite-sheet

        if (west == true)
        {
            initialFrame = 0;
            finalFrame = 4;
        }

        if (east == true)
        {
            initialFrame = 5;
            finalFrame = 9;
        }

        if (north == true)
        {
            initialFrame = 10;
            finalFrame = 14;
        }

        if (south == true)
        {
            initialFrame = 15;
            finalFrame = 19;
        }

        // When to update the current frame
        timeSinseLastFrame += gameTime.ElapsedGameTime.Milliseconds;
        if (timeSinceLastFrame > milisecondsPerFrame)
        {
            timeSinceLastFrame -= milisecondsPerFrame;
            currentFrame++;

         // Reset the frame to complete the loop
            if (currentFrame == finalFrame)
                currentFrame = initialFrame;
        }
    }

In the draw method i try to detect the position the sprite is facing, I'm not sure the best way to do it but it's not working, the enemies are drawn correctly and animated but sometimes facing the wrong direction along the map path and at a certain point they disappear:

    public override void Draw(SpriteBatch spriteBatch)
    {
        int width = texture.Width / Columns;
        int height = texture.Height / Lines;
        int line = (int)((float)currentFrame / (float)Columns);
        int column = currentFrame % Columns;

        Rectangle originRectangle = new Rectangle(width * column, height * line, width, height);
        Rectangle destinationRectangle = new Rectangle((int)position.X, (int)position.Y, width, height);


        // Heres what i think it's not correct, how to detect the direction
        // I tried to calculate it by the last X and Y position
        // So if the current Y value is smaller the last Y value
        // The sprite moved south
        Rectangle lastPosition = originRectangle;
        Rectangle destinationPosition = destinationRectangle;

        if (lastPosition.Y < destinationPosition.Y)
        {
            north = true;
            south = false;
            east = false;
            west = false;
        }

        if (destinationRectangle.Y > lastPosition.Y)
        {
            north = false;
            south = true;
            east = false;
            west = false;
        }

        if (destinationRectangle.X > lastPosition.X)
        {
            north = false;
            south = false;
            east = true;
            west = false;
        }

        if (destinationRectangle.X < lastPosition.X)
        {
            north = false;
            south = false;
            east = false;
            west = true;
        }

        spriteBatch.Draw(texture, destinationRectangle, originRectangle, Color.White);

    }
}
}

Solution

  • I solved it, i pick the position from the base class and update the last position in the base class as well, and in the enemy class the update method will handle the frames it will use depending on the position.

    Enemy class update method:

                if (lastPosition.Y < position.Y)
                {
                    initialFrame = 15;
                    lastFrame = 19;
                }
    
                if (position.Y < lastPosition.Y)
                {
                    initialFrame = 10;
                    lastFrame = 14;
                }
    
                if (position.X > lastPosition.X)
                {
                    initialFrame = 5;
                    lastFrame = 9;
                }
    
                if (position.X < lastPosition.X)
                {
                    initialFrame = 0;
                    lastFrame = 4;
                }
    
                currentFrame = initialFrame;
                totalFrame = lastFrame;
    
                timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
                if (timeSinceLastFrame > milisecondsPerFrame)
                {
                    timeSinceLastFrame -= milisecondsPerFrame;
                    currentFrame++;
                    if (currentFrame == totalFrame)
                        currentFrame = 0;
                }       
            }