Game Development and Coding 27 Feb 2014 – Sprite Manager

The Sprite Manager Remade.

A Sprite Manager is usually a good idea to make for your game. An even better idea is to make it do as much as possible when being called on so you can focus on other things. What do I mean by that? Not that a Sprite Manager should do everything, but it’s always good to keep down the number of code lines needed to use it.

I write this, because I want to describe how the new Sprite Manager I made works as well as explain why I considered it well worth spending the time required to remake it. That is generally something you should avoid.

So what was so bad about the old Sprite Manager? Well, if you wanted to make a new instance of an object (or a new pointer) you needed about five lines of code to load a texture from a file and set the texture to a sprite. You also needed 8 arguments.

Old SpriteManager

The picture above illustrates how much code was needed to load the background image with the old Sprite Manager. The code line in the yellow box was not really the Sprite Managers fault though. However, the code in the red boxes (as well as the code line in the yellow box) was replaced with one line of code taking 3 arguments with the new Sprite Manager. See below.

New SpriteManager

The new Sprite Managers also checks if the file with the texture has already been used, and if so, reuses the data from it rather than loading it a second time. Below is a picture of the Sprite Manager class’ header file.

SpriteManager HeaderSo how does the new Sprite Manager work? Well first it is initialized, meaning you load the directory to where your sprites are store into the manager object.

SpriteManager initHere’s an example of the initialize method being used:

SpriteManager init exampleThis means that the manager will try to load sprites from a folder called “Sprites” that is placed in the same directory as the bin folder that contains the executable file.

Looking back at the second picture we see that a method called “GetSprite” is called. Here is how it works:

SpriteManager GetSpriteThe method takes 3 arguments: the name of the file the texture is to be loaded from as well as the values of the files dimensions, or in other words the pictures width and height.

[Yellow Box] The method starts by checking through a <map> container that stores pointers to previously loaded sprites to see if there is an element in it with the same name, which means it indirectly is checking if the specified file has already been used.

[Orange Box] If no element with the specified name is found in the <map> container, “GetSprite” will call on another method called “LoadSprite” that’ll take in the same arguments in order to load a sprite from the specified file and add it to the <map> container.

[Red Box] Lastly “GetSprite” will return the sprite pointer from the <map> container that has the right name.

Now we’ll take a look at the “LoadSprite” method:

SpriteManager LoadSprite[White Box] It starts by making a new sprite pointer.

[Yellow Box] Then it goes through a <map> container with stored pointers to previously loaded textures.

[Orange Box] If it can’t find the texture in question then it will use the “LoadTexture” method to load a new texture from the file and store a pointer to it in the <map> container with texture pointers.

[Red Box] The texture will then be applied to the new sprite pointer, which in turn is stored in the <map> container for sprite pointers.

We’ve almost covered everything; lastly we’ll take a look at the “LoadTexture” function:

SpriteManager LoadTexture[Yellow Box] First off, the method creates a new texture pointer.

[Orange Box] Then it uses SFML’s method for loading textures from files. Note that the filepath variable defined in the initialize method is added to the filename to create the full path to the file specified. For example, if the file was named “block.png” the full path in this case would be “../Sprites/block.png”. It also makes a sub-rectangle defining which part of the picture we want to load as a texture. Since we always want the whole picture the first two values will be 0, 0 and the last two the width and height of the picture. This means we start at point 0, 0 (the upper left corner) and stretch it the whole width horizontally and the whole height vertically.

[Red Box] The texture pointer is then saved in the <map> container for texture pointers, ready to be used.

That is all; I hope you enjoyed reading this and that you learned something from it.

Cheers!

Game Development and Coding 20 Feb 2014 – Player Sprite Animation

player_weapon Courtesy of Nils Wennergren

Animated Sprites with C++ and SFML.

It’s always helpful to see a representation of your avatar on the screen in the form of a sprite. But just having a sprite on the players location is not always enough. You’ll probably want it to be animated in some way. It seems a bit more alive then. This of course applies to a lot more objects in the game than just the player, though maybe not every single one. You don’t really need a rock to be animate unless it is kicked or otherwise moved in some way.

So how do you make an animated sprite? Well first you need a Sprite sheet of some form, and one way of getting this is to have one made for your game. You will also need to know the dimensions of the Sprite sheet as well as the dimensions of the sprites themselves. You also need to know how far from each other they are placed.

