aboutsummaryrefslogtreecommitdiff
path: root/collision_system.c
diff options
context:
space:
mode:
Diffstat (limited to 'collision_system.c')
-rw-r--r--collision_system.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/collision_system.c b/collision_system.c
new file mode 100644
index 0000000..abd5dc9
--- /dev/null
+++ b/collision_system.c
@@ -0,0 +1,105 @@
+#ifndef systems_h
+#define systems_h
+
+#include "config.h"
+#include "fx.h"
+#include "rect.h"
+#include "world.h"
+
+static void handle_bullet_vs_player(
+ World* world,
+ Entity bullet,
+ Entity player
+) {
+ const CPosition* pos;
+
+ pos = &world->positions[bullet];
+
+ destroy_entity(world, bullet);
+ new_enemy_bullet_explosion(world, pos->x, pos->y);
+}
+
+static void handle_bullet_vs_enemy(
+ World* world,
+ Entity bullet,
+ Entity enemy
+) {
+ CEnemy* e;
+
+ e = &world->enemies[enemy];
+ e->hp--;
+ destroy_entity(world, bullet);
+}
+
+static void handle(World* world, Entity a, Entity b) {
+ unsigned ab, bb;
+
+ ab = world->bitmask[a];
+ bb = world->bitmask[b];
+
+ if ((ab & ctype_enemy_bullet) && (bb & ctype_player)) {
+ handle_bullet_vs_player(world, a, b);
+ return;
+ }
+
+ if ((ab & ctype_player) && (bb & ctype_enemy_bullet)) {
+ handle_bullet_vs_player(world, b, a);
+ return;
+ }
+
+ if ((ab & ctype_player_bullet) && (bb & ctype_enemy)) {
+ handle_bullet_vs_enemy(world, a, b);
+ return;
+ }
+
+ if ((ab & ctype_enemy) && (bb & ctype_player_bullet)) {
+ handle_bullet_vs_enemy(world, b, a);
+ return;
+ }
+}
+
+void collision_system(World* world) {
+ int i, j, p0x, p0y;
+ unsigned bits;
+ const CPosition* pos0, * pos1;
+ const CCollider* col0, * col1;
+
+ for (i = 0; i < world->entity_count; i++) {
+ bits = world->bitmask[i];
+ if (
+ !(bits & ctype_collider) ||
+ !(bits & ctype_position)
+ ) { continue; }
+
+ pos0 = &world->positions[i];
+ col0 = &world->colliders[i];
+ p0x = pos0->x + col0->x;
+ p0y = pos0->y + col0->y;
+
+ for (j = i + 1; j < world->entity_count; j++) {
+ bits = world->bitmask[j];
+ if (
+ !(bits & ctype_collider) ||
+ !(bits & ctype_position)
+ ) { continue; }
+
+ pos1 = &world->positions[j];
+ col1 = &world->colliders[j];
+
+ if (rects_overlap2(
+ p0x,
+ p0y,
+ col0->w,
+ col0->h,
+ pos1->x + col1->x,
+ pos1->y + col1->y,
+ col1->w,
+ col1->h
+ )) {
+ handle(world, i, j);
+ }
+ }
+ }
+}
+
+#endif