]> git.lizzy.rs Git - nothing.git/blob - src/game/level/explosion.c
Merge pull request #821 from tsoding/814
[nothing.git] / src / game / level / explosion.c
1 #include <SDL2/SDL.h>
2 #include "system/stacktrace.h"
3
4 #include "explosion.h"
5 #include "math/rand.h"
6 #include "system/lt.h"
7 #include "system/nth_alloc.h"
8
9 #define EXPLOSION_PIECE_COUNT 20
10 #define EXPLOSION_PIECE_SIZE 20.0f
11
12 typedef struct Piece {
13     Point position;
14     float angle;
15     float angle_velocity;
16     Vec direction;
17     Triangle body;
18 } Piece;
19
20 struct Explosion
21 {
22     Lt *lt;
23
24     Vec position;
25     Color color;
26     float duration;
27     float time_passed;
28     Piece *pieces;
29 };
30
31 Explosion *create_explosion(Color color,
32                             float duration)
33 {
34     Lt *lt = create_lt();
35     if (lt == NULL) {
36         return NULL;
37     }
38
39     Explosion *explosion = PUSH_LT(lt, nth_calloc(1, sizeof(Explosion)), free);
40     if (explosion == NULL) {
41         RETURN_LT(lt, NULL);
42     }
43
44     explosion->lt = lt;
45     explosion->position = vec(0.0f, 0.0f);
46     explosion->color = color;
47     explosion->duration = duration;
48     explosion->time_passed = duration;
49
50     explosion->pieces = PUSH_LT(lt, nth_calloc(1, sizeof(Piece) * EXPLOSION_PIECE_COUNT), free);
51     if (explosion->pieces == NULL) {
52         RETURN_LT(lt, NULL);
53     }
54
55     return explosion;
56 }
57
58 void destroy_explosion(Explosion *explosion)
59 {
60     trace_assert(explosion);
61     RETURN_LT0(explosion->lt);
62 }
63
64 int explosion_render(const Explosion *explosion,
65                      Camera *camera)
66 {
67     trace_assert(explosion);
68     trace_assert(camera);
69
70     for (size_t i = 0; i < EXPLOSION_PIECE_COUNT; ++i) {
71         Color color = explosion->color;
72         color.a = fminf(1.0f, 4.0f - (float) explosion->time_passed / (float) explosion->duration * 4.0f);
73
74         if (camera_fill_triangle(
75                 camera,
76                 triangle_mat3x3_product(
77                     explosion->pieces[i].body,
78                     mat3x3_product(
79                         trans_mat(explosion->pieces[i].position.x,
80                                   explosion->pieces[i].position.y),
81                         rot_mat(explosion->pieces[i].angle))),
82                 color) < 0) {
83             return -1;
84         }
85     }
86
87     return 0;
88 }
89
90 int explosion_update(Explosion *explosion,
91                      float delta_time)
92 {
93     trace_assert(explosion);
94     trace_assert(delta_time > 0.0f);
95
96     if (explosion_is_done(explosion)) {
97         return 0;
98     }
99
100     explosion->time_passed = explosion->time_passed + delta_time;
101
102     for (size_t i = 0; i < EXPLOSION_PIECE_COUNT; ++i) {
103         vec_add(
104             &explosion->pieces[i].position,
105             vec_scala_mult(
106                 explosion->pieces[i].direction,
107                 delta_time));
108         explosion->pieces[i].angle = fmodf(
109             explosion->pieces[i].angle + explosion->pieces[i].angle_velocity * delta_time,
110             2.0f * PI);
111     }
112
113     return 0;
114 }
115
116 int explosion_is_done(const Explosion *explosion)
117 {
118     trace_assert(explosion);
119     return explosion->time_passed >= explosion->duration;
120 }
121
122 void explosion_start(Explosion *explosion,
123                      Vec position)
124 {
125     explosion->position = position;
126     explosion->time_passed = 0;
127
128     for (size_t i = 0; i < EXPLOSION_PIECE_COUNT; ++i) {
129         explosion->pieces[i].position = explosion->position;
130         explosion->pieces[i].angle = rand_float(2 * PI);
131         explosion->pieces[i].angle_velocity = rand_float(8.0f);
132         explosion->pieces[i].body = random_triangle(EXPLOSION_PIECE_SIZE);
133         explosion->pieces[i].direction = vec_from_polar(
134             rand_float_range(-PI, 0.0f),
135             rand_float_range(100.0f, 300.0f));
136     }
137 }