-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbouncy.c
163 lines (141 loc) · 5.01 KB
/
bouncy.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
#include <SDL2/SDL.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_video.h>
#include <stdio.h>
#include <stdlib.h>
#define SCREEN_WIDTH 1200
#define SCREEN_HEIGHT 300
#define SCREEN_LEFT_BORDER 0
#define SCREEN_TOP_BORDER 0
#define BIG_RECT_WIDTH 100
#define BIG_RECT_HEIGHT 100
#define BIG_RECT_MASS 10
#define BIG_RECT_INITIAL_VEL_SCALAR 1
#define BIG_RECT_INITIAL_DIRECTION 1
#define SMALL_RECT_WIDTH 100
#define SMALL_RECT_HEIGHT 100
#define SMALL_RECT_MASS 1
#define SMALL_RECT_INITIAL_VEL_SCALAR 0
#define SMALL_RECT_INITIAL_DIRECTION 1
int collision_counter = 0;
typedef struct SIM_Rect {
SDL_Rect shape; // x, y, w, h
int mass;
int width;
int height;
int direction;
float velocity;
} SIM_Rect;
void apply_bound_collisions(SIM_Rect *rect);
void apply_collisions(SIM_Rect *rect_a, SIM_Rect *rect_b);
float solve_for_va2(int ma, int mb, float va1, float vb1);
float solve_for_vb2(int ma, int mb, float va1, float vb1);
void print_square_info(SIM_Rect *rect);
int main(int argc, char *argv[]) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
return 1;
}
SDL_Window *window =
SDL_CreateWindow("Tacks", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
SCREEN_WIDTH, SCREEN_HEIGHT, 0);
if (window == NULL) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
return 1;
}
SDL_Surface *surface = SDL_GetWindowSurface(window);
SIM_Rect big_rect;
big_rect.shape = (SDL_Rect){SCREEN_WIDTH - BIG_RECT_WIDTH, 0, BIG_RECT_WIDTH,
BIG_RECT_HEIGHT};
big_rect.width = BIG_RECT_WIDTH;
big_rect.height = BIG_RECT_HEIGHT;
big_rect.mass = BIG_RECT_MASS;
big_rect.direction = BIG_RECT_INITIAL_DIRECTION;
big_rect.velocity = BIG_RECT_INITIAL_VEL_SCALAR;
SIM_Rect small_rect;
small_rect.shape = (SDL_Rect){SMALL_RECT_WIDTH + 100, 0, SMALL_RECT_WIDTH,
SMALL_RECT_HEIGHT};
small_rect.width = SMALL_RECT_WIDTH;
small_rect.height = SMALL_RECT_HEIGHT;
small_rect.mass = SMALL_RECT_MASS;
small_rect.direction = SMALL_RECT_INITIAL_DIRECTION;
small_rect.velocity = SMALL_RECT_INITIAL_VEL_SCALAR;
while (1) {
SDL_Event event;
if (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
break;
}
}
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0, 0, 0));
small_rect.shape.x += small_rect.direction * small_rect.velocity;
big_rect.shape.x += big_rect.direction * big_rect.velocity;
apply_bound_collisions(&big_rect);
apply_bound_collisions(&small_rect);
apply_collisions(&small_rect, &big_rect);
SDL_FillRect(surface, &(big_rect.shape),
SDL_MapRGB(surface->format, 150, 0, 255));
SDL_FillRect(surface, &(small_rect.shape),
SDL_MapRGB(surface->format, 255, 0, 0));
SDL_UpdateWindowSurface(window);
SDL_Delay(5);
}
SDL_UpdateWindowSurface(window);
}
void apply_collisions(SIM_Rect *rect_a, SIM_Rect *rect_b) {
if (rect_a->shape.x + rect_a->width >= rect_b->shape.x &&
rect_a->shape.x + rect_a->width <= rect_b->shape.x + rect_b->width ||
rect_b->shape.x + rect_b->width >= rect_a->shape.x &&
rect_b->shape.x + rect_b->width <= rect_a->shape.x + rect_a->width) {
float a_initial_v = rect_a->direction * rect_a->velocity;
float b_initial_v = rect_b->direction * rect_b->velocity;
float va_ans =
solve_for_va2(rect_a->mass, rect_b->mass, a_initial_v, b_initial_v);
if (va_ans < 0) {
rect_a->direction = -1;
rect_a->velocity = fabs(va_ans);
} else {
rect_a->direction = 1;
rect_a->velocity = fabs(va_ans);
}
float vb_ans =
solve_for_vb2(rect_a->mass, rect_b->mass, a_initial_v, b_initial_v);
if (vb_ans < 0) {
rect_b->direction = -1;
rect_b->velocity = fabs(vb_ans);
} else {
rect_b->direction = 1;
rect_b->velocity = fabs(vb_ans);
}
printf("collisions : %d\n", ++collision_counter);
}
}
void apply_bound_collisions(SIM_Rect *rect) {
if (rect->shape.x + rect->width >= SCREEN_WIDTH && rect->direction > 0) {
printf("first if \n");
print_square_info(rect);
rect->direction = -1;
rect->shape.x = SCREEN_WIDTH - rect->width - 1;
print_square_info(rect);
}
if (rect->shape.x <= SCREEN_LEFT_BORDER && rect->direction < 0) {
printf("second if \n");
print_square_info(rect);
rect->direction = 1;
rect->shape.x = SCREEN_LEFT_BORDER + 1;
print_square_info(rect);
}
}
float solve_for_va2(int ma, int mb, float va1, float vb1) {
return ((float)(ma - mb) / (ma + mb)) * va1 +
((float)2 * mb / (ma + mb)) * vb1;
}
float solve_for_vb2(int ma, int mb, float va1, float vb1) {
return ((float)(2 * ma) / (ma + mb)) * va1 +
((float)(mb - ma) / (ma + mb)) * vb1;
}
void print_square_info(SIM_Rect *rect) {
printf("x: %d, y: %d, w: %d, h: %d, m: %d, v: %f, d: %d\n", rect->shape.x,
rect->shape.y, rect->shape.w, rect->shape.h, rect->mass,
rect->velocity, rect->direction);
}