aboutsummaryrefslogtreecommitdiff
path: root/game/missile
diff options
context:
space:
mode:
Diffstat (limited to 'game/missile')
-rw-r--r--game/missile/AlertScript.cpp38
-rw-r--r--game/missile/AlertScript.h11
-rw-r--r--game/missile/AlertSubScene.cpp33
-rw-r--r--game/missile/AlertSubScene.h8
-rw-r--r--game/missile/MissilePool.cpp18
-rw-r--r--game/missile/MissilePool.h11
-rw-r--r--game/missile/MissileScript.cpp110
-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.cpp49
-rw-r--r--game/missile/SpawnEvent.h20
12 files changed, 431 insertions, 0 deletions
diff --git a/game/missile/AlertScript.cpp b/game/missile/AlertScript.cpp
new file mode 100644
index 0000000..24b4af9
--- /dev/null
+++ b/game/missile/AlertScript.cpp
@@ -0,0 +1,38 @@
+#include "AlertScript.h"
+#include "../Config.h"
+
+#include <crepe/api/CircleCollider.h>
+#include <crepe/api/Sprite.h>
+#include <crepe/api/Transform.h>
+
+using namespace crepe;
+
+void AlertScript::fixed_update(crepe::duration_t dt) {
+ const auto & cam = this->get_components_by_name<Transform>("camera").front().get();
+ //missile transform
+ const auto & this_transform = this->get_component<Transform>();
+ auto missile_transforms = this->get_components_by_name<Transform>("missile");
+ const auto & this_collider = this->get_component<CircleCollider>();
+
+ auto alert_sprites = this->get_components_by_name<Sprite>("missile_alert");
+ auto alert_transforms = this->get_components_by_name<Transform>("missile_alert");
+
+ int idx = 0;
+ for (int i = 0; i < missile_transforms.size(); i++) {
+ const auto & missile_transform = missile_transforms[i].get();
+ if (this_transform.game_object_id == missile_transform.game_object_id) {
+ idx = i;
+ break;
+ }
+ }
+
+ auto & alert_transform = alert_transforms[idx].get();
+ alert_transform.position.x = cam.position.x + (VIEWPORT_X / 2 - 100);
+ alert_transform.position.y = this_transform.position.y;
+
+ // check if transform is in camera view
+ if (this_transform.position.x > cam.position.x - (VIEWPORT_X / 2)
+ && this_transform.position.x < cam.position.x + (VIEWPORT_X / 2)) {
+ alert_sprites[idx].get().active = false;
+ }
+}
diff --git a/game/missile/AlertScript.h b/game/missile/AlertScript.h
new file mode 100644
index 0000000..5b0b3a1
--- /dev/null
+++ b/game/missile/AlertScript.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <crepe/api/Script.h>
+
+class AlertScript : public crepe::Script {
+private:
+ bool has_alert = false;
+
+public:
+ void fixed_update(crepe::duration_t dt);
+};
diff --git a/game/missile/AlertSubScene.cpp b/game/missile/AlertSubScene.cpp
new file mode 100644
index 0000000..5bce5ac
--- /dev/null
+++ b/game/missile/AlertSubScene.cpp
@@ -0,0 +1,33 @@
+#include "AlertSubScene.h"
+#include "../Config.h"
+
+#include <crepe/api/Animator.h>
+#include <crepe/api/Scene.h>
+#include <crepe/api/Sprite.h>
+
+using namespace crepe;
+
+MissileAlert::MissileAlert(Scene & scn) {
+ GameObject alert = scn.new_object("missile_alert", "missile_alert", {0, 0}, 0, 1);
+
+ Asset missile_alert_ss {"asset/obstacles/missile/missileAlert.png"};
+
+ auto & missile_alert_sprite = alert.add_component<Sprite>(
+ missile_alert_ss,
+ Sprite::Data {
+ .sorting_in_layer = SORT_IN_LAY_OBSTACLES,
+ .size = {0, 100},
+ }
+ );
+
+ auto & missile_alert_anim = alert.add_component<Animator>(
+ missile_alert_sprite, ivec2 {64, 64}, uvec2 {4, 2},
+ Animator::Data {
+ .fps = 15,
+ .looping = true,
+ }
+ );
+
+ missile_alert_anim.set_anim(1);
+ missile_alert_sprite.active = false;
+}
diff --git a/game/missile/AlertSubScene.h b/game/missile/AlertSubScene.h
new file mode 100644
index 0000000..8ea288f
--- /dev/null
+++ b/game/missile/AlertSubScene.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <crepe/api/Scene.h>
+
+class MissileAlert {
+public:
+ MissileAlert(crepe::Scene & scn);
+};
diff --git a/game/missile/MissilePool.cpp b/game/missile/MissilePool.cpp
new file mode 100644
index 0000000..23f03c9
--- /dev/null
+++ b/game/missile/MissilePool.cpp
@@ -0,0 +1,18 @@
+#include "MissilePool.h"
+#include "MissileSubScene.h"
+#include "missile/AlertSubScene.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) {
+ MissileAlert alert(scn);
+ 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..bcc4f5b
--- /dev/null
+++ b/game/missile/MissileScript.cpp
@@ -0,0 +1,110 @@
+#include "MissileScript.h"
+#include "../Config.h"
+#include <cmath>
+
+#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/KeyCodes.h>
+#include <crepe/api/Rigidbody.h>
+#include <crepe/api/Sprite.h>
+#include <crepe/api/Transform.h>
+#include <crepe/system/CollisionSystem.h>
+#include <crepe/types.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 collider = this->get_component<CircleCollider>();
+ auto & fly_sound = this->get_components<AudioSource>().front().get();
+ auto & this_script = this->get_components<BehaviorScript>().front().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;
+ collider.active = false;
+ 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();
+ //anim[3].get().active = true;
+
+ sprites[0].get().active = true;
+ sprites[1].get().active = true;
+ sprites[2].get().active = false;
+ //sprites[3].get().active = true;
+}
+
+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..d325050
--- /dev/null
+++ b/game/missile/MissileSubScene.cpp
@@ -0,0 +1,101 @@
+#include "MissileSubScene.h"
+#include "../Config.h"
+#include "../missile/MissileScript.h"
+#include "Random.h"
+#include "missile/AlertScript.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>
+
+using namespace crepe;
+
+void MissileSubScene::create(crepe::Scene & scn) {
+ 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;
+ missle.add_component<BehaviorScript>().set_script<AlertScript>();
+
+ auto & sound = missle.add_component<AudioSource>(missile_fire);
+ sound.volume = 0.5;
+ auto & sound2 = missle.add_component<AudioSource>(explosion_sound);
+ sound2.volume = 3;
+
+ // 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 {
+ .fps = 15,
+ .looping = true,
+ }
+ );
+
+ missle.add_component<Animator>(
+ missle_thruster_sprite, ivec2 {64, 64}, uvec2 {4, 2},
+ Animator::Data {
+ .fps = 15,
+ .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;
+
+ missle.add_component<Rigidbody>(Rigidbody::Data {
+ .body_type = Rigidbody::BodyType::KINEMATIC,
+ .max_linear_velocity = Random::f(250, 200),
+ .kinematic_collision = false,
+ .collision_layers = {COLL_LAY_PLAYER, COLL_LAY_BOT_TOP},
+ .collision_layer = COLL_LAY_MISSILE,
+ });
+
+ missle.add_component<CircleCollider>(3).active = false;
+
+ 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..c7209b7
--- /dev/null
+++ b/game/missile/SpawnEvent.cpp
@@ -0,0 +1,49 @@
+#include "SpawnEvent.h"
+#include "Random.h"
+
+#include <crepe/api/Animator.h>
+#include <crepe/api/AudioSource.h>
+#include <crepe/api/BehaviorScript.h>
+#include <crepe/api/Camera.h>
+#include <crepe/api/CircleCollider.h>
+#include <crepe/api/Sprite.h>
+#include <crepe/api/Transform.h>
+
+#include <cstdlib>
+
+using namespace crepe;
+
+void MissileSpawnEventHandler::init() {
+ subscribe<MissileSpawnEvent>([this](const MissileSpawnEvent & ev) -> bool {
+ return this->on_event(ev);
+ });
+}
+
+bool MissileSpawnEventHandler::on_event(const MissileSpawnEvent & event) {
+ auto missile_transforms = this->get_components_by_name<Transform>("missile");
+ auto alert_sprites = this->get_components_by_name<Sprite>("missile_alert");
+ auto alert_transforms = this->get_components_by_name<Transform>("missile_alert");
+ auto colliders = this->get_components_by_name<CircleCollider>("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 * 2].get();
+ if (script.active) continue;
+ script.active = true;
+ colliders[i].get().active = true;
+ missile_audiosources[i * 2].get().play();
+
+ auto & transform = missile_transforms[i].get();
+ transform.position.x = camera_transform.position.x + this->MISSILE_OFFSET;
+ transform.position.y = Random::i(this->MAX_RANGE, this->MIN_RANGE);
+
+ auto & alert_transform = alert_transforms[i].get();
+ auto & alert_sprite = alert_sprites[i].get();
+ alert_sprite.active = true;
+ break;
+ }
+
+ return false;
+}
diff --git a/game/missile/SpawnEvent.h b/game/missile/SpawnEvent.h
new file mode 100644
index 0000000..58293d7
--- /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;
+ 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);
+};