From a8ff0d19d27697c931315da9d59d623dd71ceae7 Mon Sep 17 00:00:00 2001 From: Juan Manuel Tomas Date: Wed, 26 Jan 2022 01:58:42 -0300 Subject: Extract terrain concept --- main.c | 102 +++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 40 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 9bcd467..539180a 100644 --- a/main.c +++ b/main.c @@ -26,6 +26,28 @@ typedef struct { int alive; } Projectile; +typedef struct { + float *mask; + int width; + int height; + int updated; +} Terrain; + +void PaintTerrain(Terrain *t, float x, float y, float color, float size) { + for (int j = y - size; j < y + size; j++) { + for (int i = x - size; i < x + size; i++) { + float dj = y - j; + float di = x - i; + if (i > 0 && i < t->width && j > 0 && j < t->height + && dj * dj + di * di <= size * size / 2) { + size_t index = i + j * t->width; + t->mask[index] = color; + } + } + } + t->updated = 1; +} + static inline double GetCurrentTimestamp() { return (double) SDL_GetTicks64() / 1000.0; } @@ -53,41 +75,31 @@ SDL_Texture *CreateTiledTexture(SDL_Renderer *context, const char *filename, int return texture; } -void PaintMask(float *mask, int width, int height, float x, float y, float color, float size) { - for (int j = y - size; j < y + size; j++) { - for (int i = x - size; i < x + size; i++) { - float dj = y - j; - float di = x - i; - if (i > 0 && i < width && j > 0 && j < height - && dj * dj + di * di <= size * size / 2) { - size_t index = i + j * width; - mask[index] = color; - } - } - } -} - void GameMain(SDL_Renderer *context) { SDL_Texture *background = CreateTiledTexture(context, "background.bmp", WINDOW_W, WINDOW_H); SDL_Texture *foreground = CreateTiledTexture(context, "foreground.bmp", WINDOW_W, WINDOW_H); SDL_SetTextureBlendMode(foreground, SDL_BLENDMODE_MOD); - SDL_Texture *terrain = SDL_CreateTexture(context, + SDL_Texture *terrain_texture = SDL_CreateTexture(context, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, WINDOW_W, WINDOW_H); - SDL_SetTextureBlendMode(terrain, SDL_BLENDMODE_BLEND); + SDL_SetTextureBlendMode(terrain_texture, SDL_BLENDMODE_BLEND); SDL_Texture *mask_texture = SDL_CreateTexture(context, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, WINDOW_W, WINDOW_H); - float *mask = calloc(WINDOW_W * WINDOW_H, sizeof(float)); + Terrain terrain = {0}; + terrain.width = WINDOW_W; + terrain.height = WINDOW_H; + terrain.mask = calloc(WINDOW_W * WINDOW_H, sizeof(float)); for (int i = 0; i < 100 * WINDOW_W; i++) { - mask[i] = 1.0; + terrain.mask[i] = 1.0; } + terrain.updated = 1; Cannon player = {0}; player.x = 100; @@ -100,15 +112,12 @@ void GameMain(SDL_Renderer *context) { int exit = 0; while (!exit) { - double new_t = GetCurrentTimestamp(); - double dt = (new_t - old_t) * 10; - old_t = new_t; - SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { exit = 1; - } else if (event.type == SDL_KEYDOWN && event.key.state == SDL_PRESSED && event.key.keysym.sym == SDLK_SPACE && !projectile.alive) { + } else if (event.type == SDL_KEYDOWN && event.key.state == SDL_PRESSED && + event.key.keysym.sym == SDLK_SPACE && !projectile.alive) { projectile.alive = 1; projectile.x = player.x; projectile.y = player.y; @@ -116,13 +125,20 @@ void GameMain(SDL_Renderer *context) { projectile.vx = cos(player.angle) * player.power; } } + int simulation_frames = 10; + while (simulation_frames > 0) { + simulation_frames--; + double new_t = GetCurrentTimestamp(); + double dt = (new_t - old_t); + old_t = new_t; + int mouse_x, mouse_y; Uint32 mouse_state = SDL_GetMouseState(&mouse_x, &mouse_y); float size = 20; if (mouse_state & SDL_BUTTON_LMASK) { - PaintMask(mask, WINDOW_W, WINDOW_H, mouse_x, WINDOW_H - mouse_y, 1.0, size); + PaintTerrain(&terrain, mouse_x, WINDOW_H - mouse_y, 1.0, size); } else if (mouse_state & SDL_BUTTON_RMASK) { - PaintMask(mask, WINDOW_W, WINDOW_H, mouse_x, WINDOW_H - mouse_y, 0.0, size); + PaintTerrain(&terrain, mouse_x, WINDOW_H - mouse_y, 0.0, size); } const Uint8 *keys = SDL_GetKeyboardState(0); @@ -136,6 +152,7 @@ void GameMain(SDL_Renderer *context) { player.angle += PI / 180 * dt; } if (keys[SDL_SCANCODE_S] && player.angle > 0) { + player.angle -= PI / 180 * dt; } @@ -143,11 +160,11 @@ void GameMain(SDL_Renderer *context) { player.y = WINDOW_H - 1; player.vy = 0; } - if (mask[(int)player.x + (int)player.y * WINDOW_W] == 0.0 && + if (terrain.mask[(int)player.x + (int)player.y * WINDOW_W] == 0.0 && player.y >= 0) { player.y += player.vy * dt; player.vy += GRAVITY * dt; - while (mask[(int)player.x + (int)player.y * WINDOW_W] != 0.0) { + while (terrain.mask[(int)player.x + (int)player.y * WINDOW_W] != 0.0) { player.y += 1; player.vy = 0; } @@ -156,45 +173,50 @@ void GameMain(SDL_Renderer *context) { if (projectile.alive) { if (projectile.y >= 0 && projectile.y < WINDOW_H && projectile.x >= 0 && projectile.x < WINDOW_W && - mask[(int)projectile.x + (int)projectile.y * WINDOW_W] == 0.0) { + terrain.mask[(int)projectile.x + (int)projectile.y * WINDOW_W] == 0.0) { projectile.x += projectile.vx * dt; projectile.y += projectile.vy * dt; projectile.vy += GRAVITY * dt; } else { projectile.alive = 0; - PaintMask(mask, WINDOW_W, WINDOW_H, projectile.x, projectile.y, 0.0, 40); + PaintTerrain(&terrain, projectile.x, projectile.y, 0.0, 40); } } - void *pixels; - int pitch; - SDL_LockTexture(mask_texture, 0, &pixels, &pitch); - Uint32 *p = (Uint32 *) pixels; - for (int j = 0; j < WINDOW_H; j++) { - for (int i = 0; i < WINDOW_W; i++) { - p[i + j * WINDOW_W] = mask[i + (WINDOW_H - j) * WINDOW_W] ? 0xffffffff : 0x00000000; + if (terrain.updated) { + void *pixels; + int pitch; + SDL_LockTexture(mask_texture, 0, &pixels, &pitch); + Uint32 *p = (Uint32 *) pixels; + for (int j = 0; j < WINDOW_H; j++) { + for (int i = 0; i < WINDOW_W; i++) { + p[i + j * WINDOW_W] = terrain.mask[i + (WINDOW_H - j) * WINDOW_W] ? 0xffffffff : 0x00000000; + } } + SDL_UnlockTexture(mask_texture); + terrain.updated = 0; + } } - SDL_UnlockTexture(mask_texture); SDL_SetRenderDrawColor(context, 40, 40, 40, 255); SDL_RenderClear(context); SDL_RenderCopy(context, background, 0, 0); - SDL_SetRenderTarget(context, terrain); + SDL_SetRenderTarget(context, terrain_texture); SDL_SetRenderDrawColor(context, 0, 0, 0, 0); SDL_RenderClear(context); SDL_RenderCopy(context, mask_texture, 0, 0); SDL_RenderCopy(context, foreground, 0, 0); SDL_SetRenderTarget(context, 0); - SDL_RenderCopy(context, terrain, 0, 0); + SDL_RenderCopy(context, terrain_texture, 0, 0); SDL_SetRenderDrawColor(context, 255, 0, 0, 255); SDL_Rect player_rect = {player.x - 5, WINDOW_H - player.y - 10, 10, 10 }; SDL_RenderFillRect(context, &player_rect); - SDL_RenderDrawLine(context, player.x, WINDOW_H - player.y, player.x + cos(player.angle) * 100, WINDOW_H - player.y - sin(player.angle) * 100); + SDL_RenderDrawLine(context, player.x, WINDOW_H - player.y, + player.x + cos(player.angle) * 100, WINDOW_H - player.y - sin(player.angle) * 100); if (projectile.alive) { SDL_SetRenderDrawColor(context, 0, 255, 0, 255); -- cgit v1.2.3