From 1cbcbc19e4c7c60ce55c9bc57f7a9386db958822 Mon Sep 17 00:00:00 2001 From: Sten Rune Lyngmo Date: Fri, 18 Jun 2021 04:26:50 +0200 Subject: [PATCH 1/3] Many animations for a single animationcomponent --- Chapter01/Game.vcxproj | 6 ++-- Chapter02/AnimSpriteComponent.cpp | 49 ++++++++++++++++++++++++++----- Chapter02/AnimSpriteComponent.h | 8 +++++ Chapter02/Game.vcxproj | 6 ++-- Chapter02/Ship.cpp | 20 +++++++++++-- Chapter02/Ship.h | 1 + 6 files changed, 74 insertions(+), 16 deletions(-) diff --git a/Chapter01/Game.vcxproj b/Chapter01/Game.vcxproj index e16204f8..030533ff 100644 --- a/Chapter01/Game.vcxproj +++ b/Chapter01/Game.vcxproj @@ -21,19 +21,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/Chapter02/AnimSpriteComponent.cpp b/Chapter02/AnimSpriteComponent.cpp index 8b5f15e9..8294b036 100644 --- a/Chapter02/AnimSpriteComponent.cpp +++ b/Chapter02/AnimSpriteComponent.cpp @@ -13,6 +13,9 @@ AnimSpriteComponent::AnimSpriteComponent(Actor* owner, int drawOrder) :SpriteComponent(owner, drawOrder) , mCurrFrame(0.0f) , mAnimFPS(24.0f) + , mCurrentAnimation(-1) + , mNextAnimationTimer(0.f) + , mCanChangeAnimation(true) { } @@ -20,16 +23,27 @@ void AnimSpriteComponent::Update(float deltaTime) { SpriteComponent::Update(deltaTime); - if (mAnimTextures.size() > 0) + if (!mCanChangeAnimation) + { + mNextAnimationTimer += deltaTime; + + if (mNextAnimationTimer > 0.5f) + { + mCanChangeAnimation = true; + mNextAnimationTimer = 0.f; + } + } + + if (!mAnimTextures.empty()) { // Update the current frame based on frame rate // and delta time mCurrFrame += mAnimFPS * deltaTime; // Wrap current frame if needed - while (mCurrFrame >= mAnimTextures.size()) + while (mCurrFrame >= mAnimationStartEnd[mCurrentAnimation].second + 1) { - mCurrFrame -= mAnimTextures.size(); + mCurrFrame -= mAnimationStartEnd[mCurrentAnimation].second - mAnimationStartEnd[mCurrentAnimation].first; } // Set the current texture @@ -39,11 +53,32 @@ void AnimSpriteComponent::Update(float deltaTime) void AnimSpriteComponent::SetAnimTextures(const std::vector& textures) { - mAnimTextures = textures; - if (mAnimTextures.size() > 0) + if (!textures.empty()) { + mCurrFrame = mAnimTextures.size(); + mAnimationStartEnd.emplace_back(std::make_pair(mCurrFrame, mCurrFrame + textures.size() - 1)); + + SDL_Log("Animation start: %i Animation end: %i", mAnimationStartEnd.back().first, mAnimationStartEnd.back().second); + + mAnimTextures.insert(mAnimTextures.end(), textures.begin(), textures.end()); + // Set the active texture to first frame - mCurrFrame = 0.0f; - SetTexture(mAnimTextures[0]); + SetTexture(mAnimTextures[mCurrFrame]); + mCurrentAnimation++; + } +} + +void AnimSpriteComponent::NextAnimation() +{ + if (mAnimationStartEnd.size() > 1 && mCanChangeAnimation) + { + if (++mCurrentAnimation == mAnimationStartEnd.size()) + { + mCurrentAnimation = 0; + } + + SetTexture(mAnimTextures[mAnimationStartEnd[mCurrentAnimation].first]); + + mCanChangeAnimation = false; } } diff --git a/Chapter02/AnimSpriteComponent.h b/Chapter02/AnimSpriteComponent.h index d5aa387a..a3b11f6a 100644 --- a/Chapter02/AnimSpriteComponent.h +++ b/Chapter02/AnimSpriteComponent.h @@ -20,6 +20,7 @@ class AnimSpriteComponent : public SpriteComponent // Set/get the animation FPS float GetAnimFPS() const { return mAnimFPS; } void SetAnimFPS(float fps) { mAnimFPS = fps; } + void NextAnimation(); private: // All textures in the animation std::vector mAnimTextures; @@ -27,4 +28,11 @@ class AnimSpriteComponent : public SpriteComponent float mCurrFrame; // Animation frame rate float mAnimFPS; + + int mCurrentAnimation; + + std::vector> mAnimationStartEnd; + + float mNextAnimationTimer; + bool mCanChangeAnimation; }; diff --git a/Chapter02/Game.vcxproj b/Chapter02/Game.vcxproj index 35c39009..c749cb54 100644 --- a/Chapter02/Game.vcxproj +++ b/Chapter02/Game.vcxproj @@ -35,19 +35,19 @@ {BC508D87-495F-4554-932D-DD68388B63CC} Win32Proj Game - 10.0.16299.0 + 10.0 Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/Chapter02/Ship.cpp b/Chapter02/Ship.cpp index 5daca54a..00c89017 100644 --- a/Chapter02/Ship.cpp +++ b/Chapter02/Ship.cpp @@ -16,14 +16,24 @@ Ship::Ship(Game* game) ,mDownSpeed(0.0f) { // Create an animated sprite component - AnimSpriteComponent* asc = new AnimSpriteComponent(this); - std::vector anims = { + asc = new AnimSpriteComponent(this); + std::vector shipAnimation = { game->GetTexture("Assets/Ship01.png"), game->GetTexture("Assets/Ship02.png"), game->GetTexture("Assets/Ship03.png"), game->GetTexture("Assets/Ship04.png"), }; - asc->SetAnimTextures(anims); + asc->SetAnimTextures(shipAnimation); + + std::vector walkingAnimation = { + game->GetTexture("Assets/Character01.png"), + game->GetTexture("Assets/Character02.png"), + game->GetTexture("Assets/Character03.png"), + game->GetTexture("Assets/Character04.png"), + game->GetTexture("Assets/Character05.png"), + game->GetTexture("Assets/Character06.png"), + }; + asc->SetAnimTextures(walkingAnimation); } void Ship::UpdateActor(float deltaTime) @@ -75,4 +85,8 @@ void Ship::ProcessKeyboard(const uint8_t* state) { mDownSpeed -= 300.0f; } + if (state[SDL_SCANCODE_E]) + { + asc->NextAnimation(); + } } diff --git a/Chapter02/Ship.h b/Chapter02/Ship.h index 8a34e962..5ca0330e 100644 --- a/Chapter02/Ship.h +++ b/Chapter02/Ship.h @@ -19,4 +19,5 @@ class Ship : public Actor private: float mRightSpeed; float mDownSpeed; + class AnimSpriteComponent* asc; }; \ No newline at end of file From 3a0771e34c6caa3cc1d2c641b9eea3c2dd5bd9e3 Mon Sep 17 00:00:00 2001 From: Sten Rune Lyngmo Date: Fri, 16 Jul 2021 19:10:17 +0200 Subject: [PATCH 2/3] Support for non looping animations --- Chapter02/AnimSpriteComponent.cpp | 23 +++++++++++++++-------- Chapter02/AnimSpriteComponent.h | 19 +++++++++++++++++-- Chapter02/Ship.cpp | 2 +- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/Chapter02/AnimSpriteComponent.cpp b/Chapter02/AnimSpriteComponent.cpp index 8294b036..0fb67826 100644 --- a/Chapter02/AnimSpriteComponent.cpp +++ b/Chapter02/AnimSpriteComponent.cpp @@ -41,9 +41,16 @@ void AnimSpriteComponent::Update(float deltaTime) mCurrFrame += mAnimFPS * deltaTime; // Wrap current frame if needed - while (mCurrFrame >= mAnimationStartEnd[mCurrentAnimation].second + 1) + while (mCurrFrame >= mAnimSpriteInfos[mCurrentAnimation].end + 1) { - mCurrFrame -= mAnimationStartEnd[mCurrentAnimation].second - mAnimationStartEnd[mCurrentAnimation].first; + if (!mAnimSpriteInfos[mCurrentAnimation].looping) + { + mCurrFrame = mAnimSpriteInfos[mCurrentAnimation].end; + } + else + { + mCurrFrame -= mAnimSpriteInfos[mCurrentAnimation].end - mAnimSpriteInfos[mCurrentAnimation].start; + } } // Set the current texture @@ -51,14 +58,14 @@ void AnimSpriteComponent::Update(float deltaTime) } } -void AnimSpriteComponent::SetAnimTextures(const std::vector& textures) +void AnimSpriteComponent::SetAnimTextures(const std::vector& textures, bool looping) { if (!textures.empty()) { mCurrFrame = mAnimTextures.size(); - mAnimationStartEnd.emplace_back(std::make_pair(mCurrFrame, mCurrFrame + textures.size() - 1)); + mAnimSpriteInfos.emplace_back(mCurrFrame, (mCurrFrame + textures.size() - 1), looping); - SDL_Log("Animation start: %i Animation end: %i", mAnimationStartEnd.back().first, mAnimationStartEnd.back().second); + SDL_Log("Animation start: %i Animation end: %i", mAnimSpriteInfos.back().start, mAnimSpriteInfos.back().end); mAnimTextures.insert(mAnimTextures.end(), textures.begin(), textures.end()); @@ -70,14 +77,14 @@ void AnimSpriteComponent::SetAnimTextures(const std::vector& textu void AnimSpriteComponent::NextAnimation() { - if (mAnimationStartEnd.size() > 1 && mCanChangeAnimation) + if (mAnimSpriteInfos.size() > 1 && mCanChangeAnimation) { - if (++mCurrentAnimation == mAnimationStartEnd.size()) + if (++mCurrentAnimation == mAnimSpriteInfos.size()) { mCurrentAnimation = 0; } - SetTexture(mAnimTextures[mAnimationStartEnd[mCurrentAnimation].first]); + SetTexture(mAnimTextures[mAnimSpriteInfos[mCurrentAnimation].start]); mCanChangeAnimation = false; } diff --git a/Chapter02/AnimSpriteComponent.h b/Chapter02/AnimSpriteComponent.h index a3b11f6a..1034bf74 100644 --- a/Chapter02/AnimSpriteComponent.h +++ b/Chapter02/AnimSpriteComponent.h @@ -9,6 +9,21 @@ #pragma once #include "SpriteComponent.h" #include + +class AnimSpriteInfo +{ +public: + AnimSpriteInfo(int start, int end, bool looping) + :start(start) + ,end(end) + ,looping(looping) + {} + + int start; + int end; + bool looping; +}; + class AnimSpriteComponent : public SpriteComponent { public: @@ -16,7 +31,7 @@ class AnimSpriteComponent : public SpriteComponent // Update animation every frame (overriden from component) void Update(float deltaTime) override; // Set the textures used for animation - void SetAnimTextures(const std::vector& textures); + void SetAnimTextures(const std::vector& textures, bool looping = true); // Set/get the animation FPS float GetAnimFPS() const { return mAnimFPS; } void SetAnimFPS(float fps) { mAnimFPS = fps; } @@ -31,7 +46,7 @@ class AnimSpriteComponent : public SpriteComponent int mCurrentAnimation; - std::vector> mAnimationStartEnd; + std::vector mAnimSpriteInfos; float mNextAnimationTimer; bool mCanChangeAnimation; diff --git a/Chapter02/Ship.cpp b/Chapter02/Ship.cpp index 00c89017..dc6cf967 100644 --- a/Chapter02/Ship.cpp +++ b/Chapter02/Ship.cpp @@ -33,7 +33,7 @@ Ship::Ship(Game* game) game->GetTexture("Assets/Character05.png"), game->GetTexture("Assets/Character06.png"), }; - asc->SetAnimTextures(walkingAnimation); + asc->SetAnimTextures(walkingAnimation, false); } void Ship::UpdateActor(float deltaTime) From 4664ad38f2b37dde93628f9a27565d7d12c4bfe9 Mon Sep 17 00:00:00 2001 From: Sten Rune Lyngmo Date: Fri, 16 Jul 2021 23:47:15 +0200 Subject: [PATCH 3/3] Tilemaps implemented --- Chapter02/AnimSpriteComponent.h | 3 +- Chapter02/Game.cpp | 8 +++ Chapter02/Game.vcxproj | 2 + Chapter02/Game.vcxproj.filters | 6 +++ Chapter02/TileMapComponent.cpp | 93 +++++++++++++++++++++++++++++++++ Chapter02/TileMapComponent.h | 20 +++++++ 6 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 Chapter02/TileMapComponent.cpp create mode 100644 Chapter02/TileMapComponent.h diff --git a/Chapter02/AnimSpriteComponent.h b/Chapter02/AnimSpriteComponent.h index 1034bf74..0d2b13a7 100644 --- a/Chapter02/AnimSpriteComponent.h +++ b/Chapter02/AnimSpriteComponent.h @@ -10,9 +10,8 @@ #include "SpriteComponent.h" #include -class AnimSpriteInfo +struct AnimSpriteInfo { -public: AnimSpriteInfo(int start, int end, bool looping) :start(start) ,end(end) diff --git a/Chapter02/Game.cpp b/Chapter02/Game.cpp index 2bf0af03..93835cdc 100644 --- a/Chapter02/Game.cpp +++ b/Chapter02/Game.cpp @@ -13,6 +13,7 @@ #include "SpriteComponent.h" #include "Ship.h" #include "BGSpriteComponent.h" +#include "TileMapComponent.h" Game::Game() :mWindow(nullptr) @@ -179,6 +180,13 @@ void Game::LoadData() }; bg->SetBGTextures(bgtexs); bg->SetScrollSpeed(-200.0f); + // Create Tilemap + TileMapComponent* tm = new TileMapComponent(temp); + //tm->LoadTilemap("Assets/MapLayer3.csv", GetTexture("Assets/Tiles.png"), 32); + //tm = new TileMapComponent(temp); + tm->LoadTilemap("Assets/MapLayer2.csv", GetTexture("Assets/Tiles.png"), 32); + tm = new TileMapComponent(temp); + tm->LoadTilemap("Assets/MapLayer1.csv", GetTexture("Assets/Tiles.png"), 32); } void Game::UnloadData() diff --git a/Chapter02/Game.vcxproj b/Chapter02/Game.vcxproj index c749cb54..a4776960 100644 --- a/Chapter02/Game.vcxproj +++ b/Chapter02/Game.vcxproj @@ -20,6 +20,7 @@ + @@ -30,6 +31,7 @@ + {BC508D87-495F-4554-932D-DD68388B63CC} diff --git a/Chapter02/Game.vcxproj.filters b/Chapter02/Game.vcxproj.filters index 760534ef..c557d1f7 100644 --- a/Chapter02/Game.vcxproj.filters +++ b/Chapter02/Game.vcxproj.filters @@ -34,6 +34,9 @@ Source Files + + Source Files + @@ -60,5 +63,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Chapter02/TileMapComponent.cpp b/Chapter02/TileMapComponent.cpp new file mode 100644 index 00000000..e4971104 --- /dev/null +++ b/Chapter02/TileMapComponent.cpp @@ -0,0 +1,93 @@ +#include "TileMapComponent.h" +#include "Actor.h" +#include +#include +#include + +TileMapComponent::TileMapComponent(Actor* owner, int drawOrder) +:SpriteComponent(owner, drawOrder) +{ +} + +void TileMapComponent::Draw(SDL_Renderer* renderer) +{ + if (mTexture) + { + SDL_Rect dsrect; + dsrect.w = mTileSize; + dsrect.h = mTileSize; + for (int i = 0; i < mLoadedCSV.size(); i++) + { + dsrect.y = i * mTileSize; + for (int j = 0; j < mLoadedCSV[i].size(); j++) + { + if (mLoadedCSV[i][j] > -1) + { + dsrect.x = j * mTileSize; + + // Draw (have to convert angle from radians to degrees, and clockwise to counter) + SDL_RenderCopyEx(renderer, + mTexture, + &mTileRects[mLoadedCSV[i][j]], + &dsrect, + -Math::ToDegrees(mOwner->GetRotation()), + nullptr, + SDL_FLIP_NONE); + } + } + } + } +} + +void TileMapComponent::LoadTilemap(std::string&& CSVPath, SDL_Texture* tilemapTexture, int tileSize) +{ + mTexture = tilemapTexture; + mTileSize = tileSize; + + SDL_QueryTexture(tilemapTexture, nullptr, nullptr, &mTexWidth, &mTexHeight); + + // Split the texture in to tiles to use with a csv tilemap. + int tilesW = mTexWidth / tileSize; + int tilesH = mTexHeight / tileSize; + for (int i = 0; i < tilesH; i++) + { + for (int j = 0; j < tilesW; j++) + { + SDL_Rect tilerect; + tilerect.x = j * tileSize; + tilerect.y = i * tileSize; + tilerect.w = tileSize; + tilerect.h = tileSize; + + mTileRects.emplace_back(std::move(tilerect)); + } + } + + std::cout << "Tiles loaded: " << mTileRects.size() << std::endl; + + // Load desired tiles from csv file. + std::ifstream fin(std::move(CSVPath)); + std::string s; + char cstring[4]; + while (std::getline(fin, s)) + { + std::istringstream ss; + ss.str(s); + std::vector CSVLine; + while (ss.getline(cstring, 4, ',')) + { + CSVLine.emplace_back(stoi(std::string(cstring))); + } + mLoadedCSV.emplace_back(std::move(CSVLine)); + } + + // Print loaded tilemap to console. + for (auto& intvec : mLoadedCSV) + { + for (int i : intvec) + { + std::cout << i; + } + std::cout << std::endl; + } +} diff --git a/Chapter02/TileMapComponent.h b/Chapter02/TileMapComponent.h new file mode 100644 index 00000000..c4d82d16 --- /dev/null +++ b/Chapter02/TileMapComponent.h @@ -0,0 +1,20 @@ +#pragma once +#include "SpriteComponent.h" +#include +#include +#include "Math.h" + + + +class TileMapComponent : public SpriteComponent +{ +public: + TileMapComponent(Actor* owner, int drawOrder = 50); + void LoadTilemap(std::string&& CSVPath, SDL_Texture* tilemapTexture, int tileSize); + virtual void Draw(SDL_Renderer* renderer); +private: + std::vector> mLoadedCSV; + std::vector mTileRects; + int mTileSize; +}; +