From 2f975d8e742c6159228ac080d5c8db289c1c0a66 Mon Sep 17 00:00:00 2001 From: Rorikstr | Rust Dev Date: Wed, 15 Oct 2025 15:59:56 +0300 Subject: [PATCH] from frames speed to timespeed --- src/brick_game/tetris/01_automato.h | 23 ++++++++++++--------- src/brick_game/tetris/02_tetris.c | 13 ++++++++---- src/brick_game/tetris/03_automato.c | 14 +++++++++---- src/brick_game/tetris/04_init.c | 7 ++++--- src/brick_game/tetris/06_move.c | 30 ++++++++++++++++------------ src/brick_game/tetris/08_attaching.c | 2 +- src/gui/cli/main.c | 11 ++++++---- 7 files changed, 62 insertions(+), 38 deletions(-) diff --git a/src/brick_game/tetris/01_automato.h b/src/brick_game/tetris/01_automato.h index 2ce371d..64f1ccd 100644 --- a/src/brick_game/tetris/01_automato.h +++ b/src/brick_game/tetris/01_automato.h @@ -1,9 +1,12 @@ #ifndef AUTOMATO_H #define AUTOMATO_H +#define _POSIX_C_SOURCE 199309L // Добавляем здесь для POSIX + #include "00_tetris.h" #include #include +#include // Для clock_gettime typedef enum { Init, @@ -34,10 +37,10 @@ typedef enum { } Sprite_t; typedef struct { - int x, y; // Позиция фигуры на поле - int mtrx[4][4]; // сама матрица - Sprite_t sprite; // Тип фигуры - int rotation; // Поворот (0–3) + int x, y; + int mtrx[4][4]; + Sprite_t sprite; + int rotation; } Figure_t; typedef struct { @@ -47,18 +50,21 @@ typedef struct { Moving_t moving_type; int field[FIELD_HEIGHT][FIELD_WIDTH]; GameInfo_t* info; - long long frame_count; // Общий счётчик кадров - long long last_move_frame; // Кадр, когда фигура последний раз двигалась + long long last_move_time; // Время последнего движения (мс) + long long pause_start_time; // Время начала паузы (мс) } GameState_t; GameState_t* get_game_state(void); // Функции состояний -// init void do_init(void); int load_high_score(); void save_high_score(int score); void generate_next_figure(void); +void terminate_and_free(void); // Добавляем прототип здесь + +// Вспомогательная функция для времени +long long get_current_time_ms(void); // spawn void do_spawn(void); @@ -82,7 +88,6 @@ int is_game_over(); // Функции фигур const int (*get_figure_shape(Sprite_t sprite, int rotation))[4]; -// Остальные фигуры... const int (*i_fig_up())[4]; const int (*i_fig_right())[4]; const int (*i_fig_down())[4]; @@ -110,4 +115,4 @@ const int (*z_fig_down())[4]; const int (*z_fig_left())[4]; const int (*empty_fig())[4]; -#endif \ No newline at end of file +#endif diff --git a/src/brick_game/tetris/02_tetris.c b/src/brick_game/tetris/02_tetris.c index e37f674..70eb61b 100644 --- a/src/brick_game/tetris/02_tetris.c +++ b/src/brick_game/tetris/02_tetris.c @@ -24,6 +24,7 @@ void userInput(UserAction_t action, bool hold) { state->info->high_score = state->info->score; save_high_score(state->info->high_score); } + terminate_and_free(); // Освобождаем память здесь - единственное место state->state = GameOver; break; case Left: @@ -43,6 +44,12 @@ void userInput(UserAction_t action, bool hold) { state->moving_type = ToDown; break; case Pause: + if (!state->info->pause) { + state->pause_start_time = get_current_time_ms(); + } else { + long long pause_duration = get_current_time_ms() - state->pause_start_time; + state->last_move_time += pause_duration; + } state->info->pause = !state->info->pause; break; default: @@ -52,8 +59,6 @@ void userInput(UserAction_t action, bool hold) { GameInfo_t updateCurrentState() { GameState_t* state = get_game_state(); - - state->frame_count++; if (!state->info->pause || state->state == GameOver) { switch (state->state) { @@ -91,7 +96,7 @@ GameInfo_t updateCurrentState() { int x = fig->x + j; int y = fig->y + i; if (y >= 0 && y < FIELD_HEIGHT && x >= 0 && x < FIELD_WIDTH) { - state->info->field[y][x] = 1; // активная фигура + state->info->field[y][x] = 1; } } } @@ -104,4 +109,4 @@ GameInfo_t updateCurrentState() { } return *state->info; -} \ No newline at end of file +} diff --git a/src/brick_game/tetris/03_automato.c b/src/brick_game/tetris/03_automato.c index c0adab0..a70039b 100644 --- a/src/brick_game/tetris/03_automato.c +++ b/src/brick_game/tetris/03_automato.c @@ -1,5 +1,11 @@ #include "01_automato.h" +long long get_current_time_ms(void) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000LL + ts.tv_nsec / 1000000LL; +} + int load_high_score() { FILE* file = fopen("build/high_score.txt", "r"); int high_score = 0; @@ -35,12 +41,12 @@ GameState_t* get_game_state(void) { for (int i = 0; i < 4; i++) { state.info->next[i] = malloc(4 * sizeof(int)); } - state.info->speed = 10; + state.info->speed = 1; state.info->score = 0; state.info->level = 1; state.info->pause = 0; - state.frame_count = 0; - state.last_move_frame = 0; + state.last_move_time = get_current_time_ms(); + state.pause_start_time = 0; state.info->high_score = load_high_score(); state.state = GameOver; @@ -79,4 +85,4 @@ void terminate_and_free() { free(state->info); state->info = NULL; } -} \ No newline at end of file +} diff --git a/src/brick_game/tetris/04_init.c b/src/brick_game/tetris/04_init.c index 64736b0..ab1ba28 100644 --- a/src/brick_game/tetris/04_init.c +++ b/src/brick_game/tetris/04_init.c @@ -11,12 +11,13 @@ void reset_game_stats(void) { GameState_t* state = get_game_state(); state->info->score = 0; state->info->level = 1; - state->info->speed = 10; + state->info->speed = 1; + state->last_move_time = get_current_time_ms(); } void do_init(void) { clear_field(); reset_game_stats(); generate_next_figure(); - get_game_state()->state = Spawn; // Переход в Spawn -} \ No newline at end of file + get_game_state()->state = Spawn; +} diff --git a/src/brick_game/tetris/06_move.c b/src/brick_game/tetris/06_move.c index f3b6539..8ba3880 100644 --- a/src/brick_game/tetris/06_move.c +++ b/src/brick_game/tetris/06_move.c @@ -1,28 +1,32 @@ #include "01_automato.h" -int get_frames_to_wait(void) { +int get_milliseconds_to_wait(void) { GameState_t* state = get_game_state(); + if (state->moving_type == ToDown) { - return 1; // TODO - } else { - return 1000 / state->info->speed; // TODO + return 30; } + + // Скорость от 1 до 10: 1000ms -> 100ms + int base_delay = 1100 - (state->info->speed * 100); + return base_delay > 100 ? base_delay : 100; } void do_move(void) { GameState_t* state = get_game_state(); - - int frames_to_wait = get_frames_to_wait(); - - if (state->frame_count - state->last_move_frame < frames_to_wait) { - return; // TODO + + long long current_time = get_current_time_ms(); + int ms_to_wait = get_milliseconds_to_wait(); + + if (current_time - state->last_move_time < ms_to_wait) { + return; } - - state->last_move_frame = state->frame_count; - + + state->last_move_time = current_time; + state->curr.y++; if (check_collision()) { state->curr.y--; state->state = Attaching; } -} \ No newline at end of file +} diff --git a/src/brick_game/tetris/08_attaching.c b/src/brick_game/tetris/08_attaching.c index 59396ff..086b02d 100644 --- a/src/brick_game/tetris/08_attaching.c +++ b/src/brick_game/tetris/08_attaching.c @@ -92,7 +92,7 @@ void clear_lines() { if (new_level > state->info->level) { state->info->level = new_level; - state->info->speed = new_level * 10; + state->info->speed = new_level * 3; } } } \ No newline at end of file diff --git a/src/gui/cli/main.c b/src/gui/cli/main.c index 292a38e..bfa3d8b 100644 --- a/src/gui/cli/main.c +++ b/src/gui/cli/main.c @@ -1,10 +1,14 @@ #include #include -#include "../../brick_game/tetris/00_tetris.h" +#include +#include +#include "../../brick_game/tetris/00_tetris.h" // Только этот хедер! void display_game(GameInfo_t game_state); int main() { + srand(time(NULL)); + initscr(); cbreak(); noecho(); @@ -12,7 +16,6 @@ int main() { nodelay(stdscr, FALSE); curs_set(0); - // Цикл ожидания нажатия F/f mvprintw(FIELD_HEIGHT / 2, FIELD_WIDTH - 4, "Press F to Start"); refresh(); @@ -38,7 +41,7 @@ int main() { switch (ch) { case 'q': - userInput(Terminate, false); + userInput(Terminate, false); // Это освободит память через бэкенд running = false; break; case 'r': case ' ': @@ -83,4 +86,4 @@ int main() { endwin(); return 0; -} \ No newline at end of file +}