Skip to content

Created Double Shrinker #224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.a !text !filter !merge !diff
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@ out
CMakeSettings.json
compile_commands.json
.cache/
vcpkg_installed/
CMakeFiles/
CMakeCache.txt
Makefile
cmake_install.cmake
vcpkg-bootstrap.log
vcpkg-manifest-install.log
.DS_Store
2 changes: 1 addition & 1 deletion src/battle_game/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
file(GLOB files *)

foreach(file ${files})
if (IS_DIRECTORY ${file})
if (IS_DIRECTORY ${file} AND NOT ${file} STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}/CMakeFiles")
file(RELATIVE_PATH short_name ${CMAKE_CURRENT_SOURCE_DIR} ${file})
set(COMPONENT_NAME ${short_name})
add_subdirectory(${file})
Expand Down
12 changes: 12 additions & 0 deletions src/battle_game/app/built_in_shaders.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// This file is generated by CMake
#include "shaders/render.frag.h"
#include "shaders/render.vert.h"

std::map<std::string, std::pair<const char *, unsigned int>> shader_list = {
{"shaders/render.frag", {reinterpret_cast<const char *>(shaders_render_frag), shaders_render_frag_len}},
{"shaders/render.vert", {reinterpret_cast<const char *>(shaders_render_vert), shaders_render_vert_len}},
};

std::string GetShaderCode(const std::string& file_name) {
return std::string(shader_list[file_name].first, shader_list[file_name].second);
}
1 change: 1 addition & 0 deletions src/battle_game/core/selectable_units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ void GameCore::GeneratePrimaryUnitList() {
* TODO: Add Your Unit Here!
* */
ADD_SELECTABLE_UNIT(unit::Tank);
ADD_SELECTABLE_UNIT(unit::DoubleShrinker);

unit.reset();
}
Expand Down
202 changes: 202 additions & 0 deletions src/battle_game/core/units/double_shrinker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
#include "double_shrinker.h"

#include "battle_game/core/bullets/bullets.h"
#include "battle_game/core/game_core.h"
#include "battle_game/graphics/graphics.h"

namespace battle_game::unit {

namespace {
uint32_t tank_body_model_index = 0xffffffffu;
uint32_t tank_turret_model_index = 0xffffffffu;
} // namespace

DoubleShrinker::DoubleShrinker(GameCore *game_core, uint32_t id, uint32_t player_id)
: Unit(game_core, id, player_id) {
if (!~tank_body_model_index) {
auto mgr = AssetsManager::GetInstance();
{
/* Tank Body */
tank_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});
}

{
/* Tank Turret */
std::vector<ObjectVertex> turret_vertices;
std::vector<uint32_t> 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<float>() * 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);
tank_turret_model_index =
mgr->RegisterModel(turret_vertices, turret_indices);
}
}
}

void DoubleShrinker::Render() {
glm::vec2 scale = glm::vec2(1.0f);
if (shrink_timer_ > 0) {
scale = glm::vec2(0.5f);
}
battle_game::SetTransformation(position_, rotation_, scale);
battle_game::SetTexture(0);
battle_game::SetColor(game_core_->GetPlayerColor(player_id_));
battle_game::DrawModel(tank_body_model_index);
battle_game::SetRotation(turret_rotation_);
battle_game::DrawModel(tank_turret_model_index);
battle_game::SetRotation(turret_rotation_ + glm::radians(180.0f));
battle_game::DrawModel(tank_turret_model_index);
}

void DoubleShrinker::Update() {
TankMove(3.0f, glm::radians(180.0f));
TurretRotate();
FireGuns();
Shrink();
if (shrink_timer_ > 0) {
shrink_timer_--;
}
if (shrink_count_down_ > 0) {
shrink_count_down_--;
}
}

void DoubleShrinker::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;
}
if (input_data.key_down[GLFW_KEY_S]) {
offset.y -= 1.0f;
}
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);
}
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 DoubleShrinker::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 DoubleShrinker::FireGuns() {
if (fire_count_down_ == 0) {
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 velocity1 = Rotate(glm::vec2{0.0f, 20.0f}, turret_rotation_);
auto velocity2 = Rotate(glm::vec2{0.0f, -20.0f}, turret_rotation_);
GenerateBullet<bullet::CannonBall>(
position_ + Rotate({0.0f, 1.2f}, turret_rotation_),
turret_rotation_, GetDamageScale(), velocity1);
GenerateBullet<bullet::CannonBall>(
position_ + Rotate({0.0f, -1.2f}, turret_rotation_),
turret_rotation_ + glm::radians(180.0f), GetDamageScale(), velocity2);
fire_count_down_ = kTickPerSecond; // Fire interval 1 second.
}
}
}
if (fire_count_down_) {
fire_count_down_--;
}
}

void DoubleShrinker::Shrink() {
auto player = game_core_->GetPlayer(player_id_);
if (player) {
auto &input_data = player->GetInputData();
if (input_data.key_down[GLFW_KEY_R] && shrink_count_down_ == 0) {
shrink_timer_ = 3 * kTickPerSecond;
shrink_count_down_ = 6 * kTickPerSecond;
}
}
}

bool DoubleShrinker::IsHit(glm::vec2 position) const {
position = WorldToLocal(position);
if (shrink_timer_ > 0) {
return position.x > -0.4f && position.x < 0.4f && position.y > -0.5f &&
position.y < 0.5f && position.x + position.y < 0.8f &&
position.y - position.x < 0.8f;
}
else{
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 *DoubleShrinker::UnitName() const {
return "Double Shrinker";
}

const char *DoubleShrinker::Author() const {
return "JerryLin828";
}

} // namespace battle_game::unit
25 changes: 25 additions & 0 deletions src/battle_game/core/units/double_shrinker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include "battle_game/core/unit.h"

namespace battle_game::unit {
class DoubleShrinker : public Unit {
public:
DoubleShrinker(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 TankMove(float move_speed, float rotate_angular_speed);
void TurretRotate();
void FireGuns();
void Shrink();
[[nodiscard]] const char *UnitName() const override;
[[nodiscard]] const char *Author() const override;

float turret_rotation_{0.0f};
uint32_t fire_count_down_{0};
uint32_t shrink_timer_{0};
uint32_t shrink_count_down_{0};
};
} // namespace battle_game::unit
5 changes: 5 additions & 0 deletions src/battle_game/core/units/units.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This is a generated file
#pragma once
#include "battle_game/core/units/double_shrinker.h"
#include "battle_game/core/units/tiny_tank.h"
#include "battle_game/core/units/units.h"