diff options
Diffstat (limited to 'game/coins')
-rw-r--r-- | game/coins/CoinPool.cpp | 16 | ||||
-rw-r--r-- | game/coins/CoinPool.h | 12 | ||||
-rw-r--r-- | game/coins/CoinScript.cpp | 36 | ||||
-rw-r--r-- | game/coins/CoinScript.h | 13 | ||||
-rw-r--r-- | game/coins/CoinSubScene.cpp | 39 | ||||
-rw-r--r-- | game/coins/CoinSubScene.h | 12 | ||||
-rw-r--r-- | game/coins/CoinSystemScript.cpp | 248 | ||||
-rw-r--r-- | game/coins/CoinSystemScript.h | 98 |
8 files changed, 474 insertions, 0 deletions
diff --git a/game/coins/CoinPool.cpp b/game/coins/CoinPool.cpp new file mode 100644 index 0000000..439b3b3 --- /dev/null +++ b/game/coins/CoinPool.cpp @@ -0,0 +1,16 @@ +#include "CoinPool.h" +#include "CoinScript.h" +#include "CoinSubScene.h" +#include "api/BehaviorScript.h" +#include "api/GameObject.h" + +using namespace crepe; +using namespace std; + +void CoinPool::create_coins(crepe::Scene & scn) { + int amount = 0; + CoinSubScene coin; + while(amount < this->MAXIMUM_AMOUNT){ + amount = coin.create(scn,amount); + } +} diff --git a/game/coins/CoinPool.h b/game/coins/CoinPool.h new file mode 100644 index 0000000..83058f7 --- /dev/null +++ b/game/coins/CoinPool.h @@ -0,0 +1,12 @@ +#pragma once + +#include "api/Scene.h" + + +class CoinPool { +public: + void create_coins(crepe::Scene & scn); +private: + static constexpr int MAXIMUM_AMOUNT = 100; +}; + diff --git a/game/coins/CoinScript.cpp b/game/coins/CoinScript.cpp new file mode 100644 index 0000000..a3ee3b9 --- /dev/null +++ b/game/coins/CoinScript.cpp @@ -0,0 +1,36 @@ +#include "CoinScript.h" +#include "api/CircleCollider.h" +#include "api/Sprite.h" +#include "manager/SaveManager.h" +#include "../Config.h" +#include "../Events.h" +#include "../hud/HudScript.h" + +using namespace crepe; +using namespace std; + +bool CoinScript::on_collision(const CollisionEvent & collisionData){ + if(collisionData.info.other.metadata.tag != "coin") return false; + this->get_components_by_name<Sprite>(collisionData.info.other.metadata.name).front().get().active = false; + this->get_components_by_name<CircleCollider>(collisionData.info.other.metadata.name).front().get().active = false; + this->amount++; + return false; +} + +void CoinScript::init(){ + this->subscribe<CollisionEvent>([this](const CollisionEvent & ev) -> bool { return this->on_collision(ev); }); + this->subscribe<EndGameEvent>([this](const EndGameEvent e)-> bool { return this->save(); }); +} + +void CoinScript::fixed_update(crepe::duration_t dt) { + this->trigger_event(GetCoinEvent{ + .amount_of_coins = this->amount, + }); +} + +bool CoinScript::save(){ + SaveManager & savemgr = this->get_save_manager(); + savemgr.set(TOTAL_COINS_RUN, this->amount); + this->amount = 0; + return false; +} diff --git a/game/coins/CoinScript.h b/game/coins/CoinScript.h new file mode 100644 index 0000000..6fcb64e --- /dev/null +++ b/game/coins/CoinScript.h @@ -0,0 +1,13 @@ +#pragma once + +#include "api/Script.h" + +class CoinScript : public crepe::Script { +public: + void init() override; + void fixed_update(crepe::duration_t dt) override; + bool on_collision(const crepe::CollisionEvent & collisionData); + bool save(); +private: + int amount = 0; +}; diff --git a/game/coins/CoinSubScene.cpp b/game/coins/CoinSubScene.cpp new file mode 100644 index 0000000..9c9caa3 --- /dev/null +++ b/game/coins/CoinSubScene.cpp @@ -0,0 +1,39 @@ +#include "CoinSubScene.h" +#include "api/Animator.h" +#include "api/BehaviorScript.h" +#include "api/CircleCollider.h" +#include "api/Rigidbody.h" +#include "api/Scene.h" +#include "api/AudioSource.h" +#include "CoinScript.h" +#include "../Config.h" + +using namespace crepe; +using namespace std; + +int CoinSubScene::create(Scene & scn,int coin_counter){ + vec2 size = {20, 20}; + + string unique_name = "coin_" + to_string(coin_counter++); + + GameObject coin = scn.new_object(unique_name.c_str(),"coin",vec2{650,0},0,1); + coin.add_component<Rigidbody>(Rigidbody::Data{ + .body_type = Rigidbody::BodyType::KINEMATIC, + .kinematic_collision = false, + .collision_layers = {COLL_LAY_PLAYER}, + }); + coin.add_component<CircleCollider>((size.x / 2)-3).active = false; + crepe::OptionalRef<crepe::Sprite> coin_sprite = coin.add_component<Sprite>(Asset{"asset/coin/coin1_TVOS.png"}, Sprite::Data{ + .sorting_in_layer = SORT_IN_LAY_COINS, + .order_in_layer = 0, + .size = size, + }); + coin_sprite->active = false; + coin.add_component<Animator>(coin_sprite, ivec2{32, 32}, uvec2{8, 1}, + Animator::Data{ + .fps = 15, + .looping = true, + }); + coin.add_component<AudioSource>(Asset{"asset/sfx/coin_pickup_1.ogg"}); + return coin_counter; +} diff --git a/game/coins/CoinSubScene.h b/game/coins/CoinSubScene.h new file mode 100644 index 0000000..ddb6450 --- /dev/null +++ b/game/coins/CoinSubScene.h @@ -0,0 +1,12 @@ +#pragma once + +#include <crepe/api/GameObject.h> + +namespace crepe { +class Scene; +} + +class CoinSubScene { +public: + int create(crepe::Scene & scn,int coin_counter); +}; diff --git a/game/coins/CoinSystemScript.cpp b/game/coins/CoinSystemScript.cpp new file mode 100644 index 0000000..573c825 --- /dev/null +++ b/game/coins/CoinSystemScript.cpp @@ -0,0 +1,248 @@ +#include "CoinSystemScript.h" +#include "CoinPool.h" +#include "api/CircleCollider.h" +#include "api/Metadata.h" +#include "api/Sprite.h" +#include "api/Transform.h" +#include <random> + +using namespace crepe; +using namespace std; + + + +void CoinSystemScript::init() { + engine.seed(rd()); +} + +void CoinSystemScript::add_location(const crepe::vec2& location){ + coin_locations.push_back(CoinData(location)); +} + +float CoinSystemScript::preset_1(const vec2 & begin_position){ + vec2 top = {begin_position.x, begin_position.y - (this->ROW_OFFSET_1)}; + vec2 bottom = {begin_position.x, begin_position.y + (this->ROW_OFFSET_1)}; + + // Add locations for the top row + for (int i = 0; i < COLUM_AMOUNT_1; ++i) { + add_location(top); + top.x += this->COLUM_OFFSET_1; + } + + // Add locations for the bottom row + bottom.x +=this->COLUM_OFFSET_1 * COLUM_AMOUNT_1; + for (int i = 0; i < COLUM_AMOUNT_1; ++i) { + add_location(bottom); + bottom.x += this->COLUM_OFFSET_1; + } + + // Add locations for the next set of the top row + top.x += this->COLUM_OFFSET_1 * COLUM_AMOUNT_1; + for (int i = 0; i < COLUM_AMOUNT_1; ++i) { + add_location(top); + top.x += this->COLUM_OFFSET_1; + } + + // Add locations for the next set of the bottom row + bottom.x +=this->COLUM_OFFSET_1 * COLUM_AMOUNT_1; + for (int i = 0; i < COLUM_AMOUNT_1; ++i) { + add_location(bottom); + bottom.x += this->COLUM_OFFSET_1; + } + + return bottom.x-begin_position.x; +} + +float CoinSystemScript::preset_2(const vec2 & begin_position){ + vec2 top = {begin_position.x+this->COLUM_OFFSET_2, begin_position.y - this->ROW_OFFSET_2}; + vec2 middle = begin_position; + vec2 bottom = {begin_position.x+this->COLUM_OFFSET_2, begin_position.y + this->ROW_OFFSET_2}; + + // Add locations for the next set of the bottom row + for (int i = 0; i < COLUM_AMOUNT_2-2; ++i) { + add_location(bottom); + bottom.x += this->COLUM_OFFSET_2; + } + + // Add locations for the next set of the middle row + for (int i = 0; i < COLUM_AMOUNT_2; ++i) { + add_location(middle); + middle.x += this->COLUM_OFFSET_2; + } + + // Add locations for the next set of the top row + for (int i = 0; i < COLUM_AMOUNT_2-2; ++i) { + add_location(top); + top.x += this->COLUM_OFFSET_2; + } + + return middle.x-begin_position.x; +} + +float CoinSystemScript::preset_3(const vec2 & begin_position){ + vec2 location = {begin_position.x, begin_position.y - (this->ROW_OFFSET_3)}; + + + // Add locations for the top row + for (int i = 0; i < COLUM_AMOUNT_3; ++i) { + add_location(location); + location.x += this->COLUM_OFFSET_3; + } + + // Add locations for the bottom row + location.y +=this->ROW_OFFSET_3; + location.x += this->COLUM_OFFSET_3; + for (int i = 0; i < COLUM_AMOUNT_3; ++i) { + add_location(location); + location.x += this->COLUM_OFFSET_3; + } + + // Add locations for the next set of the top row + location.y +=this->ROW_OFFSET_3; + location.x += this->COLUM_OFFSET_3; + for (int i = 0; i < COLUM_AMOUNT_3; ++i) { + add_location(location); + location.x += this->COLUM_OFFSET_3; + } + + return location.x-begin_position.x; +} + +float CoinSystemScript::preset_4(const vec2 & begin_position){ + vec2 location = {begin_position.x, begin_position.y + (this->ROW_OFFSET_4)}; + + + // Add locations for the top row + for (int i = 0; i < COLUM_AMOUNT_4; ++i) { + add_location(location); + location.x += this->COLUM_OFFSET_4; + } + + // Add locations for the bottom row + location.y -=this->ROW_OFFSET_4; + location.x += this->COLUM_OFFSET_4; + for (int i = 0; i < COLUM_AMOUNT_4; ++i) { + add_location(location); + location.x += this->COLUM_OFFSET_4; + } + + // Add locations for the next set of the top row + location.y -=this->ROW_OFFSET_4; + location.x += this->COLUM_OFFSET_4; + for (int i = 0; i < COLUM_AMOUNT_4; ++i) { + add_location(location); + location.x += this->COLUM_OFFSET_4; + } + + return location.x-begin_position.x; +} + +float CoinSystemScript::preset_5(const vec2 & begin_position){ + vec2 location = {begin_position.x, begin_position.y-ROW_OFFSET_5/2}; + for (int i = 0; i < COLUM_AMOUNT_5; ++i){ + add_location(location); + location.x += this->COLUM_OFFSET_5; + } + return location.x-begin_position.x; +} + + + +void CoinSystemScript::frame_update(crepe::duration_t dt) +{ + this->despawn_coins(); + this->generate_locations(); + this->spawn_coins(); +} + +void CoinSystemScript::despawn_coins() { + // Get the current x-position of the CoinSystem's Transform component + float position = this->get_component<Transform>().position.x; + + // Retrieve all active coin sprites tagged as "coin" + RefVector<Sprite> coin_sprites = this->get_components_by_tag<Sprite>("coin"); + + for (Sprite& coin_sprite : coin_sprites) { + if (!coin_sprite.active) continue; // Skip inactive sprites + + // Retrieve the corresponding Transform, Metadata, and CircleCollider components + Transform& coin_transform = this->get_components_by_id<Transform>(coin_sprite.game_object_id).front().get(); + Metadata& coin_metadata = this->get_components_by_id<Metadata>(coin_sprite.game_object_id).front().get(); + CircleCollider& coin_collider = this->get_components_by_id<CircleCollider>(coin_sprite.game_object_id).front().get(); + + // Check if the coin is out of bounds based on DESPAWN_DISTANCE + if (coin_transform.position.x < position - this->DESPAWN_DISTANCE) { + // Find the coin in the coin_locations vector using its name + auto it = std::find_if( + coin_locations.begin(), + coin_locations.end(), + [&coin_metadata](const CoinData& data) { + return data.name == coin_metadata.name; + } + ); + + // If a match is found, erase it from coin_locations + if (it != coin_locations.end()) { + coin_locations.erase(it); + coin_sprite.active = false; + coin_collider.active = false; + } + } + } +} + +void CoinSystemScript::spawn_coins(){ + // Get the current x-position of the CoinSystem's Transform component + float position = this->get_component<Transform>().position.x; + + // Iterate through the list of coin locations + for (auto& coin : coin_locations) { + // Skip this coin if it is already active + if (coin.active)continue; + // Skip this coin if it is not within the defined spawn area + if (coin.start_location.x < this->SPAWN_DISTANCE + position || coin.start_location.x > this->SPAWN_AREA + this->SPAWN_DISTANCE + position) continue; + + // Retrieve all sprites tagged as "coin" + RefVector<Sprite> coin_sprites = this->get_components_by_tag<Sprite>("coin"); + + // Check for an available (inactive) coin sprite + for (Sprite& coin_sprite : coin_sprites) { + // Skip this sprite if it is already active + if (coin_sprite.active) continue; + + // Found an available (inactive) coin sprite + // Retrieve its associated components + Transform & coin_transform = this->get_components_by_id<Transform>(coin_sprite.game_object_id).front().get(); + Metadata & coin_metadata = this->get_components_by_id<Metadata>(coin_sprite.game_object_id).front().get(); + CircleCollider & coin_collider = this->get_components_by_id<CircleCollider>(coin_sprite.game_object_id).front().get(); + + // Assign data and set active + coin.name = coin_metadata.name; + coin.active = true; + coin_sprite.active = true; + coin_collider.active = true; + coin_transform.position = coin.start_location; + + // Break out of the inner loop since we've assigned this coin to an available sprite + break; + } + } +} + +void CoinSystemScript::generate_locations(){ + float position = this->get_component<Transform>().position.x; + if(position + SPAWN_DISTANCE + SYSTEM_POSITION_OFFSET < this->system_position) return; + + std::discrete_distribution<int> dist(weights.begin(), weights.end()); + int selected_index = dist(engine); + + std::uniform_real_distribution<float> space_dist(SPAWN_SPACING_MIN, SPAWN_SPACING_MAX); + float spacing = space_dist(engine); + + // Call the corresponding function and return the new x position + this->system_position += functions[selected_index]({this->system_position,0}); + this->system_position += spacing; +} + + + diff --git a/game/coins/CoinSystemScript.h b/game/coins/CoinSystemScript.h new file mode 100644 index 0000000..c65b533 --- /dev/null +++ b/game/coins/CoinSystemScript.h @@ -0,0 +1,98 @@ +#pragma once + +#include "types.h" +#include <string> +#include "api/CircleCollider.h" +#include "api/Script.h" +#include "api/Sprite.h" +#include "api/Transform.h" +#include <random> + +class CoinSystemScript : public crepe::Script { +private: + struct CoinData{ + crepe::vec2 start_location = {0,0}; + std::string name = ""; + bool active = false; + CoinData(crepe::vec2 start_location) : start_location(start_location),name(""), active(false) {} + }; +public: + CoinSystemScript() {}; + void init() override; + void frame_update(crepe::duration_t dt) override; +private: + void add_location(const crepe::vec2& location); + void despawn_coins(); + void spawn_coins(); + void generate_locations(); + float preset_1(const crepe::vec2 & begin_position); + float preset_2(const crepe::vec2 & begin_position); + float preset_3(const crepe::vec2 & begin_position); + float preset_4(const crepe::vec2 & begin_position); + float preset_5(const crepe::vec2 & begin_position); +private: + std::vector<std::function<float(const crepe::vec2&)>> functions = { + [this](const crepe::vec2& pos) { return preset_1(pos); }, + [this](const crepe::vec2& pos) { return preset_2(pos); }, + [this](const crepe::vec2& pos) { return preset_3(pos); }, + [this](const crepe::vec2& pos) { return preset_4(pos); }, + [this](const crepe::vec2& pos) { return preset_5(pos); } + }; + std::vector<int> weights = {20, 20,20,20, 20}; + std::random_device rd; + std::default_random_engine engine; + float system_position = 1200; + static constexpr float SYSTEM_POSITION_OFFSET = 200; +private: + static constexpr float SPAWN_SPACING_MIN = 400; + static constexpr float SPAWN_SPACING_MAX = 1000; + static constexpr float SPAWN_DISTANCE = 600; + static constexpr float DESPAWN_DISTANCE = 600; + static constexpr float SPAWN_AREA = 50; + std::vector<CoinData> coin_locations; +private: +// preset one settings +// ***** ***** +// +// +// +// ***** ***** + static constexpr float ROW_OFFSET_1 = 100; + static constexpr float COLUM_OFFSET_1 = 25; + static constexpr int COLUM_AMOUNT_1 = 5; +private: +// preset two settings +// +// ******** +// ********** +// ******** +// + static constexpr float ROW_OFFSET_2 = 25; + static constexpr float COLUM_OFFSET_2 = 25; + static constexpr int COLUM_AMOUNT_2 = 10; +// preset three settings +// *** +// +// *** +// +// *** + static constexpr float ROW_OFFSET_3 = 100; + static constexpr float COLUM_OFFSET_3 = 25; + static constexpr int COLUM_AMOUNT_3 = 3; +// preset four settings +// *** +// +// *** +// +// *** + static constexpr float ROW_OFFSET_4 = 100; + static constexpr float COLUM_OFFSET_4 = 25; + static constexpr int COLUM_AMOUNT_4 = 3; +// preset five settings +// +// *** +// + static constexpr float ROW_OFFSET_5 = 25; + static constexpr float COLUM_OFFSET_5 = 25; + static constexpr int COLUM_AMOUNT_5 = 3; +}; |