Air-Trap 1.0.0
A multiplayer R-Type clone game engine built with C++23 and ECS architecture
Loading...
Searching...
No Matches
EntityBuilder.cpp
Go to the documentation of this file.
1/*
2** EPITECH PROJECT, 2025
3** Air-Trap, Client
4** File description:
5**
6 * EnemyBuilder implementation
7*/
8
11
12namespace rtp::client
13{
14
16 : _registry(registry)
17 {
18 }
19
21 -> std::expected<ecs::Entity, Error>
22 {
23 auto e = _registry.spawn();
24 if (!e) {
25 return std::unexpected{e.error()};
26 }
27 auto entity = e.value();
28
29 _registry.add<ecs::components::Transform>(entity, t.position,
30 t.rotation, t.scale);
31
32 if (t.withVelocity) {
33 _registry.add<ecs::components::Velocity>(entity, t.velocity);
34 }
35
36 // Apply custom sprite if exists
37 auto sprite = t.sprite;
38 auto& customizer = SpriteCustomizer::getInstance();
39
40 // Try to map entity name from template tag or common sprite names
41 std::string entityKey;
42
43 // First, check if template has a specific tag (for bullets, etc.)
44 if (!t.tag.empty()) {
45 log::debug("EntityBuilder: Checking tag '{}' for entity '{}'", t.tag, t.id);
46 }
47
48 if (t.tag == "player_bullet") {
49 entityKey = "player_shot_6";
50 log::info("EntityBuilder: Mapped player_bullet to player_shot_6");
51 } else if (t.tag == "enemy_bullet") {
52 entityKey = "enemy_shot_6";
53 log::info("EntityBuilder: Mapped enemy_bullet to enemy_shot_6");
54 } else if (t.tag == "boomerang_bullet") {
55 entityKey = "shot_1";
56 log::info("EntityBuilder: Mapped boomerang_bullet to shot_1");
57 } else if (t.tag == "player_ship") {
58 entityKey = "player_ship";
59 log::info("EntityBuilder: Mapped player_ship to player_ship");
60 } else if (sprite.texturePath.find("r-typesheet1.gif") != std::string::npos) {
61 if (sprite.rectLeft == 101 && sprite.rectTop == 3) {
62 entityKey = "player_ship";
63 } else if (sprite.rectLeft == 134 && sprite.rectTop == 18) {
64 entityKey = "shot_insane";
65 } else if (sprite.rectLeft == 2 && sprite.rectTop == 51) {
66 entityKey = "effect_1";
67 } else if (sprite.rectLeft == 215 && sprite.rectTop == 85) {
68 entityKey = "shot_1";
69 } else if (sprite.rectLeft == 232 && sprite.rectTop == 103) {
70 entityKey = "shot_2";
71 } else if (sprite.rectLeft == 200 && sprite.rectTop == 121) {
72 entityKey = "shot_3";
73 } else if (sprite.rectLeft == 168 && sprite.rectTop == 137) {
74 entityKey = "shot_4";
75 } else if (sprite.rectLeft == 104 && sprite.rectTop == 171) {
76 entityKey = "shot_5";
77 } else if (sprite.rectLeft == 211 && sprite.rectTop == 276) {
78 entityKey = "effect_2";
79 } else if (sprite.rectLeft == 72 && sprite.rectTop == 296) {
80 entityKey = "effect_3";
81 }
82 } else if (sprite.texturePath.find("r-typesheet2.gif") != std::string::npos) {
83 if (sprite.rectLeft == 159 && sprite.rectTop == 35) {
84 entityKey = "enemy_1";
85 } else if (sprite.rectLeft == 300 && sprite.rectTop == 58) {
86 entityKey = "shot_6";
87 } else if (sprite.rectLeft == 300 && sprite.rectTop == 71) {
88 entityKey = "enemy_2";
89 } else if (sprite.rectLeft == 266 && sprite.rectTop == 94) {
90 entityKey = "shot_7";
91 } else if (sprite.rectLeft == 101 && sprite.rectTop == 118) {
92 entityKey = "effect_4";
93 } else if (sprite.rectLeft == 157 && sprite.rectTop == 316) {
94 entityKey = "effect_5";
95 }
96 } else if (sprite.texturePath.find("r-typesheet3.gif") != std::string::npos) {
97 // Power-ups from r-typesheet3.gif
98 if (sprite.rectLeft == 0 && sprite.rectTop == 0) {
99 entityKey = "power_up_heal";
100 } else if (sprite.rectLeft == 64 && sprite.rectTop == 0) {
101 entityKey = "power_up_double";
102 } else if (sprite.rectLeft == 128 && sprite.rectTop == 0) {
103 entityKey = "power_up_shield";
104 }
105 } else if (sprite.texturePath.find("r-typesheet39.gif") != std::string::npos) {
106 if (sprite.rectLeft == 33 && sprite.rectTop == 1) {
107 entityKey = "boss_ship";
108 } else if (sprite.rectLeft == 1 && sprite.rectTop == 72) {
109 entityKey = "boss_shield";
110 }
111 }
112
113 if (!entityKey.empty()) {
114 log::info("EntityBuilder: entityKey='{}', hasCustomSprite={}",
115 entityKey, customizer.hasCustomSprite(entityKey));
116 }
117
118 bool hasActiveCustomization = false;
119 if (!entityKey.empty() && customizer.hasCustomSprite(entityKey)) {
120 int left = sprite.rectLeft;
121 int top = sprite.rectTop;
122 sprite.texturePath = customizer.getSpriteInfo(
123 entityKey,
124 sprite.texturePath,
125 left,
126 top,
127 sprite.rectWidth,
128 sprite.rectHeight
129 );
130 sprite.rectLeft = left;
131 sprite.rectTop = top;
132 hasActiveCustomization = true;
133 }
134
135 _registry.add<ecs::components::Sprite>(entity, sprite);
136
137 // Only disable animation if we actually applied a custom sprite
138 if (t.withAnimation && !hasActiveCustomization) {
139 _registry.add<ecs::components::Animation>(entity, t.animation);
140 }
141
142 if (t.withParallax) {
143 _registry.add<ecs::components::ParallaxLayer>(entity,
144 t.parallax);
145 }
146
147 return entity;
148 }
149
151 {
152 _registry.kill(entity);
153 }
154
156 {
157 if (auto arr = _registry.get<ecs::components::Transform>(); arr) {
158 auto &sa = arr->get();
159 if (entity < sa.size() && sa.has(entity)) {
160 auto &tr = sa[entity];
161 tr.position = t.position;
162 tr.rotation = t.rotation;
163 tr.scale = t.scale;
164 }
165 }
166
167 if (t.withVelocity) {
168 if (auto arr = _registry.get<ecs::components::Velocity>();
169 arr) {
170 auto &sa = arr->get();
171 if (entity < sa.size() && sa.has(entity)) {
172 sa[entity] = t.velocity;
173 }
174 }
175 }
176
177 if (auto arr = _registry.get<ecs::components::Sprite>(); arr) {
178 auto &sa = arr->get();
179 if (entity < sa.size() && sa.has(entity)) {
180 sa[entity] = t.sprite;
181 }
182 }
183
184 if (t.withAnimation) {
185 if (auto arr = _registry.get<ecs::components::Animation>();
186 arr) {
187 auto &sa = arr->get();
188 if (entity < sa.size() && sa.has(entity)) {
189 sa[entity] = t.animation;
190 }
191 }
192 }
193 }
194}
void update(ecs::Entity entity, const EntityTemplate &t)
void kill(ecs::Entity entity)
EntityBuilder(ecs::Registry &registry)
auto spawn(const EntityTemplate &t) -> std::expected< ecs::Entity, Error >
static SpriteCustomizer & getInstance()
Get the singleton instance.
Represents an entity in the ECS (Entity-Component-System) architecture.
Definition Entity.hpp:63
void kill(Entity entity)
Definition Registry.cpp:73
auto get(this const Self &self) -> std::expected< std::reference_wrapper< ConstLike< Self, SparseArray< T > > >, rtp::Error >
R-Type client namespace.
void info(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log an informational message.
void debug(LogFmt< std::type_identity_t< Args >... > fmt, Args &&...args) noexcept
Log a debug message.
ecs::components::Velocity velocity
Initial velocity.
Vec2f position
Spawn position.
ecs::components::Animation animation
Initial animation data.
bool withAnimation
Whether to add Animation component.
float rotation
Spawn rotation.
bool withVelocity
Whether to add Velocity component.
ecs::components::Sprite sprite
Sprite data.
Component representing an animation.
Definition Animation.hpp:17
Tag component indicating that an entity should loop its position when it exits the screen (infinite s...
Component representing a sprite.
Definition Sprite.hpp:21
Component representing position, rotation, and scale of an entity.
Definition Transform.hpp:23
Component representing a 2D velocity.
Definition Velocity.hpp:17