Explosion Animation in SFML / C#

In this post, we are going to implement of animation system to create an explosion effect after shooting invaders.

The first thing I do, I drew a sprite sheet for the explosion effect. That looks cool for an amateur. But the effect should be fast because I can't say they look well for a single frame. This is the sprite sheet that we will use:

Explosion Sprite Sheet
However, I can't use them like that. I first separate them into 8 frames. I don't want to build a system for the sprite sheet, the tutorials should be basic. I'm using Aseprite, therefore it didn't hart to separate them. I just click File > Save as and save it explosion-000.png and the program saved the rest of the parts as numbered for me, like this:
the view of vs code
Now, let's load them with TextureManager. Firstly, I define the path of explosions folder and then I created the list called explosionTeztures as a field. Now we have to reach this list to use them necessary situation. To do this, I declare property to get the list.
        private static string ASSETS_PATH = "bin/Assets/Textures/";
        private static string EXPLOSION_ASSETS_PATH = "bin/Assets/Textures/explosions/";
		
        ...
        static List<Texture> explosionTextures = new List<Texture>(); 
		
        ...
        public static List<Texture> ExplosionTextures { get { return explosionTextures; } }
Let's load the frames of the explosion to the list using for loop in LoadTexture method:
        public static void LoadTexture()
        {
            playerTexture = new Texture(ASSETS_PATH + "player.png");
            enemyTexture = new Texture(ASSETS_PATH + "enemy.png");
            backgroundTexture = new Texture(ASSETS_PATH + "background.png");
            
            for (int i = 0; i < 8 ; i++)
            {
                explosionTextures.Add(new Texture(EXPLOSION_ASSETS_PATH + "explosion-00" + i.ToString() +".png"));
            }
        }
That's it for loading texture operation. Let's create an animation for our game. The logic of the game is simple. If bullets collide enemy object. The animation should appear at the position of the enemy sprite. An animation object will be created at the time of the collision. So, let's write Animation class:
namespace shmup
{
    class Animation
    {
        private Sprite sprite;
        private int count = 0;

        private bool destroyIt = false;

        private List<Texture> textures = new List<Texture>();

        public bool DestroyIt { get { return destroyIt; }}

        public Animation(List<Texture> textures, Vector2f position)
        {
            this.sprite = new Sprite();
            this.sprite.Position = position;
            this.sprite.Texture = textures[0];
            this.textures = textures;
        }

        public void update()
        {
            if (this.count == this.textures.Count - 1) 
            {
                this.destroyIt = true;
            }
            else 
            {
                this.count += 1;
                this.sprite.Texture = this.textures[count];
            }
        }

        public void draw(RenderTarget window)
        {
            window.Draw(this.sprite);
        }
    }
}
Let's examine the code above. We have to count each frame of the animation. Because this animation should be ended at the last frame. The frames are stored by the list called textures. If the value of the count matches the size of the list then destroyIt field should be set as true, but if not match then it will change the texture of sprite in order and the animation effect will be provided this way. In the constructor method, the sprite will be created according to the position of the enemy that exploded and the first texture frame was assigned to the texture of the sprite. Also, the textures from the parameter are stored in the field of textures. I already said the update method what it does and the draw method draw the sprite on the screen.

Animation class means nothing by itself. We need to manage them with a class. Because we designed to Animation class according to usage. We need to update all of these animation objects at one point:
namespace shmup
{
    class AnimationManager
    {
        private static List<Animation> animations = new List<Animation>();

        public static List<Animation> Animations { get { return animations; } }

        public static void update()
        {
            for (int i = 0; i < animations.Count; i++)
            {
                if (animations[i].DestroyIt) 
                {
                    animations.Remove(animations[i]);
                }
                else
                {
                    animations[i].update();
                }
            }
        }

        public static void draw(RenderTarget window) 
        {
            for (int i = 0; i < animations.Count; i++)
            {
                animations[i].draw(window);
            }
        }
    }
}
This is a classic way for any manager class. It works as static so we don't create objects from this class. The important thing is in the update method. If animation should be ended then it will remove from the list.

Now let's use this manager in EnemyManager when the invader died:
        public void update(Player player) 
        {
            ...
            
            for (int i = 0; i < enemies.Count; i++)
            {
                enemies[i].update();
                if (enemies[i].Position.Y > 480 || this.collisionOfBullets(enemies[i], player)) 
                {
                    AnimationManager.Animations.Add(new Animation(TextureManager.ExplosionTextures, enemies[i].Position));
                    enemies.Remove(enemies[i]);
                }
            }
        }
In the code above, an animation will be added if the necessary conditions occur. Finally, we can use it this AnimationManager in the Game class:
        private void update() 
        {
            this.player.update();
            this.enemies.update(this.player);
            AnimationManager.update();
        }

        private void draw() 
        {
            this.window.Clear(Color.Blue);
            
            this.window.Draw(this.background); 
            this.player.draw(this.window);
            this.enemies.draw(this.window);
            AnimationManager.draw(this.window);

            this.window.Display();
        }
    }
}
Let's look at the result:
Explosion Effect with SFML / C#


No comments:

Post a Comment