Usually you want the point of the upper left corner of a box that precisely fits one Sprite. It helps if the upper left coordinate for all sprites is placed at the same distance for each other. For example, a Sprite sheet may contain an animation of three sprites, and their coordinates are placed at (0, 0), (50, 0) and (100, 0). In other words, they are placed 50 units apart each.

The picture below is not really a proper Sprite sheet, it’s only there to demonstrate.

1 - Spritesheet and coords

So how do we make these into an animated sprite? There are probably a lot of different ways to do it, but I started with loading the whole Sprite Sheet and applying it as a texture to a sprite. The sprite was then assigned to the player. Then in the players update method, after the players new position has been determined and the sprite has been moved to that location as well, I use and SFML function called “SetTextureRect( IntRect (x, y, width, height))”. What this does is that it takes a sub-rectangle, defined in its parameters, and places it on the texture loaded into the sprite. The x and y defines the position of its upper left corner and the width and height defines how far the rectangle stretches on the x-axis and y-axis respectively.

2 - IntRect example

All texture placed within that rectangle will then be displayed on the sprite’s location, not the whole Sprite sheet texture. So I define a rectangle that one of the sprites in the texture precisely fit into and position it appropriately. I will however make the input of the x-coordinate vary so that the rectangle moves from one sprite to the next until all of them have been used, after which it starts over with the first one again.

3 - Spritesheet and coords animation loop

A timer needs to be placed on the change of the x-coordinate though, so that it won’t change every game loop. That would make the animation go ridiculously fast, at least on modern computers. Instead it changes, in my case, every 0.1 seconds. The reason for specifying it to 0.1 seconds is that the graphical artists on my team told me that all animation sprites are meant to have the duration of 0.1 seconds. Otherwise I would have needed to find a way to vary the amount of time each sprite is used in the animation.

Lastly I will include a screenshot of the code that makes the player sprite animation happen in my project. The variable “elapsedtime” is the time difference between game loops taken in as an argument for the update method.

4 - code snippet

Game Development and Coding 13 Feb 2014 – Collider class

The Collider Class.

Last week I worked on the collider class. Mostly I worked on the class’ overlap methods. Each object in the game that’s capable of colliding with something has its own collider as a member.

It is the Collider that determines the actual position of the object it is a member of.

The Collider has a position in the form of a pair of coordinates on the x-axis and the y-axis. The Collider also has a pair of values that determines how far from the position coordinates it extends along both axes.

Example, if the Collider is a box and has the coordinates (x: 100, y: 100), then that position is the upper left corner of the box.

If it extends 50 units on both axis, in other words have the extension (x: 50, y: 50), then:

The upper right corner of the box is (x: 150, y: 100).

The lower right corner of the box is (x: 150, y: 150).

The lower left corner of the box is (x: 100, y: 150).

Box with coordinates

The extension is increased on both axes because in SFML the coordinate system is:

Right = +X, Left = -X, Up = -Y, Down = +Y.

SFML coordinate system

However if the Collider is a circle things look a bit different. Then you first need to determine the center of the Collider circle. This is done by adding half of the values of the extensions to the position.

You will then get the central point of a Collider that has the form of a circle. The circle will be just big enough to fit into a box that is defined from the Colliders’ position and extension.

Circle in Box

Then you will need to determine a radius for the circle to determine how big it is. This can either be done by just assigning a value to a member variable for the Collider. Alternatively, it can be defined by taking the extension on one axis and divide it by 2.

Circle in Box radius and extension

Which type of Collider shape you choose should depend on the object it is bound to. For example, in out game the view if top down, so people should have circle Colliders. People may not be shaped as circles when viewed from above, but a circle is certainly closer than a box.

The Collider class does not only have a position and a shape though, it also has methods for checking if it overlaps with other Colliders.

I choose to divide this into three different methods to make it easier to work with.

One for Box vs Box overlap.

One of Circle vs Circle overlap.

One for Circle vs Box overlap.

I also added a member value to the Collider class call “ColliderCircle”, which is a Boolean, meaning it can only have the values “true” or “false”.

This value is set depending on what object the Collider is a member of.  For example, if the Collider belongs to the player then I want it to have the shape of a circle, so the “ColliderCircle” is set to “true”. If I want the Collider to be a box, I set the “ColliderCircle” to false;

When the game then checks for collisions it will call on the Colliders “ColliderCircle”.

If two Colliders give “false” when calling the “ColliderCircle” then the Box vs Box overlap method is used to check if the two objects overlap.

If they both return “true” however, the Circle vs Circle overlap method is used and if they return different values (one true and one false) then then Circle vs Box overlap method is used.

I started with the Box vs Box overlap and the Circle vs Circle overlap because I had done methods for that before while I only had a conceptual idea on how to make the box vs circle collision. The box vs circle overlap was therefore postponed.

The following image is the code for the circle vs circle overlap:

Code example

The overlap methods I made did not just check for overlap however, but also returned an offset. The offset is a set of values (x and y) that show how much and in which direction a collided objects position needs to be adjusted on collision.

I will illustrate the reason why this is needed with an example:

Offset example

Say two box-shaped Colliders are positioned so that one of them is only two pixels to the right of the other.

The first box is then moved to the left by 5 pixels in the next game loop while the second box stays still.

The first box is now overlapping 3 pixels into the second box; therefore its position needs to be adjusted by three pixels (5-2) to the right, because the objects are not supposed to go into each other. The offset in this situation is (3, 0).

In order to get the right offset on overlap I needed the program to first check if the overlap was largest on the x-axis or the y-axis.

If the overlap is larger on the x-axis the correction of position will happen on the y-axis and vice versa.

Once that is established I will need to check if the offset is going to be positive or negative.

Offset positive x

In this situation the red square has a higher value on its x-position and therefore its offset will have a positive x-value.

Offset negative x

In this situation the opposite holds true.

Offset Negative Y

In this situation the offset for the red square will have a negative y-value because it needs to be moved up to correct its position.

The point of doing all this to return an offset value is that once it is done you only need to add the offset value to the position to get a proper correction.

I did, however, run into some problems with this method. As it turns out though, the problem was that instead of comparing position to position when the offset was determined I accidentally made the overlap method compare the objects position with the other objects extension, which meant that the offset always had the same value. This meant that no matter which side an object collided from it was offset downwards.

Like this:

offset error

Once I had finally sorted this out the circle vs circle overlap method worked properly but not the box vs box. I then decided to scrap box vs box and box vs circle overlap because we really only needed those for one object in the game and that object was non-essential, so all our Colliders will be circles.

The offset on the circle vs circle overlap works fine except for edge cases (when edge collide with edge, see below) where the objects vibrate somewhat against one another.

This is probably due to the computers calculation of float values (values with a decimal) being somewhat uncertain so the offset might be calculated inaccurately by a pixel or so every loop.

Game Developement and Coding

This week we had our first scrum sprint, meaning we set up assignments for each group member to be done with by Friday. The assignments were either art, music or code to be used in the game we are making, Dangerous Dander.

Being a coder my assignments were to start on the different classes of our game objects as well as their inheritance structure. That basically means I had to make so called Parent classes from which other classes will inherit variables and methods. This will save time when coding the rest of the game since I only need to make new classes inherit what they will need instead of coding it all over again for each new class created.

I did have some problems when coding the Parent classes though. I had to jump back and forth between them moving variables and methods around after realizing that I had misplaced something.

For example, to start off I had a variable related to collision detection on the Entity class from which most classes will inherit, including other Parent classes such as the Interactive Object parent class. The Interactive Object class is the Parent class that all objects that will be able to collide shall inherit from and so said variable was better placed in it rather than Entity. Having that variable in the entity class would mean even objects that aren’t going to have collision detection will inherit that variable as well, which would be wasteful.
This problem I consider to be a result of my own inexperience in planning code as well as coding in and of itself.

I also started working on overlap, collision detection and collision handling, in other words how different objects in the game will detect if they are in contact with one another and what should happen if they are.

My inexperience showed itself again as I was once again forced to move about certain methods and variables.

By Friday, however, I had managed to code everything I was supposed to. We now have a proper inheritance structure to use when creating more classes, as well as collision detection.  I have not been able to test it though as we yet don’t have anything playable to test things with. Once again inexperience shows itself as we probably should have at least a movable character in a rendered window to test collision etc. We need to remedy that as soon as possible next week.