aboutsummaryrefslogtreecommitdiff
path: root/collision_system.c
blob: 68e3b09967335b17910e001139df9a84bbd4d756 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#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];

	player_take_damage(&world->player, 1);
	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