no segs and correct points

This commit is contained in:
Rorikstr | Rust Dev 2025-09-28 19:09:23 +03:00
parent 6b80483129
commit 3c7e55dd6f
5 changed files with 76 additions and 40 deletions

1
.gitignore vendored
View file

@ -56,3 +56,4 @@ src/.gpskip
.gpskip
ginpee.toml
src/ginpee.toml
.vscode/launch.json

View file

@ -46,12 +46,11 @@ void init_game() {
state->next_figure.rotation = 0;
state->score = 0;
state->high_score = 0;
state->level = 1;
state->drop_time = time(NULL) * 1000;
state->game_over = false;
state->paused = false;
state->state = FSM_Start;
state->state = FSM_Start; // Начинаем в состоянии Start
}
void place_figure() {
@ -65,7 +64,7 @@ void place_figure() {
int x = f->x + j;
int y = f->y + i;
if (y >= 0 && y < FIELD_HEIGHT && x >= 0 && x < FIELD_WIDTH) {
state->game_field[y][x] = 1;
state->game_field[y][x] = 1; // Фиксируем блок
}
}
}
@ -74,12 +73,26 @@ void place_figure() {
// Проверяем и удаляем заполненные строки
clear_completed_lines();
// Меняем состояние на Spawn для генерации новой фигуры
state->state = FSM_Spawn;
// Спавним новую фигуру
state->current_figure = state->next_figure;
state->current_figure.x = FIELD_WIDTH / 2 - 2;
state->current_figure.y = 0;
state->current_figure.rotation = 0;
// Генерируем следующую фигуру
state->next_figure.type = get_random_figure();
state->next_figure.rotation = 0;
// Проверяем, возможно ли размещение новой фигуры
if (check_collision()) {
state->state = FSM_GameOver;
} else {
state->state = FSM_Moving;
}
}
void clear_completed_lines() {
GameStateData* state = get_instance();
GameStateData* state = get_game_state();
int lines_cleared = 0;
int write_row = FIELD_HEIGHT - 1;
@ -122,7 +135,7 @@ void clear_completed_lines() {
} else {
score_points = points[4]; // для > 4 линий
}
state->score += score_points * state->level;
state->score += score_points; // УБРАЛ УМНОЖЕНИЕ НА УРОВЕНЬ
if (state->score > state->high_score) {
state->high_score = state->score;
@ -164,11 +177,11 @@ bool check_collision() {
}
void fsm_transition() {
GameStateData* state = get_instance();
GameStateData* state = get_game_state();
switch (state->state) {
case FSM_Start:
state->state = FSM_Spawn;
// Ожидание начала игры - не делаем ничего, пока не будет нажата Start
break;
case FSM_Spawn:
@ -202,7 +215,8 @@ void fsm_transition() {
case FSM_Attaching:
place_figure();
state->state = FSM_Spawn;
// После place_figure проверяем, не произошел ли Game Over
// В place_figure уже устанавливается FSM_Spawn, но нужно проверить столкновение
break;
case FSM_GameOver:

View file

@ -44,27 +44,14 @@ void userInput(UserAction_t action, bool hold) {
GameInfo_t* game_info = get_game_info_instance();
switch (action) {
case Start:
if (state->state == FSM_GameOver) {
// Перезапуск игры
int saved_high_score = state->high_score;
init_game();
state->high_score = saved_high_score;
state->state = FSM_Spawn;
} else {
state->paused = !state->paused;
}
break;
case Pause:
state->paused = !state->paused;
break;
case Terminate:
// Освобождаем память при завершении
if (game_info->field != NULL) {
for (int i = 0; i < FIELD_HEIGHT; i++) {
free(game_info->field[i]);
if (game_info->field[i] != NULL) {
free(game_info->field[i]);
game_info->field[i] = NULL;
}
}
free(game_info->field);
game_info->field = NULL;
@ -72,15 +59,38 @@ void userInput(UserAction_t action, bool hold) {
if (game_info->next != NULL) {
for (int i = 0; i < 4; i++) {
free(game_info->next[i]);
if (game_info->next[i] != NULL) {
free(game_info->next[i]);
game_info->next[i] = NULL;
}
}
free(game_info->next);
game_info->next = NULL;
}
return; // ВАЖНО: выходим из функции, не делаем ничего после Terminate
case Start:
if (state->state == FSM_GameOver) {
// Перезапуск игры после Game Over
int saved_high_score = state->high_score;
init_game();
state->high_score = saved_high_score;
// Не меняем состояние, пусть остается в Start до следующего нажатия
} else if (state->state == FSM_Start) {
// Начинаем игру из состояния Start
state->state = FSM_Spawn;
} else {
// Для всех других состояний (Moving, Move) - ставим на паузу
state->paused = !state->paused;
}
break;
case Pause:
state->paused = !state->paused;
break;
default:
if (state->state == FSM_GameOver || state->paused) {
if (state->state == FSM_GameOver || state->paused || state->state == FSM_Start) {
break;
}
@ -136,7 +146,7 @@ GameInfo_t updateCurrentState() {
GameStateData* state = get_game_state();
GameInfo_t* game_info = get_game_info_instance();
if (!state->game_over && !state->paused) {
if (state->state != FSM_Start && !state->game_over && !state->paused) {
long long current_time = time(NULL) * 1000;
// Определяем интервал падения в зависимости от уровня
@ -149,8 +159,10 @@ GameInfo_t updateCurrentState() {
}
}
// Выполняем переходы FSM
fsm_transition();
// Выполняем переходы FSM (но не в состоянии Start)
if (state->state != FSM_Start) {
fsm_transition();
}
// Обновляем game_info.field из state->game_field
for (int i = 0; i < FIELD_HEIGHT; i++) {
@ -159,7 +171,7 @@ GameInfo_t updateCurrentState() {
}
}
// Добавляем активную фигуру на поле для отображения (если не game_over)
// Добавляем активную фигуру на поле для отображения (если не в Start или GameOver)
if ((state->state == FSM_Moving || state->state == FSM_Move) && !state->game_over) {
Figure* f = &state->current_figure;
const int (*shape)[4] = get_figure_shape(f->type, f->rotation);
@ -168,8 +180,12 @@ GameInfo_t updateCurrentState() {
if (shape[i][j]) {
int x = f->x + j;
int y = f->y + i;
// Проверяем границы перед записью
if (x >= 0 && x < FIELD_WIDTH && y >= 0 && y < FIELD_HEIGHT) {
game_info->field[y][x] = 1;
// Не перезаписываем уже зафиксированные блоки
if (state->game_field[y][x] == 0) {
game_info->field[y][x] = 1;
}
}
}
}
@ -178,8 +194,8 @@ GameInfo_t updateCurrentState() {
// Обновляем next
const int (*next_shape)[4];
if (state->state == FSM_GameOver) {
// При game_over показываем пустую фигуру
if (state->state == FSM_GameOver || state->state == FSM_Start) {
// При game_over или в начальном состоянии показываем пустую фигуру
next_shape = empty_fig();
} else {
next_shape = get_figure_shape(state->next_figure.type, state->next_figure.rotation);

View file

@ -3,9 +3,13 @@
#include "../../brick_game/tetris/tetris.h"
void display_game() {
printf("DEBUG: display_game called\n");
clear();
GameInfo_t game_state = updateCurrentState();
printf("DEBUG: Got game state, field: %p, next: %p\n",
game_state.field, game_state.next);
// Отображение игрового поля
for (int i = 0; i < FIELD_HEIGHT; i++) {
@ -43,4 +47,5 @@ void display_game() {
}
refresh();
printf("DEBUG: display_game completed\n");
}

View file

@ -64,12 +64,12 @@ int main() {
userInput(current_action, false);
}
updateCurrentState();
display_game();
if (running) { // Обновляем состояние только если не завершаемся
updateCurrentState();
display_game();
}
}
// Вызов userInput с Terminate для освобождения памяти
userInput(Terminate, false);
endwin();
return 0;
}