Tetris – The Next Generation

 Очень хочется рассказать про мою самую любимую разработку – игру Тетрис. Начиналось всё с обычной проверки “смогу ли”. Это была как раз производственная практика в колледже, времени было полно. Практику я проходил с другом, по этому он мне подкинул идею добавить в игру бонусы и прочие мелочи.

 Ну а дальше больше. Появилась анимация, огромное кол-во бонусов, которые нужно было покупать, отрицательные бонусы, которые либо вызывались “плохой” игрой, либо неудачным выбором.

На данный момент размер основного кода насчитывает более 8 тыс. строк.
Вот объявление основного игрового класса, связывающего все и вся. Он создает все объекты, подгружает графику, связывает события и конечно же отрисовывает всю игру.

  TTetrisGame = class                                                           //Игровой "двигатель"
   private                                                                      //Личные
    aEmpty:Byte;                                                                 //Пустая ячейка
    AlreadyShownButtons:Boolean;                                                 //Уже были показаны кнопки (при запуске)
    AnswerShut:Byte;                                                             //Переменная для ответа при завершении игры
    BonusAmountWidth:Byte;                                                       //Кол-во бонусов в ширину
    CanBeContinue:Boolean;                                                       //Игра может быть продолжена
    Confirm:Boolean;                                                             //Дан ответ или нет
    CreatedBoss:Boolean;                                                         //Создан босс
    Creating:Boolean;                                                            //Идет инициализация
    DebugEnabled:Boolean;                                                        //Отладка
    DoDrawFigure:TDrawType;                                                      //Состояние редактирования фигуры
    Drawing:Boolean;                                                             //Идет отрисовка
    FBoom:Byte;                                                                  //Сила тряски
    FButtonsHided:Boolean;                                                       //Кнопки скрыты
    FButtonsHiding:Boolean;                                                      //Кнопки скрываются
    FCols:Byte;                                                                  //Кол-во столбцов
    FDrawCanvas:TCanvas;                                                         //Холст для передачи
    FEditBoxActive:Boolean;                                                      //Поле для ввода имени активно (Статистика)
    FEditBoxText:string;                                                         //Текст поля для ввода (Статистика)
    FFPS:integer;                                                                //Показаталь FPS
    FGameKeyCount:Byte;                                                          //Кол-во игровых клавиш спец. обработки
    FGameState:TGameState;                                                       //Состояние игры
    FHelper:Boolean;                                                             //Бонус - "Помошник"
    FHeight:Byte;                                                                //Высота ячеек
    FieldWidth:Word;                                                             //Ширина поля
    FieldHeight:Word;                                                            //Высота поля
    FInfoMode:TInfoMode;                                                         //Режим инф. дисплея
    FirstUpGold:Boolean;                                                         //Первое пополнение золота
    FKeyIDDown:Byte;                                                             //ИД клавиши вниз
    FKeyIDLeft:Byte;                                                             //ИД клавиши влево
    FKeyIDRight:Byte;                                                            //ИД клавиши вправо
    FKeyIDRL:Byte;                                                               //ИД клавиши поворот влево
    FKeyIDRR:Byte;                                                               //ИД клавиши поворот вправо
    FKeyIDUP:Byte;                                                               //ИД клавиши вверх
    FLevel:Byte;                                                                 //Текущий уровень
    FLevels:TLevels;                                                             //Уровни
    FLines:Integer;                                                              //Собранные линии
    FPauseTutorial:Boolean;                                                      //Пауза для туториала
    FRows:Byte;                                                                  //Кол-во строк
    FShownTutScene:set of Byte;                                                  //Показанные сцены
    FSpeedRate:Smallint;                                                         //Повышение/понижение скорости
    FTimerActivate:Boolean;                                                      //Активность таймеров
    FWaitAmount:Word;                                                            //Кол-во ожиданий
    FWidth:Byte;                                                                 //Ширина ячеек
    GameKeys:TGameKeys;                                                          //Игровые клавиши
    Ghost:Boolean;                                                               //Режим "Призрачная фигура"
    IDDrawFigure:Byte;                                                           //ИД элемента фигуры
    OldIM:TInfoMode;                                                             //Перыдущий режим инф. дисплея
    SLeft:Integer;                                                               //Положение поля слева
    STop:Integer;                                                                //Положение поля справа
    TutorialImg:TPNGObject;                                                      //Страница туториала
    TutorialPos:Integer;                                                         //Позиция страницы по X
    WasGhostColl:Boolean;                                                        //Произошло столкновение "Призрака о дно"
    function GetFLevel(Index:Byte):Boolean;                                      //Пройденные уровни
    function GetLevel:Byte;                                                      //Текущий уровень
    function GetScaleLvl:Byte;                                                   //Получить значение кол-ва строк %
    function KeyIsDown(VK_KEY:Word):Boolean;                                     //Нажата ли клавиша
    procedure SetGameState(Value:TGameState);                                    //Установить состояние игры
    procedure SetLevel(Value:Byte);                                              //Установить уровень
    procedure SetLines(Value:Integer);                                           //Установить кол-во удаленных линий
    procedure SetHelper(Value:Boolean);                                          //Установить значение "Помошника"
    procedure SetIM(Value:TInfoMode);                                            //Установить режми
    procedure SetTimers(Value:Boolean);                                          //Установить активность таймеров
   public                                                                       //Общие
    ArrayOfBonuses:TBonuses;                                                     //Список бонусов
    ArrayOfBosses:TArrayOfFigure;                                                //Массив боссов
    ArrayOfButtons:TArrayOfButton;                                               //Список кнопок
    ArrayOfClears:TArrayOfClears;                                                //Список удалюящихся элементов
    ArrayOfExing:TArrayOfExing;                                                  //Список выполненных бонусов
    ArrayOfFigure:TArrayOfFigure;                                                //Массив имеющихся фигур
    ArrayOfPanels:TArrayOfPanels;                                                //Список панелей
    ArrayOfToDo:TBonuses;                                                        //Список бонусов на выполнение
    BadGameBonusCount:Word;                                                      //Кол-во пропущенных бонусов
    Bitmaps:TBitmaps;                                                            //Графические объекты
    CurFigure:TFigure;                                                           //Текущая фигура
    DoBoom:Boolean;                                                              //"Тряска"
    DrawBMP:TBitmap;                                                             //Холст
    ExecutingBonus:Boolean;                                                      //Выполняется одноразовый бонус
    FigureEnable:Boolean;                                                        //Фигура идет
    FontTextAutor:TFont;                                                         //Шрифт - автор
    FontTextBonuses:TFont;                                                       //Шрифт - таймер бонусов
    FontTextButtons:TFont;                                                       //Шрифт - кнопки
    FontTextDisplay:TFont;                                                       //Шрифт - инф. текст
    FontTextGameOver:TFont;                                                      //Шрифт - конец игры (ваш счет)
    ForcedCoord:TPoint;                                                          //Принудительные координаты
    ForcedCoordinates:Boolean;                                                   //Использовать принудительное смещение поля
    FPS:Integer;                                                                 //Показатель FPS
    Gold:Cardinal;                                                               //Золото
    GoldPos:TPoint;                                                              //Позиция золота
    Hint:TTextHint;                                                              //Подсказка
    IsCreating:Boolean;                                                          //Идет создание фигуры
    IsTheBoss:Boolean;                                                           //Идет босс
    IsWait:Boolean;                                                              //Ожидание
    LeftPos:Byte;                                                                //Позиция идущей фигуры слева
    LinesAmountForLevelUp:Byte;                                                  //Количество линия для повышения уровня
    MainTet:TTetArray;                                                           //Главный массив
    MoveTet:TTetArray;                                                           //Двигающийся массив
    NeedShot:Boolean;                                                            //Сделсть снимок
    NextFigure:TFigure;                                                          //Следуюшая фигура
    NextFigureOld:TFigure;                                                       //Старая "следующая фигура"
    NextID:Integer;                                                              //ID следующей фигуры
    MarshMode:Boolean;                                                           //Режмим "Болото"
    Mouse:TPoint;                                                                //Курсор
    OldLevel:Byte;                                                               //Предыдущий уровень
    Patched:TFigureItem;                                                         //Залатанный элемент
    RectForAutor:TRect;                                                          //Область для автора т.е. меня =)
    RectForBonuses:TRect;                                                        //Поле для бонусов
    RectForBonusesMouse:TRect;                                                   //Поле активности мыши для бонусов
    RectForButtons:TRect;                                                        //Поле для кнопок
    RectForChangeMode:TRect;                                                     //Поле для изменения режима инф. дисплея
    RectForExed:TRect;                                                           //Поле для исп. бонусов
    RectForInfoText:TRect;                                                       //Поле для текста
    RectForNextFigure:TRect;                                                     //Поле для след. фигуры
    Redraw:TRedrawing;                                                           //Класс перерисовки
    Score:Cardinal;                                                              //Дисплейный счет
    Shade:TShade;                                                                //"Тень"
    ShowCursos:Boolean;                                                          //Отрисовка собственного курсора
    Shutdowning:Boolean;                                                         //Идет завершение игры
    Sound:TSound;                                                                //Звуковое сопровождение
    StartGold:Cardinal;                                                          //Стартовое золото
    StartSpeed:Word;                                                             //Стартовое значение таймера шага
    Statistics:TStatistics;                                                      //Статистика
    TimerAnalysis:TTimer;                                                        //Таймер анализирования игры
    TimerAnimateFrames:TTimer;                                                   //Таймер аимации кадров персонажа
    TimerBG:TTimer;                                                              //Таймер смены фона
    TimerBonus:TTimer;                                                           //Таймер истечения времени бонусов
    TimerBonusCtrl:TTimer;                                                       //Таймер контроля выполнения бонусов
    TimerBoom:TTimer;                                                            //Таймер обработки тряски
    TimerDraw:TTimer;                                                            //Таймер отрисовки
    TimerStep: TTimer;                                                           //Таймер шага фигуры
    TimerUpValues:TTimer;                                                        //Таймер счета
    TheardDraw:TDrawThread;                                                      //Отдельный поток для отрисовки
    ToGold:Cardinal;                                                             //Золото
    TopPos:Byte;                                                                 //Позиция идущей фигуры сверху
    ToScore:Cardinal;                                                            //Счет
    Versa:Boolean;                                                               //Обратить управление
    UserFPS:Word;                                                                //Предел кадров в сек.
    ZeroGravity:Boolean;                                                         //Невесомость
    function BuyAndExcecute(ABonus:TBonus):Integer;                              //Купить и выполнить бонус (результат - затрата, 0 - не куплен)
    function CalcBrokenBonus:Word;                                               //Анализ игрового поля
    function CheckCollision(TetArray:TTetArray; ATop:Byte; IsShade:Boolean):Boolean; overload; //Проверить измен. фигуру на столкновение на определенной высоте
    function CheckCollision(TetArray:TTetArray; ATop, ALeft:Byte; IsShade:Boolean):Boolean; overload; //Проверить измен. фигуру на столкновение в опред. коорд.
    function CheckCollision(TetArray:TTetArray; IsShade:Boolean):Boolean; overload; //Проверить измен. фигуру на столкновение на высоте фигуры
    function CheckLine:Boolean;                                                  //Проверить на заполнение верхней (скрытой) части поля
    function CheckPause:Boolean;                                                 //Проверить на пауза и на завершение игры
    function CreateBMP(FName:string):TBitmap; overload;                          //Создать BMP
    function CreateBMP(DLL:Cardinal; ID:string):TBitmap; overload;               //Создать BMP из ресурса
    function CreateBonus(var Figure:TFigure):Boolean;                            //Создать бонусы в фигуре
    function CreateFigure(Deg:Word; FigureName:string):TFigure;                  //Создание фигуры (преобразование 10 to 2)
    function DeleteFilled(Row:Byte):Byte;                                        //Удалить заполненные линии, начиная с Row
    function ElemCount(Figure:TFigure):Byte;                                     //Объем фигуры
    function GetNextBoss:TFigure;                                                //Получить следующего босса
    function GetPreviewFigure:TFigure;                                           //Получить случайную фигуру
    function GetRandomFigure:TFigure;                                            //Получить случайную фигуру
    function GetSpeed:Word;                                                      //Текущая скорость
    function GetTop:Byte;                                                        //Узнать высоту заполнения поля
    function HeightOfFigure(AFigure:TFigure):Byte;                               //Высота фигуры
    function Load:Boolean;                                                       //Выполнить загрузку игры
    function LoadGame:Boolean;                                                   //Загрузка игры
    function Max(Val1, Val2:Integer):Integer;                                    //Максимальное из двух значение
    function Min(Val1, Val2:Integer):Integer;                                    //Минимальное из двух значение
    function RotateFigure(Figure:TFigure; OnSentry:Boolean):TFigure;             //Поворот фигуры (со смещением вверх, влево)
    function SaveGame:Boolean;                                                   //Сохранить игру
    function UpGold(Value:Word):Word;                                            //Добавить золота
    function UpScore(Value:Integer):Integer;                                     //Добавить к счету
    function WidthOfFigure(AFigure:TFigure):Byte;                                //Ширина фигуры
    procedure ActuateTimers;                                                     //Активировать необходимые таймеры
    procedure AddButton(AButton:TExtButton);                                     //Добавить кнопку
    procedure AddFigure(Figure:TFigure; var Dest:TArrayOfFigure);                //Добавить фигуру в массив фигур
    procedure AddToActionList(Bonus:TBonus);                                     //Добавить бонус к списку для выполнения в свободное время
    procedure AddToExed(Bonus:TBonus);                                           //Добавить бонус в список только что исп.
    procedure AnimateDelete(ATop:Integer); overload;                             //Выполнить удаление элементов в строке ATop
    procedure AnimateDelete(ATop:Integer; Elems:TFiguresL2); overload;           //Выполнить удаление некоторых элементов на высоте ATop
    procedure Boom(Size:Byte; BTime:Word);                                       //Тряска
    procedure BoomStop;                                                          //Остановить тряску
    procedure ContinueGame;                                                      //Продолжить сохраненную игру
    procedure CreateBonuses;                                                     //Заполнить список бонусов
    procedure CreateButtons;                                                     //Заполнить список кнопок
    procedure CreateFigures;                                                     //Создать фигуры
    procedure CreateFonts;                                                       //Создание шрифтов
    procedure CreateGameKeys;                                                    //Создание игровых клавиш
    procedure CreateGraphicsAndSound;                                            //Инициализация графики и звука
    procedure CreateHints;                                                       //Создание подсказок
    procedure CreateNextBoss;                                                    //Следующая фигура - босс
    procedure CreateNextFigure;                                                  //Создать следующую фигуру
    procedure CreatePanels;                                                      //Заполнить список панелей
    procedure CreateRectAreas;                                                   //Создание областей реагирования
    procedure CreateTimers;                                                      //Создание таймеров
    procedure ChangeBackground(ALevel:Byte);                                     //Сменить фон
    procedure ClearAll;                                                          //Очистить все поля
    procedure ClrChng(var Chng:TTetArray);                                       //Очистить изм. массив
    procedure DeactivateAllBonuses;                                              //Деактивировать все бонусы
    procedure DecGold(Cost:Word);                                                //Снять золото
    procedure DeleteSaved;                                                       //Удалить сохр. игру
    procedure Draw;                                                              //Отрисовка на холсте
    procedure DrawBonuses;                                                       //Рисовать бонусы
    procedure DrawingFigure;                                                     //Включить режим редактирования след. фигуры
    procedure DrawingFigureClose(State:TGameState);                              //Выключить режим ред. с выходом из игры
    procedure DrawingFigureEnd(State:TGameState);                                //Выключить режим ред.
    procedure ExecuteBonus(Bonus:TBonus);                                        //Выполнить бонус
    procedure ExecuteRandomBonus(TB:TTypeBonus);                                 //Выполнить случайный бонус
    procedure ExecutingDelete;                                                   //Проверить и удалить заполненные строки
    procedure Event(e, param1, param2:Integer);                                  //Событие
    procedure HideButtons(ShowAnimate:Boolean);                                  //Скрыть кнопки управления (Показывать анимацию скрытия)
    procedure KeyDown;                                                           //Действие клавиши вниз
    procedure KeyLeft;                                                           //Действие клавиши влево
    procedure KeyRight;                                                          //Действие клавиши вправо
    procedure KeyRotateLeft;                                                     //Действие клавиши поворот влево
    procedure KeyRotateRight;                                                    //Действие клавиши поворот вправо
    procedure KeyUp;                                                             //Действие клавиши вверх
    procedure LevelUp;                                                           //Увеличить уровень
    procedure LinesUp(Value:Integer);                                            //Увеличить кол-во удаленных линий
    procedure Merger;                                                            //Слияние осн. поля и фигуры
    procedure Move(Bottom:Byte);                                                 //Удалиние линии
    procedure MoveMouse;                                                         //Убрать мышь с поля
    procedure NeedDraw;                                                          //Принудительная отрисовка
    procedure NewFigure;                                                         //Новая фигура
    procedure NewGame;                                                           //Новая игра
    procedure Normalization(var Figure:TFigure);                                 //Нормализовать фигуру
    procedure OnBonusExecuted(Bonus:TBonus);                                     //После выполнения бонуса
    procedure OnBonusStartExecute(Bonus:TBonus);                                 //Перед выполнением
    procedure OnKeyDown(Key:Word; Shift:TShiftState);                            //При нажатии клавиши
    procedure OnKeyPress(Key:Char);                                              //При нажатии клавиши (Символ)
    procedure OnMouseDown(Button:TMouseButton; Shift:TShiftState; X, Y: Integer);//При нажатии кнопки мыши
    procedure OnMouseMove(Shift:TShiftState; X, Y: Integer);                     //При перемещении мыши
    procedure OnMouseUp(Button:TMouseButton; Shift:TShiftState; X, Y: Integer);  //При отпускинии кнопки мыши
    procedure PauseGame;                                                         //Пауза
    procedure Reset;                                                             //Сбросить значения
    procedure RotateGameFigure(OnSentry:Boolean);                                //Повернуть текущую фигуру
    procedure ShowAnimate(ID:Byte);                                              //Установить нужную анимацию
    procedure ShowButtons;                                                       //Показать кнопки
    procedure ShowFigureChanging(FStart, FEnd:TFigure);                          //Анимация изменения фигуры
    procedure ShowGoldDec(Size:Word);                                            //Показать сколько золота убыло (-Size)
    procedure ShowHideButtons;                                                   //Показать/скрыть кнопки
    procedure Shutdown;                                                          //Завершение работы программы
    procedure SpeedDown(Value:Byte);                                             //Понизить скорость
    procedure SpeedUp(Value:Byte);                                               //Повысить скорость
    procedure StepDown;                                                          //Упустить фигуру на одну линии (шаг)
    procedure StepDownBonuses;                                                   //Шаг таймеров бонусов
    procedure StepLeft;                                                          //Сместить влево
    procedure StepRight;                                                         //Сместить вправо
    procedure StopGame;                                                          //Закончить игру
    procedure StepUp;                                                            //Сместить вверх
    procedure TimerAnalysisTimer(Sender: TObject);                               //Обработка таймера для анализа игры
    procedure TimerAnimateFramesTimer(Sender: TObject);                          //Обработка анимационных кадров
    procedure TimerBGTimer(Sender: TObject);                                     //Обработка смены фона
    procedure TimerBonusCtrlTimer(Sender: TObject);                              //Обработка очереди бонусов
    procedure TimerBonusTimer(Sender: TObject);                                  //Обработка таймеров бонусов
    procedure TimerBoomTimer(Sender: TObject);                                   //Обработка тряски
    procedure TimerDownStart;                                                    //Запуск таймера движения
    procedure TimerDownStop;                                                     //Остановка таймера движения
    procedure TimerDrawTimer(Sender: TObject);                                   //Обработка отрисовки
    procedure TimerStepTimer(Sender: TObject);                                   //Обработка шага
    procedure TimerUpValuesTimer(Sender: TObject);                               //Обработка значений
    procedure Tutorial(Scene:Byte);                                              //Туториал определённой сцены
    procedure UpdateSpeed;                                                       //Обновить скорость движения фигуры
    procedure UseAllExcept(IDOfTheFigure:Byte);                                  //Исп. все фигуры кроме одной
    procedure UseAllFigures;                                                     //Исп. все фигуры
    procedure UseOnly(IDOfTheFigure:Byte);                                       //Исп. только один тип фигуры
    procedure Wait(MTime:Word);                                                  //Подождать
    procedure WaitWithoutStop(MTime:Word);                                       //Подождать без остановки игры
    procedure WriteDebug(Text:string);                                           //Запись в отладочный файл
    property ButtonsHided:Boolean read FButtonsHided;                            //Скрыты ли кнопки
    property Cols:Byte read FCols default 15;                                    //Кол-во столбцов
    property EditBoxActive:Boolean read FEditBoxActive;                          //Активность поля для ввода имени игрока (Статистика)
    property GameState:TGameState read FGameState write SetGameState;            //Состояние игры
    property Helper:Boolean read FHelper write SetHelper;                        //Помошник
    property InfoMode:TInfoMode read FInfoMode write SetIM;                      //Режим инф. дисп.
    property Level:Byte read GetLevel write SetLevel;                            //Уровень
    property Levels[Index :Byte]:Boolean read GetFLevel;                         //Список уровней
    property Lines:Integer read FLines write SetLines;                           //Собранные и удаленные линии
    property Rows:Byte read FRows default 23;                                    //Кол-во строк
    property ScaleLvl:Byte read GetScaleLvl;                                     //Шкала линий
    property SHeight:Byte read FHeight default 20;                               //Высота ячеек
    property SWidth:Byte read FWidth default 20;                                 //Ширина ячеек
    property Timers:Boolean read FTimerActivate write SetTimers;                 //Активность таймеров
    constructor Create(FCanvas:TCanvas);                                         //Конструктор
  end;

