Showing posts with label sprites. Show all posts
Showing posts with label sprites. Show all posts

Thursday, 15 May 2025

[SFML & C++] 7 - Animating Sprites // Tutorial

This is part of a series of small projects and tutorials using C++ and SFML

Library version: SFML 3.0.0
C++ Standard: ISO C++20

In this project, we'll make a simple app that loads a texture (image), gives that texture to a sprite and animates it. Here's what the finished product will look like:

How To SFML Animate Sprites Tutorial using C++ - Basic Beginner


Step 1 - Creating a Sprite

What is a sprite? In game development it usually refers to a drawable object that references a texture. They usually have functions that allow you to set the position, rotation, scale and others. They are used primarily for the main "objects" in your games like the main character, enemies, items etc. 

By themselves, sprites have no concept of animation. They load a single image each frame. Therefore to animate them, you need some code that updates the image each frame.

Why doesn't SFML do this for you? Well, animations come in all shapes, sizes and varieties. The speed, duration, loop ability. These are all left down to the programmer to implement as the developers of the libraries cannot be expected to cater to every situation.

Enough talking though. Let's make a sprite and show it on the screen. Sprites load textures. So we'll need a texture first and give a reference of it to the Sprite.

I'll be using the following spritesheet for the purposes of this tutorial:

Please note this is for learning purposes only.

The reason I'm using it is because all the separate frames we need are nicely laid out into little squares so we can easily access them from our texture when we need to update the animation each frame.




Step 2 - Offsetting into a Texture

Now this doesn't work as expected because we're just loading the entire image and displaying that. We only want to display part of the texture. So we'll need to create an offset into it. I've already done some calculations for you and those squares are 48x48 pixels. The start of the walk animation is at x268, y576.



That's better.

Step 3 - Animating the Frames

So to animate this, all we have to do is move the texture rect 48 pixels to the right (+ a 4 pixel gap between frames) to give us the next frame. Then we do the same again, then go backwards to the start. We can simulate this by just using a vector to store the positions.



How To SFML Animate Sprites Tutorial using C++ - Basic Beginner

And done! And that's how you basically animate sprites. We use the delta time to gives us a nice animation speed as well. Animation is a massive part of game development and it would be nice if we could wrap up of our animating code into something reusable.

Friday, 24 December 2021

C++ & SFML // Creating The Disintegrating Shields in Space invaders

Whilst making a clone of Space Invaders, I got to the point where I had to make the shields. They are interesting as only parts of them get destroyed when hit by bullets:


The damage done to the shields is based on the type of bullet and where they hit. It reminds me of the old Worms and Lemmings games that have disintegrating terrain due to explosions.

The player's shot and 2 of the invader shots deal the same type of damage. However the "plunger" looking invader shot is the most powerful and deals more damage. Therefore, having the shields as sprites make no sense as you can't manipulate the pixels in a sprite, so I started looking into ways to draw and modify pixels in SFML as well as do per-pixel collisions.

I eventually came across this post:

This seems super long winded for what I want as it copies the image from the gpu into an array of pixels, then you modify those pixels and then send that array back to the texture. But it's also the closest to how the original game implements the shields (in a way).

I then found this after googling "sfml array of pixels":

I was able to write a program that can draw individual pixels to the screen:

This is more along the lines of what I wanted, as I could now simply create a vector of vertices in the shape of the shield. SFML already provides this type called VertexArray which can be passed directly to a RenderWindow's draw call.

Here's a simple program I wrote that uses a VertexArray to create a rectangle with a gradient fill:

In my version, the shields are 66x48 pixels, with each vertex needing 4 uint8's of data (RGBA), so that means I need to supply 12,672 uint8's and I don't really want to type that out. So I had to start looking for a way to read in that data from something. SFML does not provide a way to convert textures or images to VertexArrays. I can get the pixel colour data by using the first method and copying the texture to an image but that doesn't provide pixel positions (which a vertex wants). So I wrote a method to combine the two. 

It creates a temporary texture, copies the texture to an image then loops through every pixel, pushing back a new Vertex after all 4 pieces of the pixel have been collected. The positions are calculated using an offset from the top left hand corner. So after 66 vertices have been pushed back, the y co-ord is shifted down 1 pixel. However there is still a glaring problem with this method; I have 4 arrays containing 3168 elements.

So I went back to the drawing board and found this post:

Using the code from Laurent (the developer of SFML) I managed to write a program that creates a "mask" from a png and uses that to turn pixels transparent:

C++ & SFML // Creating The Disintegrating Shields in Space invaders

Armed with this knowledge I then set about creating a cannon that fires lasers at the doge image to destroy it:
C++ & SFML // Creating The Disintegrating Shields in Space invaders

The next issue to solve was the per-pixel collisions as the laser was still colliding with the bounding box of the sprite. I hackily solved this by writing a very simple collision check:

C++ & SFML // Creating The Disintegrating Shields in Space invaders

First, it only does a per-pixel check if the laser has collided with the bounding box of doge. Then, it checks to see if 3 spots on the laser have hit solid pixels. If they're all transparent then the laser can pass through.

This isn't perfect, but it's good enough.

Friday, 26 February 2021

C++ & FLTK // Adding Simple "Sprite" Support

This isn't really a tutorial, more of a "hey, I wanted to add 'sprites' to my FLTK build, how would I do that?"

For those of you new to my blog, I've been working my way through Bjarne Stroustrup's Practice & Principles using C++ in which there are several chapters focused on graphics programming. For this he supplies a couple of helper files that wrap some fltk features in a "higher level bow" so to speak. Over the months I've been editing these quite a bit to create my own shapes and add other functionality.

After these graphics chapters ended, I started to wonder if I could make a 2d engine using fltk and what does every good 2d engine need? Sprite support.

After an hour of tinkering, I had achieved this:

C++ & FLTK - Adding "Sprite" Support

Very exciting. I'd like to note, this did not capture well and it kind of looks like there's a slight stall after a few frames but when running the program it's fine.

So I first went about this by creating a new simple window that supports "ticking". It has a quit button and a tick function that's registered with fltk's callback system to run every 0.1 seconds.

Then I made a new class called Sprite which inherits from the Shape class. I soon learnt that Shape is great for basic stuff, but when you want to start doing event based game stuff, the way shapes are drawn and updated is kind of clunky so I need to re-do shapes. But for now I worked round it.

So a Sprite takes in a point to draw from the top left-hand corner, a file name, frame width, frame height and the number of rows in the spritesheet; kind of reaching for the moment as it can't deal with sprites with multiple rows just yet.

The Sprite itself is just an Fl_Image that holds the png "spritesheet". This was mine:

C++ & FLTK - Adding "Sprite" Support

It's the coin blocks from Super Mario World. When attaching this image to the window, obviously the entire image was displayed. Sprites should be able to only display a certain portion or 'frame' of their spritesheet, so I made a function called drawFrame() that takes in a frame number. This frame number is stored and used in draw_lines() to display a particular part of the image. This is the annoying part of using a Shape; I must override draw_lines() and use that to draw. 

To only display a certain part of the image, you can just use built-in functionality of Fl_Image. The draw() function allows you to specify a part of the image to draw by passing in the top left corner locations and an offset. This essentially "crops" the image to the size given. The width and height is then multiplied by the frame number each frame to advance it to the next image:
C++ & FLTK - Adding "Sprite" Support

C++ & FLTK - Adding "Sprite" Support

Here, my spritesheet is 200x400 pixels with each block being 40x40. Therefore, to play an animation, fltk is told to start at frame 0 and increase by 1 each frame until it hits 3, then go back to 0. This stops it from showing the brown block, which is frame number 4.

So to show the second image block, it would do 40 * 1, which is 40. This gives an x offset of 40. Then the x and y coordinates of the new cropped image are obtained by getting the top left of the full sprite sheet (I set it to 50, 50) then adding on the offset; making the new draw point 90, 50. The draw() function is handy though as it can display the cropped image in the same position as the last through the first two parameters. The Y offset is ignored right now as we don't have multiple rows.

It's also important that post increment is used here. I usually detest using post++, however here it is necessary as the current frame needs to be drawn before it's incremented. If it was ++frame, then the next frame would be drawn as it's incremented before use.

And that's pretty much it for creating the most basic of basic sprite systems for FLTK. I have plans to rewrite the shape class so I have full control over how they're drawn.

You can find the full code for this project here along with a project file: