Skip to main content
gamedev.net
🔒 Locked

Problems detecting passable objects

Started by Peter Conn Sep 25, 2006 at 1:34 PM 1 replies 650+ views
Original Post
Peter Conn
Peter Conn
Hiya I am currently making a game in C++ with SDL. It's 2D and so far I've managed to make a map and get a player to move around it. My problem comes when I try to add in collision detection with the surrounding tiles. Here is my code: Map.h (contains all classes to do with showing the map)

#ifndef MAP_H
#define MAP_H
#include "Includes.h"

class Tile : public CSprite{
public:
    bool passable;
    void WipeBG();
    void clearBG();
    Tile(CSpriteBase *base, SDL_Surface *screen, bool passable);
    void tDescribe();
    void setOld(int x, int y);
};

class Layer{
public:
    std::vector< std::vector<int> > Tiles;
    std::vector< Tile* > TileSet;
};

class Map{
public:
    std::string name;
    std::string description;
    std::vector< Layer > Layers;
    void Draw(int x, int y);
    int OldOffsetX, OldOffsetY;
    Map();
};

#endif

Map.cpp

#include "Includes.h"

Map::Map(){
    OldOffsetX = 0;
    OldOffsetY = 0;
}

void Map::Draw(int OffSetX, int OffSetY){
    for(int lay = 0; lay < Layers.size(); lay ++)
    {
        for(int row = 0; row < Layers[lay].Tiles.size(); row ++)
        {
            for(int col = 0; col < Layers[lay].Tiles[row].size(); col++)
            {
                int curTile = this->Layers[lay].Tiles[row][col];
                this->Layers[ lay ].TileSet[ curTile ]->setOld((col*TileWidth) + OldOffsetX, (row*TileHeight) + OldOffsetY);
                this->Layers[ lay ].TileSet[ curTile ]->set((col*TileWidth) + OffSetX, (row*TileHeight) + OffSetY);

                this->Layers[ lay ].TileSet[ curTile ]->WipeBG();
                this->Layers[ lay ].TileSet[ curTile ]->draw();
            }
        }
    }
    this->OldOffsetX = OffSetX;
    this->OldOffsetY = OffSetY;
}

Tile::Tile(CSpriteBase *base, SDL_Surface *screen, bool pass){
  mSpriteBase = base;
  if(mSpriteBase->mBuilt)
  {
    if(mSpriteBase->mNumframes>1) mAnimating=1;
    mBackreplacement =
               SDL_DisplayFormat(mSpriteBase->mAnim[0].image);
  }
  mScreen = screen;
  mFrame = 0;
  mDrawn = 0;
  mLastupdate = 0;
  passable = pass;
}

void Tile::clearBG()
{
  if(mDrawn==1)
  {
    SDL_Rect dest;
    dest.x = mOldX;
    dest.y = mOldY;
    dest.w = mSpriteBase->mW;
    dest.h = mSpriteBase->mH;
    SDL_FillRect(mBackreplacement, NULL, 0 );
    //SDL_BlitSurface(mBackreplacement, NULL, mScreen, &dest);
  }
}

void Tile::WipeBG()
{
    SDL_Rect backSpace;
    backSpace.x = mOldX;
    backSpace.y = mOldY;
    backSpace.w = this->GetW();
    backSpace.h = this->GetH();
    SDL_FillRect(mScreen, &backSpace, 0);
}

void Tile::tDescribe(){
    printf("\n\tX and Y: %d, %d", this->X(), this->Y());
    printf("\n\tOld X and Y: %d, %d", this->mOldX, this->mOldY);
}

void Tile::setOld(int x, int y){
    mOldX = x;
    mOldY = y;
}

This is where my collision detection is, and this causes the problems:

void Player::Move(Direction dir, Map const *place){
    int col = (GlobalX / TileWidth);
    int row = (GlobalY / TileHeight);
    int lay = GlobalLevel;
    if(m_movingDir == None)
    {
        int nextTile;
        if(dir==Up){
            if(col-1 < 0)
                return;
            nextTile = place->Layers[lay].Tiles[row][col-1];
        }
        if(dir==Down){
            if(col+1 >= place->Layers[lay].Tiles[row].size())
                return;
            nextTile = place->Layers[lay].Tiles[row][col+1];
        }
        if(dir==Right){
            if(row+1 >= place->Layers[lay].Tiles.size())
                return;
            nextTile = place->Layers[lay].Tiles[row+1][col];
        }
        if(dir==Left){
            if(row-1 < 0)
                return;
            nextTile = place->Layers[lay].Tiles[row-1][col];
        }

        if(place->Layers[ lay ].TileSet[ nextTile ]->passable)
            m_movingDir = dir;
    }
}

At the moment if the player can move in a direction is totally random (or so it seems to me), although then he gets to the edge of the map, where the game promptly crashes. I am sure that this crash is due to trying to access non-exsistant places in the vector, but I don't know why my checks are stopping it. Any help would be much apprecieated.
Whether you think you can or think you can’t, you’re probably right – Henry Ford
Artum
Artum
Hmm. Sounds like an out of bounds issue if it's crashing when you get to the edge. I don't have much time, but I'll try to help right quick.

Try doing something like...
void Player::Move(Direction dir, Map const *place){    int col = (GlobalX / TileWidth);    int row = (GlobalY / TileHeight);    int lay = GlobalLevel;    if(m_movingDir == None)    {        int nextTile=-1;        if(dir==Up&&col-1>=0){            nextTile = place->Layers[lay].Tiles[row][col-1];        }        if(dir==Down&&col+1<SIZEofCOLS){            nextTile = place->Layers[lay].Tiles[row][col+1];        }        if(dir==Right&&row+1<SIZEofROWS){            nextTile = place->Layers[lay].Tiles[row+1][col];        }        if(dir==Left&&row-1>=0){            nextTile = place->Layers[lay].Tiles[row-1][col];        }        if(nextTile!=-1)        if(place->Layers[ lay ].TileSet[ nextTile ]->passable)            m_movingDir = dir;    }}


Ok, the first thing I posted was way off. Anyway, on the the fun stuff...

You set nextTile to -1 to initialize it. Then if where you're going is out of bounds you just don't update nextTile, leaving it as -1. Then I placed an extra if statement checking the value of nextTile. If it's still -1 (that means out of bounds because it hasn't changed) then you don't move. Try it and see if that helps. It should work, but this is really the blind leading the deaf here.

-Artum.

[Edited by - Artum on September 28, 2006 7:00:55 PM]
Peter Conn
Peter Conn
Thanks, that sorted the crashing problem, now I've still got the problem with collision detections, although I'm sure I can sort that out given time.
Unfortunatly because of the way I've made the maps it you need to access it:
Layers[lay].Tiles[y][x]
which is going to be confusing.
Whether you think you can or think you can’t, you’re probably right – Henry Ford

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.