Игра 2048 на Pascal ABC .NET

Попросил меня однажды один человек помочь ему с курсовой. Все делали что-то простенькое, а он вот решил выделиться, замахнулся на игру, даже начал, но потом он понял, что как-то не понимает некоторых вещей, поэтому обратился за помощью ко мне 🙂
Ну а я что… Помог ему, конечно же! Да и самому было интересно! А теперь расскажу о некоторых подробностях и «возможностях» игры, а также ниже можно будет ссылку на исходники найти 🙂 

Если честно, до этого мало дел имел с паскалем, к тому же, с паскалем .net!
Открыв наброски, которые тот человек уже сделал, увидел модули GraphABC, ABCObjects, с которыми раньше не приходилось работать.
Но до меня уже была часть работы сделана, а именно создание окна нужного размера и размещение «сетки» квадратиков 4х4.
Это облегчило задачу, потому что я увидел, что много схожестей есть с обычными паскалевскими объектами или графическими примитивами, а тут ещё удобство было в том, что все эти объекты (квадратики, кружочки и другие штуки) сами отвечают за свою прорисовку, не нужно рисовать на canvas-е и т.д., тут можно просто указать новую позицию или ещё как-то изменить объект, а перерисуется он уже сам!
И тут началась разработка! Никогда не приходилось до этого делать игру 2048, но найдя на просторах интернетов браузерную реализацию данной игры, пришлось поиграть в неё, опробовать разные ситуации, чтобы наглядно ознакомиться с правилами. Оттуда же были стянуты цвета и записаны в несколько чудном формате, потому что оказалось, что данный паскаль не поддерживает запись цветов через $, как это сделано в том же Delphi, например )
Вот такой вышел код, который возвращал нужный цвет текста и фона, в зависимости от цифры.

//получить цвет в зависимости от цифры
function getSquareColorByNumber(num: integer): TSquareColor;
begin
  case num of
    2: result := createColor(rgb(238, 228, 218), rgb(119, 110, 101));
    4: result := createColor(rgb(237, 224, 200), rgb(119, 110, 101));
    8: result := createColor(rgb(242, 177, 121), rgb(249, 246, 242));
    16: result := createColor(rgb(245, 149, 99), rgb(249, 246, 242));
    32: result := createColor(rgb(246, 124, 95), rgb(249, 246, 242));
    64: result := createColor(rgb(246, 94, 59), rgb(249, 246, 242));
    128: result := createColor(rgb(237, 207, 114), rgb(249, 246, 242));
    256: result := createColor(rgb(237, 204, 97), rgb(249, 246, 242));
    512: result := createColor(rgb(237, 200, 80), rgb(249, 246, 242));
    1024: result := createColor(rgb(237, 197, 63), rgb(249, 246, 242));
    2048: result := createColor(rgb(237, 194, 46), rgb(249, 246, 242));
    4096: result := createColor(rgb(60, 58, 50), rgb(249, 246, 242));
    else result := createColor(rgb(238, 228, 218), rgb(119, 110, 101));
  end;
end;

TSquareColor — это запись, хранящая в себе фоновый цвет и цвет текста. Функция createColor принимает на вход первым параметром цвет фона, а вторым — цвет текста и возвращает уже заполненную запись TSquareColor, которая потом уже используется для задания цвета определённой клеточки )

Вообще, код неплохо откомментирован. В некоторых местах даже избыточно, т.к. это курсовая работа, пришлось комментировать почти всё 🙂
А некоторые куски кода, которые можно было бы оптимизировать и вынести в отдельную функцию, лишь изменяя некоторые параметры, пришлось оставить так, как есть, задублированными… )
Поэтому всякие объяснения можно найти в коде!
Сразу скажу, что настройки размера поля, отступов клеточек друг от друга, другие отступы, настройки анимации и т.д. можно задавать тоже в коде, эти константы вынесены специально для этих целей )

Настало время показать, как это дело выглядит! А вот так:

Игра 2048. Окно программы в самом разгаре игры!

Ничего особенного. Всё как обычно )

А в заголовке отображается ещё и количество очков. Управление то же самое, как и в классической реализации игры. Поведение тоже )
При появлении и сложении клеточек есть анимация небольшая, которая порой работает кривовато… Тут уж был задействован таймер, а также изменение размеров этих блоков. Иногда просто почему-то размер не доходит до начального состояния, и поэтому некоторые клеточки так и остаются немного больше или меньше, но это происходит редко )

Также был написан небольшой класс для показа «диалоговых» окон, который содержит в себе простенькую реализацию некоего подобия окна подтверждения (которое содержит вопрос и кнопки ОК и Отмена). Суть в том, что можно динамически создавать эти диалоговые окошки, модально показывать их, реагируют они также на нажатия клавиши Esc (отмена) и Enter (ок).
Также можно показывать просто уведомление с кнопкой Ок!
Простенько, но большего и не нужно.. ) Даже это уже было лишним 🙂
Код класса этого находится в файле controlUtils.pas, который тоже находится в архиве 🙂
Выглядят окошки примерно вот так:

Игра 2048. Вопрос о начале новой игры (при нажатии на Esc)
Игра 2048. Конец игры. Лол!

Про модальные диалоги я, конечно, загнул немножко )
Вся модальность работает вот так:

procedure KeyDown(Key: integer);
begin
  //если открыто какое-то диалоговое окно!
  if dialogs.modalVisible then
  begin
    case Key of
      VK_RETURN: dialogs.pressOK;
      VK_ESCAPE: dialogs.closeLastDialog();
    end;
    exit;
  end;
  
  //если нет открытого диалогового окна
  case Key of 
    VK_UP: move(tdUp);
    VK_DOWN: move(tdDown);
    VK_LEFT: move(tdLeft);
    VK_RIGHT: move(tdRight);
    VK_Escape: dialogs.showConfirm('Вы действительно хотите начать заново?', newGame);
  end; 
end;

 
Обрабатываются нажатия в главном окне программы, а там уже идёт проверка, если открыто какое-то диалоговое окно, то нужно обрабатывать нажатия несколько иначе, а если же нет никаких окон, то там уж управлять игрой нужно )
При нажатии мышкой на кнопку ОК или Enter на клавиатуре срабатывает уже определённое заданное событие, которое передаётся как callback (типа того) при вызове функции dialogs.showConfirm. Как-то так оно и работает… )

Прикольно, в общем. Остальное можно найти в коде и в комментариях, которых там, как уже было сказано выше, предостаточно.

Были некоторые идеи, типа сохранения состояния игры при закрытии и восстановление при открытии, но как-то не было в этом необходимости, да и интерес через некоторое время пропал, поэтому всё осталось на таком уровне, на котором есть сейчас. К тому же, для курсовой тому человеку всех этих окошек диалоговых не нужно, поэтому на каком-то этапе он просто оставил старую версию и стал дорабатывать её по-своему )

Скачать исходник и готовый ехе-шник, который, кстати, весит довольно мало из-за .Net, можно вот в этом замечательном архиве: http://shpirat.net/etc/2048_PascalABC.NET.zip

Сделано это всё было ещё осенью, но сейчас стало можно это опубликовать, может, ещё кому-то пригодится или же просто интересно будет 🙂

Вам также может понравиться

About the Author: karamush

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

Войти с помощью: 

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Докажи, что ты избранный! * Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.