А вот некоторые типы и классы:

  TBitmaps     = class;                                                         //Графические объекты (картинки)
  TBonus       = class;                                                         //Основа бонуса
  TExtButton   = class;                                                         //Графическая кнопка (не control)
  THelpObject  = class;                                                         //Подсказка
  TLineClear   = class;                                                         //Линия удаления (для отрисовки анимированного стирания)
  TSimpleBonus = class;                                                         //Простой бонус
  TSound       = class;                                                         //Звуковое сопровождение (потоки звуков, bass.dll)
  TTetrisGame  = class;                                                         //Движок игры
  TTextHint    = class;                                                         //Простая подсказка
  TTextPanel   = class;                                                         //Текстовая панель
  TTimeBonus   = class;                                                         //Временной бонус
  TRedrawing   = class;                                                         //Клаасс перерисовки
  TStatistics  = class;                                                         //Статистика
  TAppendStat  = class;                                                         //Математика статистики
  TGameKey     = class;                                                         //Игровая клавиша

  TState = (bsEmpty, bsElement, bsBonus, bsBonusTiming, bsBonusBroken);         //Состояние элемента (Пусто, Элемент фигуры, Бонус, Бонус (Таймер), Бонус (Сломан))
  TFigureItem = record                                                          //Элемент фигуры
   ID:Byte;                                                                      //Идентификатор элемента (фигуры)
   State:TState;                                                                 //Состояние
   TimeLeft:Word;                                                                //Осталось времени (для бонуса)
  end;
  TClearFigureItem = record                                                     //Удаляемый элемент
   X, Y:Extended;                                                                //Текущие координаты
   Speed:Byte;                                                                   //Скорость
   Angle:Smallint;                                                               //Угол отклонения
  end;
  TExing = record                                                               //Элемент массива выполненных бонусов
   Bonus:TBonus;                                                                 //Бонус
   Active:Boolean;                                                               //Есть ли элемент в сетке
  end;
  TElements = array[1..GlSize, 1..GlSize] of TFigureItem;                       //Матрица элементов фигуры
  TFigure = record                                                              //Одна фигура
   Allowed:Boolean;                                                              //Доступность
   Elements:TElements;                                                           //Элементы фигуры
   Name:string;                                                                  //Название
  end;
  TStatRecord = record                                                          //Запись статистики
   Gold:Cardinal;                                                                //Кол-во золота
   Score:Cardinal;                                                               //Счет
   Lines:Cardinal;                                                               //Кол-во удаленных линии
   Figure:Cardinal;                                                              //Кол-во сброшенных фигур
   Level:Byte;                                                                   //Уровень
  end;
  TStatTop = record                                                             //Запись топ - игрока
   Name:string[255];                                                             //Имя
   Score:Cardinal;                                                               //Счет
  end;
  TGameKeyInfo = record                                                         //Структура информации о клавише
   Code:Word;                                                                    //Код клавиши
   FForceDown:Word;                                                              //Время в нажатом состоянии (мс)
   Name:string;                                                                  //Название
  end;


  TArrayOfButton = array of TExtButton;                                         //Массив кнопок
  TArrayOfClears = array[1..GlRows] of TLineClear;                              //Удаляющие классы
  TArrayOfExing  = array[1..GlExes] of TExing;                                  //Список выполннеых бонусов
  TArrayOfFigure = array of TFigure;                                            //Массив имеющихся фигур
  TArrayOfPanels = array of TTextPanel;                                         //Массив текстовых панелей
  TBonuses       = array of TBonus;                                             //Список бонусов
  TBonusType     = (btForAll, btForGame, btForUser);                            //Тип доступа к бонусам
  TDrawType      = (dtNotWork, dtNone, dtElement, dtEmpty);                     //Режим рисования (Не рисуем, ожидание, рисуем, стираем)
  TFiguresL1     = array[1..GlCols] of TClearFigureItem;                        //Список удаляющихся элементов
  TFiguresL2     = array[1..GlCols] of TFigureItem;                             //Список удаляемых элементов
  TGameKeys      = array of TGameKey;                                           //Список игровых клавиш
  TButtonState   = (bsNormal, bsOver, bsDown);                                  //Состояние кнопки
  TButtonType    = (btFigure, btPicture);                                       //Тип кнопки (Фигура, рисунок)
  TGameState     = (gsNone, gsPlay, gsPause, gsStop, gsDrawFigure, gsShutdown); //Состояние игры (Нет, Идет игра, На паузе, Конец игры, Рисует фигуру, Завершение игры)
  TInfoMode      = (imInfoText, imBonuses, imTransforming);                     //Режим инф. дисплея
  TLevels        = array[1..GlLvls] of Boolean;                                 //Массив уровней
  TPoints        = array[0..255] of TPoint;                                     //Массив точек для полигона (для кнопки)
  TProcedure     = procedure of object;                                         //Процедура
  TTetArray      = array[1..GlRows, 1..GlCols] of TFigureItem;                  //Основной тип - поле
  TTypeBonus     = (tbCare, tbBad, tbGood);                                     //Вид бонуса (Нейтральный, отрицательный, положительный)

Весь код, от начала до конца прокомментирован и объяснён (за исключением повторений и мелочей).

Как и все мои остальные графические приложения, игра Тетрис работает без стороннего графического движка, лишь средствами GUI и некоторых наработок и хитростей. Например, здесь отрисовка выполнена в отдельном потоке “TDrawThread” (при чем без синхронизации). Также управление осуществляется не с помощью событий от ОС, а по средством проверки нажатия клавиш классом “TGameKey” для каждой необходимой клавиши:

procedure TTetrisGame.CreateGameKeys;

  function AddKey(KC:Word; UN:string; AAction:TProcedure; FTime, MTime:Word):Byte;
  begin
   SetLength(GameKeys, Length(GameKeys) + 1);
   Result:=Length(GameKeys) - 1;
   GameKeys[Result]:=TGameKey.Create(Self);
   with GameKeys[Result] do
    begin
     with GameKeyInfo do
      begin
       Code:=KC;
       Name:=UN;
      end;
     Action:=AAction;
     StartTime:=FTime;
     MinTime:=MTime;
    end;
  end;

begin
 //Создаем специальные игровые клавиши управления
 FKeyIDDown:= AddKey(VK_DOWN,  'Вниз',   KeyDown, 100, 20);    //Стрелка вниз/"S"
 FKeyIDUP:=   AddKey(VK_UP,    'Вверх',  KeyUp, 150, 50);      //Стрелка вверх/"W"
 FKeyIDLeft:= AddKey(VK_LEFT,  'Влево',  KeyLeft, 150, 50);    //Стрелка влево/"A"
 FKeyIDRight:=AddKey(VK_RIGHT, 'Вправо', KeyRight, 150, 50);   //Стрелка вправо/"D"
 FKeyIDRL:=AddKey(Ord('Q'), 'Поворот фигуры против часовой стрелки', KeyRotateLeft, 200, 50);
 FKeyIDRR:=AddKey(Ord('E'), 'Поворот фигуры по часовой стрелке',     KeyRotateRight, 200, 50);
 //Укажем количество клавиш
 FGameKeyCount:=Length(GameKeys);
 //Установка противостоящих клавиш
 GameKeys[FKeyIDDown].Contradiction:=FKeyIDUP;
 GameKeys[FKeyIDUP].Contradiction:=FKeyIDDown;
 GameKeys[FKeyIDLeft].Contradiction:=FKeyIDRight;
 GameKeys[FKeyIDRight].Contradiction:=FKeyIDLeft;
 GameKeys[FKeyIDRL].Contradiction:=FKeyIDRR;
 GameKeys[FKeyIDRR].Contradiction:=FKeyIDRL;
end;

Что позволило реализовать ещё и степень “нажатия” на клавишу, подсчетом времени её в нажатом состоянии. Также это повысило отклик нажатий и устранило обработку окном и прочими элементами управления, которые могли бы этому помешать.

Таблица бонусов:

№ п/п Название Описание Оценка полезности Приватность $ Уровни
1 Заполнение Заполнить всё поле 120,00 Только игрок 1000 1-15
2 Очистка Очистить всё поле 110,00 Только игрок 500 1-15
3 Удар-пресс Сместить элементы вниз в пустые места 100,00 Общий 300 4-15
4 Невесомость Включить или выключить гравитацию 100,00 Только игрок 250 1-13
5 Град Рассыпать бонусы по фигурам 90,00 Общий 1300 1-13
6 Призрак Позволяет проходить сквозь элементы 55,00 Общий 200 1-13
7 Карандаш Позволяет отредактировать следующую фигуру 50,00 Только игрок 200 1-15
8 Дубликат Использовать только следующий тип фигур (20 сек) 40,00 Общий 150 1-13
9 Пластырь Залатать все одиночные «дыры» 30,00 Общий 100 2, 5-15
10 Помощник Отображает конечный пункт фигуры (2 мин) 20,00 Общий 90 1-15
11 Фигура Сменить следующую фигуру 20,00 Общий 80 1-15
12 Болото Активирует/деактивирует режим “Болото” 15,00 Общий 70 1-15
13 Нож Срезает самую верхнюю часть 10,00 Общий 50 1, 3-15
14 Лазер Срезает верхний слой каждого столбца 5,00 Общий 20 1-6, 10-15
15 Исключение Исключить один тип фигур (40 сек) 0,00 Только игра 1-13
16 Босс Вызвать босса текущего уровня -5,00 Только игра 1-15
17 Дождь Разбросать элементы поля -5,00 Только игра 1-13
18 Дробь Делает выстрел дробью -10,00 Только игра 1-15
19 Ой, ой Меняет местами кнопки управления -20,00 Только игра 1-13
20 Вылазка Выдавить фигуру со стороны поля -30,00 Только игра 1-15
21 Дьявол Сам дьявол управляет фигурой (22 сек) -40,00 Только игра 1-15

 

