Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 12.01.2015, 17:05   #1
NIKOLAYY2
Форумчанин
 
Регистрация: 23.12.2014
Сообщений: 220
По умолчанию Алгоритм создания игры тетрис

Давайте рассмотрим общий алгоритм, в гугле тем много, а толкового ни чего так и не удалось найти.

Рассмотрим хотябы такие вопросы:
1) Что взять за основу фигуры тетриса
2) Как организовать движение фигур
3) Как организовать поворот фигуры
4) Как организовать столкновение фигуры (когда она упала)
Ну и прочие вопросы.

В приемере на картинке за основу я взял шейп и имагу. (ли что-то другое удобнее будет?)
Алгоритм движения фигуры у меня представляется таким образом. Если фигура состоит из четырех компонентов типа "шейп" то в качестве передачи движения фигуры мы передаем координаты Left и Top нижнему шейпу, а этот шейп автоматически уже связан с остальными своими "соседями". Ну что-то на подобие примера кораблик из книги Культина метод (базовой точки)

Поворот, что значит поворот для фигуры из шейпов? Я так понимаю это просто задание шейпам принять новые координаты на форме? Верно нет?
Поворот для имаги я думаю проще организовать проще сменой ее картинки на другую, уже повернутую.

Столкновение, Фигура упала. К шейпу ладно можно привязаться и к координатам, но к имаге к координатам уже непривяжешся, если имга упала то это незначит что фигура уже упала...

Кто-то может уже создавал подобное и столкнулся с какими-то проблемами, а кто-то уже и создал и все получилось.
Ваше мнение и предложения по реализации данной игры?
Изображения
Тип файла: jpg 3333.jpg (75.3 Кб, 586 просмотров)
NIKOLAYY2 вне форума Ответить с цитированием
Старый 12.01.2015, 17:35   #2
NetSpace
Участник клуба
 
Аватар для NetSpace
 
Регистрация: 03.06.2009
Сообщений: 1,871
По умолчанию

на, не мучайся. скачай архив, попробуй игрушку и скажи, надо ли тебе исходник. пробел - пауза. управляющие кнопки - стрелки
PS. белая точка заполняет пустоту, чёрная - прожигает всё до низа. я всегда играю на 11-м уровне, но больше 245 очков сам не смог набрать
PPS. я просто взял чужой написанный код, находящийся в свободном доступе, разобрался в нём, немного свихнулся, немного добавил своего в геймплей и доработал количество фигур, добавил уровни и ещё пару штучек.
Изображения
Тип файла: jpg 11111.jpg (75.3 Кб, 609 просмотров)
Вложения
Тип файла: rar Tetris4.rar (143.2 Кб, 365 просмотров)
Программирование - это единственный способ заставить компьютер делать то, что тебе хочется, а не то, что приходится.

Последний раз редактировалось NetSpace; 12.01.2015 в 17:42.
NetSpace вне форума Ответить с цитированием
Старый 12.01.2015, 17:47   #3
NIKOLAYY2
Форумчанин
 
Регистрация: 23.12.2014
Сообщений: 220
По умолчанию

NetSpace
Ага скачал нормальная игра, жалко исходника нету
NIKOLAYY2 вне форума Ответить с цитированием
Старый 12.01.2015, 17:53   #4
NetSpace
Участник клуба
 
Аватар для NetSpace
 
Регистрация: 03.06.2009
Сообщений: 1,871
По умолчанию

держи исходник. вот там и разберёшься: как они сталкиваются, как поворачиваются и прочие вопросы. на при мерах - самое то изучать. если помог - жми на весы
Вложения
Тип файла: rar Tetris_4.rar (322.7 Кб, 623 просмотров)
Программирование - это единственный способ заставить компьютер делать то, что тебе хочется, а не то, что приходится.

Последний раз редактировалось NetSpace; 12.01.2015 в 17:57.
NetSpace вне форума Ответить с цитированием
Старый 12.01.2015, 22:57   #5
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Какие шейпы, какие имейджи ? Для игр на дельфи эти вещи практически бесполезны.
Делать такое стоит на массивах и структурном программировании - на процедурах по сути. Скинутый код, конечно, неплох в этом плане, но в нём есть много других косяков, в основном по стилю, но и по архитектуре и инфраструктуре не очень. Поэтому, лучше для образовательных целей писать с нуля, максимум изучив код и реализовывая его суть, но своими конструкциями.

