Player Spritesheet Problems

Started by
0 comments, last by Dante12129 10 years, 11 months ago

I am making a tile-based game using C++ and SDL. I've been writing a library to make certain parts of it easier. My current problem is that I have a player that has a spritesheet that has images for each possible direction. Its dimensions are 128x32, with each sprite being 32x32. The rpoblem is that if i try to access anything besides the sprite at the first position at vector, it doesn't return an image. I also have a spritesheet for the terrain, but it renders fine no matter which sprite I choose, but it is 512x512.

Spritesheet.hpp


#ifndef SPRITESHEET_HPP_INCLUDED
#define SPRITESHEET_HPP_INCLUDED

#include <vector>
#include "Image.hpp"
#include "Primitives.hpp"
#include "General.hpp"

/**
 * \file
 * \brief File that contains everything needed to load nad handle a spritesheet.
 * \author Dante12129
 * \version 1.0
 */

 namespace grnbll
 {
     class Spritesheet : public Applyable
     {
         public:
            //Constructors and destructor
            Spritesheet();
            Spritesheet(std::string filename, unsigned int width, unsigned int height, unsigned int sprite_width, unsigned int sprite_height);
            ~Spritesheet();

            //Getters
            unsigned int GetSpriteWidth();
            unsigned int GetSpriteHeight();
            Rectangle& GetSprite(int spritenumber);
            SDL_Surface* GetSurface();

            //Manipulation Functions
            int MakeTransparent(uint8_t r, uint8_t g, uint8_t b);

         private:
            //Container of all the coordinates of the images
            std::vector<Rectangle> sprites;

            //Height and width of the whole image
            unsigned int whole_width, whole_height;
            //Height and width of a single sprite
            unsigned int m_sprite_width, m_sprite_height;

            //The image of the spritesheet
            Image m_img_whole;

            //Number of sprites in the image
            int m_num_of_sprites, m_sprites_per_row, m_sprites_per_column;

            //The name of the spritesheet for the file
            std::string m_filename;

     };
 }

#endif // SPRITESHEET_HPP_INCLUDED

Spritesheet.cpp


#include "Spritesheet.hpp"

//Spritesheet
//Constructors and destructor
grnbll::Spritesheet::Spritesheet()
{
    //Initalize all sizes to 0
    whole_width = 0; whole_height = 0; m_sprite_width = 0; m_sprite_height = 0;
    m_num_of_sprites = 0; m_sprites_per_row = 0; m_sprites_per_column = 0;
    //The image and vector don't contain anything
    //Set the filename to nothing
    m_filename = "";
}
grnbll::Spritesheet::Spritesheet(std::string filename, unsigned int width, unsigned int height, unsigned int sprite_width, unsigned int sprite_height)
{
    //Initalize the sizes
    whole_width = width; whole_height = height; m_sprite_width = sprite_width; m_sprite_height = sprite_height;
    m_sprites_per_row = whole_width/m_sprite_width; m_sprites_per_column = whole_height/m_sprite_height; m_num_of_sprites = m_sprites_per_row*m_sprites_per_column;
    //Initialize the image
    m_img_whole = Image(width, height, filename);
    //Initialize the vector so that sprites can be accessed
    if(m_sprites_per_column == 1)
    {
        for(int i = 0; i < m_sprites_per_row; i++)
        {
            sprites.push_back(Rectangle(i*m_sprite_width, 0, m_sprite_width, m_sprite_height));
        }
    }
    else if(m_sprites_per_row == 1)
    {
        for(int i = 0; i < m_sprites_per_column; i++)
        {
            sprites.push_back(Rectangle(0, i*m_sprite_width, m_sprite_width, m_sprite_height));
        }
    }
    else
    {
        for(int i = 0; i < m_sprites_per_row; i++)
        {
            for(int j = 0; j < m_sprites_per_column; j++)
            {
                sprites.push_back(Rectangle(j*m_sprite_width, i*m_sprite_height, m_sprite_width, m_sprite_height));
            }
        }
    }
}
grnbll::Spritesheet::~Spritesheet() = default;

//Getters
unsigned int grnbll::Spritesheet::GetSpriteWidth() { return m_sprite_width; }
unsigned int grnbll::Spritesheet::GetSpriteHeight() { return m_sprite_height; }
grnbll::Rectangle& grnbll::Spritesheet::GetSprite(int spritenumber){ return sprites.at(spritenumber); }
SDL_Surface* grnbll::Spritesheet::GetSurface() { return m_img_whole.GetSurface(); }

//Manipulation functions
int grnbll::Spritesheet::MakeTransparent(uint8_t r, uint8_t g, uint8_t b)
{
    return m_img_whole.MakeTransparent(r, g, b);
}

Player.hpp


#ifndef PLAYER_HPP_INCLUDED
#define PLAYER_HPP_INCLUDED

#include "New_Engine.hpp"

namespace survgame
{
    enum class Directions
    {
        Up = 3,
        Down = 1,
        Left = 2,
        Right = 0
    };

    class Player : public grnbll::Applyable
    {
        public:
            //Constructors and destructor
            Player(int start_x, int start_y, Directions starting_direction, std::string filename);
            ~Player();

            //Getters
            int GetX();
            int GetY();
            int GetXOld();
            int GetYOld();

            //Setters
            void SetX(int x);
            void SetY(int y);
            void SetXOld(int x);
            void SetYOld(int y);

            //Handlers
            void HandleEvents(grnbll::Event& event);
            SDL_Surface* GetSurface();
            grnbll::Rectangle& GetDirection();

        private:
            //Position variables
            int x_pos, y_pos;
            int x_old, y_old;
            Directions facing_direction;

            //The spritesheet for the player
            grnbll::Spritesheet player_sprites;
    };
}

#endif // PLAYER_HPP_INCLUDED

Player.cpp


#include "Player.hpp"

//Player
//Constructors and destructor
survgame::Player::Player(int start_x, int start_y, Directions starting_direction, std::string filename)
{
    //Initialize the positions and the direction.
    x_pos = start_x; y_pos = start_y;
    x_old = start_x; y_old = start_y;
    facing_direction = starting_direction;

    //Load the spritesheet.
    player_sprites = grnbll::Spritesheet(filename, 128, 32, 32 ,32);
    player_sprites.MakeTransparent(0xED, 0x0B, 0xB5);
}
survgame::Player::~Player() = default;

//Getters
int survgame::Player::GetX() { return x_pos; }
int survgame::Player::GetY() { return y_pos; }
int survgame::Player::GetXOld() { return x_old; }
int survgame::Player::GetYOld() { return y_old; }

//Setters
void survgame::Player::SetX(int x) { x_pos = x; }
void survgame::Player::SetY(int y) { y_pos = y; }
void survgame::Player::SetXOld(int x) { x_old = x; }
void survgame::Player::SetYOld(int y) { y_old = y; }

//Handlers
void survgame::Player::HandleEvents(grnbll::Event& event)
{
    x_old = x_pos;
    y_old = y_pos;
    if(event.GetOther().other == grnbll::OtherEvents::KeyPress)
    {
        switch(event.GetKeyboard().key)
        {
            case grnbll::Keys::Left:
                x_pos--;
                facing_direction = Directions::Left;
                break;
            case grnbll::Keys::Right:
                x_pos++;
                facing_direction = Directions::Right;
                break;
            case grnbll::Keys::Up:
                y_pos--;
                facing_direction = Directions::Up;
                break;
            case grnbll::Keys::Down:
                y_pos++;
                facing_direction = Directions::Down;
                break;
        }
    }
}
SDL_Surface* survgame::Player::GetSurface() { return player_sprites.GetSurface(); }
grnbll::Rectangle& survgame::Player::GetDirection() { return player_sprites.GetSprite(0); }

main.cpp


#include <fstream>
#include <cstdlib>
#include "New_Engine.hpp"
#include "Player.hpp"

int main ( int argc, char* argv[] )
{
    //Variables necessary to the screen and program
    grnbll::Screen screen(512, 612, "Game");
    grnbll::Event event;
    grnbll::FPSRegulator fps(60); fps.Start();
    bool running = true;

    //Spritesheets
    grnbll::Spritesheet terrain("Terrain.png", 512, 512, 32, 32);
    terrain.MakeTransparent(0xED, 0x0B, 0xB5);

    //Map file
    std::ifstream map_file("World1.map");

    //Player Info
    survgame::Player player(4, 0, survgame::Directions::Down, "Player.png");

    //Others

    //Load the map
    int map_array[16][16];
    for(int i = 0; i < 16; i++)
    {
        for(int j = 0; j < 16; j++)
        {
            char current_map_piece;
            map_file >> current_map_piece;
            map_array[j] = current_map_piece - '0';
        }
    }

    //Setup the screen
    screen.SetBackgroundColor(SDL_MapRGB(SDL_GetVideoSurface()->format, 0xFF, 0xFF, 0xFF));
    if(map_file.is_open())
    {
        for(int i = 0; i < 16; i++)
        {
            for(int j = 0; j < 16; j++)
            {
                screen.Apply(terrain, j*32, i*32, terrain.GetSprite(map_array[j]));
            }
        }
        screen.Flip();
    }

    while(running)
    {
        //Event handling
        while(event.Poll())
        {
            if(event.GetOther().other == grnbll::OtherEvents::Quit)
            {
                running = false;
            }
            player.HandleEvents(event);
        }

        //Logic
        if(map_array[player.GetX()][player.GetY()] == 3)
        {
            running = false;
        }

        //Rendering
        if((player.GetX() > 15) || (player.GetX() < 0) || (player.GetY() > 15) || (player.GetY() < 0) || (map_array[player.GetX()][player.GetY()] == 1))
        {
            player.SetX(player.GetXOld());
            player.SetY(player.GetYOld());
            screen.Apply(player, player.GetX()*32, player.GetY()*32, player.GetDirection());
            screen.Flip();
        }
        else
        {
            screen.Apply(terrain, player.GetXOld()*32, player.GetYOld()*32, terrain.GetSprite(map_array[player.GetXOld()][player.GetYOld()]));
            screen.Apply(player, player.GetX()*32, player.GetY()*32, player.GetDirection());
            screen.Flip();
        }

        fps.Delay();
    }

    return 0;
}

The rectangles are constructed like (x, y, w, h).

The apply function takes a reference to an Applyable class so that it can get a pointer for blitting, the x and y positions to blit, and then a rectangle of what part of the source image to blit.

If I replace the "0" in Player::GetDirection() with an int between one and three or static_cast<int>(facing_direction), it won't give me the correct part of the spritesheet. I was wondering if this has to do with the player spritesheet having its sprite height and whole height equal instead of the terrain spritesheet, where they aren't equal.

Advertisement

I got it working. I had forgotten I had hardcoded sprite widths and heights into the Apply method instead of getting them from the rectangle that is passed.

This topic is closed to new replies.

Advertisement