aboutsummaryrefslogtreecommitdiff
path: root/game/missile
diff options
context:
space:
mode:
authorheavydemon21 <nielsstunnebrink1@gmail.com>2025-01-08 14:10:27 +0100
committerheavydemon21 <nielsstunnebrink1@gmail.com>2025-01-08 14:10:27 +0100
commitb445a1716a46dc875e0b2180c1a1b6022ec7a6d3 (patch)
tree1395518417ef02ca8adfa961e0734ea7aeb71a6d /game/missile
parentc9c9702edc58ff8f40b13dc6b86b216421f79e9b (diff)
missile/preview/schedular/PreviewScene
Diffstat (limited to 'game/missile')
-rw-r--r--game/missile/MissilePool.cpp16
-rw-r--r--game/missile/MissilePool.h11
-rw-r--r--game/missile/MissileScript.cpp105
-rw-r--r--game/missile/MissileScript.h20
-rw-r--r--game/missile/MissileSubScene.cpp101
-rw-r--r--game/missile/MissileSubScene.h12
-rw-r--r--game/missile/SpawnEvent.cpp47
-rw-r--r--game/missile/SpawnEvent.h20
8 files changed, 332 insertions, 0 deletions
diff --git a/game/missile/MissilePool.cpp b/game/missile/MissilePool.cpp
new file mode 100644
index 0000000..e549210
--- /dev/null
+++ b/game/missile/MissilePool.cpp
@@ -0,0 +1,16 @@
+#include "MissilePool.h"
+#include "MissileSubScene.h"
+
+#include <crepe/api/Scene.h>
+
+using namespace std;
+using namespace crepe;
+
+MissilePool::MissilePool(Scene & scn) {
+ int amount = 0;
+ MissileSubScene missile;
+ while (amount < this->MAX_MISSILE_COUNT) {
+ missile.create(scn);
+ amount++;
+ }
+}
diff --git a/game/missile/MissilePool.h b/game/missile/MissilePool.h
new file mode 100644
index 0000000..296701e
--- /dev/null
+++ b/game/missile/MissilePool.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <crepe/api/Scene.h>
+
+class MissilePool {
+public:
+ MissilePool(crepe::Scene & scn);
+
+private:
+ static constexpr unsigned int MAX_MISSILE_COUNT = 5;
+};
diff --git a/game/missile/MissileScript.cpp b/game/missile/MissileScript.cpp
new file mode 100644
index 0000000..6d0e40e
--- /dev/null
+++ b/game/missile/MissileScript.cpp
@@ -0,0 +1,105 @@
+#include "MissileScript.h"
+#include "../Config.h"
+#include "api/BehaviorScript.h"
+
+#include <crepe/api/Animator.h>
+#include <crepe/api/AudioSource.h>
+#include <crepe/api/Transform.h>
+#include <crepe/system/CollisionSystem.h>
+#include <crepe/types.h>
+
+#include <cmath>
+#include <crepe/api/AI.h>
+#include <crepe/api/KeyCodes.h>
+#include <crepe/api/Sprite.h>
+
+using namespace std;
+using namespace crepe;
+
+void MissileScript::init() {
+ subscribe<CollisionEvent>([this](const CollisionEvent & ev) -> bool {
+ return this->on_collision(ev);
+ });
+ this->seeking_disabled = false;
+}
+void MissileScript::kill_missile() {
+ auto animations = this->get_components<Animator>();
+ auto sprites = this->get_components<Sprite>();
+ auto & fly_sound = this->get_components<AudioSource>().front().get();
+ auto & this_script = this->get_components<BehaviorScript>().back().get();
+
+ animations[0].get().active = false;
+ animations[1].get().active = false;
+ animations[2].get().active = true;
+ sprites[0].get().active = false;
+ sprites[1].get().active = false;
+ sprites[2].get().active = true;
+
+ this_script.active = false;
+ this->seeking_disabled = false;
+
+ fly_sound.stop();
+}
+void MissileScript::activate() {
+ auto anim = this->get_components<Animator>();
+ auto sprites = this->get_components<Sprite>();
+
+ anim[0].get().active = true;
+ anim[1].get().active = true;
+ anim[2].get().stop();
+ sprites[0].get().active = true;
+ sprites[1].get().active = true;
+ sprites[2].get().active = false;
+}
+
+bool MissileScript::on_collision(const CollisionEvent & ev) {
+ auto & explosion_sound = this->get_components<AudioSource>().back().get();
+
+ this->kill_missile();
+ explosion_sound.play();
+
+ return false;
+}
+
+bool MissileScript::is_in_x_range(const Transform & missile, const Transform & player) {
+ return fabs(missile.position.x - player.position.x) <= this->X_RANGE;
+}
+
+void MissileScript::fixed_update(crepe::duration_t dt) {
+ auto & explosion_anim = this->get_components<Animator>().back().get();
+ auto & missile = this->get_component<Transform>();
+ auto & m_ai = this->get_component<AI>();
+
+ const auto & player = this->get_components_by_name<Transform>("player").front().get();
+ const auto & cam = this->get_components_by_name<Transform>("camera").front().get();
+ const auto & velocity = this->get_component<Rigidbody>().data.linear_velocity;
+
+ if (missile.position.x < (cam.position.x - VIEWPORT_X / 1.8)) {
+ this->kill_missile();
+ return;
+ }
+
+ // check if animation is at the end
+ if (explosion_anim.data.row == 7) {
+ this->activate();
+ this->seeking_disabled = false;
+ }
+
+ if (this->seeking_disabled) {
+ m_ai.seek_off();
+ } else {
+ m_ai.seek_target = player.position;
+ m_ai.seek_on();
+
+ if (is_in_x_range(missile, player)) {
+ this->seeking_disabled = true;
+ m_ai.seek_off();
+ }
+ }
+
+ vec2 angle_pos = velocity;
+ float angle = atan2(angle_pos.y, angle_pos.x) * (180 / M_PI);
+
+ missile.rotation = angle;
+ missile.position += velocity * dt.count();
+}
diff --git a/game/missile/MissileScript.h b/game/missile/MissileScript.h
new file mode 100644
index 0000000..a492e18
--- /dev/null
+++ b/game/missile/MissileScript.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <crepe/api/Script.h>
+
+class MissileScript : public crepe::Script {
+private:
+ bool on_collision(const crepe::CollisionEvent & ev);
+
+ bool seeking_disabled;
+
+ // will be used to calculate when ai will be stopped
+ static constexpr int X_RANGE = 90;
+ bool is_in_x_range(const crepe::Transform & missile, const crepe::Transform & player);
+ void kill_missile();
+ void activate();
+
+public:
+ void init();
+ void fixed_update(crepe::duration_t dt);
+};
diff --git a/game/missile/MissileSubScene.cpp b/game/missile/MissileSubScene.cpp
new file mode 100644
index 0000000..db49f88
--- /dev/null
+++ b/game/missile/MissileSubScene.cpp
@@ -0,0 +1,101 @@
+#include "MissileSubScene.h"
+#include "../Config.h"
+#include "../missile/MissileScript.h"
+
+#include <crepe/api/AI.h>
+#include <crepe/api/Animator.h>
+#include <crepe/api/AudioSource.h>
+#include <crepe/api/BehaviorScript.h>
+#include <crepe/api/CircleCollider.h>
+#include <crepe/api/Scene.h>
+#include <crepe/api/Sprite.h>
+#include <crepe/types.h>
+#include <random>
+
+using namespace crepe;
+
+void MissileSubScene::create(crepe::Scene & scn) {
+ std::random_device rd;
+ std::mt19937 gen(rd());
+
+ GameObject missle = scn.new_object("missile", "missile", {0, 0}, 0, 1);
+
+ Asset missle_ss {"asset/obstacles/missile/missile.png"};
+ Asset missle_thruster_ss {"asset/obstacles/missile/missileEffects.png"};
+ Asset missile_explosion_ss {"asset/obstacles/missile/missileExplosion.png"};
+ Asset explosion_sound {"asset/sfx/rocket_explode_1.ogg"};
+ Asset missile_fire {"asset/sfx/missile_launch.ogg"};
+
+ missle.add_component<BehaviorScript>().set_script<MissileScript>().active = false;
+
+ auto & sound = missle.add_component<AudioSource>(missile_fire);
+ sound.volume = 0.1;
+ auto & sound2 = missle.add_component<AudioSource>(explosion_sound);
+ sound2.volume = 0.1;
+
+ // sprites
+ auto & missle_sprite = missle.add_component<Sprite>(
+ missle_ss,
+ Sprite::Data {
+ .flip = {true, false},
+ .sorting_in_layer = SORT_IN_LAY_OBSTACLES,
+ .size = {0, 35},
+ }
+ );
+
+ auto & missle_thruster_sprite = missle.add_component<Sprite>(
+ missle_thruster_ss,
+ Sprite::Data {
+ .flip = {true, false},
+ .sorting_in_layer = SORT_IN_LAY_OBSTACLES,
+ .size = {0, 35},
+ .position_offset = {-20, 0},
+ }
+ );
+
+ auto & missile_explosion_sprite = missle.add_component<Sprite>(
+ missile_explosion_ss,
+ Sprite::Data {
+ .sorting_in_layer = SORT_IN_LAY_OBSTACLES,
+ .size = {0, 50},
+ }
+ );
+
+ // Animations
+ missle.add_component<Animator>(
+ missle_sprite, ivec2 {32, 32}, uvec2 {4, 1},
+ Animator::Data {
+ .looping = true,
+ }
+ );
+
+ missle.add_component<Animator>(
+ missle_thruster_sprite, ivec2 {64, 64}, uvec2 {4, 2},
+ Animator::Data {
+ .looping = true,
+ }
+ );
+
+ auto & explosion_anim = missle.add_component<Animator>(
+ missile_explosion_sprite, ivec2 {64, 64}, uvec2 {8, 1},
+ Animator::Data {
+ .fps = 10,
+ }
+ );
+
+ missile_explosion_sprite.active = false;
+ explosion_anim.active = false;
+
+ std::uniform_int_distribution<> dist(140, 200);
+ missle.add_component<Rigidbody>(Rigidbody::Data {
+ .body_type = Rigidbody::BodyType::KINEMATIC,
+ .max_linear_velocity = static_cast<float>(dist(gen)),
+ .kinematic_collision = false,
+ .collision_layers = {COLL_LAY_PLAYER, COLL_LAY_BOT_TOP},
+ .collision_layer = COLL_LAY_MISSILE,
+ });
+
+ missle.add_component<CircleCollider>(3);
+
+ auto & missle_ai = missle.add_component<AI>(1000);
+}
diff --git a/game/missile/MissileSubScene.h b/game/missile/MissileSubScene.h
new file mode 100644
index 0000000..9ea422a
--- /dev/null
+++ b/game/missile/MissileSubScene.h
@@ -0,0 +1,12 @@
+#pragma once
+
+namespace crepe {
+class Scene;
+}
+
+class MissileSubScene {
+public:
+ MissileSubScene() = default;
+
+ void create(crepe::Scene & scn);
+};
diff --git a/game/missile/SpawnEvent.cpp b/game/missile/SpawnEvent.cpp
new file mode 100644
index 0000000..03a9b8c
--- /dev/null
+++ b/game/missile/SpawnEvent.cpp
@@ -0,0 +1,47 @@
+#include "SpawnEvent.h"
+
+#include <crepe/api/Animator.h>
+#include <crepe/api/AudioSource.h>
+#include <crepe/api/BehaviorScript.h>
+#include <crepe/api/Camera.h>
+#include <crepe/api/Sprite.h>
+#include <crepe/api/Transform.h>
+
+#include <cstdlib>
+#include <random>
+
+using namespace crepe;
+
+void MissileSpawnEventHandler::init() {
+ subscribe<MissileSpawnEvent>([this](const MissileSpawnEvent & ev) -> bool {
+ return this->on_event(ev);
+ });
+}
+
+std::random_device rd;
+std::mt19937 gen(rd());
+
+bool MissileSpawnEventHandler::on_event(const MissileSpawnEvent & event) {
+ auto missile_sprites = this->get_components_by_name<Sprite>("missile");
+ auto missile_transforms = this->get_components_by_name<Transform>("missile");
+ auto missile_behaviorscripts = this->get_components_by_name<BehaviorScript>("missile");
+ auto missile_audiosources = this->get_components_by_name<AudioSource>("missile");
+ auto & camera_transform = this->get_components_by_name<Transform>("camera").front().get();
+
+ for (size_t i = 0; i < missile_behaviorscripts.size(); ++i) {
+ auto & script = missile_behaviorscripts[i].get();
+ if (script.active) continue;
+ script.active = true;
+
+ missile_audiosources[i * 2].get().play();
+
+ auto & transform = missile_transforms[i].get();
+ transform.position.x = camera_transform.position.x + this->MISSILE_OFFSET;
+ std::uniform_int_distribution<> dist(this->MIN_RANGE, this->MAX_RANGE);
+ transform.position.y = dist(gen);
+
+ break;
+ }
+
+ return false;
+}
diff --git a/game/missile/SpawnEvent.h b/game/missile/SpawnEvent.h
new file mode 100644
index 0000000..ce301fd
--- /dev/null
+++ b/game/missile/SpawnEvent.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <crepe/api/Event.h>
+#include <crepe/api/Script.h>
+
+#include "../Config.h"
+
+struct MissileSpawnEvent : public crepe::Event {};
+
+class MissileSpawnEventHandler : public crepe::Script {
+private:
+ static constexpr int MISSILE_OFFSET = VIEWPORT_X / 1.8;
+ static constexpr int RANGE = GAME_HEIGHT / 4;
+ static constexpr int MIN_RANGE = -RANGE;
+ static constexpr int MAX_RANGE = RANGE;
+
+public:
+ void init();
+ bool on_event(const MissileSpawnEvent & ev);
+};