Фигурки то рисуются!

This commit is contained in:
Rorikstr | Rust Dev 2025-09-26 13:28:53 +03:00
parent e20765d252
commit fef0d8cbe3
6 changed files with 176 additions and 22 deletions

1
.gitignore vendored
View file

@ -50,3 +50,4 @@ modules.order
Module.symvers
Mkfile.old
dkms.conf
src/tetris

View file

@ -1,3 +1,4 @@
# src/Makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -Werror -g
LDFLAGS = -lncurses

View file

@ -0,0 +1,76 @@
// src/brick_game/tetris/tetris.c
#include "tetris.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static GameStateData game_state = {0};
static bool initialized = false;
const int (*get_figure_shape(FigureType type, int rotation))[4] {
static const int shapes[FIGURE_COUNT][4][4][4] = {
// I
{{{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}},
{{0, 0, 0, 0}, {0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
{{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}}},
// O
{{{0, 1, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}},
// T
{{{0, 1, 0, 0}, {1, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 0, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 0, 0}, {1, 1, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}}},
// L
{{{0, 0, 1, 0}, {1, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 1, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}},
{{1, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}}},
// J
{{{1, 0, 0, 0}, {1, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 1, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}},
{{0, 1, 0, 0}, {0, 1, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}}},
// S
{{{0, 1, 1, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}},
{{0, 1, 1, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}}},
// Z
{{{1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 1, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
{{1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 1, 0}, {0, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}}}};
return shapes[type][rotation];
}
void userInput(UserAction_t action, bool hold) {
(void)hold; // Подавляем предупреждение
if (!initialized) {
memset(&game_state, 0, sizeof(game_state));
initialized = true;
}
if (action >= Figure1 && action <= Figure5) {
FigureType type = (FigureType)(action - Figure1);
game_state.current_figure.type = type;
game_state.current_figure.x = FIELD_WIDTH / 2 - 2;
game_state.current_figure.y = 0;
game_state.current_figure.rotation = 0;
game_state.figure_active = true;
}
if (game_state.figure_active) {
if (action == Left) game_state.current_figure.x--;
if (action == Right) game_state.current_figure.x++;
if (action == Down) game_state.current_figure.y++;
if (action == Up) game_state.current_figure.y--;
}
}
GameStateData* getGameState() {
return &game_state;
}

View file

@ -1,13 +1,13 @@
// src/brick_game/tetris/tetris.h
#ifndef TETRIS_H
#define TETRIS_H
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
// Константы
#define FIELD_WIDTH 10
#define FIELD_HEIGHT 20
#define NEXT_SIZE 4
// Типы фигур
typedef enum {
@ -21,16 +21,6 @@ typedef enum {
FIGURE_COUNT
} FigureType;
// Состояния конечного автомата
typedef enum {
START,
SPAWN,
MOVING,
SHIFTING,
ATTACHING,
GAME_OVER
} GameState;
// Структура фигуры
typedef struct {
int x, y; // Позиция фигуры на поле
@ -42,30 +32,31 @@ typedef struct {
typedef struct {
int field[FIELD_HEIGHT][FIELD_WIDTH]; // Игровое поле
Figure current_figure; // Текущая фигура
Figure next_figure; // Следующая фигура
int score; // Текущие очки
int high_score; // Максимальные очки
int level; // Уровень
int lines_cleared; // Удалённые линии
GameState state; // Текущее состояние КА
bool paused; // Игра на паузе?
bool figure_active; // Есть активная фигура?
} GameStateData;
// Ввод пользователя
typedef enum {
Undefined = -1,
Start,
Pause,
Terminate,
Left,
Right,
Up, // не используется
Up,
Down,
Action // вращение
Action,
Figure1, // 1
Figure2, // 2
Figure3, // 3
Figure4, // 4
Figure5 // 5
} UserAction_t;
// Основные функции библиотеки
void userInput(UserAction_t action, bool hold);
GameStateData* getGameState(void);
void updateCurrentState(void);
const int (*get_figure_shape(FigureType type, int rotation))[4];
#endif

View file

@ -0,0 +1,35 @@
// src/gui/cli/display.c
#include <ncurses.h>
#include "../../brick_game/tetris/tetris.h"
void display_game() {
clear();
GameStateData* state = getGameState();
// Очистка поля
for (int i = 0; i < FIELD_HEIGHT; i++) {
for (int j = 0; j < FIELD_WIDTH; j++) {
mvaddch(i + 1, j * 2 + 1, '.');
}
}
// Если фигура активна — отображаем её
if (state->figure_active) {
Figure* f = &state->current_figure;
const int (*shape)[4] = get_figure_shape(f->type, f->rotation);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
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) {
mvaddch(y + 1, x * 2 + 1, '$');
}
}
}
}
}
refresh();
}

View file

@ -0,0 +1,50 @@
// src/gui/cli/main.c
#include <ncurses.h>
#include <time.h>
#include <unistd.h>
#include "../../brick_game/tetris/tetris.h"
void display_game();
int main() {
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
nodelay(stdscr, TRUE);
curs_set(0);
timeout(100); // Таймаут для getch()
int ch;
bool hold = false;
while (1) {
ch = getch();
UserAction_t action = Undefined;
switch (ch) {
case 'q': action = Terminate; break;
case '1': action = Figure1; break;
case '2': action = Figure2; break;
case '3': action = Figure3; break;
case '4': action = Figure4; break;
case '5': action = Figure5; break;
case KEY_LEFT: action = Left; break;
case KEY_RIGHT: action = Right; break;
case KEY_DOWN: action = Down; break;
case KEY_UP: action = Up; break;
}
if (action != Undefined) {
userInput(action, hold);
}
display_game();
if (action == Terminate) break;
}
endwin();
return 0;
}