Jackason13524
Jackason13524

Reputation: 21

Can't set 'bool solid' to only some tiles

First of all, I'd like to say that I'm relatively new to c++ so the solution to this problem is probably relatively simple. In SDL, I have been working on a small 2d game using tiles. The tile map is in a separate .txt file. The tiles are shown completely fine and are using the right textures based on the type. However, when I try to set a 'solid' bool to true in the constructor if the type is 1 (stone tile), and check for collisions in an 'update' function, it treats every tile like they are solid. This makes it so the player collides with the background. What am I doing wrong.

EDIT: I added most of the previously not-posted code.

Here is the Tile.h

#pragma once
#include "SDL.h"

class Tile
{

public:

    SDL_Rect box;

    int type;

    bool solid;

    Tile(int tileNum,int type_e);

    void show();

    bool update(SDL_Rect A);

    SDL_Surface* tile[3];

};

Tile.cpp

#include "Tile.h"
#include "Finals.h"

bool check_collisions(SDL_Rect A, SDL_Rect B);

Tile::Tile(int tileNum, int type_e)
{

    box.x = (tileNum % 16) * 40;
    box.y = (tileNum / 16) * 40;

    box.w = 40;
    box.h = 40;

    type = type_e;

    tile[0] = LoadImage("tile.png");
    tile[1] = LoadImage("tile2.png");
    tile[2] = LoadImage("tile3.png");

    if(type_e == 1)
        solid = true;
}

void Tile::show()
{

    ApplyImage(box.x, box.y, tile[type], screen);

}

bool Tile::update(SDL_Rect A)
{

    if(solid && check_collisions(A, box))
    {
        return true;
    }
    else
    {
        return false;
    }

}

main.cpp

#include "SDL.h"
#include "SDL_image.h"
#include "Finals.h"
#include <string>
#include "Tile.h"
#include <vector>
#include "Timer.h"
#include <fstream>
#include "Player.h"


SDL_Surface* screen;

SDL_Event Event;

int main( int argc, char* args[] )
{
    extern SDL_Surface* screen;
    SDL_Surface* background;

    bool quit = false;



    //Start SDL
    SDL_Init( SDL_INIT_EVERYTHING );

    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);

    std::vector<Tile> tiles;

    std::ifstream map ( "map.txt" );

    int tileType = 0;

    for (int iii = 0;iii < 192;iii++)
    {

        map >> tileType;

        tiles.push_back(Tile(iii,tileType));

    }

    map.close();

    Timer fps;

    Player myPlayer;

    while(!quit)
    {

        fps.startTimer();

        while(SDL_PollEvent(&Event))
        {

            myPlayer.handleEvents();

            if(Event.type == SDL_KEYDOWN)
            {
                if(Event.key.keysym.sym == SDLK_ESCAPE)
                    quit = true;
            }

            if(Event.type == SDL_QUIT)
                quit = true;
        }

        myPlayer.move();

        for(int iii = 0;iii < 192;iii++)
        {

            if(tiles[iii].update(myPlayer.box))
            {
                myPlayer.box.x -= myPlayer.xVel;
                myPlayer.box.y -= myPlayer.yVel;
            }

            tiles[iii].show();
        }



        myPlayer.show();

        SDL_Flip(screen);

        if(fps.getTime() < 1000 / FPS)
        {
            SDL_Delay(1000/FPS - fps.getTime());
        }
    }

    //Quit SDL
    SDL_Quit();

    return 0;    
}

Player.cpp

#include "Player.h"
#include "Finals.h"
#include "SDL.h"

Player::Player()
{

    box.x = 20;
    box.y = 20;

    xVel = 0;
    yVel = 0;

}

void Player::handleEvents()
{
    if(Event.type == SDL_KEYDOWN)
    {
        switch(Event.key.keysym.sym)
        {
        case SDLK_UP: yVel -= PLAYER_VEL; break;
        case SDLK_DOWN: yVel += PLAYER_VEL; break;
        case SDLK_RIGHT: xVel += PLAYER_VEL; break;
        case SDLK_LEFT: xVel -= PLAYER_VEL; break;
        }
    }

    if(Event.type == SDL_KEYUP)
    {
        switch(Event.key.keysym.sym)
        {
        case SDLK_UP: yVel += PLAYER_VEL; break;
        case SDLK_DOWN: yVel -= PLAYER_VEL; break;
        case SDLK_RIGHT: xVel -= PLAYER_VEL; break;
        case SDLK_LEFT: xVel += PLAYER_VEL; break;
        }
    }
}

void Player::move()
{
    box.x += xVel;
    box.y += yVel;

    if(box.x + PLAYER_WIDTH > SCREEN_WIDTH)
    {
        box.x = SCREEN_WIDTH - PLAYER_WIDTH;
    }
    if(box.y + PLAYER_HEIGHT > SCREEN_HEIGHT)
    {
        box.y = SCREEN_HEIGHT - PLAYER_HEIGHT;
    }
    if(box.x < 0)
    box.x = 0;
    if(box.y < 0)
    box.y = 0;
}

void Player::show()
{

    SDL_Surface* sprite;

    sprite = LoadImage("player.png");

    ApplyImage(box.x,box.y,sprite,screen);

    SDL_FreeSurface(sprite);

    sprite = NULL;
}

This is the context of map.txt:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Also, here is my collision function:

#include "SDL.h"

bool check_collisions(SDL_Rect A, SDL_Rect B)
{
    int topA;
    int topB;
    int bottomA;
    int bottomB;
    int rightA;
    int rightB;
    int leftA;
    int leftB;

    topA = A.y;
    bottomA = A.y + A.h;
    leftA = A.x;
    rightA = A.x + A.w;

    topB = B.y;
    bottomB = B.y + B.h;
    leftB = B.x;
    rightB = B.x + B.w;

    if (bottomA <= topB)
        return false;
    if (rightA <= leftB)
        return false;
    if (topA >= bottomB)
        return false;
    if (leftA >= rightB)
        return false;
    return true;
}

Other than what is posted I have an image loading function, an apply image function, and a timer class.

Upvotes: 1

Views: 102

Answers (2)

Jackason13524
Jackason13524

Reputation: 21

I figured it out. I never assigned myPlayer.box.w and myPlayer.box.h values. I have no idea what the default values are but for some reason it collided regardless of were the player was. Thanks for all your help!

Upvotes: 1

jhaight
jhaight

Reputation: 299

I'm not positive that this is your issue but your solid variable is unset if the type isn't 1. In your constructor you should initialize all of your member variables. You can use the initializer list to do this to make sure your variables don't have garbage in them.

Tile::Tile(int tileNum, int type_e) : solid(false) {

Upvotes: 1

Related Questions