no segs and correct points
This commit is contained in:
parent
6b80483129
commit
3c7e55dd6f
5 changed files with 76 additions and 40 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -56,3 +56,4 @@ src/.gpskip
|
||||||
.gpskip
|
.gpskip
|
||||||
ginpee.toml
|
ginpee.toml
|
||||||
src/ginpee.toml
|
src/ginpee.toml
|
||||||
|
.vscode/launch.json
|
||||||
|
|
|
||||||
|
|
@ -46,12 +46,11 @@ void init_game() {
|
||||||
state->next_figure.rotation = 0;
|
state->next_figure.rotation = 0;
|
||||||
|
|
||||||
state->score = 0;
|
state->score = 0;
|
||||||
state->high_score = 0;
|
|
||||||
state->level = 1;
|
state->level = 1;
|
||||||
state->drop_time = time(NULL) * 1000;
|
state->drop_time = time(NULL) * 1000;
|
||||||
state->game_over = false;
|
state->game_over = false;
|
||||||
state->paused = false;
|
state->paused = false;
|
||||||
state->state = FSM_Start;
|
state->state = FSM_Start; // Начинаем в состоянии Start
|
||||||
}
|
}
|
||||||
|
|
||||||
void place_figure() {
|
void place_figure() {
|
||||||
|
|
@ -65,7 +64,7 @@ void place_figure() {
|
||||||
int x = f->x + j;
|
int x = f->x + j;
|
||||||
int y = f->y + i;
|
int y = f->y + i;
|
||||||
if (y >= 0 && y < FIELD_HEIGHT && x >= 0 && x < FIELD_WIDTH) {
|
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();
|
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() {
|
void clear_completed_lines() {
|
||||||
GameStateData* state = get_instance();
|
GameStateData* state = get_game_state();
|
||||||
int lines_cleared = 0;
|
int lines_cleared = 0;
|
||||||
int write_row = FIELD_HEIGHT - 1;
|
int write_row = FIELD_HEIGHT - 1;
|
||||||
|
|
||||||
|
|
@ -122,7 +135,7 @@ void clear_completed_lines() {
|
||||||
} else {
|
} else {
|
||||||
score_points = points[4]; // для > 4 линий
|
score_points = points[4]; // для > 4 линий
|
||||||
}
|
}
|
||||||
state->score += score_points * state->level;
|
state->score += score_points; // УБРАЛ УМНОЖЕНИЕ НА УРОВЕНЬ
|
||||||
|
|
||||||
if (state->score > state->high_score) {
|
if (state->score > state->high_score) {
|
||||||
state->high_score = state->score;
|
state->high_score = state->score;
|
||||||
|
|
@ -164,11 +177,11 @@ bool check_collision() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void fsm_transition() {
|
void fsm_transition() {
|
||||||
GameStateData* state = get_instance();
|
GameStateData* state = get_game_state();
|
||||||
|
|
||||||
switch (state->state) {
|
switch (state->state) {
|
||||||
case FSM_Start:
|
case FSM_Start:
|
||||||
state->state = FSM_Spawn;
|
// Ожидание начала игры - не делаем ничего, пока не будет нажата Start
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FSM_Spawn:
|
case FSM_Spawn:
|
||||||
|
|
@ -202,7 +215,8 @@ void fsm_transition() {
|
||||||
|
|
||||||
case FSM_Attaching:
|
case FSM_Attaching:
|
||||||
place_figure();
|
place_figure();
|
||||||
state->state = FSM_Spawn;
|
// После place_figure проверяем, не произошел ли Game Over
|
||||||
|
// В place_figure уже устанавливается FSM_Spawn, но нужно проверить столкновение
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FSM_GameOver:
|
case FSM_GameOver:
|
||||||
|
|
|
||||||
|
|
@ -44,14 +44,43 @@ void userInput(UserAction_t action, bool hold) {
|
||||||
GameInfo_t* game_info = get_game_info_instance();
|
GameInfo_t* game_info = get_game_info_instance();
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case Terminate:
|
||||||
|
// Освобождаем память при завершении
|
||||||
|
if (game_info->field != NULL) {
|
||||||
|
for (int i = 0; i < FIELD_HEIGHT; 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game_info->next != NULL) {
|
||||||
|
for (int i = 0; i < 4; 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:
|
case Start:
|
||||||
if (state->state == FSM_GameOver) {
|
if (state->state == FSM_GameOver) {
|
||||||
// Перезапуск игры
|
// Перезапуск игры после Game Over
|
||||||
int saved_high_score = state->high_score;
|
int saved_high_score = state->high_score;
|
||||||
init_game();
|
init_game();
|
||||||
state->high_score = saved_high_score;
|
state->high_score = saved_high_score;
|
||||||
|
// Не меняем состояние, пусть остается в Start до следующего нажатия
|
||||||
|
} else if (state->state == FSM_Start) {
|
||||||
|
// Начинаем игру из состояния Start
|
||||||
state->state = FSM_Spawn;
|
state->state = FSM_Spawn;
|
||||||
} else {
|
} else {
|
||||||
|
// Для всех других состояний (Moving, Move) - ставим на паузу
|
||||||
state->paused = !state->paused;
|
state->paused = !state->paused;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -60,27 +89,8 @@ void userInput(UserAction_t action, bool hold) {
|
||||||
state->paused = !state->paused;
|
state->paused = !state->paused;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Terminate:
|
|
||||||
// Освобождаем память при завершении
|
|
||||||
if (game_info->field != NULL) {
|
|
||||||
for (int i = 0; i < FIELD_HEIGHT; i++) {
|
|
||||||
free(game_info->field[i]);
|
|
||||||
}
|
|
||||||
free(game_info->field);
|
|
||||||
game_info->field = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game_info->next != NULL) {
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
free(game_info->next[i]);
|
|
||||||
}
|
|
||||||
free(game_info->next);
|
|
||||||
game_info->next = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (state->state == FSM_GameOver || state->paused) {
|
if (state->state == FSM_GameOver || state->paused || state->state == FSM_Start) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +146,7 @@ GameInfo_t updateCurrentState() {
|
||||||
GameStateData* state = get_game_state();
|
GameStateData* state = get_game_state();
|
||||||
GameInfo_t* game_info = get_game_info_instance();
|
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;
|
long long current_time = time(NULL) * 1000;
|
||||||
|
|
||||||
// Определяем интервал падения в зависимости от уровня
|
// Определяем интервал падения в зависимости от уровня
|
||||||
|
|
@ -149,8 +159,10 @@ GameInfo_t updateCurrentState() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Выполняем переходы FSM
|
// Выполняем переходы FSM (но не в состоянии Start)
|
||||||
|
if (state->state != FSM_Start) {
|
||||||
fsm_transition();
|
fsm_transition();
|
||||||
|
}
|
||||||
|
|
||||||
// Обновляем game_info.field из state->game_field
|
// Обновляем game_info.field из state->game_field
|
||||||
for (int i = 0; i < FIELD_HEIGHT; i++) {
|
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) {
|
if ((state->state == FSM_Moving || state->state == FSM_Move) && !state->game_over) {
|
||||||
Figure* f = &state->current_figure;
|
Figure* f = &state->current_figure;
|
||||||
const int (*shape)[4] = get_figure_shape(f->type, f->rotation);
|
const int (*shape)[4] = get_figure_shape(f->type, f->rotation);
|
||||||
|
|
@ -168,18 +180,22 @@ GameInfo_t updateCurrentState() {
|
||||||
if (shape[i][j]) {
|
if (shape[i][j]) {
|
||||||
int x = f->x + j;
|
int x = f->x + j;
|
||||||
int y = f->y + i;
|
int y = f->y + i;
|
||||||
|
// Проверяем границы перед записью
|
||||||
if (x >= 0 && x < FIELD_WIDTH && y >= 0 && y < FIELD_HEIGHT) {
|
if (x >= 0 && x < FIELD_WIDTH && y >= 0 && y < FIELD_HEIGHT) {
|
||||||
|
// Не перезаписываем уже зафиксированные блоки
|
||||||
|
if (state->game_field[y][x] == 0) {
|
||||||
game_info->field[y][x] = 1;
|
game_info->field[y][x] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Обновляем next
|
// Обновляем next
|
||||||
const int (*next_shape)[4];
|
const int (*next_shape)[4];
|
||||||
if (state->state == FSM_GameOver) {
|
if (state->state == FSM_GameOver || state->state == FSM_Start) {
|
||||||
// При game_over показываем пустую фигуру
|
// При game_over или в начальном состоянии показываем пустую фигуру
|
||||||
next_shape = empty_fig();
|
next_shape = empty_fig();
|
||||||
} else {
|
} else {
|
||||||
next_shape = get_figure_shape(state->next_figure.type, state->next_figure.rotation);
|
next_shape = get_figure_shape(state->next_figure.type, state->next_figure.rotation);
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,14 @@
|
||||||
#include "../../brick_game/tetris/tetris.h"
|
#include "../../brick_game/tetris/tetris.h"
|
||||||
|
|
||||||
void display_game() {
|
void display_game() {
|
||||||
|
printf("DEBUG: display_game called\n");
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
GameInfo_t game_state = updateCurrentState();
|
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++) {
|
for (int i = 0; i < FIELD_HEIGHT; i++) {
|
||||||
for (int j = 0; j < FIELD_WIDTH; j++) {
|
for (int j = 0; j < FIELD_WIDTH; j++) {
|
||||||
|
|
@ -43,4 +47,5 @@ void display_game() {
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
|
printf("DEBUG: display_game completed\n");
|
||||||
}
|
}
|
||||||
|
|
@ -64,12 +64,12 @@ int main() {
|
||||||
userInput(current_action, false);
|
userInput(current_action, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (running) { // Обновляем состояние только если не завершаемся
|
||||||
updateCurrentState();
|
updateCurrentState();
|
||||||
display_game();
|
display_game();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Вызов userInput с Terminate для освобождения памяти
|
|
||||||
userInput(Terminate, false);
|
|
||||||
endwin();
|
endwin();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue