Очень хочется рассказать про мою самую любимую разработку – игру Тетрис. Начиналось всё с обычной проверки “смогу ли”. Это была как раз производственная практика в колледже, времени было полно. Практику я проходил с другом, по этому он мне подкинул идею добавить в игру бонусы и прочие мелочи.
Ну а дальше больше. Появилась анимация, огромное кол-во бонусов, которые нужно было покупать, отрицательные бонусы, которые либо вызывались “плохой” игрой, либо неудачным выбором.
На данный момент размер основного кода насчитывает более 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 |
Скриншоты игры
С каждым новым уровнем вы не только будете переживать падение замысловатой фигуры -босса, но и увидите новые пейзажи.
Совместно с написанием игры вёлся лог, который можно скачать здесь.
А теперь импортни ее на андройд,введи монетизацию и профит получай.Проект ж реально лютый,на андройде такие тайм киллеры в топах висят. А у тебя качественно и красиво реализовано.
Если реализовать игру без графического движка – как здесь – она будет очень сильно глючить даже на самом мощном смартфоне. В противном случае нужно изучать движок, например “Unity” или может какой-нибудь другой. При импорте этой игры из всего кода сохранится лишь идея.
а что тебя сдерживает оптимизировать её под смарты?
Нужно движок какой-нибудь изучать. А времени нет. Да и желания тоже.