А вообще теме место в игровом разделе. Будет неплохо , если Вы туда переместитесь (согласовав с модератором) и будете освещать ход работы, чтобы народ как раз мог поправлять и направлять.
phomm вне форума Ответить с цитированием
Старый 12.01.2015, 23:57   #6
NIKOLAYY2
Форумчанин
 
Регистрация: 23.12.2014
Сообщений: 220
По умолчанию

Цитата:
Какие шейпы, какие имейджи ? Для игр на дельфи эти вещи практически бесполезны.
А что для такой игры подойдет? Ведь из чего-то же нужно создавать фигуры.
Цитата:
Делать такое стоит на массивах
Да, согласен.
Цитата:
Поэтому, лучше для образовательных целей писать с нуля
Вот я это и хотел, чтобы разобраться что к чему, исходник я смотрел, но я там мало что понял, я даже непонял из чего там фигуры тетриса сделаны, сложный пример просто, вроде как заливка каких-то областей компонента Image, что-ли которые и прорисовывают фигуру.
Цитата:
А вообще теме место в игровом разделе. Будет неплохо
Да давайте переместим.
NIKOLAYY2 вне форума Ответить с цитированием
Старый 13.01.2015, 01:25   #7
NIKOLAYY2
Форумчанин
 
Регистрация: 23.12.2014
Сообщений: 220
По умолчанию

Хорошая идея была вот эта например:
Заливка каких-то областей компонента Image, что-ли которые и прорисовывают фигуру.
Решил ее воссоздать в примитивном виде, получилось примерно следующее, пока просто по клику мыши рисую фигуры, левой кнопки простая заливка, правой заливка картинкой.
Разлинеил область Image так же программно и прописал цифры в каждой получившейся ячейке.
Код:
const
  KOL_X = 10; //количество ячеек по ширине
  KOL_Y = 15; //количество ячеек по высоте
  RAZM_X = 30; //ширина ячейки в пикселях
  RAZM_Y = 30; //высота ячейки в пикселях

var
  Form1: TForm1;
  mr: TRect; //область (ячейка)
  i, j: Integer; //цикл
  nn: Integer; //для номеров ячеек
  nx: Integer; //коодината ячейки по X
  ny: Integer; //коодината ячейки по Y

implementation

{$R *.dfm}

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  //mr - здесь область наложения с функцией масштабирования
  mr := Rect(X div RAZM_X * RAZM_X, Y div RAZM_Y * RAZM_Y, X div RAZM_X * RAZM_X
    + RAZM_X, Y div RAZM_Y * RAZM_Y + RAZM_Y);

  //заливка областей имаги цветом
  if Shift = [ssLeft] then
    with Image1.Canvas do
    begin
      Brush.Color := clRed;
      FillRect(Rect(X div RAZM_X * RAZM_X, Y div RAZM_Y * RAZM_Y, X div RAZM_X *
        RAZM_X + RAZM_X, Y div RAZM_Y * RAZM_Y + RAZM_Y));
    end;

  //заливка областей имаги картинкой
  if Shift = [ssRight] then
    with Image1.Canvas do
    begin
      Image1.Canvas.StretchDraw(mr, Image2.Picture.Bitmap);
    end;

  //координаты уже самой ячейки
  nx := X div RAZM_X;
  ny := Y div RAZM_Y;
  Label1.Caption := ' nx = ' + IntToStr(nx) + ', ny = ' + IntToStr(ny);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  //==============================================================================
// Ширина имаги = ширина ячейки * на количество ячеек
// Тоже самое с высотой
//==============================================================================
  Image1.Width := RAZM_X * KOL_X;
  Image1.Height := RAZM_Y * KOL_Y;

  //рисуем вертикальные линии
  for i := 0 to KOL_X do
  begin
    Image1.Canvas.MoveTo(i * RAZM_X, 0); //Начальные координаты линии
    Image1.Canvas.LineTo(i * RAZM_X, RAZM_Y * KOL_Y); //Конечные координаты линии
  end;

  //рисуем горизонтальные линии
  for i := 0 to KOL_Y do
  begin
    Image1.Canvas.MoveTo(0, i * RAZM_Y); //Начальные координаты линии
    Image1.Canvas.LineTo(RAZM_X * KOL_X, i * RAZM_Y); //Конечные координаты линии
  end;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  Image1.Canvas.Font.Size := 8;
  for j := 0 to KOL_Y - 1 do
    for i := 0 to KOL_X - 1 do
    begin
      inc(nn);
      Image1.Canvas.TextOut(i * RAZM_X + 5, j * RAZM_Y + 5, IntToStr(nn));
    end;
