05 мая 2011

Демо физического платформера

Проект glVehicles не заброшен! Согласен, известий не было давно, демками не пополнялась длительное время. И вот недавно я взял себя в руки и решил сконструировать что-нибудь полноценное, играбельное. Ведь, как мне показалось, многих отталкивает debug-отрисовка физических объектов. Всем хочется сразу красивых спрайтов и "рюшечек". Рисовать самому или просить кого-то сделать несколько спрайтов для бесплатной демки с открытым кодом - как-то не хотелось. Наткнулся на этот арт и сразу родилась идея для демки. Сделалось быстро, а вот написать это сообщение, руки дошли только сейчас.

Вот, что у меня получилось:


Придумался мне платформер, где главный герой - квадратик, смешно скачет, прыгает, карабкается. В ходе разработки демки показались стильными "залипания" на стенах, которые в конечном итоге переродились в способ пропрыгивания по вертикальным стенкам. Fun, fun, fun...
В динамике это выглядит так:


Немного пробегусь по коду...
По сути самое важное, что добавилось, так это проверка на наличие контакта со стенами. Сама проверка, конечно же, находится в callback'е физики:

procedure OnProceedContactCallBack(AContactData: Pb2_ContactListenerCallBackData); cdecl;

где можно найти саму проверку на контакт с игроком:

    if(UserDataB = frmDemo9.fPlayer)then
      if (UserDataA <> nil) and not (TObject(UserDataA) is TStar) then
      begin
        if AContactData^.ContactType = 0 then
          frmDemo9.fPlayerContacts := frmDemo9.fPlayerContacts + 1
        else if AContactData^.ContactType = 2 then
          frmDemo9.fPlayerContacts := frmDemo9.fPlayerContacts - 1;

        frmDemo9.fContactTime := cst_ContactTime;
      end;

Сама отрисовка объектов происходит наипримитивнейшим образом, а именно пробегаемся по списку всех физических объектов и "кастуем" по типу объекту из UserData... вот как это происходит в OnDirectRender():

 for i := 0 to fb2BodyList.ObjectsCount - 1 do
  begin
    obj := fb2BodyList.GetObjectByIndex(i);
    if obj.GetBodyUserData = nil then
      continue;

    if obj.GetBodyUserData = fNormalBlock then
    begin
      pos := fViewer.Buffer.WorldToScreen(obj.Position);
      fNormalBlock.Position.x := pos[0] + 1;
      fNormalBlock.Position.y := fViewer.Height - pos[1] - 3;
      fNormalBlock.Render(rci);
    end;

    if (obj.GetBodyUserData = fDynamicBox) or (obj.GetBodyUserData = fPlayer) then
    begin
    ...
    end;

    if obj.GetBodyUserData = fLeftRampBlock then
    begin
    ...
    end;

    if obj.GetBodyUserData = fRightRampBlock then
    begin
    ...
    end;

Код, конечно, можно было и почище сделать, объединив похожие блоки в один. Но это просто демка, показывающая возможности Delphi, GlScene и Box2d. Ни на какие титулы "идеального кода" не претендуем :)

Вот и все... Вообще, само поведение блока мне понравилось, и, возможно, буду доводить эту дему "до ума", из этого вполне может выйти неплохая мини-игрушка.

Так что качаем или апдейтимся, компилируем, запускаем и тестим! Для меня главное - отзывы по поводу управления: насколько удобно или неудобно карабкаться и прыгать...

Сообщения, схожие по тематике:

3 коммент.:

  1. Недавно приступил к изучению box2d. Скачал исходники с репозитория. Так как использую другой граф. движок, то у Вас взял только b2Physics.pas.
    Отрисовка debug проходит на ура, т.к. отрисовываются полигончики. Но вот с отрисовыванием примитивов по координатам и углу поворота незаладилось. Если координаты и совпадают, то углы поворота какие стремные. У Вас нет случаем простейшего примерчика на чистом ogl?

    ОтветитьУдалить
  2. Антон, привет!
    Я на чистом ogl к сожалению не программирую.
    Если хочешь, можешь скинуть мне свою демку с багом - я по возможности посмотрю, может чем-то смогу помочь.
    Вообще, для Delphi также существует трансляция box2d, можно посмотреть здесь:
    http://box2d.org/forum/viewtopic.php?f=17&t=4764
    Вроде там есть рабочий тест-бед.

    ОтветитьУдалить