-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcardoom.ino
More file actions
208 lines (176 loc) · 8.17 KB
/
cardoom.ino
File metadata and controls
208 lines (176 loc) · 8.17 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
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
203
204
205
206
207
208
#include <Arduino.h>
#include <Wire.h>
#include "SSD1306Wire.h"
#define OLED_ADDR 0x3C
#define W 128 // Oled display width
#define H 64 // Oled display height
#define ANGLE_MAX 360
#define SCALE_FACTOR 1000
#define MAP_S 10
#define FOV 60
#define GAME_VERSION "v3.1_release" // Only for log
SSD1306Wire display(OLED_ADDR, SDA, SCL);
// World map (0 - free; 1 - wall)
const byte M[] = {
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,0,0,1,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,0,1,1,0,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1
};
const int16_t COS_TAB[360] PROGMEM = {
256, 256, 255, 255, 254, 253, 252, 250, 249, 247, 245, 243, 240, 238, 235, 232,
229, 226, 223, 219, 215, 212, 208, 204, 200, 195, 191, 186, 182, 177, 172, 167,
162, 157, 152, 146, 141, 136, 130, 125, 119, 114, 108, 102, 97, 91, 85, 79,
73, 67, 61, 55, 49, 43, 37, 31, 25, 19, 13, 7, 1, -5, -11, -17,
-23, -29, -35, -41, -47, -53, -59, -65, -71, -77, -83, -89, -95, -101, -107, -113,
-119, -124, -130, -135, -141, -146, -151, -156, -161, -166, -171, -176, -181, -185, -190, -194,
-199, -203, -207, -211, -215, -219, -222, -226, -229, -232, -235, -238, -241, -243, -246, -248,
-250, -252, -253, -255, -256, -256, -255, -255, -254, -253, -252, -250, -249, -247, -245, -243,
-240, -238, -235, -232, -229, -226, -223, -219, -215, -212, -208, -204, -200, -195, -191, -186,
-182, -177, -172, -167, -162, -157, -152, -146, -141, -136, -130, -125, -119, -114, -108, -102,
-97, -91, -85, -79, -73, -67, -61, -55, -49, -43, -37, -31, -25, -19, -13, -7,
-1, 5, 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89,
95, 101, 107, 113, 119, 124, 130, 135, 141, 146, 151, 156, 161, 166, 171, 176,
181, 185, 190, 194, 199, 203, 207, 211, 215, 219, 222, 226, 229, 232, 235, 238,
241, 243, 246, 248, 250, 252, 253, 255, 256, 256, 255, 255, 254, 253, 252, 250,
249, 247, 245, 243, 240, 238, 235, 232, 229, 226, 223, 219, 215, 212, 208, 204,
200, 195, 191, 186, 182, 177, 172, 167, 162, 157, 152, 146, 141, 136, 130, 125,
119, 114, 108, 102, 97, 91, 85, 79, 73, 67, 61, 55, 49, 43, 37, 31,
25, 19, 13, 7, 1, -5, -11, -17, -23, -29, -35, -41, -47, -53, -59, -65,
-71, -77, -83, -89, -95, -101, -107, -113, -119, -124, -130, -135, -141, -146, -151, -156,
-161, -166, -171, -176, -181, -185, -190, -194, -199, -203, -207, -211, -215, -219, -222, -226,
-229, -232, -235, -238, -241, -243, -246, -248, -250, -252, -253, -255
};
const int16_t SIN_TAB[360] PROGMEM = {
0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 45, 49, 53, 58, 62, 66,
70, 74, 78, 82, 86, 90, 94, 98, 102, 106, 109, 113, 116, 120, 123, 126,
130, 133, 136, 139, 142, 145, 148, 151, 154, 156, 159, 161, 164, 166, 168, 170,
172, 174, 176, 178, 180, 182, 183, 185, 186, 187, 188, 190, 191, 192, 193, 194,
195, 195, 196, 197, 197, 198, 198, 198, 199, 199, 199, 199, 199, 199, 199, 198,
198, 197, 197, 196, 195, 195, 194, 193, 192, 191, 190, 188, 187, 186, 185, 183,
182, 180, 178, 176, 174, 172, 170, 168, 166, 164, 161, 159, 156, 154, 151, 148,
145, 142, 139, 136, 133, 130, 126, 123, 120, 116, 113, 109, 106, 102, 98, 94,
90, 86, 82, 78, 74, 70, 66, 62, 58, 53, 49, 45, 40, 36, 31, 27,
22, 18, 13, 9, 4, 0, -4, -9, -13, -18, -22, -27, -31, -36, -40, -45,
-49, -53, -58, -62, -66, -70, -74, -78, -82, -86, -90, -94, -98, -102, -106, -109,
-113, -116, -120, -123, -126, -130, -133, -136, -139, -142, -145, -148, -151, -154, -156, -159,
-161, -164, -166, -168, -170, -172, -174, -176, -178, -180, -182, -183, -185, -186, -187, -188,
-190, -191, -192, -193, -194, -195, -195, -196, -197, -197, -198, -198, -198, -199, -199, -199,
-199, -199, -199, -198, -198, -197, -197, -196, -195, -195, -194, -193, -192, -191, -190, -188,
-187, -186, -185, -183, -182, -180, -178, -176, -174, -172, -170, -168, -166, -164, -161, -159,
-156, -154, -151, -148, -145, -142, -139, -136, -133, -130, -126, -123, -120, -116, -113, -109,
-106, -102, -98, -94, -90, -86, -82, -78, -74, -70, -66, -62, -58, -53, -49, -45,
-40, -36, -31, -27, -22, -18, -13, -9, -4, 0, 4, 9, 13, 18, 22, 27,
31, 36, 40, 45, 49, 53, 58, 62, 66, 70, 74, 78, 82, 86, 90, 94,
98, 102, 106, 109, 113, 116, 120, 123, 126, 130, 133, 136, 139, 142, 145, 148,
151, 154, 156, 159, 161, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 183
};
long Px = 2500, Py = 2500;
int Pa = 90;
int speed = 300;
int turn_speed = 5;
int weapon_frame = 0;
void game_clear() {
display.clear();
}
void game_draw_vline(int x, int y1, int y2, bool color) {
display.setColor(color ? WHITE : BLACK);
display.drawLine(x, max(0, y1), x, min(H - 1, y2));
}
int16_t get_cos(int angle) { return COS_TAB[angle % ANGLE_MAX]; }
int16_t get_sin(int angle) { return SIN_TAB[angle % ANGLE_MAX]; }
void handle_input() {
long cos_pa = get_cos(Pa);
long sin_pa = get_sin(Pa);
if (digitalRead(2) == LOW) { Px += (cos_pa * speed) >> 8; Py += (sin_pa * speed) >> 8; }
if (digitalRead(3) == LOW) { Px -= (cos_pa * speed) >> 8; Py -= (sin_pa * speed) >> 8; }
if (digitalRead(4) == LOW) { Pa = (Pa - turn_speed + ANGLE_MAX) % ANGLE_MAX; }
if (digitalRead(5) == LOW) { Pa = (Pa + turn_speed) % ANGLE_MAX; }
if (digitalRead(6) == LOW && weapon_frame == 0) { weapon_frame = 1; }
int map_x = Px / SCALE_FACTOR;
int map_y = Py / SCALE_FACTOR;
if (map_x >= 0 && map_x < MAP_S && map_y >= 0 && map_y < MAP_S && M[map_y * MAP_S + map_x] == 1) {
Px -= (cos_pa * speed) >> 8;
Py -= (sin_pa * speed) >> 8;
}
}
void draw_weapon(int frame) {
int wx1 = W / 2 - 10, wx2 = W / 2 + 10;
int wy1 = H - 5, wy2 = H - 20;
int offset = 0;
if (frame > 0) {
if (frame <= 3) offset = 4;
else if (frame <= 6) offset = 2;
else offset = 1;
}
display.setColor(WHITE);
display.drawLine(W/2, wy2 + offset, W/2, wy1 + offset);
display.drawLine(W/2 + 1, wy2 + offset, W/2 + 1, wy1 + offset);
for(int x = wx1; x <= wx2; x++) {
display.setPixel(x, wy1 + offset);
display.setPixel(x, wy1 + offset + 1);
}
}
void setup() {
Serial.begin(115200);
delay(100);
Serial.println(F("================================"));
Serial.println(F(" Raycaster Cardoom Game "));
Serial.print (F(" Version: "));
Serial.println(F(GAME_VERSION));
Serial.println(F(" Build: " __DATE__ " " __TIME__));
Serial.println(F("================================"));
display.init();
display.flipScreenVertically();
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
}
void loop() {
handle_input();
game_clear();
display.setColor(WHITE);
display.fillRect(0, H / 2, W, H / 2);
for (int x = 0; x < W; x++) {
int ray_angle = Pa - (FOV / 2) + (x * FOV / W);
ray_angle = ray_angle % ANGLE_MAX;
if (ray_angle < 0) ray_angle += ANGLE_MAX;
long cos_r = get_cos(ray_angle);
long sin_r = get_sin(ray_angle);
long dist = 0;
long Rx = Px, Ry = Py;
bool hit = false;
while (dist < 15000 && !hit) {
Rx += (cos_r * 50) >> 8;
Ry += (sin_r * 50) >> 8;
dist += 50;
if (M[(Ry / SCALE_FACTOR) * MAP_S + (Rx / SCALE_FACTOR)] == 1) {
hit = true;
}
}
if (hit) {
int corr_angle = (Pa - ray_angle) % ANGLE_MAX;
if (corr_angle < 0) corr_angle += ANGLE_MAX;
long cos_corr = get_cos(corr_angle);
long real_dist = (dist * cos_corr) >> 8;
int wall_h = (real_dist > 0) ? (150000 / real_dist) : H;
wall_h = min(wall_h, H);
int y_start = H / 2 - wall_h / 2;
int y_end = H / 2 + wall_h / 2;
game_draw_vline(x, y_start, y_end, (x % 2 == 0));
}
}
if (weapon_frame > 0) {
weapon_frame = (weapon_frame + 1) % 10;
}
draw_weapon(weapon_frame);
display.display();
}