end;

end.
Если пробовать идти по этому направлению, то можно создавать массив и передавать уже раскраску областей при помощи массива и таймера.
Изображения
Тип файла: jpg 2222.jpg (72.8 Кб, 155 просмотров)
Тип файла: jpg 1111.jpg (83.6 Кб, 497 просмотров)
NIKOLAYY2 вне форума Ответить с цитированием
Старый 13.01.2015, 12:56   #8
disbnt
Пользователь
 
Регистрация: 18.09.2014
Сообщений: 32
По умолчанию

Цитата:
1) Что взять за основу фигуры тетриса
Двухмерный массив со значениями 1 и 0
Цитата:
2) Как организовать движение фигур
Поле игры тоже в двухмерный массив и перемещать фигуру в массиве с некоторыми проверками
Цитата:
3) Как организовать поворот фигуры
Вот для этого я бы использовал равномерный массив фигуры.
Нужно менять значение (x,y) массива в нужном вам направлении.
То есть переворачивать массив.
Цитата:
4) Как организовать столкновение фигуры (когда она упала)
Массив поля и фигуры есть.Так что перед движением проверять на 1 и 0

Вот я бы начал примерно так :

Код:
const
  //  Размер ячейки по высоте и ширине
  R_KV = 30;

  //  1 - квадрат , 0 - ноль
  //  лучше делать массив равномерный по высоте и ширине
  //  для поворота фигуры
  fig1 : array [0..2] of array [0..2] of byte =
   ((1, 1, 0),
    (1, 0, 0),
    (1, 0, 0));

  fig2 : array [0..2] of array [0..2] of byte =
   ((1, 1, 1),
    (0, 1, 0),
    (0, 0, 0));

type
  Tpole = array of array of byte;

  Tfigura = record
    x,y : byte;
    m : array of array of byte;
  end;

  Tscore = record
    name_player : string;
    value : integer;
  end;

  Tgame = class
  private
    //  Состояние игры
    active : boolean;
    //  Счет
    score : integer;
    //  Количество взорваных линий
    line : integer;
    //  Поле
    pole : Tpole;
    //  Управляющая фигура
    figura : Tfigura;
  public
    //  Создание
    constructor create;
    //  Освобождение памяти,если потребуется
    procedure free;
    //  Инициализация
    procedure init;

    //////////////////////////////////////////////
    //  Проверки на перемещение фигуры
    /////////////////////////////////////////////

    //  Вниз
    function if_fig_down:boolean;
    //  Влево
    function if_fig_left:boolean;
    //  Вправо
    function if_fig_right:boolean;

    //  Поворот влево
    function if_fig_pov_left:boolean;
    //  Поворот вправо
    function if_fig_pov_right:boolean;

    ///////////////////////////////////////////////
    //  Управление фигурой
    //////////////////////////////////////////////

    //  Вниз
    procedure figura_down;
    //  Влево
    procedure fig_left;
    //  Вправо
    procedure fig_right;
    //  Поворот вправо
    procedure pov_right;
    //  Поворот влево
    procedure pov_left;

    ////////////////////////////////////////////////

    //  Процедура для таймера
    procedure on_timer;
    //  Здесь рисуем что нужно и выводим на холст
    procedure paint(canvas : Tcanvas; x,y : integer);

    /////////////////////////////////////////////////
    //  Результат
    /////////////////////////////////////////////////

    //  filename - наверное будет лучше записать как константу

    //  Сохранить
    procedure save_score(filename : string);
    //  Загрузить
    function open_score(filename : string):Tstringlist;
    //  Удалить
    procedure delete_score(filename : string);
  end;
disbnt вне форума Ответить с цитированием
Старый 13.01.2015, 14:03   #9
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Ну-с, начнём-с.
Для игры понадобится: форма - 1 штука, таймер - одна штука. Из области визуальной разработки - всё. По желанию можно, конечно, добавить кнопочку или мейнменю, но это если не охота гуй делать самому.
Всё остальное - чистый код.
В коде лучше сразу принять концепцию, подобную шаблону MVC (см вики, если какие термины непонятны из поста), а именно - есть данные, есть отображение этих данных, и есть сущность по управлению и изменению данных.
Т.е., поясняю, никакого рабочего кода в обработчиках формы, никаких глобальных переменных, данные лучше вообще вынести в отдельный модуль и спрятать в секцию implementation и наружу модуля выставлять только редкие функции/процедуры, без которых ну никак.

В итоге, должно быть минимум 2 модуля, а лучше 3. Один из них форма, второй - данные с управлением оными, либо последнее ещё на 2 модуля разбивается.

Данные это, по сути, некая структура/запись (а лучше класс) с кучей приватных членов для именно хранения данных и несколькими публичными методами для воздействия. В случае структур приватность и публичность можно формировать через механизм модуля, в случае классов это модификаторы доступа. Эта "защита" нужна в первую очередь от себя самого, так как проследить, нет ли какого кода, который я писал месяц назад, меняющего что-то в обход логики (хоть существовавшей, хоть новой) из-за легкодоступности - очень сложно и приводит к часам дебага "волшебных ошибок", и более того, фикс такой ошибки, может приводить к ещё более тяжким последствиям, из-за "технических долгов".

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

Самый интересный это управляющий – он как раз и отвечает за все операции. По смыслу он хранит буфер изображения, на котором производит отрисовку всей модели данных, он понимает сигналы от пользователя и т.п. (мышь, клава, таймер) и меняет данные по конкретным правилам, в результате этих изменений формирует изменения на изображении и его можно рисовать пользователю.
Также стоит отдельно хранить картинки всякие в виде списка объектов Tbitmap (никаких имейджей опять же) и рисовать их через canvas.draw, для таких задач обычно выделяют т.н. менеджер ресурсов.
Работу с мышкой можно сделать через проверку координат (мышка попала на картинку – сделать реакцию). Кнопки таким образом можно сделать красивые. Сами принципы тетриса по сути не отличаются от оригинальных.
Также хочу заметить, что выложенный код имеет дублирование , намешаны задачи, которые выполняет одна подпрограмма, опять же глобалки. Константы надо переделать в свойства объектов.

Последний раз редактировалось phomm; 13.01.2015 в 14:06.
phomm вне форума Ответить с цитированием
Старый 13.01.2015, 20:05   #10
NIKOLAYY2
Форумчанин
 
Регистрация: 23.12.2014
Сообщений: 220
По умолчанию

disbnt
Цитата:
4) Как организовать столкновение фигуры (когда она упала)
Массив поля и фигуры есть.Так что перед движением проверять на 1 и 0
Понял, значит как бы получается что самой игрой должен массив рулить, написать много процедур и функций каждая из которых отвечающая за свою работу
phomm
Цитата:
Самый интересный это управляющий – он как раз и отвечает за все операции. По смыслу он хранит буфер изображения, на котором производит отрисовку всей модели данных, он понимает сигналы от пользователя и т.п. (мышь, клава, таймер) и меняет данные по конкретным правилам, в результате этих изменений формирует изменения на изображении
Если проще сказать вся игра у нас должна происходить в какой-либо матрице, каждое нажатие пользователя кнопки-стрелочки, каждое событие на таймере- это и есть нечто такое как изменение матрицы, которая должна немедленно отрисоваться тут же графически?

Сейчас попробую показать визуально, вот есть картинка, слева- это графическое поле игры (Image это), справа- это та матрица которая эту игру и делает, каждое значение матрицы что справа соответствует графическому отображению в Image что слева.
После движения персонажа в одну из сторон следует полная прорисовка графического изображения каждой клеточки в цикле (значение которой берется из массива).
Как бы по подобному алгоритму нужно действовать?
Изображения
Тип файла: jpg 1111.jpg (86.4 Кб, 172 просмотров)

Последний раз редактировалось NIKOLAYY2; 13.01.2015 в 20:10.
NIKOLAYY2 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Идея создания онлайн игры Некромант Свободное общение 11 20.02.2011 01:32
Есть идея для создания игры!!! Mb666 Gamedev - cоздание игр: Unity, OpenGL, DirectX 8 01.04.2009 23:59
Набираю команду для создания игры Лён Gamedev - cоздание игр: Unity, OpenGL, DirectX 13 13.07.2007 16:06