From 8028320cef26978a52e47a6076b2467a71e3f941 Mon Sep 17 00:00:00 2001 From: Tamir Atias <engine.games@gmail.com> Date: Tue, 17 Apr 2012 20:23:48 +0300 Subject: [PATCH] [Add] Tile based collisions. --- Data/Img/CollisionTileset.png | Bin 0 -> 921 bytes Data/Map/Ugly.tmx | 8 ++++ src/Actor/Actor.cpp | 15 ++++-- src/Actor/Actor.h | 6 ++- src/Actor/NPC.cpp | 2 +- src/Actor/NPC.h | 2 +- src/Actor/Player.cpp | 9 +--- src/Actor/Player.h | 2 +- src/Animation/AnimatingSprite.cpp | 4 ++ src/Animation/AnimatingSprite.h | 6 +++ src/Level/Level.cpp | 73 ++++++++++++++++++++++++++++++ src/Level/Level.h | 3 ++ src/Main/Game.cpp | 4 +- 13 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 Data/Img/CollisionTileset.png diff --git a/Data/Img/CollisionTileset.png b/Data/Img/CollisionTileset.png new file mode 100644 index 0000000000000000000000000000000000000000..0eabc26af41e07f9f3bd32c111a8d199fcb2f5cf GIT binary patch literal 921 zcmV;K17`e*P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qQF!XYv0009BNkl<ZcwXh3F;>Gc3_v}0>=D>lIRFDA zM_}wR7<-c*fsrFHGBPqUFmx*e4~o>d#BO3+wk11GhP=XirR0ChvMi_SsMJwk+avt6 zm`kbEuTswn;5Untpy83b8}TJcFyJ8q_I=1NLBa(*4E&8f=jSY81RkS*nDpi-!2v%m zU~W0V1Me0vl<?T(@)&^k3m8h+G$p}?f5(J3cK_kR$Ic0DNKk4GOWX^lICw?)E7#zK z1+*3k9sDZ=K0F1?(zu04h=h+5&_%-5D4VA>9TMQ<1zbpgP<xm}VoZcj6JSUH0bg+4 zSCx<fpDti35;EcQ1k{$m0G}_QmINkv9swW$^1x27yYe}K5uQx|eozq!Har$P&I*s3 zm}!+Du~#T6VF<sbLi*mvDnKj}gy31HfN9x?guQDQMjkyucrgJNk&rGy7+zFBwuA!k z;sTN-6oM}zAX)+}ZIDCWbX|c<9ZR;)Ylsk+L1$tk^yW@~+reW82Rk{~(Gi6&76BUW zbQY)KhKbRJ$M>zsD@DctvDX3Kn|4J)CHS%ta2_RF!Uv4>tr7OcM*cidWg}o*!nd9l z#o_BjfR+HGeht?_!yoYX5_A6Yf7FVA|7`!G)F-utEg`79fMLQTA7ZpGz?JQpn;bEs z%0&R2&3UtZB?)B&bnsaGV1?(-_7x<^3!uXHOQd<WhkF9ia#&VCEd00x(G8KDfK>Rx z5@ZDA!WWdlFTjR>%HGx4ODFqu;1yuQ?_$>Dz%J746R=9)6CefOPX`eRJOZTQ1tsJQ zQ0mSoa`?jD)#Vws&9XX2Spx9k2z*FFS9tR9<B^cnM@SY>4W3y-l7Q;)wuJB=!_zd4 z7BCt3UIJ~S<&Y31U~=#b637B33!f>0Bw+IJ84`j5nt^vo2%H*u1vCdgF2P%$I0fKi zuvLnjjB`F~Lq#ml#|0QqhMyjH;kv29pF@e@p@5lvX(}Ya7BDmTbL9FY^a5rIACk}s vm^r*p!eZcE5>Nod!0Fnyn(brn+sp}ny`t7tLo&G600000NkvXXu0mjfZTX3K literal 0 HcmV?d00001 diff --git a/Data/Map/Ugly.tmx b/Data/Map/Ugly.tmx index e61661e..c074773 100644 --- a/Data/Map/Ugly.tmx +++ b/Data/Map/Ugly.tmx @@ -6,6 +6,9 @@ <tileset firstgid="1" name="AwesomeTileset" tilewidth="64" tileheight="64"> <image source="../Img/AwesomeTileset.png" width="256" height="128"/> </tileset> + <tileset firstgid="9" name="Collision" tilewidth="64" tileheight="64"> + <image source="../Img/CollisionTileset.png" width="64" height="64"/> + </tileset> <layer name="Tile Layer 1" width="60" height="60"> <data encoding="base64" compression="zlib"> eJzt0MENgDAQA8EA13/NtHCBoFhiHvv3uMYYx4+qgA28vLy8vLzVbPfOVV2Nup/MtNv95o/Zkr1f/PfUewbFy8vLy8ubEC8vLy8vb0K8vLy8vLwJ8fLy8vLyJsTLy8vLy5sQLy8vLy9vQry8vLy8a703oRIWWw== @@ -16,4 +19,9 @@ eJztleEOgjAMBrcfwPu/sTGhSf06tDNCNd4lDZDNdrdOaK21xUXbr+sexnowb5F5mzzP5LuKe70uV1tTd/ej3+nYKmMz+a7C77Wtz/rR9zjqr+/bqK+jfFrz6v4enb/eHn03FzZP8/jQfbFcbfB8JeZr9a0v2t+R7yZ5/Bz9n2h/K1x9be+rY0fnWX09+j7wc6rfVx5/zqrO3JksyfgnsnsyE/9Ela9+QzTOYtb31Tqz8ey8farGaP/e8f0mMuvHNw++teAbwTcPvrXgG8E3D7614BvBNw++teAbwTcPvrXgG8E3D7614BvBNw++teAbwTcPvrXgG8E3D7614BvBNw++teAbwTcPvrXgG8E3D761/IrvDT5XCI0= </data> </layer> + <layer name="Collision" width="60" height="60"> + <data encoding="base64" compression="zlib"> + eJzt1MEKgCAMANBd/f8f7hripoSYh/cgarKNaKOIiPa6YhD3Z1VeJPFKv1Pa5N4/Z3Vfzv6wa77ZnG+db/8uVU5Vl32XWb9TqrlkOVVd1uemfc7i0U7O9ndUu9IPdhj9Z+wbAAAAAAAAAAAAAACwywOaowOg + </data> + </layer> </map> diff --git a/src/Actor/Actor.cpp b/src/Actor/Actor.cpp index 6c32dec..fc7828c 100644 --- a/src/Actor/Actor.cpp +++ b/src/Actor/Actor.cpp @@ -2,8 +2,11 @@ #include "Actor.h" #include "../Sound/SoundEffect.h" +#include "../Level/Level.h" + +Actor::Actor(const Level* level) { + _level = level; -Actor::Actor(void) { _stepSFX[0] = sfxManager.Load("../Data/SFX/step_cloth1.wav"); _stepSFX[1] = sfxManager.Load("../Data/SFX/step_cloth2.wav"); _stepSFX[2] = sfxManager.Load("../Data/SFX/step_cloth3.wav"); @@ -54,10 +57,16 @@ void Actor::Update(float dt) { float oldX = x; float oldY = y; - // We should check for collisions now. - Move(dt); + if(x != oldX || y != oldY) { + if(_level->CheckCollision(x, y, GetAnimation()->GetMaxWidth(), GetAnimation()->GetMaxHeight())) { + x = oldX; + y = oldY; + return; + } + } + if(x != oldX || y != oldY) { GetAnimation()->SetCurrentAnimation(1); diff --git a/src/Actor/Actor.h b/src/Actor/Actor.h index 228c0fd..462af3f 100644 --- a/src/Actor/Actor.h +++ b/src/Actor/Actor.h @@ -6,6 +6,7 @@ #include "../Math/Vec2.h" class SoundEffect; +class Level; class Actor { public: @@ -23,7 +24,7 @@ public: HURT }; - Actor(void); + Actor(const Level* level); ~Actor(void); void LoadSprites(const String& basename); @@ -47,6 +48,8 @@ protected: AnimatingSprite* GetAnimation(void); + const Level* _level; + float _velocity; AnimatingSprite* _actorLeft; @@ -61,6 +64,7 @@ protected: float y; private: + SoundEffect* _stepSFX[4]; int _lastStepSFXPlayed; diff --git a/src/Actor/NPC.cpp b/src/Actor/NPC.cpp index c344ab1..673b8fe 100644 --- a/src/Actor/NPC.cpp +++ b/src/Actor/NPC.cpp @@ -1,6 +1,6 @@ #include "NPC.h" -NPC::NPC(void) : Actor() { +NPC::NPC(const Level* level) : Actor(level) { } NPC::~NPC(void) { diff --git a/src/Actor/NPC.h b/src/Actor/NPC.h index 3f96100..f5b3d61 100644 --- a/src/Actor/NPC.h +++ b/src/Actor/NPC.h @@ -4,7 +4,7 @@ class NPC : public Actor { public: - NPC(void); + NPC(const Level* level); ~NPC(void); void Update(float dt); diff --git a/src/Actor/Player.cpp b/src/Actor/Player.cpp index 11a16c5..42dfeb2 100644 --- a/src/Actor/Player.cpp +++ b/src/Actor/Player.cpp @@ -1,7 +1,7 @@ #include "Player.h" #include "../IO/Input.h" -Player::Player(void) : Actor() { +Player::Player(const Level* level) : Actor(level) { _direction = Actor::RIGHT; } @@ -34,11 +34,4 @@ void Player::Move(float dt) { _direction = Actor::FRONT; } - if(KeyDown(SDLK_LSHIFT)) { - // Run! - _velocity += 3; - } - if(KeyUp(SDLK_LSHIFT)) { - _velocity -= 3; - } } diff --git a/src/Actor/Player.h b/src/Actor/Player.h index 3a4e67c..61f4c0e 100644 --- a/src/Actor/Player.h +++ b/src/Actor/Player.h @@ -7,7 +7,7 @@ class Player : public Actor{ public: - Player(void); + Player(const Level* level); ~Player(void); void Update(float dt); diff --git a/src/Animation/AnimatingSprite.cpp b/src/Animation/AnimatingSprite.cpp index ee384aa..8c625d3 100644 --- a/src/Animation/AnimatingSprite.cpp +++ b/src/Animation/AnimatingSprite.cpp @@ -49,6 +49,8 @@ void AnimatingSprite::Update(float dt) { void AnimatingSprite::LoadAnimatingSprite(const char* filename, const char* sequence, int frames, float animationSpeed) { + _maxWidth = 0; + _maxHeight = 0; for(int i = 0; i < frames; i++) { String tempFilename; tempFilename = ""; @@ -62,6 +64,8 @@ void AnimatingSprite::LoadAnimatingSprite(const char* filename, const char* sequ } _sprites[_spriteCounter] = new Sprite(); _sprites[_spriteCounter]->LoadSprite((const char*)tempFilename); + if(_sprites[_spriteCounter]->GetWidth() > _maxWidth) _maxWidth = _sprites[_spriteCounter]->GetWidth(); + if(_sprites[_spriteCounter]->GetHeight() > _maxHeight) _maxHeight = _sprites[_spriteCounter]->GetHeight(); _spriteCounter++; } _numberOfFrames = frames; diff --git a/src/Animation/AnimatingSprite.h b/src/Animation/AnimatingSprite.h index d55cb8e..f45ed63 100644 --- a/src/Animation/AnimatingSprite.h +++ b/src/Animation/AnimatingSprite.h @@ -16,6 +16,9 @@ public: int GetTotalFrames(void) { return _sequence->GetAnimation(_currentAnimation)->frameEnd; } Sprite* GetCurrentFrameSprite(void) { return _sprites[_currentFrame - 1]; } + int GetMaxWidth(void) const { return _maxWidth; } + int GetMaxHeight(void) const { return _maxHeight; } + void Update(float dt); void Render(void); @@ -34,4 +37,7 @@ private: int _numberOfFrames; const char* _currentAnimation; + + int _maxWidth; + int _maxHeight; }; diff --git a/src/Level/Level.cpp b/src/Level/Level.cpp index 2960fbd..e7706a2 100644 --- a/src/Level/Level.cpp +++ b/src/Level/Level.cpp @@ -13,6 +13,7 @@ Level::Level() { _tileWidth = 0; _tileHeight = 0; _bgm = NULL; + _collisions = NULL; } Level::~Level() { @@ -26,6 +27,11 @@ Level::~Level() { } _tilesets.clear(); + if(_collisions) { + delete[] _collisions; + _collisions = NULL; + } + if(_bgm) { musicManager.Destroy(_bgm); _bgm = NULL; @@ -59,8 +65,23 @@ bool Level::Load(const std::string& filename) { tilesetMap.insert(std::pair<const Tmx::Tileset*, Tileset*>(tmxTileset, tileset)); } + _collisions = new bool[_width * _height]; + for(int i = 0; i < (_width * _height); i++) { + _collisions[i] = false; + } + for(int i = 0; i < map.GetNumLayers(); i++) { const Tmx::Layer* tmxLayer = map.GetLayer(i); + + if(!stricmp(tmxLayer->GetName().c_str(), "collision")) { + for(int x = 0; x < _width; x++) { + for(int y = 0; y < _height; y++) { + Tmx::MapTile tile = tmxLayer->GetTile(x, y); + _collisions[y * _width + x] = tile.gid != 0; + } + } + continue; + } Layer* layer = new Layer( tmxLayer->GetWidth(), tmxLayer->GetHeight(), @@ -114,3 +135,55 @@ void Level::Draw(int xOffset, int yOffset) { (*i)->Draw(xOffset, yOffset); } } + +bool Level::CheckCollision(float x, float y, float w, float h) const { + if(x < 0.0f || x > (float)(_width * _tileWidth) || + y < 0.0f || y > (float)(_height * _tileHeight)) { + return true; + } + + int tileX; + int tileY; + + // Check Top Left + tileX = (int)(x / (float)_tileWidth); + tileY = (int)(y / (float)_tileHeight); + if(tileX >= 0 && tileX < _width && + tileY >= 0 && tileY < _height) { + if(_collisions[tileY * _width + tileX]) { + return true; + } + } + + // Check Top Right + tileX = (int)((x + w) / (float)_tileWidth); + tileY = (int)(y / (float)_tileHeight); + if(tileX >= 0 && tileX < _width && + tileY >= 0 && tileY < _height) { + if(_collisions[tileY * _width + tileX]) { + return true; + } + } + + // Check Bottom Right + tileX = (int)((x + w) / (float)_tileWidth); + tileY = (int)((y + h) / (float)_tileHeight); + if(tileX >= 0 && tileX < _width && + tileY >= 0 && tileY < _height) { + if(_collisions[tileY * _width + tileX]) { + return true; + } + } + + // Check Bottom Left + tileX = (int)(x / (float)_tileWidth); + tileY = (int)((y + h) / (float)_tileHeight); + if(tileX >= 0 && tileX < _width && + tileY >= 0 && tileY < _height) { + if(_collisions[tileY * _width + tileX]) { + return true; + } + } + + return false; +} diff --git a/src/Level/Level.h b/src/Level/Level.h index ce0a8fe..3f09c6d 100644 --- a/src/Level/Level.h +++ b/src/Level/Level.h @@ -24,6 +24,8 @@ public: int GetTileWidth() const { return _tileWidth; } int GetTileHeight() const { return _tileHeight; } + bool CheckCollision(float x, float y, float w, float h) const; + private: int _width; int _height; @@ -32,4 +34,5 @@ private: std::list<Layer*> _layers; std::list<Tileset*> _tilesets; Music* _bgm; + bool* _collisions; }; diff --git a/src/Main/Game.cpp b/src/Main/Game.cpp index 09b69b0..1592f7e 100644 --- a/src/Main/Game.cpp +++ b/src/Main/Game.cpp @@ -16,9 +16,9 @@ #include "Game.h" Game::Game(void) { - _player = new Player(); - _NPC = new NPC(); _level = new Level(); + _player = new Player(_level); + _NPC = new NPC(_level); _NPC->SetXY(30.0f, 30.0f);