-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathphysics.cpp
More file actions
154 lines (136 loc) · 3.7 KB
/
physics.cpp
File metadata and controls
154 lines (136 loc) · 3.7 KB
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
#include "physics.hpp"
#define FRAMERATE 8.333
extern uint8_t walls[GAME_HEIGHT][GAME_WIDTH];
extern uint8_t colorBufs[3][GAME_HEIGHT][GAME_WIDTH][3];
extern int colorPos;
/*
* Physics buffer -- is drawn to by the physics engine. This is double
* buffered, so that the rendering thread can retrieve frames easily.
*/
uint8_t physicsBuffer[2][GAME_HEIGHT][GAME_WIDTH][3];
int physicsPos = 0;
pthread_mutex_t physicsMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t physicsSignal = PTHREAD_COND_INITIALIZER;
int physicsUpdate = 0;
enum {
EMPTY = 0,
SAND,
WALL
};
static int pixels[GAME_HEIGHT][GAME_WIDTH];
static int drawCount = 0;
void resetPhysics() {
printf("Physics reset!\n");
memset(pixels, EMPTY, sizeof pixels);
drawCount = 0;
}
void swapPhysicsBuffers() {
physicsPos = (physicsPos + 1) % 2;
physicsUpdate = 0;
}
static void move(int x, int y) {
static int dx[] = {0, 1, -1, -1, 1};
static int dy[] = {1, 1, 1, 0, 0};
switch(pixels[y][x]) {
/* Sand propogation */
case SAND:
if(rand() % 100 < 95) {
for(int i = 0; i < 5; i++) {
if(pixels[y + dy[i]][x + dx[i]] == EMPTY) {
pixels[y + dy[i]][x + dx[i]] = SAND;
pixels[y][x] = EMPTY;
break;
}
}
}
break;
default:
break;
}
}
static void update() {
/* Flow new particles down */
int k = GAME_WIDTH / 4;
for(int i = 0; i < 4; i++) {
for(int a = 1; a < 3; a++) {
for(int j = -10; j <= 10; j++) {
if(!(rand() % 10)) pixels[0][i * k + (k / 2) + j] = SAND;
}
}
}
/* Update existing particles */
drawCount++;
if(drawCount & 1) {
for(int i = GAME_HEIGHT - 1; i >= 0; i--) {
for(int j = 1; j < GAME_WIDTH - 1; j++) move(j, i);
}
}
else {
for(int i = GAME_HEIGHT - 1; i >= 0; i--) {
for(int j = GAME_WIDTH - 1; j > 0; j--) move(j, i);
}
}
/* Correct for edges */
for(int i = 1; i < GAME_WIDTH - 1; i++) {
pixels[0][i] = EMPTY;
pixels[GAME_HEIGHT - 1][i] = EMPTY;
}
for(int i = 1; i < GAME_HEIGHT - 1; i++) {
pixels[i][0] = WALL;
pixels[i][GAME_WIDTH - 1] = WALL;
}
}
unsigned long simulate(unsigned long delta) {
/* Update walls. At the moment we just remove and replace them */
for(int i = 0; i < GAME_HEIGHT; i++) {
for(int j = 0; j < GAME_WIDTH; j++) {
if(pixels[i][j] == WALL && !walls[i][j]) pixels[i][j] = EMPTY;
else if(pixels[i][j] == EMPTY && walls[i][j]) pixels[i][j] = WALL;
}
}
for(int i = 0; i < GAME_HEIGHT; i++) {
for(int j = 0; j < GAME_WIDTH; j++) {
if(pixels[i][j] == SAND && walls[i][j]) {
int pos = i;
while(pos >= 0 && pixels[pos][j] != EMPTY) pos--;
if(pos >= 0) pixels[pos][j] = pixels[i][j];
pixels[i][j] = WALL;
}
}
}
/* Simulate sand */
while(delta >= FRAMERATE) {
update();
delta -= FRAMERATE;
}
pthread_mutex_lock(&physicsMutex);
memcpy(physicsBuffer[(physicsPos + 1) % 2], colorBufs[colorPos], sizeof physicsBuffer[physicsPos]);
/* Render sand / walls on top of buffer */
for(int i = 0; i < GAME_HEIGHT; i++) {
for(int j = 0; j < GAME_WIDTH; j++) {
if(!walls[i][j]) {
physicsBuffer[(physicsPos + 1) % 2][i][j][0] = 0;
physicsBuffer[(physicsPos + 1) % 2][i][j][1] = 0;
physicsBuffer[(physicsPos + 1) % 2][i][j][2] = 0;
}
switch(pixels[i][j]) {
case SAND:
physicsBuffer[(physicsPos + 1) % 2][i][j][0] = 255;
physicsBuffer[(physicsPos + 1) % 2][i][j][1] = 215;
physicsBuffer[(physicsPos + 1) % 2][i][j][2] = 0;
break;
case WALL:
//physicsBuffer[(physicsPos + 1) % 2][i][j][0] = 127;
//physicsBuffer[(physicsPos + 1) % 2][i][j][1] = 127;
//physicsBuffer[(physicsPos + 1) % 2][i][j][2] = 127;
break;
default:
break;
}
}
}
physicsUpdate++;
pthread_cond_signal(&physicsSignal);
pthread_mutex_unlock(&physicsMutex);
return delta;
}