Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //------------------------------------------------------------------------------
- #ifndef TetrisH
- #define TetrisH
- //------------------------------------------------------------------------------
- #include <vcl.h>
- #include <mem.h>
- #include "Figures.h"
- //------------------------------------------------------------------------------
- //
- // class Figure
- //
- //------------------------------------------------------------------------------
- // класс фигуры
- class Figure {
- friend class Glass;
- // массив данных фигуры
- bool data[4][4];
- public:
- // конструктор
- Figure() {
- clear();
- }
- // очистка фигуры
- void clear() {
- memset(data, 0, sizeof(data));
- }
- // инициализация фигуры из массива символов
- void init(char d[4][4]) {
- for (int i=0; i<4; i++) {
- for (int j=0; j<4; j++) {
- data[i][j] = d[i][j] != ' ';
- }
- }
- }
- // инициализация фигуры из 4 строк
- void init(char l0[4], char l1[4], char l2[4], char l3[4]) {
- for (int i=0;i<4;i++) {
- data[0][i] = l0[i] != ' ';
- data[1][i] = l1[i] != ' ';
- data[2][i] = l2[i] != ' ';
- data[3][i] = l3[i] != ' ';
- }
- }
- // создавть фигуру в сцене
- void createFigure(Scene &scene, int x, int y, int size = 5) {
- // будем хранить указатель только на одну ноду,
- // будем ее двигать
- // и удалять вместе с потомками
- origin_node = new OriginNode(&Scene);
- origin_node->setPos(vec3(x, y, 0.0f));
- origin_node->setScale(vec3(size, size, size));
- for (int i=0;i<4;i++) {
- for (int j=0;j<4;j++) {
- if (data[j][i] == false) continue;
- MeshNode *node = new MeshNode(Scene, "Core/Primitives/pBox.mesh");
- node->setPos(vec3(i, j, 0.0f));
- node->setParent(origin_node, false);
- }
- }
- }
- };
- //------------------------------------------------------------------------------
- //
- // class Glass
- //
- //------------------------------------------------------------------------------
- // стакан
- class Glass {
- int **data; // массив стакана
- int width; // ширина стакана
- int height; // высота стакана
- // освободить память
- void release() {
- for (int i=0; i<height; i++) {
- delete []data[i];
- }
- delete []data;
- data = NULL;
- }
- public:
- // конструктор
- Glass(int w = 10, int h = 20) {
- setSize(w, h);
- clear();
- }
- // деструктор
- ~Glass() {
- release();
- }
- // изменить размер стакана
- void setSize(int w = 10, int h = 20) {
- release();
- width = w;
- height = h;
- data = new int *[height];
- for (int i=0; i<height; i++) {
- data[i] = new int[width];
- }
- clear();
- }
- // очистить стакан
- void clear() {
- for (int i=0; i<width; i++) {
- for (int j=0; j<height; j++) {
- data[j][i] = 0;
- }
- }
- }
- // рисовать стакан
- void render(TCanvas *canvas, int x = 0, int y = 0, int size = 5) {
- for (int i=0; i<width; i++) {
- for (int j=0; j<height; j++) {
- if (data[j][i] == 0) continue;
- canvas->Brush->Color = colors[data[j][i]-1];
- canvas->Rectangle(x + i*size, y + j*size, x + (i+1)*size, y + (j+1)*size);
- }
- }
- }
- // проверить столкновение фигуры со стаканом
- // x, y - смещение фигуры относительно стакана
- bool collide(int x, int y, const Figure &figure) {
- for (int i=0; i<4; i++) {
- for (int j=0; j<4; j++) {
- // если элемент фигуры не закрашен, столкновение не проверяем
- if (figure.data[i][j] ==) continue;
- // если элемент фигуры выходит за границы стакана или под элементом не пусто
- if (j + x < 0 || i + y < 0 || j + x >= width || i + y >= height || data[i + y][j + x]) {
- return true; // столкновение есть
- }
- }
- }
- return false; // столкновения нет
- }
- // установить фигуру в стакан и вернуть true если фигура установлена
- bool place(int x, int y, const Figure &figure, int col = 1) {
- if (collide(x, y, figure)) return false; // фигура не установлена
- for (int i=0; i<4; i++) {
- for (int j=0; j<4; j++) {
- if (figure.data[i][j] == false) continue;
- data[i + y][j + x] = col + 1;
- }
- }
- return true; // фигура установлена
- }
- // проверить заполненные линии, удалить и вернуть их количество
- int checkLines() {
- // количество заполненных линий
- int lines = 0;
- for (int i=0; i<height; i++) {
- // флаг заполненности линии
- bool is_line_full = true;
- for (int j=0; j<width; j++)
- // если хотя бы один элемент линии не заполнен
- if (data[i][j] != 0) continue;
- // сброить флаг заполненности
- is_line_full = false;
- break;
- }
- // если линия заполнена
- if (is_line_full) {
- // увеличить счетчик заполненных линий
- lines++;
- // удалить линию
- for (int k=i; k>0; k--) {
- for (int l=0; l<width; l++) {
- data[k][l] = data[k - 1][l];
- }
- }
- }
- }
- // вернуть количество удаленных заполненных линий
- return lines;
- }
- // получить центра стакана
- int getCenter() {
- return (width - 2) / 2;
- }
- // получить ширину стакана
- int getWidth() {
- return width;
- }
- // получить высоту стакана
- int getHeight() {
- return height;
- }
- };
- //------------------------------------------------------------------------------
- //
- // class Tetris
- //
- //------------------------------------------------------------------------------
- // игра тетрис
- class Tetris {
- int x; // х координата падающей фигуры
- int y; // у координата падающей фигуры
- int rotation; // поворот падающей фигуры
- int current; // тип текущей фигуры
- int next; // тип следующей фигуры
- Glass field; // игровое поле
- Figure figure[7][4]; // все фигуры, используемые в игре
- int score; // счет
- int scSingle; // количество одинарных линий
- int scDouble; // количество двойных линий
- int scTriple; // количество тройных линий
- int scQuadra; // количество четверных линий
- public:
- Tetris() {
- // иницилизировать фигуры из массива фигур
- for (int i=0; i<7; i++) {
- for (int j=0; j<4; j++) {
- figure[i][j].init(figures[i][j]);
- }
- }
- newGame();
- }
- // рисовать игру
- void render(TCanvas *canvas, int size = 10) {
- canvas->Brush->Color = 0x00000000;
- canvas->Rectangle(0, 0, field.getWidth()*size, field.getHeight()*size);
- canvas->Rectangle(
- (field.getWidth()+1)*size, field.getHeight()/2*size,
- (field.getWidth()+1)*size+size*4, field.getHeight()/2*size+size*4);
- canvas->Brush->Color = colors[next];
- figure[next][0].render(canvas, (field.getWidth()+1)*size, field.getHeight()/2*size, size);
- field.render(canvas, 0,0, size);
- canvas->Brush->Color = colors[current];
- figure[current][rotation].render(canvas, x*size, y*size, size);
- }
- // инициировать новую игру
- void newGame() {
- // сбросить счет
- score = 0;
- scSingle = 0;
- scDouble = 0;
- scTriple = 0;
- scQuadra = 0;
- // очистить поле
- field.clear();
- // иницилизировать первую и следующую фигуры
- randomize();
- next = random(7);
- nextFigure();
- }
- // сделать следующую фигуру текущей и создать следующую
- virtual void nextFigure() {
- current = next;
- next = random(7);
- rotation = 0;
- x = field.getCenter();
- y = 0;
- }
- // обновить игру
- void update() {
- moveDown();
- }
- void moveSide(int delta) {
- if (field.collide(x + delta, y, figure[current][rotation]) == false) {
- // двигать
- x += delta;
- }
- }
- // двигать фигуру влево
- void moveLeft() {
- moveSide(-1);
- }
- // двигать фигуру вправо
- void moveRight() {
- moveSide(+1);
- }
- // двигать фигуру вниз
- void moveDown() {
- // если не столкнемся
- if (field.collide(x, y + 1, figure[current][rotation]) == false) {
- // двигать
- y ++;
- } else {
- // иначе установить
- field.place(x, y, figure[current][rotation], current);
- // проверить линии
- int s = field.checkLines();
- // посчитать очки и статистику
- score += s * s;
- switch (s) {
- case 1:scSingle++;break;
- case 2:scDouble++;break;
- case 3:scTriple++;break;
- case 4:scQuadra++;break;
- default:
- }
- // создать следующую фигуру
- nextFigure();
- }
- }
- // повернуть фигуру
- void turn() {
- int new_rotation = (rotation + 1) % 4;
- // если не столкнемся
- if (field.collide(x, y, figure[current][new_rotation]) == false) {
- // повернуть фигуру
- rotation = new_rotation;
- } else {
- float move_inside_delta = 1;
- float sign = -1;
- if (x < 4) sign = 1;
- while (field.collide(x + move_inside_delta * sign, y, figure[current][new_rotation]) == true) {
- move_inside_delta ++;
- if (move_inside_delta > 4) return;
- }
- moveSide(move_inside_delta * sign);
- rotation = new_rotation;
- }
- }
- // хуйня какая-то не помню зачем
- int getOptimalSize(int w, int h)
- {
- if ((float)w/(float)field.getWidth() < (float)h/(float)field.getHeight())
- return w/field.getWidth();
- else
- return h/field.getHeight();
- }
- };
- //------------------------------------------------------------------------------
- #endif
- //------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment