-
Notifications
You must be signed in to change notification settings - Fork 0
/
body.c
202 lines (160 loc) · 4.46 KB
/
body.c
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "body.h"
#include <stdio.h>
typedef struct body {
List *points;
double mass;
double direction;
double radius;
RGBColor color;
Vector velocity;
Vector force;
Vector impulse;
double elasticity;
double angular_velocity;
Vector centroid;
void *info;
SDL_Surface *image;
FreeFunc info_freer;
bool remove;
int depth;
SDL_Texture *texture;
} Body;
Body *body_init(List *shape, double mass, RGBColor color) {
return body_init_with_info(shape, mass, color, NULL, NULL);
}
Body *body_init_with_info(List *shape, double mass, RGBColor color,
void *info, FreeFunc info_freer) {
Body *body = malloc(sizeof(Body));
assert(body);
body->points = shape;
body->mass = mass;
body->color = color;
body->direction = 0;
body->radius = 0;
body->elasticity = 1;
body->angular_velocity = 0;
body->remove = 0;
body->depth = 0;
body->info = info;
body->info_freer = info_freer;
body->velocity = VEC_ZERO;
body->force = VEC_ZERO;
body->impulse = VEC_ZERO;
body->centroid = polygon_centroid(body->points);
body->image = NULL;
body->texture = NULL;
return body;
}
void body_free(Body *body) {
list_free(body->points);
SDL_FreeSurface(body->image);
if (body->info_freer) { body->info_freer(body->info); }
free(body);
}
void body_set_image(Body *body, const char *filename) {
SDL_Surface *image = IMG_Load(filename);
body->image = image;
}
SDL_Surface *body_get_image(Body *body) {
return body->image;
}
void body_set_texture(Body *body, SDL_Texture *texture) {
body->texture = texture;
}
SDL_Texture *body_get_texture(Body *body) {
return body->texture;
}
List *body_get_shape(Body *body) {
List *copy = list_init(list_size(body->points), free);
for (size_t i = 0; i < list_size(body->points); i++) {
list_add(copy, vmalloc(*((Vector *)list_get(body->points, i))));
}
return copy;
}
Vector body_get_centroid(Body *body) {
return body->centroid;
}
double body_get_direction(Body *body) {
return body->direction;
}
double body_get_mass(Body *body) {
return body->mass;
}
double body_get_radius(Body *body) {
return body->radius;
}
Vector body_get_velocity(Body *body) {
return body->velocity;
}
RGBColor body_get_color(Body *body) {
return body->color;
}
void *body_get_info(Body *body) {
return body->info;
}
void body_set_info(Body *body, void *inf){
body->info = inf;
}
void body_set_color(Body *body, RGBColor color) {
body->color = color;
}
void body_set_radius(Body *body, double radius) {
body->radius = radius;
}
void body_vec_accelerate(Body *body, Vector v){
body->velocity.x = body->velocity.x + v.x;
body->velocity.y = body->velocity.y + v.y;
}
void body_double_accelerate(Body *body, double d){
body_vec_accelerate(body, vec_rotate((Vector){d, 0}, body->direction));
}
void body_set_centroid(Body *body, Vector x) {
polygon_translate(body->points, vec_subtract(x, body_get_centroid(body)));
body->centroid = x;
}
void body_set_velocity(Body *body, Vector v) {
body->velocity = v;
}
void body_add_force(Body *body, Vector force){
body->force = vec_add(body->force, force);
}
void body_set_force(Body *body, Vector force){
body->force = force;
}
Vector body_get_force(Body *body) {
return body->force;
}
void body_set_depth(Body *body, int depth){
body->depth = depth;
}
int body_get_depth(Body *body) {
return body->depth;
}
Vector body_get_impulse(Body *body) {
return body->impulse;
}
void body_add_impulse(Body *body, Vector impulse) {
body->impulse = vec_add(body->impulse, impulse);
}
void body_set_rotation(Body *body, double angle) {
polygon_rotate(body->points, angle - body->direction, polygon_centroid(body->points));
body->direction = angle;
}
void body_tick(Body *body, double dt) {
Vector old_vel = body->velocity;
body_vec_accelerate(body, vec_multiply(1.0 / body->mass, body->impulse));
body_vec_accelerate(body, vec_multiply(dt / body->mass, body->force));
Vector ave_vel = vec_multiply(0.5, vec_add(old_vel, body->velocity));
body_set_centroid(body, vec_add(body->centroid, vec_multiply(dt, ave_vel)));
body->impulse = VEC_ZERO;
body->force = VEC_ZERO;
}
void body_remove(Body *body) {
body->remove = 1;
}
bool body_is_removed(Body *body) {
return body->remove;
}
double body_distance(Body *b1, Body * b2){
return vec_len(vec_subtract(body_get_centroid(b1), body_get_centroid(b2)));
}