#include #include #include #include #include #define BULLET_SIZE 2 #define ENTITY_SIZE 16 static void render(void); static void update(float delta); static void process_events(void); static int checkcollision(float pos1[2], float size1[2], float pos2[2], float size2[2]); typedef struct { float pos[2]; float vel[2]; } Body; typedef struct { Body body; } Player; typedef struct { Body body; bool active; } Ghost; typedef struct { Body body; float time; bool active; } Bullet; static SDL_Window *window; static SDL_Renderer *renderer; static bool running; static Uint64 old_ticks, new_ticks; static Player player; static Ghost ghosts[1024]; static Bullet bullet[1024]; static float camera_x, camera_y; static bool shot; static int shotx, shoty; extern char map_data[]; extern int map_width, map_height; int main() { if(!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) { fprintf(stderr, "SDL_Init(): %s\n", SDL_GetError()); return 1; } if(!SDL_CreateWindowAndRenderer("window", 800, 600, SDL_WINDOW_OPENGL, &window, &renderer)) { fprintf(stderr, "SDL_CreateWindowAndRenderer: %s\n", SDL_GetError()); return -1; } for(int i = 0; i < 10; i++) { ghosts[i].active = 1; ghosts[i].body.pos[0] = rand() % 800; ghosts[i].body.pos[1] = rand() % 600; } running = true; old_ticks = SDL_GetTicksNS(); while(running) { double delta; process_events(); new_ticks = SDL_GetTicksNS(); delta = (new_ticks - old_ticks) / 1000000000.0; old_ticks = new_ticks; update(delta); render(); SDL_RenderPresent(renderer); } SDL_DestroyWindow(window); SDL_Quit(); return 0; } void render(void) { { float plx, ply, minx, miny, maxx, maxy; plx = player.body.pos[0] - camera_x; ply = player.body.pos[1] - camera_y; minx = plx - 80; miny = ply - 80; maxx = plx + 80; maxy = ply + 80; if(minx < 0) camera_x += minx; if(miny < 0) camera_y += miny; if(maxx > 800) camera_x += (maxx - 800); if(maxy > 600) camera_y += (maxy - 600); } SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); SDL_RenderClear(renderer); SDL_SetRenderDrawColor(renderer, 0xAA, 0xAA, 0xAA, 0xFF); for(int y = 0; y < map_height; y++) for(int x = 0; x < map_width; x++) { if(!map_data[x + map_width * y]) continue; SDL_RenderFillRect(renderer, &(SDL_FRect) { .x = 2 * ENTITY_SIZE * x - ENTITY_SIZE - camera_x, .y = 2 * ENTITY_SIZE * y - ENTITY_SIZE - camera_y, .w = 2.0 * ENTITY_SIZE, .h = 2.0 * ENTITY_SIZE, }); } SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); SDL_RenderRect(renderer, &(SDL_FRect){ .x = player.body.pos[0] - ENTITY_SIZE - camera_x, .y = player.body.pos[1] - ENTITY_SIZE - camera_y, .w = ENTITY_SIZE * 2.0, .h = ENTITY_SIZE * 2.0 }); for(int i = 0; i < 1024; i++) { if(!ghosts[i].active) continue; SDL_SetRenderDrawColor(renderer, 0xAA, 0xAA, 0xAA, 0xFF); SDL_RenderRect(renderer, &(SDL_FRect){ .x = ghosts[i].body.pos[0] - ENTITY_SIZE - camera_x, .y = ghosts[i].body.pos[1] - ENTITY_SIZE - camera_y, .w = ENTITY_SIZE * 2.0, .h = ENTITY_SIZE * 2.0 }); } for(int i = 0; i < 1024; i++) { if(!bullet[i].active) continue; SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0x00, 0xFF); SDL_RenderRect(renderer, &(SDL_FRect){ .x = bullet[i].body.pos[0] - BULLET_SIZE - camera_x, .y = bullet[i].body.pos[1] - BULLET_SIZE - camera_y, .w = BULLET_SIZE * 2.0, .h = BULLET_SIZE * 2.0 }); } } void update(float delta) { # define SPEED 100 const _Bool *kstate = SDL_GetKeyboardState(NULL); player.body.vel[0] = 0; player.body.vel[1] = 0; if(kstate[SDL_SCANCODE_W]) player.body.vel[1] -= SPEED; if(kstate[SDL_SCANCODE_A]) player.body.vel[0] -= SPEED; if(kstate[SDL_SCANCODE_S]) player.body.vel[1] += SPEED; if(kstate[SDL_SCANCODE_D]) player.body.vel[0] += SPEED; if(shot) { shot = false; int i; float dx = shotx - player.body.pos[0]; float dy = shoty - player.body.pos[1]; float dd = sqrtf(dx * dx + dy * dy); dx /= dd; dy /= dd; for(i = 0; i < 1024 && bullet[i].active; i++) ; if(i < 1024) { bullet[i].time = 0.5; bullet[i].body.vel[0] = dx * SPEED * 5.0; bullet[i].body.vel[1] = dy * SPEED * 5.0; bullet[i].body.pos[0] = player.body.pos[0]; bullet[i].body.pos[1] = player.body.pos[1]; bullet[i].active = true; } } for(int i = 0; i < 1024; i++) { if(!bullet[i].active) continue; for(int j = 0; j < 1024; j++) { if(!ghosts[j].active) continue; int r = checkcollision( bullet[i].body.pos, (float[2]){ BULLET_SIZE, BULLET_SIZE }, ghosts[j].body.pos, (float[2]){ ENTITY_SIZE, ENTITY_SIZE } ); if(r) { ghosts[j].active = false; bullet[i].active = false; } } } for(int i = 0; i < 1024; i++) { if(!ghosts[i].active) continue; float vx = 0, vy = 0; float dx = player.body.pos[0] - ghosts[i].body.pos[0]; float dy = player.body.pos[1] - ghosts[i].body.pos[1]; float dd = sqrtf(dx * dx + dy * dy); dx /= dd; dy /= dd; vx += dx * SPEED; vy += dy * SPEED; for(int j = 0; j < 1024; j++) { if(!ghosts[j].active || i == j) continue; float dx = ghosts[j].body.pos[0] - ghosts[i].body.pos[0]; float dy = ghosts[j].body.pos[1] - ghosts[i].body.pos[1]; float dd = sqrtf(dx * dx + dy * dy); dx /= dd; dy /= dd; if(dd < 40) { vx -= dx * 100; vy -= dy * 100; } } ghosts[i].body.vel[0] = vx; ghosts[i].body.vel[1] = vy; } player.body.pos[0] += player.body.vel[0] * delta; player.body.pos[1] += player.body.vel[1] * delta; for(int i = 0; i < 1024; i++) { if(!ghosts[i].active) continue; ghosts[i].body.pos[0] += ghosts[i].body.vel[0] * delta; ghosts[i].body.pos[1] += ghosts[i].body.vel[1] * delta; } for(int i = 0; i < 1024; i++) { if(!bullet[i].active) continue; bullet[i].time -= delta; if(bullet[i].time <= 0.0) { bullet[i].active = false; continue; } bullet[i].body.pos[0] += delta * bullet[i].body.vel[0]; bullet[i].body.pos[1] += delta * bullet[i].body.vel[1]; } } void process_events() { SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_EVENT_QUIT: running = false; break; case SDL_EVENT_MOUSE_BUTTON_DOWN: shot = true; shotx = event.button.x + camera_x; shoty = event.button.y + camera_y; break; } } } int checkcollision(float p1[2], float s1[2], float p2[2], float s2[2]) { float p[2], s[2], minx, miny, maxx, maxy; for(int i = 0; i < 2; i++) { s[i] = s1[i] + s2[i]; p[i] = p1[i] - p2[i]; } minx = p[0] - s[0]; maxx = p[0] + s[0]; miny = p[1] - s[1]; maxy = p[1] + s[1]; return minx < 0 && maxx > 0 && miny < 0 && maxy > 0; }