flappychik

Silly SDL2 game
git clone git://bsandro.tech/flappychik
Log | Files | Refs

commit 43077fd9a80eb52f92ba44cb532eeaff88d45e38
parent 9077f846501611f1de029fc430a3a6df72c2cbfa
Author: bsandro <email@bsandro.tech>
Date:   Sun, 29 May 2022 01:25:40 +0300

Actual gameplay - random columns, hitbox checking, score. Dirty but fun :)

Diffstat:
Mmain.c | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 78 insertions(+), 17 deletions(-)

diff --git a/main.c b/main.c @@ -18,9 +18,11 @@ #define GAME_FALL_ACCEL 0.85 // pixels per second^2 essentially #define GAME_BG_SCROLL_VELOCITY 0.3 #define GAME_SCROLL_VELOCITY 0.4 -#define GAME_COLUMN_WIDTH 80 +#define GAME_COLUMN_WIDTH 90 #define GAME_COLUMN_HEIGHT 200 +static float s_dpi_scale; + enum game_state_t { GAME_STATE_INIT, GAME_STATE_RUNNING, GAME_STATE_OVER }; struct sprite_t { @@ -42,6 +44,7 @@ struct game_t { int bg_x; SDL_Rect *columns; int columns_count; + int score; }; struct menu_t { @@ -49,16 +52,37 @@ struct menu_t { TTF_Font *font; SDL_Surface *surface; SDL_Texture *texture; + int score; }; +void place_column(SDL_Rect **columns, int count, SDL_Rect *column); +void init_columns(SDL_Rect **columns, int count); + +bool check_game_over(struct game_t *game) { + if (game->ship.rect.y >= game->scrH) { // falling beyond the playing area (screen) + return true; + } + + for (int i = 0; i < game->columns_count; ++i) { + SDL_Rect *column = game->columns + i; + if (SDL_HasIntersection(column, &game->ship.rect) == SDL_TRUE) { + return true; + } + } + + return false; +} + void draw_game(uint64_t ftime, struct game_t *game) { game->ship.velocity += game->ship.accel * ftime; game->ship.rect.y += (ftime * game->ship.velocity / 1000.0); int bg_offset = ftime * GAME_BG_SCROLL_VELOCITY; // background position offset game->bg_x = (game->bg_x - bg_offset) % game->bg.rect.w; // can be only %width max - if (game->ship.rect.y >= game->scrH) { // falling beyond the playing area (screen) + if (check_game_over(game)) { game->state = GAME_STATE_INIT; + init_columns(&game->columns, game->columns_count); + return; } // top border @@ -80,6 +104,15 @@ void draw_game(uint64_t ftime, struct game_t *game) { } // columns + for (int i = 0; i < game->columns_count; ++i) { + SDL_Rect *column = game->columns + i; + column->x -= bg_offset; + if (column->x + column->w < 0) { + // column should reappear from the right side + place_column(&game->columns, game->columns_count, column); + game->score++; + } + } SDL_SetRenderDrawColor(game->renderer, 0, 154, 213, 0); SDL_RenderFillRects(game->renderer, game->columns, game->columns_count); @@ -89,12 +122,23 @@ void draw_game(uint64_t ftime, struct game_t *game) { //printf("frame time: %llu\n", ftime); } -void draw_menu(struct menu_t *menu) { +void draw_menu(struct menu_t *menu, int score) { SDL_SetRenderDrawColor(menu->game->renderer, 2, 40, 223, 0); + // force redraw is score has changed + if (menu->score != score) { + menu->score = score; + SDL_DestroyTexture(menu->texture); + menu->texture = NULL; + SDL_FreeSurface(menu->surface); + menu->surface = NULL; + } + if (menu->surface == NULL) { + char out_text[255] = {0}; + snprintf(out_text, 254, "Score: %d. Press <space> to play", menu->score); SDL_Color color = { 255, 255, 255, 0 }; - menu->surface = TTF_RenderText_Solid(menu->font, "Press <space> to play", color); + menu->surface = TTF_RenderText_Solid(menu->font, out_text, color); assert(menu->surface != NULL); } @@ -111,6 +155,19 @@ void draw_menu(struct menu_t *menu) { SDL_RenderPresent(menu->game->renderer); } +void place_column(SDL_Rect **columns, int count, SDL_Rect *column) { + // @todo check for columns overlaps + (void)columns; + (void)count; + bool is_top = rand() % 2 == 1; + column->x = GAME_WIN_WIDTH * s_dpi_scale + (rand() % column->w) + column->w; + if (is_top) { + column->y = 0; + } else { + column->y = GAME_WIN_HEIGHT * s_dpi_scale - column->h; + } +} + void create_columns(SDL_Rect **rects, int count) { assert(count > 0); assert(*rects == NULL); @@ -118,14 +175,15 @@ void create_columns(SDL_Rect **rects, int count) { assert(*rects != NULL); } -void init_columns(SDL_Rect **columns, int count, int hidpi_scale) { +void init_columns(SDL_Rect **columns, int count) { assert(count > 0); for (int i = 0; i < count; ++i) { SDL_Rect *column = *columns + i; - column->w = GAME_COLUMN_WIDTH * hidpi_scale; - column->h = GAME_COLUMN_HEIGHT * hidpi_scale; - column->x = 200 * i; - column->y = 0; + column->w = GAME_COLUMN_WIDTH * s_dpi_scale; + column->h = GAME_COLUMN_HEIGHT * s_dpi_scale; + column->x = GAME_WIN_WIDTH * s_dpi_scale + 200 * s_dpi_scale * i; + //@todo use game->scrH + column->y = rand() % 2 == 1 ? 0 : GAME_WIN_HEIGHT * s_dpi_scale - column->h; } } @@ -147,6 +205,8 @@ int main(int argc, char *argv[]) { SDL_Init(SDL_INIT_VIDEO); TTF_Init(); + srand(time(0)); + game.screen = SDL_CreateWindow("flappychik", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, GAME_WIN_WIDTH, GAME_WIN_HEIGHT, WINDOW_FLAGS); assert(game.screen != NULL); game.renderer = SDL_CreateRenderer(game.screen, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); @@ -172,21 +232,21 @@ int main(int argc, char *argv[]) { SDL_RenderPresent(game.renderer); // hidpi scale - float hidpi_scale = (float)game.scrW / GAME_WIN_WIDTH; + s_dpi_scale = (float)game.scrW / GAME_WIN_WIDTH; // initial values game.last_frame = SDL_GetTicks64(); game.ship.rect.x = 150; // initial position game.ship.rect.y = 50; - game.ship.rect.w *= hidpi_scale; - game.ship.rect.h *= hidpi_scale; - game.bg.rect.w *= hidpi_scale; - game.bg.rect.h *= hidpi_scale; + game.ship.rect.w *= s_dpi_scale; + game.ship.rect.h *= s_dpi_scale; + game.bg.rect.w *= s_dpi_scale; + game.bg.rect.h *= s_dpi_scale; game.ship.accel = GAME_FALL_ACCEL; // "enemy" columns - game.columns_count = 2; // max columns on screen + game.columns_count = 8; // max columns on screen create_columns(&game.columns, game.columns_count); - init_columns(&game.columns, game.columns_count, hidpi_scale); + init_columns(&game.columns, game.columns_count); // menu struct menu_t menu = {0}; @@ -213,6 +273,7 @@ int main(int argc, char *argv[]) { game.ship.velocity = 0; game.ship.rect.x = 150; game.ship.rect.y = 50; + game.score = 0; } } break; @@ -226,7 +287,7 @@ int main(int argc, char *argv[]) { if (game.state == GAME_STATE_RUNNING) { draw_game(ftime, &game); } else { - draw_menu(&menu); + draw_menu(&menu, game.score); } game.last_frame = ts; }