Скриншоты игры

С каждым новым уровнем вы не только будете переживать падение замысловатой фигуры -босса, но и увидите новые пейзажи.


123456

Совместно с написанием игры вёлся лог, который можно скачать здесь.

Скачать готовую игру

Tetris.rar10,9 МБ

Скачать исходники

Tetris_sources.rar15,2 МБ

Share

You may also like...

19 комментариев

  1. А теперь импортни ее на андройд,введи монетизацию и профит получай.Проект ж реально лютый,на андройде такие тайм киллеры в топах висят. А у тебя качественно и красиво реализовано.

  1. 23.10.2017

    obat kondiloma akuminatum

    Hallo i particularly like about the picture / article / presentation that you describe. Very unique, interesting and useful. denature Indonesia yaitu sebuah perusahaan yang fokus dalam bidang obat herbal aman dan ampuh tanpa efek samping. obat kami san…

  2. 21.12.2018

    Google

    The time to read or stop by the subject material or web sites we’ve linked to beneath.

  3. 24.12.2018

    Hot Latina dance

    […]the time to study or visit the content material or internet sites we have linked to below the[…]

  4. 24.12.2018

    sexy Latina dance

    […]please check out the internet sites we follow, like this a single, because it represents our picks in the web[…]

  5. 25.12.2018

    drive intelbras wbn 240 win 7

    […]The information and facts mentioned inside the article are some of the very best obtainable […]

  6. 25.12.2018

    England Rugby Store

    […]usually posts some incredibly intriguing stuff like this. If you’re new to this site[…]

  7. 25.12.2018

    sexy cam performers

    […]we prefer to honor numerous other online web-sites on the internet, even if they aren’t linked to us, by linking to them. Beneath are some webpages really worth checking out[…]

  8. 25.12.2018

    Hot live females

    […]we prefer to honor several other world wide web web-sites around the net, even though they aren’t linked to us, by linking to them. Below are some webpages worth checking out[…]

  9. 25.12.2018

    MP3 Youtube Converter

    […]that will be the finish of this report. Right here you’ll come across some websites that we consider you’ll appreciate, just click the links over[…]

  10. 26.12.2018

    Free adult sex

    […]The information talked about within the post are several of the best readily available […]

  11. 26.12.2018

    Free sexy cams

    […]Here is an excellent Weblog You may Find Fascinating that we Encourage You[…]

  12. 27.12.2018

    Funny Instagram

    […]Here is a great Weblog You might Obtain Exciting that we Encourage You[…]

  13. 27.12.2018

    Free chat

    […]Here are a number of the web-sites we advocate for our visitors[…]

  14. 27.12.2018

    Free adult

    […]Wonderful story, reckoned we could combine a number of unrelated data, nonetheless seriously really worth taking a search, whoa did 1 learn about Mid East has got more problerms also […]

  15. 28.12.2018

    Yeah yeah

    […]usually posts some pretty exciting stuff like this. If you are new to this site[…]

Добавить комментарий