If you are still trying to catch your breath from the last tutorial, I recommend you sit down, because this next tutorial won't be any nicer. In this tutorial we will be extending our entity class a bit further with collisions, and movement. So hold on to your pants, and get ready.

The first order of business we'll tackle is movement. A seemingly simple idea that can be a bit tricky. Now, I am going to introduce a method that has worked for me for quiet some time, though I am not sure if it can be readily optimized, changed, or whatever. So save the criticism. The reason I like it so much is that it's pixel perfect now matter what system you are on, and it's already fast for its purpose.

But before we get into that, we're going to need a standard for movement. You see, when we play our games on old Pentium 2 as opposed to a quad core, there are apparent differences in speed. So, if we did a simple X++; on the older machine, the entity would move slower than the newer machine. So the idea is simple, figure out the frame rate of the machine, and base our movements off of the frame rate. I call that the speed factor. Now, in order for this to work, we have to have a base frame rate. I usually pick 32, as that is a good number. So if our machine had a frame rate of 32, our speed factor would be 1. If our frame rate was 64, our speed factor would be 0.5. We move twice as slower on the faster machine, that way speeds are consistent across different machines.

So, lets create this class. Create two new files called CFPS.h and CFPS.cpp. Open up the header file first:
#ifndef _CFPS_H_
    #define _CFPS_H_

#include <SDL.h>

class CFPS {
    public:
        static CFPS FPSControl;

    private:
        int     OldTime;
        int     LastTime;

        float     SpeedFactor;

        int    NumFrames;
        int     Frames;

    public:
        CFPS();

        void    OnLoop();

    public:
        int     GetFPS();

        float   GetSpeedFactor();
};

#endif
First, we have a single control for accessing our speed facor, and frame rate. Again, a singleton object that we should be used to using by now. Next, we have OldTime, which is used to calculate the Frames per second. Then we have LastTime, which is used to calculate the speed factor. SpeedFactor is the current speed factor of the game (of course), NumFrames is the games current FPS, and Frames is the frame count when calculating the frames per second (explanation for all these below). Notice that all of them are private members, so to access our FPS and SpeedFactor we have two get functions. We don't need anyone messing with those variables directly. Then, we have a simple constructor, and an OnLoop function to calculate everything.

Now, open up CFPS.cpp to add the actual code:
#include "CFPS.h"

CFPS CFPS::FPSControl;

CFPS::CFPS() {
    OldTime     = 0;
    LastTime    = 0;

    SpeedFactor    = 0;

    Frames      = 0;
    NumFrames   = 0;
}

void CFPS::OnLoop() {
    if(OldTime + 1000 < SDL_GetTicks()) {
        OldTime = SDL_GetTicks();

        NumFrames = Frames;

        Frames = 0;
    }

    SpeedFactor = ((SDL_GetTicks() - LastTime) / 1000.0f) * 32.0f;

    LastTime = SDL_GetTicks();

    Frames++;
}

int CFPS::GetFPS() {
    return NumFrames;
}

float CFPS::GetSpeedFactor() {
    return SpeedFactor;
}
I thought I'd drop a note in here, since I have had some people miss this; whenever you make a variable of a class static, you also need to declare it elsewhere. Notice I have CFPS::FPSControl at the top. If you fail to do this, you'll get an undeclared error.

Okay, we have a basic constructor, setting everything to 0. Next, we have our OnLoop function where all the magic happens. The first calculation we do, is finding the Frames per Second of the game. This is where SDL_GetTicks comes in. SDL_GetTicks returns the number of milliseconds that have passed since we have called SDL_Init. So, effectively, 1000 milliseconds equals 1 second. Now, notice the condition I am checking. I am checking if the OldTime (which is currently set to 0) + 1000, is less than the current tick count. Think about it, if OldTime is 0 + 1000, and 1001 milliseconds have passed, that means at least 1 second has passed. Why is that important? That tells use to restart the FPS counter.

Notice inside the if statement we then set OldTime to SDL_GetTicks, set NumFrames to the Frames count, and reset our Frames counter. So, going with the example above, OldTime now becomes 1001. Now, 1001 + 1000, is the next calculation, so another second must pass. Concurrent with this, is the Frames++ at the bottom of that function. This continuelly counts up, until the OldTime resets it. I hope that is easy to understand.

Next, we have the actual calculation for the SpeedFactor. Like I mentioned earlier, the SpeedFactor determines how fast to move objects. Now, for a better explanation. Say we are on a really slow computer that gets 1 FPS per second. That's a really bad computer by the way. We have the base movement rate set at 32 (our made up number). So, ideally, any computer will move objects 32 pixels per second. So this 1 FPS computer will move the object 32 pixels every second. Now, jump to a 10 FPS computer. We still want to move 32 pixels per second. So, that's 1/10 of 32 right? So, for each calculation we move 3.2 pixels, and after 1 second, we'll have moved 32 pixels.

To calculate this, we base it on how fast the computer is currently going. This is what LastTime is for. LastTime holds the time it took for the last loop in the game. So, in the constructor it's currently 0. Now, say we have an FPS of 10. That means we have 10 loops in the game every second. How many milliseconds is that? That's 100 milliseconds. So, 100 / 1000 (for 1 second), is 1/10. The same number we got above. Now multiply this by our desired movement rate, and we have our Speed Factor! I'll be showing you how to use this later on, just try to understand how we calculated it.

And lastly, we have our two get functions that return NumFrames (FPS), and the SpeedFactor.

Okay, so much already and we still have a long way to go!

From the last tutorial we loaded an area, 1.area, we'll be leaving this, as well as everything else from that code. But, we're going to take one thing out right now. Open up CApp_OnEvent.cpp and remove the following:
case SDLK_UP:      CCamera::CameraControl.OnMove( 0,  5); break;
case SDLK_DOWN:  CCamera::CameraControl.OnMove( 0, -5); break;
case SDLK_LEFT:  CCamera::CameraControl.OnMove( 5,  0); break;
case SDLK_RIGHT: CCamera::CameraControl.OnMove(-5,  0); break;
We aren't going to be controlling the camera anymore, but we'll be controlling our main Player who will dictate where the camera goes. Note: In the last tutorial I had some values backwards for the camera! Please read the notes in the last tutorial for the fix. This new tutorial will have the fixes already in place, but without any explanation.

Now, lets go ahead and add this new Player to the game. But first, some explanation. Remember, anything that moves in the game or that can be interacted with (besides the Map), is an Entity. So, our main Player will be an entity. But, Player is distinct, he likes certain things other Entities do not. So, instead of simply doing CEntity Player; we need to create a class just for Player. But! Before we can even to get to making the Player class, we're going to need to extend the Entity class. Things like this include the ability to Move an Entity, Collision (what we've all been waiting for), Animation states, and Entity Flags. Jumping and a few other things will have to wait until the next lesson (sorry).

So open up CEntity.h and change it to the following:
#ifndef _CENTITY_H_
    #define _CENTITY_H_

#include <vector>

#include "CArea.h"
#include "CAnimation.h"
#include "CCamera.h"
#include "CFPS.h"
#include "CSurface.h"

enum {
    ENTITY_TYPE_GENERIC = 0,

    ENTITY_TYPE_PLAYER
};

enum {
    ENTITY_FLAG_NONE     = 0,

    ENTITY_FLAG_GRAVITY    = 0x00000001,
    ENTITY_FLAG_GHOST    = 0x00000002,
    ENTITY_FLAG_MAPONLY    = 0x00000004
};

class CEntity {
    public:
        static std::vector<CEntity*>    EntityList;

    protected:
        CAnimation      Anim_Control;

        SDL_Surface*    Surf_Entity;

    public:
        float           X;
        float           Y;

        int             Width;
        int             Height;

        bool        MoveLeft;
        bool        MoveRight;

    public:
        int        Type;

        bool        Dead;
        int        Flags;

    protected:
        float        SpeedX;
        float        SpeedY;

        float        AccelX;
        float        AccelY;

    public:
        float        MaxSpeedX;
        float        MaxSpeedY;

    protected:
        int             CurrentFrameCol;
        int             CurrentFrameRow;

    protected:
        int        Col_X;
        int        Col_Y;
        int        Col_Width;
        int        Col_Height;

    public:
        CEntity();

        virtual ~CEntity();

    public:
        virtual bool OnLoad(char* File, int Width, int Height, int MaxFrames);

        virtual void OnLoop();

        virtual void OnRender(SDL_Surface* Surf_Display);

        virtual void OnCleanup();

        virtual void OnAnimate();

        virtual void OnCollision(CEntity* Entity);

    public:
        void    OnMove(float MoveX, float MoveY);

        void     StopMove();

    public:
        bool    Collides(int oX, int oY, int oW, int oH);

    private:
        bool     PosValid(int NewX, int NewY);

        bool     PosValidTile(CTile* Tile);

        bool     PosValidEntity(CEntity* Entity, int NewX, int NewY);        
};

class CEntityCol {
    public:
        static std::vector<CEntityCol>    EntityColList;

    public:
        CEntity* EntityA;
        CEntity* EntityB;

    public:
        CEntityCol();
};

#endif
Oh geez, what happened, and where did all this code come from?! Sorry, for all of you who just fainted, maybe you'll understand a little bit more now why this tutorial is so long and took so long. It's a lot to handle, let alone trying to teach to everyone. One step at a time.

First, we have the basic things still there, OnLoad, OnLoop, OnRender, and OnCleanup. The two new virtual functions are OnAnimate and OnCollision. Now, OnAnimate is used to define Animation States, like I mentioned earlier. This is useful for selecting the right animation when the Player moves left or right. The second, OnCollision, is called when an Entity collides with another Entity.

So, for example, if EntityA and EntityB collide, what happens? Well, first, neither can pass through each other; that's the easy part. The other part, is that EntityA needs to know EntityB collided with him. Such as, Mario falling on a spike. The spike notifies Mario, "Hey, I killed you! Change your animation and die." Well, the thing is, we cannot notify the other entity when the collision happens. One important reason is that, if the Spike kills Mario, Mario may not have been able to notify the Goomba that he killed him. So, what we do instead is store everything in a queue. This is the new vector called CEntityColList. This stores any collision that have happened when all the entities have moved. And once all movement has taken place, that is when we'll notify all the Entities of collisions, and call OnCollision.

Whew. Also, in correlation with this, is Collides function, which is used to determine the actual collision (more on this later). Also with this, is four Col_ variables. These variables are used to offset a collision for an entity. Back in previous tutorials we had a Yoshi image we were using. If you notice, it would make little sense to use the width of the image for collision purposes. Yoshi doesn't actually come to the edges of the images; so, we have to offset it a little, so when Yoshi runs into a wall it actually looks like his nose is hitting the wall, and not being a few pixels away. And since these variables are used to collision purposes only, I have prefixed them with Col_.

Now, for some movement explanation. Whenever an Entity wants to move, we do not move it to where it wants to go immediately. What we do instead, is move it in the direction we want it to go at a certain speed. Remember the whole CFPS class? That's why time based movement is so important. So, in the new OnMove function, we pass it how fast we want our Entity to go. If we want the Entity to move 1 pixel a second to the right, we would do OnMove(1, 0). Now, I wish it was this simple, but it's not. In real life we don't move in steps. We move according to speed and acceleration. Meaning, it takes us a little time to start moving at first (inertia). It looks unnatural to have entities jumping around.

So, to get past this, we have six variables SpeedX, SpeedY, AccelX, AccelY, MaxSpeedX, and MaxSpeedY. Using these is simple. First, the MaxSpeed variables cap how fast the entity can go; if we didn't cap it, the Entities would continue to go faster and faster into infinity. The SpeedX and SpeedY are the current speed of the entity. If these were 1, again, that would be 1 pixel per second. Now, the AccelX and AccelY, determine how fast we increase or decrease our speed. If AccelX and AccelY are 0, then we aren't moving at all. If AccelX is 1, then our SpeedX is increasing over time. Now, this is where it gets a little confusing with the Speed factor.

I want my player to increase in speed 1 pixel per second. This would be:
AccelX = 1;

SpeedX += AccelX * CFPS::FPSControl.GetSpeedFactor();
Notice we multiply the AccelX by the Speed Factor. That's because we want to increase the speed 1 pixel every second. If I wanted to increase the speed 1 pixel every loop, I would leave the speed factor out of it. Now, when OnMove receives these Speed variables, it also has to figure in the speed factor:
MoveX *= CFPS::FPSControl.GetSpeedFactor();
MoveY *= CFPS::FPSControl.GetSpeedFactor();
(MoveX and MoveY are the arguments passed to OnMove). Now, the SpeedX and SpeedY only determine how fast we want to move per second. So we have to multiply it by the speed factor. A little hint for you people out there, the entire speed of the game is determined by the Speed Factor! If we changed the Speed Factor of the game, it would determine how fast anything in the games moves. Slow motion deaths anyone?

Now, whenever an Entity moves, there are some things to consider. Say in one loop we are supposed to move the Entity 4 pixels (slow computer perhaps, or really fast entity). Now, lets say 2 pixels away there is a wall. Now, if we checked 4 pixels in front of use, we wouldn't let our guy move. But, we still want him to move as close as he can. So, to move this 2 pixel distance, we have to check every pixel along the way. Now, you might be thinking this will be slow. Well, not really. Someone with a 100 FPS who wants to move 5 pixels a second (a reasonable speed), will move less than one pixel every loop (0.05 to be exact). So, every loop, this entity moves 0.05 pixels over. That means we have 1 or 2 checks when checking for collisions for that entity. More explanation on this later when we actually implement moving.

Before an entity is allowed to move, we have to check a few things. The first is if the entity collides with the map, and the second is if the entity collides with another entity. This is where the three PosValid functions come in. The first, PosValid(), is the main function that handles the other two. It checks to see if the tile the entity is trying to move to is valid, and also checks the entities. The other two PosValid functions determine what a valid tile is, and what a valid entity is. Again, more explanation later.

Now, last for movement, we have MoveLeft, MoveRight, Flags, and StopMove. Now, MoveLeft and MoveRight are simply flags, true or false, that determine if the entity is moving left or right. If true, the AccelX will be set a value, causing the entity to move. Now, StopMove simply sets the AccelX in the opposite direction until we reach 0. Again, we don't stop suddenly in real life, we gradually stop. The last item, Flags, is used to determine a few things. In the second enum, you'll notice several flags.
ENTITY_FLAG_NONE
ENTITY_FLAG_GRAVITY
ENTITY_FLAG_GHOST
ENTITY_FLAG_MAPONLY
These are used to determine certain properties about an entity. For example, an entity that is affected by gravity will have the ENTITY_FLAG_GRAVITY turned on. An Entity that can go through walls, will have ENTITY_FLAG_GHOST turned on. An entity that only collides with the map, and not other entities, will have ENTITY_FLAG_MAPONLY turned on. Now, notice how we have them numbered in hex. This is because we're treating the Flags in binary. This way, we can activate multiple flags at once:
Flags = ENTITY_FLAG_GRAVITY | ENTITY_FLAG_GHOST;

To check for a single flag is simple:

if(Flags & ENTITY_FLAG_MAPONLY) {
    //Map only
}
Wow, what a load, but still more in the class to explain. Next, we have some Animation variables. There are only two of them: CurrentFrameCol, and CurrentFrameRow. These two determine where on our image we start to find individual frames of an animation. A CurrentFrameCol and CurrentFrameRow would be the top left of the image. Moving over one column would change things. Think of it like tilesets. Look at the example image below:




(Save this Image for this Tutorial)


Last, but not least, we have variables to indicate if a variable is dead, and the type of entity. You'll notice we have another enum, like the Flags, to specify the type of entity. This is important when dealing with collision events. So, back to the Mario and Spike example; lets say a Goomba happens to step in a spike. Now, in Mario world, the Goomba would not die. So, the Spike needs to know that entities type. Simple enough I think.

Okay, lets get into the core of the class now. Open up CEntity.cpp and lets have some more fun. Since we have had so many drastic changes, I am going to go through this line by line with the basics, and then move on to specific areas of the class. So, starting at the top we have our basic constructor, and statics:
std::vector<CEntity*>     CEntity::EntityList;

std::vector<CEntityCol> CEntityCol::EntityColList;

CEntityCol::CEntityCol() {
    EntityA = NULL;
    EntityB = NULL;
}

CEntity::CEntity() {
    Surf_Entity = NULL;

    X = 0;
    Y = 0;

    Width     = 0;
    Height     = 0;

    MoveLeft  = false;
    MoveRight = false;

    Type =     ENTITY_TYPE_GENERIC;

    Dead = false;
    Flags = ENTITY_FLAG_GRAVITY;

    SpeedX = 0;
    SpeedY = 0;

    AccelX = 0;
    AccelY = 0;

    MaxSpeedX = 5;
    MaxSpeedY = 5;

    CurrentFrameCol = 0;
    CurrentFrameRow = 0;

    Col_X = 0;
    Col_Y = 0;

    Col_Width  = 0;
    Col_Height = 0;
}
Everything is simply set to 0, NULL, or some respective value. One thing to notice is the MaxSpeed variables. Set these to whatever you like. Usually this will depend on the particular entity that is in the game. Such as Mario will be able to move faster than a Goomba. Notice that I have grouped two classes into one file; that is okay to do sometimes! OnLoad is the exact same, so skip over that, and then move on to OnLoop:
void CEntity::OnLoop() {
    //We're not Moving
    if(MoveLeft == false && MoveRight == false) {
        StopMove();
    }

    if(MoveLeft) {
        AccelX = -0.5;
    }else

    if(MoveRight) {
        AccelX = 0.5;
    }

    if(Flags & ENTITY_FLAG_GRAVITY) {
        AccelY = 0.75f;
    }

    SpeedX += AccelX * CFPS::FPSControl.GetSpeedFactor();
    SpeedY += AccelY * CFPS::FPSControl.GetSpeedFactor();

    if(SpeedX > MaxSpeedX)  SpeedX =  MaxSpeedX;
    if(SpeedX < -MaxSpeedX) SpeedX = -MaxSpeedX;
    if(SpeedY > MaxSpeedY)  SpeedY =  MaxSpeedY;
    if(SpeedY < -MaxSpeedY) SpeedY = -MaxSpeedY;

    OnAnimate();
    OnMove(SpeedX, SpeedY);
}
Lots of new things here. First, remember MoveLeft and MoveRight are used to indicate if the entity is moving left or right (duh). If both are these are false, we call StopMove, which will handle settings Acceleration in the reverse direction so we come to a gradual stop. Below that, if MoveLeft or MoveRight are true, we give AccelX a value. 0.5 is an arbitrary number, you probably want to mess with this until you find a value that you like. Just below that, we have a condition checking if gravity is turned on for that particular entity. If it is, we set AccelY. This will cause our entity to fall down. Again, this is whatever value you want. The larger the number, the faster you will fall. Next, below that we have our SpeedX and SpeedY. Again, we increase the Speed of the entity over time in correlation to our Speed Factor. Then, below that, we check against our MaxSpeed variables to make sure we only go a certain speed. Finally, we call OnAnimate for our entity to animate, and then OnMove, which will actually move our entity.

Moving on, we have a few changes to OnRender:
void CEntity::OnRender(SDL_Surface* Surf_Display) {
    if(Surf_Entity == NULL || Surf_Display == NULL) return;

    CSurface::OnDraw(Surf_Display, Surf_Entity, X - CCamera::CameraControl.GetX(), Y - CCamera::CameraControl.GetY(), CurrentFrameCol * Width, (CurrentFrameRow + Anim_Control.GetCurrentFrame()) * Height, Width, Height);
}
First, we have added the Camera X and Y to the rendering coordinates for the entity. This makes the entities render in connection to where the camera is. This way, if the camera moves, all the entities will in respect to the camera position. Next, we have added CurrentFrameCol and CurrentFrameRow to the X2 and Y2 of OnDraw. This makes it so we can set different animations.

The first column has Yoshi facing the left, while the second column has Yoshi facing to the right. When we move to the left, we will want to set CurrentFrameCol = 0, so that Yoshi appears to be walking left. And when we move to the right, we will set CurrentFrameCol = 1, so that Yoshi appears to be walking to the right.

Skip over OnCleanup, nothing new there. We then have OnAnimate:
void CEntity::OnAnimate() {
    if(MoveLeft) {
        CurrentFrameCol = 0;
    }else

    if(MoveRight) {
        CurrentFrameCol = 1;
    }

    Anim_Control.OnAnimate();
}
This is fairly straight forward. Like I said above, depending on which direction we are moving, we set the animation. Next, we have OnCollision:
void CEntity::OnCollision(CEntity* Entity) {
}
Yay, an empty function. This function will be called whenever two entities hit each other. This entire time we've been creating an class for basic entities. In order to take advantage of this function, you will need to create our own class (like CPlayer, which we'll do later on in this tutorial) and override this function. This is because the action taken by an entity depends upon it's type. Like my earlier examples, a Goomba will not react the same way to a collision with a spike as Mario would.

Next, we our OnMove function.
void CEntity::OnMove(float MoveX, float MoveY) {
    if(MoveX == 0 && MoveY == 0) return;

    double NewX = 0;
    double NewY = 0;

    MoveX *= CFPS::FPSControl.GetSpeedFactor();
    MoveY *= CFPS::FPSControl.GetSpeedFactor();

    if(MoveX != 0) {
        if(MoveX >= 0)     NewX =  CFPS::FPSControl.GetSpeedFactor();
        else             NewX = -CFPS::FPSControl.GetSpeedFactor();
    }

    if(MoveY != 0) {
        if(MoveY >= 0)     NewY =  CFPS::FPSControl.GetSpeedFactor();
        else             NewY = -CFPS::FPSControl.GetSpeedFactor();
    }

    while(true) {
        if(Flags & ENTITY_FLAG_GHOST) {
            PosValid((int)(X + NewX), (int)(Y + NewY)); //We don't care about collisions, but we need to send events to other entities

            X += NewX;
            Y += NewY;
        }else{
            if(PosValid((int)(X + NewX), (int)(Y))) {
                X += NewX;
            }else{
                SpeedX = 0;
            }

            if(PosValid((int)(X), (int)(Y + NewY))) {
                Y += NewY;
            }else{
                SpeedY = 0;
            }
        }

        MoveX += -NewX;
        MoveY += -NewY;

        if(NewX > 0 && MoveX <= 0) NewX = 0;
        if(NewX < 0 && MoveX >= 0) NewX = 0;

        if(NewY > 0 && MoveY <= 0) NewY = 0;
        if(NewY < 0 && MoveY >= 0) NewY = 0;

        if(MoveX == 0) NewX = 0;
        if(MoveY == 0) NewY = 0;

        if(MoveX == 0 && MoveY     == 0)     break;
        if(NewX  == 0 && NewY     == 0)     break;
    }
}
This function is quite a bit to take in. Lets see if we can straighten it all out. First, MoveX and MoveY are the where we want to move our entity. Remember up above, we call this passing our SpeedX and SpeedY. So, calling OnMove(1, 0) we would want to move 1 pixel to the right every second. At the top, we check our Speed, and if 0, we don't do anything (duh). Below that, we do something I explained earlier. We multiply MoveX and MoveY by the speed factor. This gives us the correct movement per second. Just below that, we figure out the values for two new variables, NewX and NewY. These will be our X and Y increments. Remember, I mentioned above that this method is pixel perfect, so we need to inch closer and closer to our desired position. Now, we set our NewX and NewY to our speed factor because this is how much we should use to inch closer and closer to our desired position.

Below that, we have a seemingly infinite loop. This is where the movement magic happens and collision. First, we have a condition to check if the entity is a ghost, if it is, we increase the X and Y regardless if a collision has happened. We still call PosValid though, because this will notify entities of any collision that have taken place. Notice in PosValid we pass the current X and Y, along with adding NewX and NewY. This is where we want to go, so we check if that spot is empty.

If the entity is not a ghost, we do normal collision. We check X and Y separatly because we may be able to move up but not forward (think jumping into a wall). If the position is valid (empty), we increase the X or Y, if not, we set SpeedX or SpeedY to 0 which causes you to immediately stop (this is as close to reality as we need, if you do run into a wall you usually stop immediately). Now, below that, we change MoveX and MoveY depending upon our NewX. Say our MoveX was 2, and our NewX was 0.5. We would slowly decrease MoveX until it reaches 0. Once it does, we have come to our desired position and we are done. The 8 if statements below check if MoveX and MoveY have reached 0, and break out of the loop.

Moving on, we have StopMove:
void CEntity::StopMove() {
    if(SpeedX > 0) {
        AccelX = -1;
    }

    if(SpeedX < 0) {
        AccelX =  1;
    }

    if(SpeedX < 2.0f && SpeedX > -2.0f) {
        AccelX = 0;
        SpeedX = 0;
    }
}
This one is fairly straight forward. Depending on our Speed, we set the Acceleration in the reverse direction. So, if we are moving right, we set the acceleration to the left. The last if statement is simply a boundary to how slow we need to be going until we stop. If we didn't do that, it's possible that we could be stuck in a loop of moving left to right.

Next, we have a function that determines collision of two boxes. I will say right now that this function was borrowed from Cone3D (), and then modified. If it works, why fix it?

Anyway, lets take a look at it to see if I can help explain. At the top we define 8 variables, to define 8 sides. 4 sides are for the first object, and 4 sides are for the second object. Basically, we are doing bounding box collision:



So, in a very basic sense, we want to check if two boxes have overlapped. The easiest method, is to determine if we have not collided on all 4 sides. So first, we determine the locations of all the sides:
int left1, left2;
int right1, right2;
int top1, top2;
int bottom1, bottom2;

int tX = (int)X + Col_X;
int tY = (int)Y + Col_Y;

left1 = tX;
left2 = oX;

right1 = left1 + Width - 1 - Col_Width;
right2 = oX + oW - 1;

top1 = tY;
top2 = oY;

bottom1 = top1 + Height - 1 - Col_Height;
bottom2 = oY + oH - 1;
Look at the figure below to get an idea:

The top and left, are the X,Y of the object, and the right and bottom, are the X+Width-1, Y+Height-1. We subtract one in order to get the true coordinate of the side.

Next, we finally do the checking. What we do here is to check if one of the 4 sides of the first object are out of range of the second object. If one is, then we cannot possibly be colliding. But, if all 4 checks fail, we are colliding. So, if bottom1 is less than top2, that means the Bottom side of the first object is higher up on the screen then the Top of the second object:
if (bottom1 < top2) return false;
if (top1 > bottom2) return false;

if (right1 < left2) return false;
if (left1 > right2) return false;
Finally, if all checks pass, then we return true for a collision. One note, remember that the Col_ variables are used to simply offset the size of the entity. If the entity is 32 width, but we offset by 2, that means when we check collision we use the Width of 30. Here's how our final Collides method looks:
bool CEntity::Collides(int oX, int oY, int oW, int oH) {
    int left1, left2;
    int right1, right2;
    int top1, top2;
    int bottom1, bottom2;

    int tX = (int)X + Col_X;
    int tY = (int)Y + Col_Y;

    left1 = tX;
    left2 = oX;

    right1 = left1 + Width - 1 - Col_Width;
    right2 = oX + oW - 1;

    top1 = tY;
    top2 = oY;

    bottom1 = top1 + Height - 1 - Col_Height;
    bottom2 = oY + oH - 1;


    if (bottom1 < top2) return false;
    if (top1 > bottom2) return false;

    if (right1 < left2) return false;
    if (left1 > right2) return false;

    return true;
}
Moving on we find some more fun. We have our 3 last functions, the 3 PosValid functions. Overall, this functions basically determine if a collision has taken place. Remember, earlier OnMove will call PosValid to determine if a requested position is open to move to. So, keep in mind that NewX, and NewY in these functions is where the Entity wants to move to, not where it currently is.

Lets first look at PosValid. This function will determine any type of collision that has taken place, and return true or false. Now, this function basically has only two type of collision, Entity to Entity, and Map to Entity. That's what PosValidTile and PosValidEntity are used for.
bool CEntity::PosValid(int NewX, int NewY) {
    bool Return = true;

    int StartX     = (NewX + Col_X) / TILE_SIZE;
    int StartY     = (NewY + Col_Y) / TILE_SIZE;

    int EndX    = ((NewX + Col_X) + Width - Col_Width - 1)         / TILE_SIZE;
    int EndY    = ((NewY + Col_Y) + Height - Col_Height - 1)    / TILE_SIZE;

    for(int iY = StartY;iY <= EndY;iY++) {
        for(int iX = StartX;iX <= EndX;iX++) {
            CTile* Tile = CArea::AreaControl.GetTile(iX * TILE_SIZE, iY * TILE_SIZE);

            if(PosValidTile(Tile) == false) {
                Return = false;
            }
        }
    }

    if(Flags & ENTITY_FLAG_MAPONLY) {
    }else{
        for(int i = 0;i < EntityList.size();i++) {
            if(PosValidEntity(EntityList[i], NewX, NewY) == false) {
                Return = false;
            }
        }
    }

    return Return;
}
Now, the first collision we check for is a Map Collision. This is done by first grabbing 4 variables about our Entity. Basically, we want to know all the TileIDs that this entity is over. This is done by grabbing the X (and the Col_ offset) and dividing by the TILE_SIZE. This gives us our TileID for our X. The same goes for the Y variable. These two calculations determine our StartX and StartY. Now, EndX and EndY are determined in a similiar fashion, but we want to also add the Width and Height (just like we determined sides in the Collision function above). This will give us an area of tiles that this entity is over:
int StartX     = (NewX + Col_X) / TILE_SIZE;
int StartY     = (NewY + Col_Y) / TILE_SIZE;

int EndX    = ((NewX + Col_X) + Width - Col_Width - 1)     / TILE_SIZE;
int EndY    = ((NewY + Col_Y) + Height - Col_Height - 1)    / TILE_SIZE;
Now that we have the Start and End of tiles, we simply loop through them:
for(int iY = StartY;iY <= EndY;iY++) {
    for(int iX = StartX;iX <= EndX;iX++) {
    }
}
Inside of this loop, this is where we check each tile to see if it's a valid tile to move into. It the tile happens to be a wall, we would set the Return variable to false, to indicate that this requested position (hence the name PosValid) is not good:
CTile* Tile = CArea::AreaControl.GetTile(iX * TILE_SIZE, iY * TILE_SIZE);

if(PosValidTile(Tile) == false) {
    Return = false;
}
Notice the new function GetTile, we'll define this later on in this tutorial. But to explain it here, GetTile will return the CTile of any X and Y coordinate. After we get the tile, we pass it on to PosValidTile for it to figure out if the tile can be moved over or not. So, for a moment, jump on over to PosValidTile:
bool CEntity::PosValidTile(CTile* Tile) {
    if(Tile == NULL) {
        return true;
    }

    if(Tile->TypeID == TILE_TYPE_BLOCK) {
        return false;
    }

    return true;
}
Remember the enum in CTile.h at the top? Those enums were a list of types that you could give a tile. They are used here now, to determine if a tile can be moved on or not. So, that's basically what we do here. First, if the Tile is NULL (which you should always check your pointers), we return true (meaning, yes, they can walk on this tile). Next, we check if the tile is a TILE_TYPE_BLOCK, if so, then no, the entity cannot walk on this tile. And finally, for all other types, yes, they can walk on this tile. Simple enough.

Now, jump back to the PosValid function. You will then find another loop:
if(Flags & ENTITY_FLAG_MAPONLY) {
}else{
    for(int i = 0;i < EntityList.size();i++) {
        if(PosValidEntity(EntityList[i], NewX, NewY) == false) {
            Return = false;
        }
    }
}
First, we do a simple check with our Flags again, this will check if we have the ENTITY_FLAG_MAPONLY flag turned on. If so, this means we're only checking collisions against the map, so we don't worry about Entity collisions. If we are checking collisions, then we jump to the loop. The loop is fairly simply, we go through the EntityList and pass each entity to the PosValidEntity, along with NewX and NewY. So, Jump on over to PosValidEntity:
bool CEntity::PosValidEntity(CEntity* Entity, int NewX, int NewY) {
    if(this != Entity && Entity != NULL && Entity->Dead == false &&
        Entity->Flags ^ ENTITY_FLAG_MAPONLY &&
        Entity->Collides(NewX + Col_X, NewY + Col_Y, Width - Col_Width - 1, Height - Col_Height - 1) == true) {

        CEntityCol EntityCol;

        EntityCol.EntityA = this;
        EntityCol.EntityB = Entity;

        CEntityCol::EntityColList.push_back(EntityCol);

        return false;
    }

    return true;
}
Okay, this function is actually quite simple. We do some checks first on the Entity (the Entity we are wanting to collide with) to determine that this Entity is not the same Entity we're moving (Mario cannot collide with Mario). That's the "this != Entity." It simply checks to make sure the Entities are not the same. We then check to make sure the Entity is not NULL, not Dead, and doesn't have the ENTITY_FLAG_MAPONLY flag turned on. So far, so good. If all these checks pass, then we finally pass it to the Collides function of that Entity, passing along our Entities coordinates and Width/Height (with Col_ offsets). Remember, if any part of an if statement fails, like this != Entity, none of the other code in the if statement will be executed.

So, if the Entities do collide, finally, we use our new CEntityCol class. This will be a queue of collisions that have taken place. So, we push our Entity into EntityA, and the other Entity into EntityB, and then push it into the list. Finally, we return false, to indicate that this position is not valid. Wow, we are almost done!

Don't rush out to compile, it won't work. Why? Because, remember that GetTile function? :)

So, let's add this into our code. Open CArea.h and add two functions at the bottom of the class:
public:
    CMap*    GetMap(int X, int Y);

    CTile*    GetTile(int X, int Y);
Then, open CArea.cpp and add the functions:
CMap* CArea::GetMap(int X, int Y) {
    int MapWidth  = MAP_WIDTH * TILE_SIZE;
    int MapHeight = MAP_HEIGHT * TILE_SIZE;

    int ID = X / MapWidth;
        ID = ID + ((Y / MapHeight) * AreaSize);

    if(ID < 0 || ID >= MapList.size()) {
        return NULL;
    }

    return &MapList[ID];
}

CTile* CArea::GetTile(int X, int Y) {
    int MapWidth  = MAP_WIDTH * TILE_SIZE;
    int MapHeight = MAP_HEIGHT * TILE_SIZE;

    CMap* Map = GetMap(X, Y);

    if(Map == NULL) return NULL;

    X = X % MapWidth;
    Y = Y % MapHeight;

    return Map->GetTile(X, Y);
}
I know, I know... they are more complicated than they look. First, look at GetMap. GetMap simply returns a CMap pointer at the given coordinates. It's just like GetTile, but for Maps. Now, how it works is first by determining the size of our maps. We then translate our X,Y into an ID, and then return the CMap pointer. I won't go into how translating X,Y into an ID works, because I believe this is explained in the last tutorial.

Now, go to GetTile. We determine the MapWidth and MapHeight, again (and I suppose this can be optimized), and then grab the Map with GetMap. We do a simple check for a NULL pointer (hint, hint), and then turn our X and Y into Tile coordinates. So, if our TILE_SIZE was 16, and our X was at 128, our Tile coordinate for X would be 8. Meaning, we are 8 tiles over. We finally then send this over to the Map GetTile. (Oh yes, one other function). This is why we have a GetMap function, if you are wondering. Rememember, CArea is a bunch of maps making one big area. So, we will have to determine which map is needed when grabbing tiles.

So, jump over to CMap.h now, and add this at the bottom:
public:
    CTile*    GetTile(int X, int Y);
Then, open CMap.cpp and add this at the bottom:
CTile* CMap::GetTile(int X, int Y) {
    int ID = 0;

    ID = X / TILE_SIZE;
    ID = ID + (MAP_WIDTH * (Y / TILE_SIZE));

    if(ID < 0 || ID >= TileList.size()) {
        return NULL;
    }

    return &TileList[ID];
}
This is basically just like GetMap, but uses the TileList instead.

We're almost done!

Just a few more changes to go. Create two new files called CPlayer.h and CPlayer.cpp. This class will be our main player and will extend our new CEntity class. So, open up CPlayer.h:
#ifndef _CPLAYER_H_
    #define _CPLAYER_H_

#include "CEntity.h"

class CPlayer : public CEntity {
    public:
        CPlayer();

        bool OnLoad(char* File, int Width, int Height, int MaxFrames);

        void OnLoop();

        void OnRender(SDL_Surface* Surf_Display);

        void OnCleanup();

        void OnAnimate();

        void OnCollision(CEntity* Entity);
};

#endif
I won't explain any of this other than it's overriding all the virtual functions from CEntity.

Now, open up CPlayer.cpp:
#include "CPlayer.h"

CPlayer::CPlayer() {
}

bool CPlayer::OnLoad(char* File, int Width, int Height, int MaxFrames) {
    if(CEntity::OnLoad(File, Width, Height, MaxFrames) == false) {
        return false;
    }

    return true;
}

void CPlayer::OnLoop() {
    CEntity::OnLoop();
}

void CPlayer::OnRender(SDL_Surface* Surf_Display) {
    CEntity::OnRender(Surf_Display);
}

void CPlayer::OnCleanup() {
    CEntity::OnCleanup();
}

void CPlayer::OnAnimate() {
    if(SpeedX != 0) {
        Anim_Control.MaxFrames = 8;
    }else{
        Anim_Control.MaxFrames = 0;
    }

    CEntity::OnAnimate();
}

void CPlayer::OnCollision(CEntity* Entity) {
}
Again, just like CEntity, but simply overriding the functions. One minor note, look at OnAnimate. In there we check our SpeedX to make a modification to our MaxFrames. Basically, if SpeedX != 0, (which means we are moving) we set our MaxFrames to 8. If we aren't moving we set it to 0. Now, remember our Yoshi animation above, it has 8 frames for walking. So, if our Speed is not 0, we make Yoshi walk, otherwise we make it look like he's standing still. This is the area where you would define other animations, like Idle, Walking, Running, Jumping, and so on.

Now, open up CApp.h and add the header file at the top:
#include "CPlayer.h"
Then, add two Players in your class:
CPlayer    Player;
CPlayer Player2;
Then, open up CApp_OnInit.cpp and initialize them:
if(Player.OnLoad("yoshi.png", 64, 64, 8) == false) {
    return false;
}

if(Player2.OnLoad("yoshi.png", 64, 64, 8) == false) {
    return false;
}

Player2.X = 100;

CEntity::EntityList.push_back(&Player);
CEntity::EntityList.push_back(&Player2);
Simple enough. We set PlayerX, the other Yoshi, over, so that we're not on top of each other initially. Now, just below this add this extra code:
CCamera::CameraControl.TargetMode = TARGET_MODE_CENTER;
CCamera::CameraControl.SetTarget(&Player.X, &Player.Y);
Remember I said earlier, we're going to make the camera follow our Yoshi. Now, open up CApp_OnRender and change this:
CArea::AreaControl.OnRender(Surf_Display, CCamera::CameraControl.GetX(), CCamera::CameraControl.GetY());
To this:
CArea::AreaControl.OnRender(Surf_Display, -CCamera::CameraControl.GetX(), -CCamera::CameraControl.GetY());
This change is also related to the Camera bug I mentioned above earlier. Open up CCamera.h and change the TargetX and TargetY from ints to floats. Also change the SetTarget ints to floats.

One last change now! Open up CApp.h and add this to your code (you should already have OnKeyDown):
void OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode);
Then, open up CApp_OnEvent.cpp:
void CApp::OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode) {
    switch(sym) {
        case SDLK_LEFT: {
            Player.MoveLeft = true;
            break;
        }

        case SDLK_RIGHT: {
            Player.MoveRight = true;
            break;
        }

        default: {
        }
    }
}

void CApp::OnKeyUp(SDLKey sym, SDLMod mod, Uint16 unicode) {
    switch(sym) {
        case SDLK_LEFT: {
            Player.MoveLeft = false;
            break;
        }

        case SDLK_RIGHT: {
            Player.MoveRight = false;
            break;
        }

        default: {
        }
    }
}
To go over this quickly, we basically check if Left or Right is pressed, and set MoveLeft or MoveRight on our Entity to true. If the key is depressed, we set it to false.

Now, we're done! Remember to grab the Yoshi picture above to make sure he shows up right. Also, I changed the 1.map to have TILE_TYPE_BLOCKs in it. You can grab an updated one here: Example Map. Since this tutorial is so lengthy, and took me a long time (sorry), please be sure to let me know of any bugs or something I forgot to address. Thanks.

P.S.
In the next tutorial, we'll see how to react to collisions that happen. In this tutorial, though we pushed collisions into a queue, we didn't do anything with the queue yet.