diff options
Diffstat (limited to 'contrib/SDL-3.2.8/examples/demo/02-woodeneye-008/woodeneye-008.c')
| -rw-r--r-- | contrib/SDL-3.2.8/examples/demo/02-woodeneye-008/woodeneye-008.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/examples/demo/02-woodeneye-008/woodeneye-008.c b/contrib/SDL-3.2.8/examples/demo/02-woodeneye-008/woodeneye-008.c new file mode 100644 index 0000000..b97b06a --- /dev/null +++ b/contrib/SDL-3.2.8/examples/demo/02-woodeneye-008/woodeneye-008.c | |||
| @@ -0,0 +1,480 @@ | |||
| 1 | /* | ||
| 2 | * This code is public domain. Feel free to use it for any purpose! | ||
| 3 | */ | ||
| 4 | |||
| 5 | #define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ | ||
| 6 | #include <SDL3/SDL.h> | ||
| 7 | #include <SDL3/SDL_main.h> | ||
| 8 | |||
| 9 | #define MAP_BOX_SCALE 16 | ||
| 10 | #define MAP_BOX_EDGES_LEN (12 + MAP_BOX_SCALE * 2) | ||
| 11 | #define MAX_PLAYER_COUNT 4 | ||
| 12 | #define CIRCLE_DRAW_SIDES 32 | ||
| 13 | #define CIRCLE_DRAW_SIDES_LEN (CIRCLE_DRAW_SIDES + 1) | ||
| 14 | |||
| 15 | typedef struct { | ||
| 16 | SDL_MouseID mouse; | ||
| 17 | SDL_KeyboardID keyboard; | ||
| 18 | double pos[3]; | ||
| 19 | double vel[3]; | ||
| 20 | unsigned int yaw; | ||
| 21 | int pitch; | ||
| 22 | float radius, height; | ||
| 23 | unsigned char color[3]; | ||
| 24 | unsigned char wasd; | ||
| 25 | } Player; | ||
| 26 | |||
| 27 | typedef struct { | ||
| 28 | SDL_Window *window; | ||
| 29 | SDL_Renderer *renderer; | ||
| 30 | int player_count; | ||
| 31 | Player players[MAX_PLAYER_COUNT]; | ||
| 32 | float edges[MAP_BOX_EDGES_LEN][6]; | ||
| 33 | } AppState; | ||
| 34 | |||
| 35 | static const struct { | ||
| 36 | const char *key; | ||
| 37 | const char *value; | ||
| 38 | } extended_metadata[] = { | ||
| 39 | { SDL_PROP_APP_METADATA_URL_STRING, "https://examples.libsdl.org/SDL3/demo/02-woodeneye-008/" }, | ||
| 40 | { SDL_PROP_APP_METADATA_CREATOR_STRING, "SDL team" }, | ||
| 41 | { SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Placed in the public domain" }, | ||
| 42 | { SDL_PROP_APP_METADATA_TYPE_STRING, "game" } | ||
| 43 | }; | ||
| 44 | |||
| 45 | static int whoseMouse(SDL_MouseID mouse, const Player players[], int players_len) | ||
| 46 | { | ||
| 47 | int i; | ||
| 48 | for (i = 0; i < players_len; i++) { | ||
| 49 | if (players[i].mouse == mouse) return i; | ||
| 50 | } | ||
| 51 | return -1; | ||
| 52 | } | ||
| 53 | |||
| 54 | static int whoseKeyboard(SDL_KeyboardID keyboard, const Player players[], int players_len) | ||
| 55 | { | ||
| 56 | int i; | ||
| 57 | for (i = 0; i < players_len; i++) { | ||
| 58 | if (players[i].keyboard == keyboard) return i; | ||
| 59 | } | ||
| 60 | return -1; | ||
| 61 | } | ||
| 62 | |||
| 63 | static void shoot(int shooter, Player players[], int players_len) | ||
| 64 | { | ||
| 65 | int i, j; | ||
| 66 | double x0 = players[shooter].pos[0]; | ||
| 67 | double y0 = players[shooter].pos[1]; | ||
| 68 | double z0 = players[shooter].pos[2]; | ||
| 69 | double bin_rad = SDL_PI_D / 2147483648.0; | ||
| 70 | double yaw_rad = bin_rad * players[shooter].yaw; | ||
| 71 | double pitch_rad = bin_rad * players[shooter].pitch; | ||
| 72 | double cos_yaw = SDL_cos( yaw_rad); | ||
| 73 | double sin_yaw = SDL_sin( yaw_rad); | ||
| 74 | double cos_pitch = SDL_cos(pitch_rad); | ||
| 75 | double sin_pitch = SDL_sin(pitch_rad); | ||
| 76 | double vx = -sin_yaw*cos_pitch; | ||
| 77 | double vy = sin_pitch; | ||
| 78 | double vz = -cos_yaw*cos_pitch; | ||
| 79 | for (i = 0; i < players_len; i++) { | ||
| 80 | if (i == shooter) continue; | ||
| 81 | Player *target = &(players[i]); | ||
| 82 | int hit = 0; | ||
| 83 | for (j = 0; j < 2; j++) { | ||
| 84 | double r = target->radius; | ||
| 85 | double h = target->height; | ||
| 86 | double dx = target->pos[0] - x0; | ||
| 87 | double dy = target->pos[1] - y0 + (j == 0 ? 0 : r - h); | ||
| 88 | double dz = target->pos[2] - z0; | ||
| 89 | double vd = vx*dx + vy*dy + vz*dz; | ||
| 90 | double dd = dx*dx + dy*dy + dz*dz; | ||
| 91 | double vv = vx*vx + vy*vy + vz*vz; | ||
| 92 | double rr = r * r; | ||
| 93 | if (vd < 0) continue; | ||
| 94 | if (vd * vd >= vv * (dd - rr)) hit += 1; | ||
| 95 | } | ||
| 96 | if (hit) { | ||
| 97 | target->pos[0] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256; | ||
| 98 | target->pos[1] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256; | ||
| 99 | target->pos[2] = (double)(MAP_BOX_SCALE * (SDL_rand(256) - 128)) / 256; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | static void update(Player *players, int players_len, Uint64 dt_ns) | ||
| 105 | { | ||
| 106 | int i; | ||
| 107 | for (i = 0; i < players_len; i++) { | ||
| 108 | Player *player = &players[i]; | ||
| 109 | double rate = 6.0; | ||
| 110 | double time = (double)dt_ns * 1e-9; | ||
| 111 | double drag = SDL_exp(-time * rate); | ||
| 112 | double diff = 1.0 - drag; | ||
| 113 | double mult = 60.0; | ||
| 114 | double grav = 25.0; | ||
| 115 | double yaw = (double)player->yaw; | ||
| 116 | double rad = yaw * SDL_PI_D / 2147483648.0; | ||
| 117 | double cos = SDL_cos(rad); | ||
| 118 | double sin = SDL_sin(rad); | ||
| 119 | unsigned char wasd = player->wasd; | ||
| 120 | double dirX = (wasd & 8 ? 1.0 : 0.0) - (wasd & 2 ? 1.0 : 0.0); | ||
| 121 | double dirZ = (wasd & 4 ? 1.0 : 0.0) - (wasd & 1 ? 1.0 : 0.0); | ||
| 122 | double norm = dirX * dirX + dirZ * dirZ; | ||
| 123 | double accX = mult * (norm == 0 ? 0 : ( cos*dirX + sin*dirZ) / SDL_sqrt(norm)); | ||
| 124 | double accZ = mult * (norm == 0 ? 0 : (-sin*dirX + cos*dirZ) / SDL_sqrt(norm)); | ||
| 125 | double velX = player->vel[0]; | ||
| 126 | double velY = player->vel[1]; | ||
| 127 | double velZ = player->vel[2]; | ||
| 128 | player->vel[0] -= velX * diff; | ||
| 129 | player->vel[1] -= grav * time; | ||
| 130 | player->vel[2] -= velZ * diff; | ||
| 131 | player->vel[0] += diff * accX / rate; | ||
| 132 | player->vel[2] += diff * accZ / rate; | ||
| 133 | player->pos[0] += (time - diff/rate) * accX / rate + diff * velX / rate; | ||
| 134 | player->pos[1] += -0.5 * grav * time * time + velY * time; | ||
| 135 | player->pos[2] += (time - diff/rate) * accZ / rate + diff * velZ / rate; | ||
| 136 | double scale = (double)MAP_BOX_SCALE; | ||
| 137 | double bound = scale - player->radius; | ||
| 138 | double posX = SDL_max(SDL_min(bound, player->pos[0]), -bound); | ||
| 139 | double posY = SDL_max(SDL_min(bound, player->pos[1]), player->height - scale); | ||
| 140 | double posZ = SDL_max(SDL_min(bound, player->pos[2]), -bound); | ||
| 141 | if (player->pos[0] != posX) player->vel[0] = 0; | ||
| 142 | if (player->pos[1] != posY) player->vel[1] = (wasd & 16) ? 8.4375 : 0; | ||
| 143 | if (player->pos[2] != posZ) player->vel[2] = 0; | ||
| 144 | player->pos[0] = posX; | ||
| 145 | player->pos[1] = posY; | ||
| 146 | player->pos[2] = posZ; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | static void drawCircle(SDL_Renderer *renderer, float r, float x, float y) | ||
| 151 | { | ||
| 152 | float ang; | ||
| 153 | SDL_FPoint points[CIRCLE_DRAW_SIDES_LEN]; | ||
| 154 | int i; | ||
| 155 | for (i = 0; i < CIRCLE_DRAW_SIDES_LEN; i++) { | ||
| 156 | ang = 2.0f * SDL_PI_F * (float)i / (float)CIRCLE_DRAW_SIDES; | ||
| 157 | points[i].x = x + r * SDL_cosf(ang); | ||
| 158 | points[i].y = y + r * SDL_sinf(ang); | ||
| 159 | } | ||
| 160 | SDL_RenderLines(renderer, (const SDL_FPoint*)&points, CIRCLE_DRAW_SIDES_LEN); | ||
| 161 | } | ||
| 162 | |||
| 163 | static void drawClippedSegment( | ||
| 164 | SDL_Renderer *renderer, | ||
| 165 | float ax, float ay, float az, | ||
| 166 | float bx, float by, float bz, | ||
| 167 | float x, float y, float z, float w) | ||
| 168 | { | ||
| 169 | if (az >= -w && bz >= -w) return; | ||
| 170 | float dx = ax - bx; | ||
| 171 | float dy = ay - by; | ||
| 172 | if (az > -w) { | ||
| 173 | float t = (-w - bz) / (az - bz); | ||
| 174 | ax = bx + dx * t; | ||
| 175 | ay = by + dy * t; | ||
| 176 | az = -w; | ||
| 177 | } else if (bz > -w) { | ||
| 178 | float t = (-w - az) / (bz - az); | ||
| 179 | bx = ax - dx * t; | ||
| 180 | by = ay - dy * t; | ||
| 181 | bz = -w; | ||
| 182 | } | ||
| 183 | ax = -z * ax / az; | ||
| 184 | ay = -z * ay / az; | ||
| 185 | bx = -z * bx / bz; | ||
| 186 | by = -z * by / bz; | ||
| 187 | SDL_RenderLine(renderer, x + ax, y - ay, x + bx, y - by); | ||
| 188 | } | ||
| 189 | |||
| 190 | static char debug_string[32]; | ||
| 191 | static void draw(SDL_Renderer *renderer, const float (*edges)[6], const Player players[], int players_len) | ||
| 192 | { | ||
| 193 | int w, h, i, j, k; | ||
| 194 | if (!SDL_GetRenderOutputSize(renderer, &w, &h)) { | ||
| 195 | return; | ||
| 196 | } | ||
| 197 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE); | ||
| 198 | SDL_RenderClear(renderer); | ||
| 199 | if (players_len > 0) { | ||
| 200 | float wf = (float)w; | ||
| 201 | float hf = (float)h; | ||
| 202 | int part_hor = players_len > 2 ? 2 : 1; | ||
| 203 | int part_ver = players_len > 1 ? 2 : 1; | ||
| 204 | float size_hor = wf / ((float)part_hor); | ||
| 205 | float size_ver = hf / ((float)part_ver); | ||
| 206 | for (i = 0; i < players_len; i++) { | ||
| 207 | const Player *player = &players[i]; | ||
| 208 | float mod_x = (float)(i % part_hor); | ||
| 209 | float mod_y = (float)(i / part_hor); | ||
| 210 | float hor_origin = (mod_x + 0.5f) * size_hor; | ||
| 211 | float ver_origin = (mod_y + 0.5f) * size_ver; | ||
| 212 | float cam_origin = (float)(0.5 * SDL_sqrt(size_hor * size_hor + size_ver * size_ver)); | ||
| 213 | float hor_offset = mod_x * size_hor; | ||
| 214 | float ver_offset = mod_y * size_ver; | ||
| 215 | SDL_Rect rect; | ||
| 216 | rect.x = (int)hor_offset; | ||
| 217 | rect.y = (int)ver_offset; | ||
| 218 | rect.w = (int)size_hor; | ||
| 219 | rect.h = (int)size_ver; | ||
| 220 | SDL_SetRenderClipRect(renderer, &rect); | ||
| 221 | double x0 = player->pos[0]; | ||
| 222 | double y0 = player->pos[1]; | ||
| 223 | double z0 = player->pos[2]; | ||
| 224 | double bin_rad = SDL_PI_D / 2147483648.0; | ||
| 225 | double yaw_rad = bin_rad * player->yaw; | ||
| 226 | double pitch_rad = bin_rad * player->pitch; | ||
| 227 | double cos_yaw = SDL_cos( yaw_rad); | ||
| 228 | double sin_yaw = SDL_sin( yaw_rad); | ||
| 229 | double cos_pitch = SDL_cos(pitch_rad); | ||
| 230 | double sin_pitch = SDL_sin(pitch_rad); | ||
| 231 | double mat[9] = { | ||
| 232 | cos_yaw , 0, -sin_yaw , | ||
| 233 | sin_yaw*sin_pitch, cos_pitch, cos_yaw*sin_pitch, | ||
| 234 | sin_yaw*cos_pitch, -sin_pitch, cos_yaw*cos_pitch | ||
| 235 | }; | ||
| 236 | SDL_SetRenderDrawColor(renderer, 64, 64, 64, 255); | ||
| 237 | for (k = 0; k < MAP_BOX_EDGES_LEN; k++) { | ||
| 238 | const float *line = edges[k]; | ||
| 239 | float ax = (float)(mat[0] * (line[0] - x0) + mat[1] * (line[1] - y0) + mat[2] * (line[2] - z0)); | ||
| 240 | float ay = (float)(mat[3] * (line[0] - x0) + mat[4] * (line[1] - y0) + mat[5] * (line[2] - z0)); | ||
| 241 | float az = (float)(mat[6] * (line[0] - x0) + mat[7] * (line[1] - y0) + mat[8] * (line[2] - z0)); | ||
| 242 | float bx = (float)(mat[0] * (line[3] - x0) + mat[1] * (line[4] - y0) + mat[2] * (line[5] - z0)); | ||
| 243 | float by = (float)(mat[3] * (line[3] - x0) + mat[4] * (line[4] - y0) + mat[5] * (line[5] - z0)); | ||
| 244 | float bz = (float)(mat[6] * (line[3] - x0) + mat[7] * (line[4] - y0) + mat[8] * (line[5] - z0)); | ||
| 245 | drawClippedSegment(renderer, ax, ay, az, bx, by, bz, hor_origin, ver_origin, cam_origin, 1); | ||
| 246 | } | ||
| 247 | for (j = 0; j < players_len; j++) { | ||
| 248 | if (i == j) continue; | ||
| 249 | const Player *target = &players[j]; | ||
| 250 | SDL_SetRenderDrawColor(renderer, target->color[0], target->color[1], target->color[2], 255); | ||
| 251 | for (k = 0; k < 2; k++) { | ||
| 252 | double rx = target->pos[0] - player->pos[0]; | ||
| 253 | double ry = target->pos[1] - player->pos[1] + (target->radius - target->height) * (float)k; | ||
| 254 | double rz = target->pos[2] - player->pos[2]; | ||
| 255 | double dx = mat[0] * rx + mat[1] * ry + mat[2] * rz; | ||
| 256 | double dy = mat[3] * rx + mat[4] * ry + mat[5] * rz; | ||
| 257 | double dz = mat[6] * rx + mat[7] * ry + mat[8] * rz; | ||
| 258 | double r_eff = target->radius * cam_origin / dz; | ||
| 259 | if (!(dz < 0)) continue; | ||
| 260 | drawCircle(renderer, (float)(r_eff), (float)(hor_origin - cam_origin*dx/dz), (float)(ver_origin + cam_origin*dy/dz)); | ||
| 261 | } | ||
| 262 | } | ||
| 263 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
| 264 | SDL_RenderLine(renderer, hor_origin, ver_origin-10, hor_origin, ver_origin+10); | ||
| 265 | SDL_RenderLine(renderer, hor_origin-10, ver_origin, hor_origin+10, ver_origin); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | SDL_SetRenderClipRect(renderer, 0); | ||
| 269 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | ||
| 270 | SDL_RenderDebugText(renderer, 0, 0, debug_string); | ||
| 271 | SDL_RenderPresent(renderer); | ||
| 272 | } | ||
| 273 | |||
| 274 | static void initPlayers(Player *players, int len) | ||
| 275 | { | ||
| 276 | int i; | ||
| 277 | for (i = 0; i < len; i++) { | ||
| 278 | players[i].pos[0] = 8.0 * (i & 1 ? -1.0 : 1.0); | ||
| 279 | players[i].pos[1] = 0; | ||
| 280 | players[i].pos[2] = 8.0 * (i & 1 ? -1.0 : 1.0) * (i & 2 ? -1.0 : 1.0); | ||
| 281 | players[i].vel[0] = 0; | ||
| 282 | players[i].vel[1] = 0; | ||
| 283 | players[i].vel[2] = 0; | ||
| 284 | players[i].yaw = 0x20000000 + (i & 1 ? 0x80000000 : 0) + (i & 2 ? 0x40000000 : 0); | ||
| 285 | players[i].pitch = -0x08000000; | ||
| 286 | players[i].radius = 0.5f; | ||
| 287 | players[i].height = 1.5f; | ||
| 288 | players[i].wasd = 0; | ||
| 289 | players[i].mouse = 0; | ||
| 290 | players[i].keyboard = 0; | ||
| 291 | players[i].color[0] = (1 << (i / 2)) & 2 ? 0 : 0xff; | ||
| 292 | players[i].color[1] = (1 << (i / 2)) & 1 ? 0 : 0xff; | ||
| 293 | players[i].color[2] = (1 << (i / 2)) & 4 ? 0 : 0xff; | ||
| 294 | players[i].color[0] = (i & 1) ? players[i].color[0] : ~players[i].color[0]; | ||
| 295 | players[i].color[1] = (i & 1) ? players[i].color[1] : ~players[i].color[1]; | ||
| 296 | players[i].color[2] = (i & 1) ? players[i].color[2] : ~players[i].color[2]; | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | static void initEdges(int scale, float (*edges)[6], int edges_len) | ||
| 301 | { | ||
| 302 | int i, j; | ||
| 303 | const float r = (float)scale; | ||
| 304 | const int map[24] = { | ||
| 305 | 0,1 , 1,3 , 3,2 , 2,0 , | ||
| 306 | 7,6 , 6,4 , 4,5 , 5,7 , | ||
| 307 | 6,2 , 3,7 , 0,4 , 5,1 | ||
| 308 | }; | ||
| 309 | for(i = 0; i < 12; i++) { | ||
| 310 | for (j = 0; j < 3; j++) { | ||
| 311 | edges[i][j+0] = (map[i*2+0] & (1 << j) ? r : -r); | ||
| 312 | edges[i][j+3] = (map[i*2+1] & (1 << j) ? r : -r); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | for(i = 0; i < scale; i++) { | ||
| 316 | float d = (float)(i * 2); | ||
| 317 | for (j = 0; j < 2; j++) { | ||
| 318 | edges[i+12][3*j+0] = j ? r : -r; | ||
| 319 | edges[i+12][3*j+1] = -r; | ||
| 320 | edges[i+12][3*j+2] = d-r; | ||
| 321 | edges[i+12+scale][3*j+0] = d-r; | ||
| 322 | edges[i+12+scale][3*j+1] = -r; | ||
| 323 | edges[i+12+scale][3*j+2] = j ? r : -r; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
| 328 | SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) | ||
| 329 | { | ||
| 330 | if (!SDL_SetAppMetadata("Example splitscreen shooter game", "1.0", "com.example.woodeneye-008")) { | ||
| 331 | return SDL_APP_FAILURE; | ||
| 332 | } | ||
| 333 | int i; | ||
| 334 | for (i = 0; i < SDL_arraysize(extended_metadata); i++) { | ||
| 335 | if (!SDL_SetAppMetadataProperty(extended_metadata[i].key, extended_metadata[i].value)) { | ||
| 336 | return SDL_APP_FAILURE; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | AppState *as = SDL_calloc(1, sizeof(AppState)); | ||
| 341 | if (!as) { | ||
| 342 | return SDL_APP_FAILURE; | ||
| 343 | } else { | ||
| 344 | *appstate = as; | ||
| 345 | } | ||
| 346 | |||
| 347 | if (!SDL_Init(SDL_INIT_VIDEO)) { | ||
| 348 | return SDL_APP_FAILURE; | ||
| 349 | } | ||
| 350 | if (!SDL_CreateWindowAndRenderer("examples/demo/woodeneye-008", 640, 480, 0, &as->window, &as->renderer)) { | ||
| 351 | return SDL_APP_FAILURE; | ||
| 352 | } | ||
| 353 | |||
| 354 | as->player_count = 1; | ||
| 355 | initPlayers(as->players, MAX_PLAYER_COUNT); | ||
| 356 | initEdges(MAP_BOX_SCALE, as->edges, MAP_BOX_EDGES_LEN); | ||
| 357 | debug_string[0] = 0; | ||
| 358 | |||
| 359 | SDL_SetRenderVSync(as->renderer, false); | ||
| 360 | SDL_SetWindowRelativeMouseMode(as->window, true); | ||
| 361 | SDL_SetHintWithPriority(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1", SDL_HINT_OVERRIDE); | ||
| 362 | return SDL_APP_CONTINUE; | ||
| 363 | } | ||
| 364 | |||
| 365 | SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) | ||
| 366 | { | ||
| 367 | AppState *as = appstate; | ||
| 368 | Player *players = as->players; | ||
| 369 | int player_count = as->player_count; | ||
| 370 | int i; | ||
| 371 | switch (event->type) { | ||
| 372 | case SDL_EVENT_QUIT: | ||
| 373 | return SDL_APP_SUCCESS; | ||
| 374 | break; | ||
| 375 | case SDL_EVENT_MOUSE_REMOVED: | ||
| 376 | for (i = 0; i < player_count; i++) { | ||
| 377 | if (players[i].mouse == event->mdevice.which) { | ||
| 378 | players[i].mouse = 0; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | break; | ||
| 382 | case SDL_EVENT_KEYBOARD_REMOVED: | ||
| 383 | for (i = 0; i < player_count; i++) { | ||
| 384 | if (players[i].keyboard == event->kdevice.which) { | ||
| 385 | players[i].keyboard = 0; | ||
| 386 | } | ||
| 387 | } | ||
| 388 | break; | ||
| 389 | case SDL_EVENT_MOUSE_MOTION: { | ||
| 390 | SDL_MouseID id = event->motion.which; | ||
| 391 | int index = whoseMouse(id, players, player_count); | ||
| 392 | if (index >= 0) { | ||
| 393 | players[index].yaw -= ((int)event->motion.xrel) * 0x00080000; | ||
| 394 | players[index].pitch = SDL_max(-0x40000000, SDL_min(0x40000000, players[index].pitch - ((int)event->motion.yrel) * 0x00080000)); | ||
| 395 | } else if (id) { | ||
| 396 | for (i = 0; i < MAX_PLAYER_COUNT; i++) { | ||
| 397 | if (players[i].mouse == 0) { | ||
| 398 | players[i].mouse = id; | ||
| 399 | as->player_count = SDL_max(as->player_count, i + 1); | ||
| 400 | break; | ||
| 401 | } | ||
| 402 | } | ||
| 403 | } | ||
| 404 | break; | ||
| 405 | } | ||
| 406 | case SDL_EVENT_MOUSE_BUTTON_DOWN: { | ||
| 407 | SDL_MouseID id = event->button.which; | ||
| 408 | int index = whoseMouse(id, players, player_count); | ||
| 409 | if (index >= 0) { | ||
| 410 | shoot(index, players, player_count); | ||
| 411 | } | ||
| 412 | break; | ||
| 413 | } | ||
| 414 | case SDL_EVENT_KEY_DOWN: { | ||
| 415 | SDL_Keycode sym = event->key.key; | ||
| 416 | SDL_KeyboardID id = event->key.which; | ||
| 417 | int index = whoseKeyboard(id, players, player_count); | ||
| 418 | if (index >= 0) { | ||
| 419 | if (sym == SDLK_W) players[index].wasd |= 1; | ||
| 420 | if (sym == SDLK_A) players[index].wasd |= 2; | ||
| 421 | if (sym == SDLK_S) players[index].wasd |= 4; | ||
| 422 | if (sym == SDLK_D) players[index].wasd |= 8; | ||
| 423 | if (sym == SDLK_SPACE) players[index].wasd |= 16; | ||
| 424 | } else if (id) { | ||
| 425 | for (i = 0; i < MAX_PLAYER_COUNT; i++) { | ||
| 426 | if (players[i].keyboard == 0) { | ||
| 427 | players[i].keyboard = id; | ||
| 428 | as->player_count = SDL_max(as->player_count, i + 1); | ||
| 429 | break; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | } | ||
| 433 | break; | ||
| 434 | } | ||
| 435 | case SDL_EVENT_KEY_UP: { | ||
| 436 | SDL_Keycode sym = event->key.key; | ||
| 437 | SDL_KeyboardID id = event->key.which; | ||
| 438 | if (sym == SDLK_ESCAPE) return SDL_APP_SUCCESS; | ||
| 439 | int index = whoseKeyboard(id, players, player_count); | ||
| 440 | if (index >= 0) { | ||
| 441 | if (sym == SDLK_W) players[index].wasd &= 30; | ||
| 442 | if (sym == SDLK_A) players[index].wasd &= 29; | ||
| 443 | if (sym == SDLK_S) players[index].wasd &= 27; | ||
| 444 | if (sym == SDLK_D) players[index].wasd &= 23; | ||
| 445 | if (sym == SDLK_SPACE) players[index].wasd &= 15; | ||
| 446 | } | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | } | ||
| 450 | return SDL_APP_CONTINUE; | ||
| 451 | } | ||
| 452 | |||
| 453 | SDL_AppResult SDL_AppIterate(void *appstate) | ||
| 454 | { | ||
| 455 | AppState *as = appstate; | ||
| 456 | static Uint64 accu = 0; | ||
| 457 | static Uint64 last = 0; | ||
| 458 | static Uint64 past = 0; | ||
| 459 | Uint64 now = SDL_GetTicksNS(); | ||
| 460 | Uint64 dt_ns = now - past; | ||
| 461 | update(as->players, as->player_count, dt_ns); | ||
| 462 | draw(as->renderer, (const float (*)[6])as->edges, as->players, as->player_count); | ||
| 463 | if (now - last > 999999999) { | ||
| 464 | last = now; | ||
| 465 | SDL_snprintf(debug_string, sizeof(debug_string), "%" SDL_PRIu64 " fps", accu); | ||
| 466 | accu = 0; | ||
| 467 | } | ||
| 468 | past = now; | ||
| 469 | accu += 1; | ||
| 470 | Uint64 elapsed = SDL_GetTicksNS() - now; | ||
| 471 | if (elapsed < 999999) { | ||
| 472 | SDL_DelayNS(999999 - elapsed); | ||
| 473 | } | ||
| 474 | return SDL_APP_CONTINUE; | ||
| 475 | } | ||
| 476 | |||
| 477 | void SDL_AppQuit(void *appstate, SDL_AppResult result) | ||
| 478 | { | ||
| 479 | SDL_free(appstate); // just free the memory, SDL will clean up the window/renderer for us. | ||
| 480 | } \ No newline at end of file | ||
