From 336f6d6286b4f9f1c661e6cd63798fa5bd72ffb3 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 20:28:52 +0800 Subject: [PATCH 01/19] Snowball bullet and example tank --- assets/textures/snowball.png | Bin 0 -> 81229 bytes src/battle_game/core/bullets/bullets.h | 1 + src/battle_game/core/bullets/snowball.cpp | 58 +++++++ src/battle_game/core/bullets/snowball.h | 22 +++ src/battle_game/core/game_core.cpp | 11 ++ src/battle_game/core/game_core.h | 1 + src/battle_game/core/selectable_units.cpp | 2 +- src/battle_game/core/units/inferno_tank.cpp | 2 +- .../core/units/snowball_sample_sledge.cpp | 164 ++++++++++++++++++ .../core/units/snowball_sample_sledge.h | 21 +++ src/battle_game/core/units/units.h | 2 +- 11 files changed, 281 insertions(+), 3 deletions(-) create mode 100644 assets/textures/snowball.png create mode 100644 src/battle_game/core/bullets/snowball.cpp create mode 100644 src/battle_game/core/bullets/snowball.h create mode 100644 src/battle_game/core/units/snowball_sample_sledge.cpp create mode 100644 src/battle_game/core/units/snowball_sample_sledge.h diff --git a/assets/textures/snowball.png b/assets/textures/snowball.png new file mode 100644 index 0000000000000000000000000000000000000000..bb24393ae7437bf0b36069c23f1daacd98fb2b11 GIT binary patch literal 81229 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

