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:
M | main.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;
}