d`5haXWgUQcfXfg%CM5 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

rgq*ZHs>Z4^U`bt|Nxi!#Lcy-{ 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 literal 0 HcmV?d00001 diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 598bc923..94252b1a 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -11,3 +11,4 @@ #include "battle_game/core/bullets/sweaty_soybean.h" #include "battle_game/core/bullets/warning_line.h" #include "battle_game/core/bullets/water_drop.h" +#include "battle_game/core/bullets/snowball.h" \ No newline at end of file diff --git a/src/battle_game/core/bullets/snowball.cpp b/src/battle_game/core/bullets/snowball.cpp new file mode 100644 index 00000000..33c9a77d --- /dev/null +++ b/src/battle_game/core/bullets/snowball.cpp @@ -0,0 +1,58 @@ +#include "battle_game/core/bullets/snowball.h" + +#include "battle_game/core/game_core.h" +#include "battle_game/core/particles/particles.h" + +namespace battle_game::bullet { +SnowBall::SnowBall(GameCore *core, + uint32_t id, + uint32_t unit_id, + uint32_t player_id, + glm::vec2 position, + float rotation, + float damage_scale, + glm::vec2 velocity) + : Bullet(core, id, unit_id, player_id, position, rotation, damage_scale), + velocity_(velocity) { +} + +void SnowBall::Render() { + SetTransformation(position_, rotation_, glm::vec2{0.4f}); + SetColor(game_core_->GetPlayerColor(player_id_)); + SetTexture("../../textures/snowball.png"); + DrawModel(0); +} + +void SnowBall::Update() { + position_ += velocity_ * kSecondPerTick; + bool should_die = false; + if (game_core_->IsBlockedByObstacles(position_)) { + should_die = true; + } + + auto &units = game_core_->GetUnits(); + for (auto &unit : units) { + if (unit.first == unit_id_) { + continue; + } + if (unit.second->IsHit(position_)) { + game_core_->PushEventDealDamage(unit.first, id_, damage_scale_ * 5.0f); + game_core_->PushEventMoveRelativeUnit(unit.first, + velocity_ * (5*kSecondPerTick)); + should_die = true; + } + } + + if (should_die) { + game_core_->PushEventRemoveBullet(id_); + } +} + +SnowBall::~SnowBall() { + for (int i = 0; i < 5; i++) { + game_core_->PushEventGenerateParticle( + position_, rotation_, game_core_->RandomInCircle() * 2.0f, 0.2f, + glm::vec4{0.0f, 0.0f, 0.0f, 1.0f}, 3.0f); + } +} +} // namespace battle_game::bullet \ No newline at end of file diff --git a/src/battle_game/core/bullets/snowball.h b/src/battle_game/core/bullets/snowball.h new file mode 100644 index 00000000..c936df3c --- /dev/null +++ b/src/battle_game/core/bullets/snowball.h @@ -0,0 +1,22 @@ +#pragma once +#include "battle_game/core/bullet.h" + +namespace battle_game::bullet { +class SnowBall : public Bullet { + public: + SnowBall(GameCore *core, + uint32_t id, + uint32_t unit_id, + uint32_t player_id, + glm::vec2 position, + float rotation, + float damage_scale, + glm::vec2 velocity); + ~SnowBall() override; + void Render() override; + void Update() override; + + private: + glm::vec2 velocity_{}; +}; +} // namespace battle_game::bullet \ No newline at end of file diff --git a/src/battle_game/core/game_core.cpp b/src/battle_game/core/game_core.cpp index 9f6c1c3e..5cfbe504 100644 --- a/src/battle_game/core/game_core.cpp +++ b/src/battle_game/core/game_core.cpp @@ -166,6 +166,17 @@ void GameCore::PushEventMoveUnit(uint32_t unit_id, glm::vec2 new_position) { }); } +void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, + glm::vec2 relative_position) { + event_queue_.emplace( + [this, unit_id, relative_position]() { auto unit = GetUnit(unit_id); + auto new_position = unit->GetPosition() + relative_position; + if (unit && !IsBlockedByObstacles(new_position)) { + unit->SetPosition(new_position); + } + }); +}//this function is used for weight system. + void GameCore::PushEventRotateUnit(uint32_t unit_id, float new_rotation) { event_queue_.emplace([this, unit_id, new_rotation]() { auto unit = GetUnit(unit_id); diff --git a/src/battle_game/core/game_core.h b/src/battle_game/core/game_core.h index 0e81d8e4..5bb7d8eb 100644 --- a/src/battle_game/core/game_core.h +++ b/src/battle_game/core/game_core.h @@ -123,6 +123,7 @@ class GameCore { [[nodiscard]] Obstacle *GetBlockedObstacle(glm::vec2 p) const; void PushEventMoveUnit(uint32_t unit_id, glm::vec2 new_position); + void PushEventMoveRelativeUnit(uint32_t unit_id, glm::vec2 relative_position); void PushEventRotateUnit(uint32_t unit_id, float new_rotation); void PushEventDealDamage(uint32_t dst_unit_id, uint32_t src_unit_id, diff --git a/src/battle_game/core/selectable_units.cpp b/src/battle_game/core/selectable_units.cpp index 7b4a28cd..1909c267 100644 --- a/src/battle_game/core/selectable_units.cpp +++ b/src/battle_game/core/selectable_units.cpp @@ -30,6 +30,7 @@ void GameCore::GeneratePrimaryUnitList() { * TODO: Add Your Unit Here! * */ ADD_SELECTABLE_UNIT(unit::InfernoTank); + ADD_SELECTABLE_UNIT(unit::snowball_sample_sledge); ADD_SELECTABLE_UNIT(unit::RoundUFO); ADD_SELECTABLE_UNIT(unit::Tank); ADD_SELECTABLE_UNIT(unit::DoubleScatterTank); @@ -49,7 +50,6 @@ void GameCore::GeneratePrimaryUnitList() { ADD_SELECTABLE_UNIT(unit::Sparky); ADD_SELECTABLE_UNIT(unit::CritTank); ADD_SELECTABLE_UNIT(unit::Railgun); - unit.reset(); } } // namespace battle_game diff --git a/src/battle_game/core/units/inferno_tank.cpp b/src/battle_game/core/units/inferno_tank.cpp index 9bf7717a..15b03cfc 100644 --- a/src/battle_game/core/units/inferno_tank.cpp +++ b/src/battle_game/core/units/inferno_tank.cpp @@ -103,7 +103,7 @@ void InfernoTank::Inferno() { for (int i = -9; i < 9; ++i) { auto offset = glm::radians(20.0f * i); velocity = Rotate(glm::vec2{0.0f, 20.0f}, turret_rotation_ + offset); - GenerateBullet( + GenerateBullet( position_ + Rotate({0.0f, 1.2f}, turret_rotation_ + offset), turret_rotation_ + offset, GetDamageScale(), velocity); } diff --git a/src/battle_game/core/units/snowball_sample_sledge.cpp b/src/battle_game/core/units/snowball_sample_sledge.cpp new file mode 100644 index 00000000..00ad673a --- /dev/null +++ b/src/battle_game/core/units/snowball_sample_sledge.cpp @@ -0,0 +1,164 @@ +#include "battle_game/core/bullets/bullets.h" +#include "battle_game/core/game_core.h" +#include "battle_game/graphics/graphics.h" +#include "snowball_sample_sledge.h" + +namespace battle_game::unit { + +namespace { +uint32_t sledge_body_model_index = 0xffffffffu; +uint32_t sledge_turret_model_index = 0xffffffffu; +} // namespace + +snowball_sample_sledge::snowball_sample_sledge(GameCore *game_core, + uint32_t id, + uint32_t player_id) + : Unit(game_core, id, player_id) { + if (!~sledge_body_model_index) { + auto mgr = AssetsManager::GetInstance(); + { + /* Sledge Body */ + sledge_body_model_index = mgr->RegisterModel( + { + {{-0.8f, 0.8f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + {{-0.8f, -1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + {{0.8f, 0.8f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + {{0.8f, -1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + // distinguish front and back + {{0.6f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + {{-0.6f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + }, + {0, 1, 2, 1, 2, 3, 0, 2, 5, 2, 4, 5}); + } + + { + /* Sledge Turret */ + std::vector turret_vertices; + std::vector turret_indices; + const int precision = 60; + const float inv_precision = 1.0f / float(precision); + for (int i = 0; i < precision; i++) { + auto theta = (float(i) + 0.5f) * inv_precision; + theta *= glm::pi() * 2.0f; + auto sin_theta = std::sin(theta); + auto cos_theta = std::cos(theta); + turret_vertices.push_back({{sin_theta * 0.5f, cos_theta * 0.5f}, + {0.0f, 0.0f}, + {0.7f, 0.7f, 0.7f, 1.0f}}); + turret_indices.push_back(i); + turret_indices.push_back((i + 1) % precision); + turret_indices.push_back(precision); + } + turret_vertices.push_back( + {{0.0f, 0.0f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); + turret_vertices.push_back( + {{-0.1f, 0.0f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); + turret_vertices.push_back( + {{0.1f, 0.0f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); + turret_vertices.push_back( + {{-0.1f, 1.2f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); + turret_vertices.push_back( + {{0.1f, 1.2f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); + turret_indices.push_back(precision + 1 + 0); + turret_indices.push_back(precision + 1 + 1); + turret_indices.push_back(precision + 1 + 2); + turret_indices.push_back(precision + 1 + 1); + turret_indices.push_back(precision + 1 + 2); + turret_indices.push_back(precision + 1 + 3); + sledge_turret_model_index = + mgr->RegisterModel(turret_vertices, turret_indices); + } + } +} + +void snowball_sample_sledge::Render() { + battle_game::SetTransformation(position_, rotation_); + battle_game::SetTexture(0); + battle_game::SetColor(game_core_->GetPlayerColor(player_id_)); + battle_game::DrawModel(sledge_body_model_index); + battle_game::SetRotation(turret_rotation_); + battle_game::DrawModel(sledge_turret_model_index); +} + +void snowball_sample_sledge::Update() { + SledgeMove(3.0f, glm::radians(180.0f)); + TurretRotate(); + Fire(); +} + +void snowball_sample_sledge::SledgeMove(float move_speed, + float rotate_angular_speed) { + auto player = game_core_->GetPlayer(player_id_); + if (player) { + auto &input_data = player->GetInputData(); + glm::vec2 offset{0.0f}; + if (input_data.key_down[GLFW_KEY_W]) { + offset.y += 1.0f; + } + if (input_data.key_down[GLFW_KEY_S]) { + offset.y -= 1.0f; + } + float speed = move_speed * GetSpeedScale(); + offset *= kSecondPerTick * speed; + auto relative_position = glm::vec2{ + glm::rotate(glm::mat4{1.0f}, rotation_, glm::vec3{0.0f, 0.0f, 1.0f}) * + glm::vec4{offset, 0.0f, 0.0f}}; + game_core_->PushEventMoveRelativeUnit(id_, relative_position); + float rotation_offset = 0.0f; + if (input_data.key_down[GLFW_KEY_A]) { + rotation_offset += 1.0f; + } + if (input_data.key_down[GLFW_KEY_D]) { + rotation_offset -= 1.0f; + } + rotation_offset *= kSecondPerTick * rotate_angular_speed * GetSpeedScale(); + game_core_->PushEventRotateUnit(id_, rotation_ + rotation_offset); + } +} + +void snowball_sample_sledge::TurretRotate() { + auto player = game_core_->GetPlayer(player_id_); + if (player) { + auto &input_data = player->GetInputData(); + auto diff = input_data.mouse_cursor_position - position_; + if (glm::length(diff) < 1e-4) { + turret_rotation_ = rotation_; + } else { + turret_rotation_ = std::atan2(diff.y, diff.x) - glm::radians(90.0f); + } + } +} + +void snowball_sample_sledge::Fire() { + if (fire_count_down_) { + fire_count_down_--; + } else { + auto player = game_core_->GetPlayer(player_id_); + if (player) { + auto &input_data = player->GetInputData(); + if (input_data.mouse_button_down[GLFW_MOUSE_BUTTON_LEFT]) { + auto velocity = Rotate(glm::vec2{0.0f, 20.0f}, turret_rotation_); + GenerateBullet( + position_ + Rotate({0.0f, 1.2f}, turret_rotation_), + turret_rotation_, GetDamageScale(), velocity); + fire_count_down_ = kTickPerSecond; // Fire interval 1 second. + } + } + } +} + +bool snowball_sample_sledge::IsHit(glm::vec2 position) const { + position = WorldToLocal(position); + return position.x > -0.8f && position.x < 0.8f && position.y > -1.0f && + position.y < 1.0f && position.x + position.y < 1.6f && + position.y - position.x < 1.6f; +} + +const char *snowball_sample_sledge::UnitName() const { + return "sledge_lyc"; +} + +const char *snowball_sample_sledge::Author() const { + return "cylic14790382"; +} +} // namespace battle_game::unit \ No newline at end of file diff --git a/src/battle_game/core/units/snowball_sample_sledge.h b/src/battle_game/core/units/snowball_sample_sledge.h new file mode 100644 index 00000000..3c7ed9f7 --- /dev/null +++ b/src/battle_game/core/units/snowball_sample_sledge.h @@ -0,0 +1,21 @@ +#pragma once +#include "battle_game/core/unit.h" + +namespace battle_game::unit { +class snowball_sample_sledge : public Unit { + public: + snowball_sample_sledge(GameCore *game_core, uint32_t id, uint32_t player_id); + void Render() override; + void Update() override; + [[nodiscard]] bool IsHit(glm::vec2 position) const override; + + protected: + void SledgeMove(float move_speed, float rotate_angular_speed); + void TurretRotate(); + void Fire(); + [[nodiscard]] const char *UnitName() const override; + [[nodiscard]] const char *Author() const override; + float turret_rotation_{0.0f}; + uint32_t fire_count_down_{0}; +}; +} // namespace battle_game::unit \ No newline at end of file diff --git a/src/battle_game/core/units/units.h b/src/battle_game/core/units/units.h index bc30561c..58fbedfd 100644 --- a/src/battle_game/core/units/units.h +++ b/src/battle_game/core/units/units.h @@ -1,5 +1,5 @@ #pragma once - +#include "battle_game/core/units/snowball_sample_sledge.h" #include "battle_game/core/units/Whaooooo_tank.h" #include "battle_game/core/units/crit_tank.h" #include "battle_game/core/units/dark_fury.h" From f2ee87b7914cc48c844dcb37bd418670f0b2086f Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 20:31:12 +0800 Subject: [PATCH 02/19] delete changes --- src/battle_game/core/units/inferno_tank.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_game/core/units/inferno_tank.cpp b/src/battle_game/core/units/inferno_tank.cpp index 15b03cfc..9bf7717a 100644 --- a/src/battle_game/core/units/inferno_tank.cpp +++ b/src/battle_game/core/units/inferno_tank.cpp @@ -103,7 +103,7 @@ void InfernoTank::Inferno() { for (int i = -9; i < 9; ++i) { auto offset = glm::radians(20.0f * i); velocity = Rotate(glm::vec2{0.0f, 20.0f}, turret_rotation_ + offset); - GenerateBullet( + GenerateBullet( position_ + Rotate({0.0f, 1.2f}, turret_rotation_ + offset), turret_rotation_ + offset, GetDamageScale(), velocity); } From 2c952b425daa583c8041f00cfdb1fdae32991831 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 21:08:11 +0800 Subject: [PATCH 03/19] clang --- src/battle_game/core/bullets/bullets.h | 1 + src/battle_game/core/bullets/snowball.cpp | 2 +- src/battle_game/core/game_core.cpp | 12 ++++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 94252b1a..4a01bab3 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -1,4 +1,5 @@ #pragma once + #include "battle_game/core/bullets/cannon_ball.h" #include "battle_game/core/bullets/coin.h" #include "battle_game/core/bullets/crit_bullet.h" diff --git a/src/battle_game/core/bullets/snowball.cpp b/src/battle_game/core/bullets/snowball.cpp index 33c9a77d..b801f25c 100644 --- a/src/battle_game/core/bullets/snowball.cpp +++ b/src/battle_game/core/bullets/snowball.cpp @@ -38,7 +38,7 @@ void SnowBall::Update() { if (unit.second->IsHit(position_)) { game_core_->PushEventDealDamage(unit.first, id_, damage_scale_ * 5.0f); game_core_->PushEventMoveRelativeUnit(unit.first, - velocity_ * (5*kSecondPerTick)); + velocity_ * (5.0f * kSecondPerTick)); should_die = true; } } diff --git a/src/battle_game/core/game_core.cpp b/src/battle_game/core/game_core.cpp index 5cfbe504..d23f64f1 100644 --- a/src/battle_game/core/game_core.cpp +++ b/src/battle_game/core/game_core.cpp @@ -167,15 +167,15 @@ void GameCore::PushEventMoveUnit(uint32_t unit_id, glm::vec2 new_position) { } void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, - glm::vec2 relative_position) { - event_queue_.emplace( - [this, unit_id, relative_position]() { auto unit = GetUnit(unit_id); + glm::vec2 relative_position) { + event_queue_.emplace([this, unit_id, relative_position]() { + auto unit = GetUnit(unit_id); auto new_position = unit->GetPosition() + relative_position; if (unit && !IsBlockedByObstacles(new_position)) { - unit->SetPosition(new_position); + unit->SetPosition(new_position); } - }); -}//this function is used for weight system. + }); +} // this function is used for weight system. void GameCore::PushEventRotateUnit(uint32_t unit_id, float new_rotation) { event_queue_.emplace([this, unit_id, new_rotation]() { From 2cd48cf4bcc182af85f8a5aec0d269948b26b092 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 21:20:08 +0800 Subject: [PATCH 04/19] clang2 --- src/battle_game/core/bullets/snowball.h | 14 +++++++------- src/battle_game/core/game_core.cpp | 3 +-- .../core/units/snowball_sample_sledge.cpp | 4 ++-- src/battle_game/core/units/units.h | 1 + 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/battle_game/core/bullets/snowball.h b/src/battle_game/core/bullets/snowball.h index c936df3c..99ea57bd 100644 --- a/src/battle_game/core/bullets/snowball.h +++ b/src/battle_game/core/bullets/snowball.h @@ -5,13 +5,13 @@ namespace battle_game::bullet { class SnowBall : public Bullet { public: SnowBall(GameCore *core, - uint32_t id, - uint32_t unit_id, - uint32_t player_id, - glm::vec2 position, - float rotation, - float damage_scale, - glm::vec2 velocity); + uint32_t id, + uint32_t unit_id, + uint32_t player_id, + glm::vec2 position, + float rotation, + float damage_scale, + glm::vec2 velocity); ~SnowBall() override; void Render() override; void Update() override; diff --git a/src/battle_game/core/game_core.cpp b/src/battle_game/core/game_core.cpp index d23f64f1..22bb2f00 100644 --- a/src/battle_game/core/game_core.cpp +++ b/src/battle_game/core/game_core.cpp @@ -166,8 +166,7 @@ void GameCore::PushEventMoveUnit(uint32_t unit_id, glm::vec2 new_position) { }); } -void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, - glm::vec2 relative_position) { +void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, glm::vec2 relative_position) { event_queue_.emplace([this, unit_id, relative_position]() { auto unit = GetUnit(unit_id); auto new_position = unit->GetPosition() + relative_position; diff --git a/src/battle_game/core/units/snowball_sample_sledge.cpp b/src/battle_game/core/units/snowball_sample_sledge.cpp index 00ad673a..d05ed0cc 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.cpp +++ b/src/battle_game/core/units/snowball_sample_sledge.cpp @@ -11,8 +11,8 @@ uint32_t sledge_turret_model_index = 0xffffffffu; } // namespace snowball_sample_sledge::snowball_sample_sledge(GameCore *game_core, - uint32_t id, - uint32_t player_id) + uint32_t id, + uint32_t player_id) : Unit(game_core, id, player_id) { if (!~sledge_body_model_index) { auto mgr = AssetsManager::GetInstance(); diff --git a/src/battle_game/core/units/units.h b/src/battle_game/core/units/units.h index 58fbedfd..008e249e 100644 --- a/src/battle_game/core/units/units.h +++ b/src/battle_game/core/units/units.h @@ -1,4 +1,5 @@ #pragma once + #include "battle_game/core/units/snowball_sample_sledge.h" #include "battle_game/core/units/Whaooooo_tank.h" #include "battle_game/core/units/crit_tank.h" From a7c0995ddad24410ca999c41b0b5013ca1f45712 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 21:27:43 +0800 Subject: [PATCH 05/19] delete spaces --- src/battle_game/core/bullets/bullets.h | 1 - src/battle_game/core/bullets/snowball.cpp | 3 +-- src/battle_game/core/units/snowball_sample_sledge.cpp | 2 +- src/battle_game/core/units/units.h | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 4a01bab3..94252b1a 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -1,5 +1,4 @@ #pragma once - #include "battle_game/core/bullets/cannon_ball.h" #include "battle_game/core/bullets/coin.h" #include "battle_game/core/bullets/crit_bullet.h" diff --git a/src/battle_game/core/bullets/snowball.cpp b/src/battle_game/core/bullets/snowball.cpp index b801f25c..798a4c2a 100644 --- a/src/battle_game/core/bullets/snowball.cpp +++ b/src/battle_game/core/bullets/snowball.cpp @@ -37,8 +37,7 @@ void SnowBall::Update() { } if (unit.second->IsHit(position_)) { game_core_->PushEventDealDamage(unit.first, id_, damage_scale_ * 5.0f); - game_core_->PushEventMoveRelativeUnit(unit.first, - velocity_ * (5.0f * kSecondPerTick)); + game_core_->PushEventMoveRelativeUnit(unit.first, velocity_ * (5.0f * kSecondPerTick)); should_die = true; } } diff --git a/src/battle_game/core/units/snowball_sample_sledge.cpp b/src/battle_game/core/units/snowball_sample_sledge.cpp index d05ed0cc..4bcb2691 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.cpp +++ b/src/battle_game/core/units/snowball_sample_sledge.cpp @@ -87,7 +87,7 @@ void snowball_sample_sledge::Update() { } void snowball_sample_sledge::SledgeMove(float move_speed, - float rotate_angular_speed) { + float rotate_angular_speed) { auto player = game_core_->GetPlayer(player_id_); if (player) { auto &input_data = player->GetInputData(); diff --git a/src/battle_game/core/units/units.h b/src/battle_game/core/units/units.h index 008e249e..58fbedfd 100644 --- a/src/battle_game/core/units/units.h +++ b/src/battle_game/core/units/units.h @@ -1,5 +1,4 @@ #pragma once - #include "battle_game/core/units/snowball_sample_sledge.h" #include "battle_game/core/units/Whaooooo_tank.h" #include "battle_game/core/units/crit_tank.h" From 94ed92495bfbbf87efd4664a97398f5cdc440667 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 21:34:47 +0800 Subject: [PATCH 06/19] ctrlaxv --- src/battle_game/core/bullets/snowball.cpp | 3 ++- src/battle_game/core/game_core.cpp | 3 ++- src/battle_game/core/units/snowball_sample_sledge.cpp | 3 ++- src/battle_game/core/units/units.h | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/battle_game/core/bullets/snowball.cpp b/src/battle_game/core/bullets/snowball.cpp index 798a4c2a..23275f38 100644 --- a/src/battle_game/core/bullets/snowball.cpp +++ b/src/battle_game/core/bullets/snowball.cpp @@ -37,7 +37,8 @@ void SnowBall::Update() { } if (unit.second->IsHit(position_)) { game_core_->PushEventDealDamage(unit.first, id_, damage_scale_ * 5.0f); - game_core_->PushEventMoveRelativeUnit(unit.first, velocity_ * (5.0f * kSecondPerTick)); + game_core_->PushEventMoveRelativeUnit( + unit.first, velocity_ * (5.0f * kSecondPerTick)); should_die = true; } } diff --git a/src/battle_game/core/game_core.cpp b/src/battle_game/core/game_core.cpp index 22bb2f00..d23f64f1 100644 --- a/src/battle_game/core/game_core.cpp +++ b/src/battle_game/core/game_core.cpp @@ -166,7 +166,8 @@ void GameCore::PushEventMoveUnit(uint32_t unit_id, glm::vec2 new_position) { }); } -void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, glm::vec2 relative_position) { +void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, + glm::vec2 relative_position) { event_queue_.emplace([this, unit_id, relative_position]() { auto unit = GetUnit(unit_id); auto new_position = unit->GetPosition() + relative_position; diff --git a/src/battle_game/core/units/snowball_sample_sledge.cpp b/src/battle_game/core/units/snowball_sample_sledge.cpp index 4bcb2691..c194beef 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.cpp +++ b/src/battle_game/core/units/snowball_sample_sledge.cpp @@ -1,7 +1,8 @@ +#include "snowball_sample_sledge.h" + #include "battle_game/core/bullets/bullets.h" #include "battle_game/core/game_core.h" #include "battle_game/graphics/graphics.h" -#include "snowball_sample_sledge.h" namespace battle_game::unit { diff --git a/src/battle_game/core/units/units.h b/src/battle_game/core/units/units.h index 58fbedfd..198ad6ab 100644 --- a/src/battle_game/core/units/units.h +++ b/src/battle_game/core/units/units.h @@ -1,5 +1,4 @@ #pragma once -#include "battle_game/core/units/snowball_sample_sledge.h" #include "battle_game/core/units/Whaooooo_tank.h" #include "battle_game/core/units/crit_tank.h" #include "battle_game/core/units/dark_fury.h" @@ -12,6 +11,7 @@ #include "battle_game/core/units/rebounding_sample_tank.h" #include "battle_game/core/units/round_UFO.h" #include "battle_game/core/units/smoke_bomb_tank.h" +#include "battle_game/core/units/snowball_sample_sledge.h" #include "battle_game/core/units/sparky.h" #include "battle_game/core/units/square_tank.h" #include "battle_game/core/units/tankK.h" From b7afbb3a4689de714f62b4703a9ef9280921f13e Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 21:49:41 +0800 Subject: [PATCH 07/19] guessing add spaces? --- src/battle_game/core/bullets/bullets.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 94252b1a..4a01bab3 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -1,4 +1,5 @@ #pragma once + #include "battle_game/core/bullets/cannon_ball.h" #include "battle_game/core/bullets/coin.h" #include "battle_game/core/bullets/crit_bullet.h" From 7ae165ff1468e7e2f808821673f8d3676b74d04b Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 21:55:11 +0800 Subject: [PATCH 08/19] IDK --- src/battle_game/core/bullets/bullets.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 4a01bab3..94252b1a 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -1,5 +1,4 @@ #pragma once - #include "battle_game/core/bullets/cannon_ball.h" #include "battle_game/core/bullets/coin.h" #include "battle_game/core/bullets/crit_bullet.h" From e077709ac2a23da0ebd2bfe964745132a9a25a44 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 22:17:23 +0800 Subject: [PATCH 09/19] trying --- src/battle_game/core/bullets/bullets.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 94252b1a..8a2b9610 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -1,3 +1,4 @@ + #pragma once #include "battle_game/core/bullets/cannon_ball.h" #include "battle_game/core/bullets/coin.h" From f37ee02de2ed348cee8a39be478797dc8614f308 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 22:24:27 +0800 Subject: [PATCH 10/19] l --- src/battle_game/core/bullets/bullets.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 8a2b9610..94252b1a 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -1,4 +1,3 @@ - #pragma once #include "battle_game/core/bullets/cannon_ball.h" #include "battle_game/core/bullets/coin.h" From 7b112d1e828661f1e58660a28944a061aefdc79c Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Fri, 13 Jan 2023 22:38:13 +0800 Subject: [PATCH 11/19] still clang problem .... --- src/battle_game/core/bullets/bullets.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_game/core/bullets/bullets.h b/src/battle_game/core/bullets/bullets.h index 94252b1a..fd4de522 100644 --- a/src/battle_game/core/bullets/bullets.h +++ b/src/battle_game/core/bullets/bullets.h @@ -8,7 +8,7 @@ #include "battle_game/core/bullets/rebounding_ball.h" #include "battle_game/core/bullets/rocket.h" #include "battle_game/core/bullets/smoke_bomb.h" +#include "battle_game/core/bullets/snowball.h" #include "battle_game/core/bullets/sweaty_soybean.h" #include "battle_game/core/bullets/warning_line.h" #include "battle_game/core/bullets/water_drop.h" -#include "battle_game/core/bullets/snowball.h" \ No newline at end of file From 9c1017a825496144520139c366326a7d6712242e Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Sat, 14 Jan 2023 10:56:56 +0800 Subject: [PATCH 12/19] changes --- src/battle_game/core/selectable_units.cpp | 2 +- .../core/units/snowball_sample_sledge.cpp | 104 ++---------------- .../core/units/snowball_sample_sledge.h | 10 +- 3 files changed, 17 insertions(+), 99 deletions(-) diff --git a/src/battle_game/core/selectable_units.cpp b/src/battle_game/core/selectable_units.cpp index 1909c267..e1e30245 100644 --- a/src/battle_game/core/selectable_units.cpp +++ b/src/battle_game/core/selectable_units.cpp @@ -29,8 +29,8 @@ void GameCore::GeneratePrimaryUnitList() { /* * TODO: Add Your Unit Here! * */ + ADD_SELECTABLE_UNIT(unit::Snowball_Sample_Sledge); ADD_SELECTABLE_UNIT(unit::InfernoTank); - ADD_SELECTABLE_UNIT(unit::snowball_sample_sledge); ADD_SELECTABLE_UNIT(unit::RoundUFO); ADD_SELECTABLE_UNIT(unit::Tank); ADD_SELECTABLE_UNIT(unit::DoubleScatterTank); diff --git a/src/battle_game/core/units/snowball_sample_sledge.cpp b/src/battle_game/core/units/snowball_sample_sledge.cpp index c194beef..555ff2fd 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.cpp +++ b/src/battle_game/core/units/snowball_sample_sledge.cpp @@ -2,6 +2,7 @@ #include "battle_game/core/bullets/bullets.h" #include "battle_game/core/game_core.h" +#include "battle_game/core/units/tiny_tank.h" #include "battle_game/graphics/graphics.h" namespace battle_game::unit { @@ -11,84 +12,23 @@ uint32_t sledge_body_model_index = 0xffffffffu; uint32_t sledge_turret_model_index = 0xffffffffu; } // namespace -snowball_sample_sledge::snowball_sample_sledge(GameCore *game_core, +Snowball_Sample_Sledge::Snowball_Sample_Sledge(GameCore *game_core, uint32_t id, uint32_t player_id) - : Unit(game_core, id, player_id) { - if (!~sledge_body_model_index) { - auto mgr = AssetsManager::GetInstance(); - { - /* Sledge Body */ - sledge_body_model_index = mgr->RegisterModel( - { - {{-0.8f, 0.8f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, - {{-0.8f, -1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, - {{0.8f, 0.8f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, - {{0.8f, -1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, - // distinguish front and back - {{0.6f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, - {{-0.6f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, - }, - {0, 1, 2, 1, 2, 3, 0, 2, 5, 2, 4, 5}); - } - - { - /* Sledge Turret */ - std::vector turret_vertices; - std::vector turret_indices; - const int precision = 60; - const float inv_precision = 1.0f / float(precision); - for (int i = 0; i < precision; i++) { - auto theta = (float(i) + 0.5f) * inv_precision; - theta *= glm::pi() * 2.0f; - auto sin_theta = std::sin(theta); - auto cos_theta = std::cos(theta); - turret_vertices.push_back({{sin_theta * 0.5f, cos_theta * 0.5f}, - {0.0f, 0.0f}, - {0.7f, 0.7f, 0.7f, 1.0f}}); - turret_indices.push_back(i); - turret_indices.push_back((i + 1) % precision); - turret_indices.push_back(precision); - } - turret_vertices.push_back( - {{0.0f, 0.0f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); - turret_vertices.push_back( - {{-0.1f, 0.0f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); - turret_vertices.push_back( - {{0.1f, 0.0f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); - turret_vertices.push_back( - {{-0.1f, 1.2f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); - turret_vertices.push_back( - {{0.1f, 1.2f}, {0.0f, 0.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}); - turret_indices.push_back(precision + 1 + 0); - turret_indices.push_back(precision + 1 + 1); - turret_indices.push_back(precision + 1 + 2); - turret_indices.push_back(precision + 1 + 1); - turret_indices.push_back(precision + 1 + 2); - turret_indices.push_back(precision + 1 + 3); - sledge_turret_model_index = - mgr->RegisterModel(turret_vertices, turret_indices); - } - } -} + : Tank(game_core, id, player_id){}; -void snowball_sample_sledge::Render() { - battle_game::SetTransformation(position_, rotation_); - battle_game::SetTexture(0); - battle_game::SetColor(game_core_->GetPlayerColor(player_id_)); - battle_game::DrawModel(sledge_body_model_index); - battle_game::SetRotation(turret_rotation_); - battle_game::DrawModel(sledge_turret_model_index); +void Snowball_Sample_Sledge::Render() { + Tank::Render(); } -void snowball_sample_sledge::Update() { - SledgeMove(3.0f, glm::radians(180.0f)); +void Snowball_Sample_Sledge::Update() { + TankMove(3.0f, glm::radians(180.0f)); TurretRotate(); Fire(); } -void snowball_sample_sledge::SledgeMove(float move_speed, - float rotate_angular_speed) { +void Snowball_Sample_Sledge::TankMove(float move_speed, + float rotate_angular_speed) { auto player = game_core_->GetPlayer(player_id_); if (player) { auto &input_data = player->GetInputData(); @@ -117,20 +57,7 @@ void snowball_sample_sledge::SledgeMove(float move_speed, } } -void snowball_sample_sledge::TurretRotate() { - auto player = game_core_->GetPlayer(player_id_); - if (player) { - auto &input_data = player->GetInputData(); - auto diff = input_data.mouse_cursor_position - position_; - if (glm::length(diff) < 1e-4) { - turret_rotation_ = rotation_; - } else { - turret_rotation_ = std::atan2(diff.y, diff.x) - glm::radians(90.0f); - } - } -} - -void snowball_sample_sledge::Fire() { +void Snowball_Sample_Sledge::Fire() { if (fire_count_down_) { fire_count_down_--; } else { @@ -148,18 +75,11 @@ void snowball_sample_sledge::Fire() { } } -bool snowball_sample_sledge::IsHit(glm::vec2 position) const { - position = WorldToLocal(position); - return position.x > -0.8f && position.x < 0.8f && position.y > -1.0f && - position.y < 1.0f && position.x + position.y < 1.6f && - position.y - position.x < 1.6f; -} - -const char *snowball_sample_sledge::UnitName() const { +const char *Snowball_Sample_Sledge::UnitName() const { return "sledge_lyc"; } -const char *snowball_sample_sledge::Author() const { +const char *Snowball_Sample_Sledge::Author() const { return "cylic14790382"; } } // namespace battle_game::unit \ No newline at end of file diff --git a/src/battle_game/core/units/snowball_sample_sledge.h b/src/battle_game/core/units/snowball_sample_sledge.h index 3c7ed9f7..e8ea75c2 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.h +++ b/src/battle_game/core/units/snowball_sample_sledge.h @@ -1,21 +1,19 @@ #pragma once #include "battle_game/core/unit.h" +#include "battle_game/core/units/tiny_tank.h" namespace battle_game::unit { -class snowball_sample_sledge : public Unit { +class Snowball_Sample_Sledge : public Tank { public: - snowball_sample_sledge(GameCore *game_core, uint32_t id, uint32_t player_id); + Snowball_Sample_Sledge(GameCore *game_core, uint32_t id, uint32_t player_id); void Render() override; void Update() override; - [[nodiscard]] bool IsHit(glm::vec2 position) const override; protected: - void SledgeMove(float move_speed, float rotate_angular_speed); - void TurretRotate(); void Fire(); + void TankMove(float move_speed, float rotate_angular_speed); [[nodiscard]] const char *UnitName() const override; [[nodiscard]] const char *Author() const override; - float turret_rotation_{0.0f}; uint32_t fire_count_down_{0}; }; } // namespace battle_game::unit \ No newline at end of file From 749ae9e104c311ece11e54b9cec5c7ea468d284c Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Sat, 14 Jan 2023 18:20:52 +0800 Subject: [PATCH 13/19] a little bug found when respawning --- src/battle_game/core/game_core.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/battle_game/core/game_core.cpp b/src/battle_game/core/game_core.cpp index 874f5499..939c9f0e 100644 --- a/src/battle_game/core/game_core.cpp +++ b/src/battle_game/core/game_core.cpp @@ -170,9 +170,11 @@ void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, glm::vec2 relative_position) { event_queue_.emplace([this, unit_id, relative_position]() { auto unit = GetUnit(unit_id); - auto new_position = unit->GetPosition() + relative_position; - if (unit && !IsBlockedByObstacles(new_position)) { - unit->SetPosition(new_position); + if (unit) { + auto new_position = unit->GetPosition() + relative_position; + if (!IsBlockedByObstacles(new_position)) { + unit->SetPosition(new_position); + } } }); } // this function is used for weight system. From 166b187c60b6fa20d8f316aac7cf0ad8c0fc5901 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Mon, 16 Jan 2023 18:58:29 +0800 Subject: [PATCH 14/19] Weight system and better simulation --- .gitignore | 3 +- src/battle_game/core/bullets/snowball.cpp | 6 +- src/battle_game/core/game_core.cpp | 48 ++++++-- src/battle_game/core/game_core.h | 6 + src/battle_game/core/unit.cpp | 9 ++ src/battle_game/core/unit.h | 19 +++- src/battle_game/core/units/round_UFO.cpp | 17 +-- .../core/units/snowball_sample_sledge.cpp | 106 +++++++++++++----- .../core/units/snowball_sample_sledge.h | 14 ++- src/battle_game/core/units/tiny_tank.cpp | 13 +-- 10 files changed, 181 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index 1669b9bb..e191c24e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ build out CMakeSettings.json compile_commands.json -.cache/ \ No newline at end of file +.cache/ +/src/battle_game/core/effect.cpp diff --git a/src/battle_game/core/bullets/snowball.cpp b/src/battle_game/core/bullets/snowball.cpp index 23275f38..7a3ffc78 100644 --- a/src/battle_game/core/bullets/snowball.cpp +++ b/src/battle_game/core/bullets/snowball.cpp @@ -37,8 +37,10 @@ void SnowBall::Update() { } if (unit.second->IsHit(position_)) { game_core_->PushEventDealDamage(unit.first, id_, damage_scale_ * 5.0f); - game_core_->PushEventMoveRelativeUnit( - unit.first, velocity_ * (5.0f * kSecondPerTick)); + auto distance_per_tick= velocity_ * (kSecondPerTick * 0.22f / + (0.1f + unit.second->GetWeight())); + game_core_->PushEventMoveRUForTicks(unit.first, + distance_per_tick, 50); should_die = true; } } diff --git a/src/battle_game/core/game_core.cpp b/src/battle_game/core/game_core.cpp index 939c9f0e..fb8d28b4 100644 --- a/src/battle_game/core/game_core.cpp +++ b/src/battle_game/core/game_core.cpp @@ -45,6 +45,10 @@ void GameCore::Update() { particle.second->Update(); } ProcessEventQueue(); + ProcessAwaitingQueue(); + for (auto &units : units_) { + units.second->EndTick(); + } } /* @@ -135,6 +139,13 @@ void GameCore::ProcessEventQueue() { } } +void GameCore::ProcessAwaitingQueue() { + while (!awaiting_queue_.empty()) { + awaiting_queue_.front()(); + awaiting_queue_.pop(); + } +} + bool GameCore::IsBlockedByObstacles(glm::vec2 p) const { if (IsOutOfRange(p)) { return true; @@ -161,7 +172,7 @@ void GameCore::PushEventMoveUnit(uint32_t unit_id, glm::vec2 new_position) { event_queue_.emplace([this, unit_id, new_position]() { auto unit = GetUnit(unit_id); if (unit) { - unit->SetPosition(new_position); + unit->position_change_ += new_position - unit->GetPosition(); } }); } @@ -171,23 +182,46 @@ void GameCore::PushEventMoveRelativeUnit(uint32_t unit_id, event_queue_.emplace([this, unit_id, relative_position]() { auto unit = GetUnit(unit_id); if (unit) { - auto new_position = unit->GetPosition() + relative_position; - if (!IsBlockedByObstacles(new_position)) { - unit->SetPosition(new_position); - } + unit->position_change_ += relative_position; } }); -} // this function is used for weight system. +} // this function is inspired by XieRujian, completely abandon the queue + +void GameCore::PushEventMoveRUForTicks(uint32_t unit_id, + glm::vec2 r_p, + uint32_t remaining_ticks) { + if (remaining_ticks > 0) { + event_queue_.emplace([this, unit_id, r_p, remaining_ticks]() { + auto unit = GetUnit(unit_id); + if (unit) { + unit->position_change_ += r_p; + awaiting_queue_.emplace([=]() { + PushEventMoveRUForTicks(unit_id, r_p, remaining_ticks - 1); + }); + } + }); + } +} // this function is an easy simulation for "effects" void GameCore::PushEventRotateUnit(uint32_t unit_id, float new_rotation) { event_queue_.emplace([this, unit_id, new_rotation]() { auto unit = GetUnit(unit_id); if (unit) { - unit->SetRotation(new_rotation); + unit->rotation_change_ += new_rotation - unit->GetRotation(); } }); } +void GameCore::PushEventRotateRelativeUnit(uint32_t unit_id, + float relative_rotation) { + event_queue_.emplace([this, unit_id, relative_rotation]() { + auto unit = GetUnit(unit_id); + if (unit) { + unit->rotation_change_ += relative_rotation; + } + }); +} // change another btw, although I dont actually use + Unit *GameCore::GetUnit(uint32_t unit_id) const { if (!units_.count(unit_id)) { return nullptr; diff --git a/src/battle_game/core/game_core.h b/src/battle_game/core/game_core.h index 5bb7d8eb..67fae9e4 100644 --- a/src/battle_game/core/game_core.h +++ b/src/battle_game/core/game_core.h @@ -124,7 +124,11 @@ class GameCore { void PushEventMoveUnit(uint32_t unit_id, glm::vec2 new_position); void PushEventMoveRelativeUnit(uint32_t unit_id, glm::vec2 relative_position); + void PushEventMoveRUForTicks(uint32_t unit_id, + glm::vec2 r_p, + uint32_t remaining_ticks); void PushEventRotateUnit(uint32_t unit_id, float new_rotation); + void PushEventRotateRelativeUnit(uint32_t unit_id, float new_rotation); void PushEventDealDamage(uint32_t dst_unit_id, uint32_t src_unit_id, float damage); @@ -164,6 +168,7 @@ class GameCore { } void ProcessEventQueue(); + void ProcessAwaitingQueue(); void SetCamera(glm::vec2 position, float rotation = 0.0f); [[nodiscard]] glm::vec2 GetCameraPosition() const { @@ -187,6 +192,7 @@ class GameCore { private: std::queue> event_queue_; + std::queue> awaiting_queue_;//this one is for "buff" type std::map> units_; uint32_t unit_index_{1}; diff --git a/src/battle_game/core/unit.cpp b/src/battle_game/core/unit.cpp index 1c64960c..9073b256 100644 --- a/src/battle_game/core/unit.cpp +++ b/src/battle_game/core/unit.cpp @@ -118,6 +118,15 @@ void Unit::RenderLifeBar() { void Unit::RenderHelper() { } +void Unit::EndTick() { + if (!game_core_->IsBlockedByObstacles(position_ + position_change_) && + !game_core_->IsOutOfRange(position_ + position_change_)) + position_ += position_change_; + rotation_ += rotation_change_; + position_change_ = {.0f, .0f}; + rotation_change_ = {.0f}; +} + const char *Unit::UnitName() const { return "Unknown Unit"; } diff --git a/src/battle_game/core/unit.h b/src/battle_game/core/unit.h index 45d335b8..d307d5ba 100644 --- a/src/battle_game/core/unit.h +++ b/src/battle_game/core/unit.h @@ -36,6 +36,10 @@ class Unit : public Object { return health_; } + [[nodiscard]] float GetWeight() const { + return weight_; + } + /* * The value of new_health will be clamped to [0, 1] * */ @@ -43,6 +47,13 @@ class Unit : public Object { health_ = std::clamp(new_health, 0.0f, 1.0f); } + /* + * The value of new_weight will be a float from 0 to \infty + * */ + void SetWeight(float new_weight) { + weight_ = new_weight; + } + void SetLifeBarLength(float new_length); void SetLifeBarOffset(glm::vec2 new_offset); void SetLifeBarFrontColor(glm::vec4 new_color); @@ -84,9 +95,15 @@ class Unit : public Object { return skills_; } + void EndTick(); // inspired by XieRujian + + glm::vec2 position_change_{glm::vec2(.0f, .0f)}; + float rotation_change_{.0f}; + protected: uint32_t player_id_{}; float health_{1.0f}; + float weight_{1.0f}; std::vector skills_; bool lifebar_display_{true}; glm::vec2 lifebar_offset_{}; @@ -100,5 +117,3 @@ class Unit : public Object { }; } // namespace battle_game - -// add something to pull \ No newline at end of file diff --git a/src/battle_game/core/units/round_UFO.cpp b/src/battle_game/core/units/round_UFO.cpp index 91109768..9c088ccd 100644 --- a/src/battle_game/core/units/round_UFO.cpp +++ b/src/battle_game/core/units/round_UFO.cpp @@ -78,10 +78,8 @@ void RoundUFO::Teleport_() { auto player = game_core_->GetPlayer(player_id_); if (player) { auto &input_data = player->GetInputData(); - auto new_position = input_data.mouse_cursor_position; - if (!game_core_->IsBlockedByObstacles(new_position)) { - game_core_->PushEventMoveUnit(id_, new_position); - } + game_core_->PushEventMoveRelativeUnit(id_, + input_data.mouse_cursor_position); } } @@ -113,13 +111,10 @@ void RoundUFO::UFOMove(float move_speed) { } float speed = move_speed * GetSpeedScale(); offset *= kSecondPerTick * speed; - auto new_position = - position_ + glm::vec2{glm::rotate(glm::mat4{1.0f}, rotation_, - glm::vec3{0.0f, 0.0f, 1.0f}) * - glm::vec4{offset, 0.0f, 0.0f}}; - if (!game_core_->IsBlockedByObstacles(new_position)) { - game_core_->PushEventMoveUnit(id_, new_position); - } + auto relative_position = glm::vec2{ + glm::rotate(glm::mat4{1.0f}, rotation_, glm::vec3{0.0f, 0.0f, 1.0f}) * + glm::vec4{offset, 0.0f, 0.0f}}; + game_core_->PushEventMoveRelativeUnit(id_, relative_position); auto diff = input_data.mouse_cursor_position - position_; float new_rotation; diff --git a/src/battle_game/core/units/snowball_sample_sledge.cpp b/src/battle_game/core/units/snowball_sample_sledge.cpp index 555ff2fd..41136677 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.cpp +++ b/src/battle_game/core/units/snowball_sample_sledge.cpp @@ -15,48 +15,98 @@ uint32_t sledge_turret_model_index = 0xffffffffu; Snowball_Sample_Sledge::Snowball_Sample_Sledge(GameCore *game_core, uint32_t id, uint32_t player_id) - : Tank(game_core, id, player_id){}; + : Tank(game_core, id, player_id) { + Skill temp; + temp.name = "Antigravity mode"; + temp.description = "-50% weight, less damage in all directions"; + temp.time_remain = 0; + temp.time_total = 360; + temp.type = E; + temp.function = SKILL_ADD_FUNCTION(Snowball_Sample_Sledge::AntigravityClick); + skills_.push_back(temp); + id_ = id; +}; void Snowball_Sample_Sledge::Render() { Tank::Render(); } -void Snowball_Sample_Sledge::Update() { - TankMove(3.0f, glm::radians(180.0f)); - TurretRotate(); - Fire(); +void Snowball_Sample_Sledge::AntigravityClick() { + hidden_count_down_ = 3 * kTickPerSecond; + antigravity_count_down_ = 6 * kTickPerSecond; } -void Snowball_Sample_Sledge::TankMove(float move_speed, - float rotate_angular_speed) { - auto player = game_core_->GetPlayer(player_id_); - if (player) { - auto &input_data = player->GetInputData(); - glm::vec2 offset{0.0f}; - if (input_data.key_down[GLFW_KEY_W]) { - offset.y += 1.0f; +void Snowball_Sample_Sledge::Antigravity() { + skills_[0].time_remain = antigravity_count_down_; + if (antigravity_count_down_) { + antigravity_count_down_--; + } else { + auto player = game_core_->GetPlayer(player_id_); + if (player) { + auto &input_data = player->GetInputData(); + if (input_data.key_down[GLFW_KEY_E]) { + AntigravityClick(); + } } - if (input_data.key_down[GLFW_KEY_S]) { - offset.y -= 1.0f; + } +} + +void Snowball_Sample_Sledge::Antigravity_() { + if (hidden_count_down_ == 3 * kTickPerSecond) { + auto &units = game_core_->GetUnits(); + for (auto &unit : units) { + if (unit.first == id_) { + continue; + } + unit.second->SetWeight(0.5f * unit.second->GetWeight()); } - float speed = move_speed * GetSpeedScale(); - offset *= kSecondPerTick * speed; - auto relative_position = glm::vec2{ - glm::rotate(glm::mat4{1.0f}, rotation_, glm::vec3{0.0f, 0.0f, 1.0f}) * - glm::vec4{offset, 0.0f, 0.0f}}; - game_core_->PushEventMoveRelativeUnit(id_, relative_position); - float rotation_offset = 0.0f; - if (input_data.key_down[GLFW_KEY_A]) { - rotation_offset += 1.0f; + speed_ *= 2; + } + if (hidden_count_down_ > 0 && hidden_count_down_ < 3 * kTickPerSecond + 1) { + Antigravity_fire(); + hidden_count_down_--; + } + if (hidden_count_down_ == 0) { + auto &units = game_core_->GetUnits(); + for (auto &unit : units) { + if (unit.first == id_) { + continue; + } + unit.second->SetWeight(2.0f * unit.second->GetWeight()); } - if (input_data.key_down[GLFW_KEY_D]) { - rotation_offset -= 1.0f; + speed_ /= 2; + hidden_count_down_ = 181; + } +} + +void Snowball_Sample_Sledge::Antigravity_fire() { + if (shoot_count_down_) { + shoot_count_down_--; + } else { + auto player = game_core_->GetPlayer(player_id_); + if (player) { + auto &input_data = player->GetInputData(); + auto velocity = Rotate(glm::vec2{0.0f, 10.0f}, turret_rotation_); + for (int i = -19; i < 19; ++i) { + auto offset = glm::radians(10.0f * i); + velocity = Rotate(glm::vec2{0.0f, 10.0f}, turret_rotation_ + offset); + GenerateBullet( + position_ + Rotate({0.0f, 1.2f}, turret_rotation_ + offset), + turret_rotation_ + offset, 0, velocity); + } } - rotation_offset *= kSecondPerTick * rotate_angular_speed * GetSpeedScale(); - game_core_->PushEventRotateUnit(id_, rotation_ + rotation_offset); + shoot_count_down_ = 30; } } +void Snowball_Sample_Sledge::Update() { + Tank::TankMove(speed_, glm::radians(180.0f)); + Tank::TurretRotate(); + Antigravity(); + Antigravity_(); + Fire(); +} + void Snowball_Sample_Sledge::Fire() { if (fire_count_down_) { fire_count_down_--; diff --git a/src/battle_game/core/units/snowball_sample_sledge.h b/src/battle_game/core/units/snowball_sample_sledge.h index e8ea75c2..5f5103c7 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.h +++ b/src/battle_game/core/units/snowball_sample_sledge.h @@ -8,12 +8,22 @@ class Snowball_Sample_Sledge : public Tank { Snowball_Sample_Sledge(GameCore *game_core, uint32_t id, uint32_t player_id); void Render() override; void Update() override; - + protected: void Fire(); - void TankMove(float move_speed, float rotate_angular_speed); + void AntigravityClick(); + void Antigravity(); + void Antigravity_(); + void Antigravity_fire(); [[nodiscard]] const char *UnitName() const override; [[nodiscard]] const char *Author() const override; uint32_t fire_count_down_{0}; + uint32_t antigravity_count_down_{360}; + uint32_t shoot_count_down_{0}; + uint32_t hidden_count_down_{181}; + float speed_{5.0f}; + + private: + uint32_t id_{0}; }; } // namespace battle_game::unit \ No newline at end of file diff --git a/src/battle_game/core/units/tiny_tank.cpp b/src/battle_game/core/units/tiny_tank.cpp index 99b61f59..2509050a 100644 --- a/src/battle_game/core/units/tiny_tank.cpp +++ b/src/battle_game/core/units/tiny_tank.cpp @@ -98,13 +98,12 @@ void Tank::TankMove(float move_speed, float rotate_angular_speed) { } float speed = move_speed * GetSpeedScale(); offset *= kSecondPerTick * speed; - auto new_position = - position_ + glm::vec2{glm::rotate(glm::mat4{1.0f}, rotation_, + + auto relative_position = glm::vec2{glm::rotate(glm::mat4{1.0f}, rotation_, glm::vec3{0.0f, 0.0f, 1.0f}) * glm::vec4{offset, 0.0f, 0.0f}}; - if (!game_core_->IsBlockedByObstacles(new_position)) { - game_core_->PushEventMoveUnit(id_, new_position); - } + game_core_->PushEventMoveRelativeUnit(id_, relative_position); + float rotation_offset = 0.0f; if (input_data.key_down[GLFW_KEY_A]) { rotation_offset += 1.0f; @@ -113,7 +112,7 @@ void Tank::TankMove(float move_speed, float rotate_angular_speed) { rotation_offset -= 1.0f; } rotation_offset *= kSecondPerTick * rotate_angular_speed * GetSpeedScale(); - game_core_->PushEventRotateUnit(id_, rotation_ + rotation_offset); + game_core_->PushEventRotateRelativeUnit(id_, rotation_offset); } } @@ -137,7 +136,7 @@ void Tank::Fire() { auto &input_data = player->GetInputData(); if (input_data.mouse_button_down[GLFW_MOUSE_BUTTON_LEFT]) { auto velocity = Rotate(glm::vec2{0.0f, 20.0f}, turret_rotation_); - GenerateBullet( + GenerateBullet( position_ + Rotate({0.0f, 1.2f}, turret_rotation_), turret_rotation_, GetDamageScale(), velocity); fire_count_down_ = kTickPerSecond; // Fire interval 1 second. From 968f99b2090288225852d530f1be12826af1010e Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Mon, 16 Jan 2023 19:38:24 +0800 Subject: [PATCH 15/19] clangformat --- src/battle_game/core/bullets/snowball.cpp | 7 +++---- src/battle_game/core/game_core.h | 3 ++- src/battle_game/core/unit.cpp | 6 +++--- src/battle_game/core/units/tiny_tank.cpp | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/battle_game/core/bullets/snowball.cpp b/src/battle_game/core/bullets/snowball.cpp index 7a3ffc78..663d6d65 100644 --- a/src/battle_game/core/bullets/snowball.cpp +++ b/src/battle_game/core/bullets/snowball.cpp @@ -37,10 +37,9 @@ void SnowBall::Update() { } if (unit.second->IsHit(position_)) { game_core_->PushEventDealDamage(unit.first, id_, damage_scale_ * 5.0f); - auto distance_per_tick= velocity_ * (kSecondPerTick * 0.22f / - (0.1f + unit.second->GetWeight())); - game_core_->PushEventMoveRUForTicks(unit.first, - distance_per_tick, 50); + auto distance_per_tick = velocity_ * (kSecondPerTick * 0.22f / + (0.1f + unit.second->GetWeight())); + game_core_->PushEventMoveRUForTicks(unit.first, distance_per_tick, 50); should_die = true; } } diff --git a/src/battle_game/core/game_core.h b/src/battle_game/core/game_core.h index 67fae9e4..2b4354c7 100644 --- a/src/battle_game/core/game_core.h +++ b/src/battle_game/core/game_core.h @@ -192,7 +192,8 @@ class GameCore { private: std::queue> event_queue_; - std::queue> awaiting_queue_;//this one is for "buff" type + std::queue> awaiting_queue_; + // this one is for "buff" type std::map> units_; uint32_t unit_index_{1}; diff --git a/src/battle_game/core/unit.cpp b/src/battle_game/core/unit.cpp index 9073b256..e186b528 100644 --- a/src/battle_game/core/unit.cpp +++ b/src/battle_game/core/unit.cpp @@ -122,9 +122,9 @@ void Unit::EndTick() { if (!game_core_->IsBlockedByObstacles(position_ + position_change_) && !game_core_->IsOutOfRange(position_ + position_change_)) position_ += position_change_; - rotation_ += rotation_change_; - position_change_ = {.0f, .0f}; - rotation_change_ = {.0f}; + rotation_ += rotation_change_; + position_change_ = {.0f, .0f}; + rotation_change_ = {.0f}; } const char *Unit::UnitName() const { diff --git a/src/battle_game/core/units/tiny_tank.cpp b/src/battle_game/core/units/tiny_tank.cpp index 2509050a..81c544af 100644 --- a/src/battle_game/core/units/tiny_tank.cpp +++ b/src/battle_game/core/units/tiny_tank.cpp @@ -98,10 +98,10 @@ void Tank::TankMove(float move_speed, float rotate_angular_speed) { } float speed = move_speed * GetSpeedScale(); offset *= kSecondPerTick * speed; - - auto relative_position = glm::vec2{glm::rotate(glm::mat4{1.0f}, rotation_, - glm::vec3{0.0f, 0.0f, 1.0f}) * - glm::vec4{offset, 0.0f, 0.0f}}; + + auto relative_position = glm::vec2{ + glm::rotate(glm::mat4{1.0f}, rotation_, glm::vec3{0.0f, 0.0f, 1.0f}) * + glm::vec4{offset, 0.0f, 0.0f}}; game_core_->PushEventMoveRelativeUnit(id_, relative_position); float rotation_offset = 0.0f; From b7ebeddad4a7cb88736b1c487557f6f86ac139a6 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Mon, 16 Jan 2023 19:47:26 +0800 Subject: [PATCH 16/19] clang --- .gitignore | 2 +- src/battle_game/core/units/snowball_sample_sledge.h | 1 - src/battle_game/core/units/tiny_tank.cpp | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index e191c24e..b4d0a0ae 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ out CMakeSettings.json compile_commands.json .cache/ -/src/battle_game/core/effect.cpp + diff --git a/src/battle_game/core/units/snowball_sample_sledge.h b/src/battle_game/core/units/snowball_sample_sledge.h index 5f5103c7..630d28f7 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.h +++ b/src/battle_game/core/units/snowball_sample_sledge.h @@ -8,7 +8,6 @@ class Snowball_Sample_Sledge : public Tank { Snowball_Sample_Sledge(GameCore *game_core, uint32_t id, uint32_t player_id); void Render() override; void Update() override; - protected: void Fire(); void AntigravityClick(); diff --git a/src/battle_game/core/units/tiny_tank.cpp b/src/battle_game/core/units/tiny_tank.cpp index 81c544af..fe40270f 100644 --- a/src/battle_game/core/units/tiny_tank.cpp +++ b/src/battle_game/core/units/tiny_tank.cpp @@ -136,7 +136,7 @@ void Tank::Fire() { auto &input_data = player->GetInputData(); if (input_data.mouse_button_down[GLFW_MOUSE_BUTTON_LEFT]) { auto velocity = Rotate(glm::vec2{0.0f, 20.0f}, turret_rotation_); - GenerateBullet( + GenerateBullet( position_ + Rotate({0.0f, 1.2f}, turret_rotation_), turret_rotation_, GetDamageScale(), velocity); fire_count_down_ = kTickPerSecond; // Fire interval 1 second. From e527eb320f74cbf42c576edf8f2d20e7e42bcf41 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Mon, 16 Jan 2023 19:53:37 +0800 Subject: [PATCH 17/19] trying clang --- src/battle_game/core/units/snowball_sample_sledge.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/battle_game/core/units/snowball_sample_sledge.h b/src/battle_game/core/units/snowball_sample_sledge.h index 630d28f7..0fe26f00 100644 --- a/src/battle_game/core/units/snowball_sample_sledge.h +++ b/src/battle_game/core/units/snowball_sample_sledge.h @@ -4,16 +4,20 @@ namespace battle_game::unit { class Snowball_Sample_Sledge : public Tank { + private: + uint32_t id_{0}; + public: Snowball_Sample_Sledge(GameCore *game_core, uint32_t id, uint32_t player_id); void Render() override; void Update() override; + protected: - void Fire(); void AntigravityClick(); void Antigravity(); void Antigravity_(); void Antigravity_fire(); + void Fire(); [[nodiscard]] const char *UnitName() const override; [[nodiscard]] const char *Author() const override; uint32_t fire_count_down_{0}; @@ -21,8 +25,5 @@ class Snowball_Sample_Sledge : public Tank { uint32_t shoot_count_down_{0}; uint32_t hidden_count_down_{181}; float speed_{5.0f}; - - private: - uint32_t id_{0}; }; } // namespace battle_game::unit \ No newline at end of file From 3353f8b19880a2657f029a0be37aa90234f47515 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Mon, 16 Jan 2023 20:05:17 +0800 Subject: [PATCH 18/19] gcc --- src/battle_game/core/unit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_game/core/unit.h b/src/battle_game/core/unit.h index d307d5ba..9e836cc2 100644 --- a/src/battle_game/core/unit.h +++ b/src/battle_game/core/unit.h @@ -48,7 +48,7 @@ class Unit : public Object { } /* - * The value of new_weight will be a float from 0 to \infty + * The value of new_weight will be a float from 0 to \infty * */ void SetWeight(float new_weight) { weight_ = new_weight; From bb7da9c1bb509ca36c74372646e7e0ce2b2750d1 Mon Sep 17 00:00:00 2001 From: cylic14790382 Date: Mon, 16 Jan 2023 20:08:51 +0800 Subject: [PATCH 19/19] finally --- src/battle_game/core/unit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_game/core/unit.h b/src/battle_game/core/unit.h index 9e836cc2..d307d5ba 100644 --- a/src/battle_game/core/unit.h +++ b/src/battle_game/core/unit.h @@ -48,7 +48,7 @@ class Unit : public Object { } /* - * The value of new_weight will be a float from 0 to \infty + * The value of new_weight will be a float from 0 to \infty * */ void SetWeight(float new_weight) { weight_ = new_weight;