Разработка RPG – LittleAge (часть 1)

Опубликовал – 27.08.2010

Доброе время суток, товарищи! Наконец у меня появился свободный вечерок, который я могу посвятить написанию новой статьи по LittleAge. Сегодня мы подготовим нашу рабочую среду для дальнейшей работы и попробуем описать графический вывод.

Собственно, проще и глючней DelphiX для работы с DirectX я не нашел, потому будем писать именно с этими компонентами. Думаю нам понадобится асинхронная озвучка, которую он тоже поддерживает. Но весь DelphiX мы использовать не будем, дабы не использовать их глючные компоненты TDXSprite и остальную хрень типа списков из спрайтов. Для этого мы создадим свою библиотеку для хранения изображений, которая будет хранить картинку в структуре стандартного DirectDraw версии 7 или 8. Из DelphiX нам понадобиться только компонент TDXDraw, который будет отвечать за инициализацию DirectDraw и двух буферов. Тут я не буду подробно объяснять как работает DirectDraw, ибо про это написано много документации. Но основной принцип отрисовки поверхностей вы должны понимать: Для работы DirectDraw нужны Back и Front буфера (TDirectDrawSurface), каждый кадр мы будем рисовать на заднем буфере и делать Flip поверхностей. Flip в полноэкранном режиме приложения просто меняет адреса задней и передней поверхности местами, тем самым подготавливает передний буфер к выводу на экран. Соответственно, в оконном режиме нужно побайтово скопировать все данные из одного буфера в другой, поэтому такой режим будет работать дольше. Но обо всем этом заботится DirectX. Далее мы должны очистить задний буфер и отобразить на экран передний, после все повторяется по кругу. Если Вам понравится статья, после прочтений кликните на рекламу перед комментариями от гугла, Вам это ничего не будет стоить, Спасибо.

Итак, давайте скачаем и установим DelphiX под Вашу версию Delphi (если уж совсем ничего не будет получаться, напишу отдельный урок по установке). Чтобы не дублировать уроки, создадим приложение, как это делалось в первой и второй частях создание игры Fly. Только на форму, помимо компонента TApplicationEvents, помещаем еще TDXDraw; у меня это выглядит так:

Тут я буду пояснять только модуль менеджера графики, который будет отвечать за отрисовку и хранение графики; полные исходники будут в конце статьи. Собственно, давайте договоримся, что будем хранить все изображения в видео памяти, ибо вручную нам доступ к пикселям не нужен, будем пользоваться аппаратными возможностями видео карты – это очень ускоряет процесс вывода. Помнится, писал давно игрушку на DirectDraw, хранил все изображения и внеэкранные поверхности в системной памяти (RAM), а на ассемблере мучил пиксели для достижения эффекта полупрозрачности, ротатинга и даже делал в ручную тень под объектами, так вот Fps при этом было 20-30. Немного неудобно, но если хранить изображения в видео памяти и обрабатывать их вручную, скорость была бы еще меньше! Ибо для начала он перегоняет графику по AGP или PCI(-E) в RAM, и только тогда можно «запирать» изображение в памяти и начинать работать с набором пикселей. Итак, часть модуля uGraphics:

type
  TGraph = class
  public
    mainscr: TDirectDrawSurface; //тут будем рисовать
    dxdraw: TDXDraw; //объект DelphiX
    procedure ClearScreen(); //чистим экран
    procedure Flip(); //переворачиваем поверхности
    constructor Create(dx: TDXDraw);
    destructor Destroy(); override;
  end;

  //узел для библиотеки изображений
  PBmpNode = ^TBmpNode;
  TBmpNode = record
    bmp: TDirectDrawSurface; //поверхность
    name: String[255]; //имя файла
  end;

  TBmpLib = class(TList)
  private
    dxdraw: TDXDraw;
    function FindBmp(aname: String): TDirectDrawSurface;
    function AddBmp(aname: String): TDirectDrawSurface;
  public
    constructor Create(dx: TDXDraw);
    function GetBmp(aname: String): TDirectDrawSurface;
    destructor Destroy(); override;
  end;

var
  graph: TGraph;
  bmplib: TBmpLib;

implementation

{--TGraph--}

constructor TGraph.Create(dx: TDXDraw);
begin
  inherited Create();

  dxdraw := dx;

  //создаем главную поверхность
  mainscr := TDirectDrawSurface.Create(DXDraw.DDraw);
  //храним данные в видео памяти
  mainscr.SystemMemory := false;
  //цвет который будет прозрачный
  mainscr.TransparentColor := 0;
  //размер поверхности
  mainscr.SetSize(SCREEN_WIDTH, SCREEN_HEIGHT);
end;

procedure TGraph.ClearScreen();
begin
  mainscr.Fill($0); //красим в черный цвет
end;

procedure TGraph.Flip();
begin
  //сначало копируем на системную поверхность
  dxdraw.Surface.Draw(0 ,0 , rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), graph.mainscr, false);
  //флипаем
  dxdraw.Flip();
end;

destructor TGraph.Destroy();
begin
  //чистим за собой все
  mainscr.Free();
  mainscr := nil;
  inherited ;
end;

{--TBmpLib--}

constructor TBmpLib.Create(dx: TDXDraw);
begin
  //просто определяем экземпляр объекта
  dxdraw := dx;
end;

function TBmpLib.FindBmp(aname: String): TDirectDrawSurface;
var i: Integer;
begin
  //ищем в списке имя, если нет создаем
  result := nil;
  for i := 0 to pred(Count) do
    if (PBmpNode(Items[i])^.name = UpperCase(aname)) then begin
      result := PBmpNode(Items[i])^.bmp;
      exit;
    end;
end;

function TBmpLib.AddBmp(aname: String): TDirectDrawSurface;
var
  pnode: PBmpNode;
begin
  //создаем узел, поверхность в нем и добавляем в список
  new(pnode);
  pnode^.bmp := TDirectDrawSurface.Create(DXDraw.DDraw);

  if (pnode^.bmp = nil) then Messagebox(0, @aname[1], 'что-то новое', MB_OK);

  //видео память..
  pnode^.bmp.SystemMemory := false;
  //имя
  pnode^.bmp.LoadFromFile(aname + '.bmp');
  //черный цвет будет прозрачным
  pnode^.bmp.TransparentColor := 0;

  pnode^.name := UpperCase(aname);
  Add(pnode);
  result := pnode^.bmp;
end;

function TBmpLib.GetBmp(aname: String): TDirectDrawSurface;
var
  bmp: TDirectDrawSurface;
begin
  bmp := FindBmp(aname);
  if (bmp = nil) then bmp := AddBmp(aname);
  result := bmp;
end;

destructor TBmpLib.Destroy();
var
  i: Integer;
  pnode: PBmpNode;
begin
  //очищаем список и удаляем его
  for i := 0 to pred(Count) do begin
    pnode := Items[i];
    pnode^.bmp.Free();
    pnode^.bmp := nil;
    dispose(pnode);
  end;
  inherited;
end;

Тут можно скачать исходники LittleAge (part1).

Рассказать друзьям:
  • Добавить ВКонтакте заметку об этой странице
  • Мой Мир
  • Facebook
  • Twitter
  • Яндекс.Закладки
  • В Живую Ленту Google
  • Сто закладок
Комментарии (10) - Разработка RPG – LittleAge (часть 1)

Ответ

  1. Анонимно:

    Когда новая статья????

    Thumb up Thumb down +3

    • Очень завален работой.. постараюсь по мере разгребания уделить время.. сама игра уже написана.. могу сразу выложить полные исходняки и краткое пояснение.. и уже после обсуждать отдельные моменты

      • ПАВЕЛ ВИКТОРОВИЧ:

        Здраствуйте Александр Сергеевич а можно выложить полный исходник.
        Охото посмотреть игру в полной её кросе

        Thumb up Thumb down +1

        • думаю в скором времени я сделаю это.. но без комментариев там не обойтись.. так что лучше подождать статей.. сейчас со временем туговато.. но основные аспекты я уже выкладываю..

          • ПАВЕЛ ВИКТОРОВИЧ:

            Так и когда же нам ждать продолжения? Уже не терпиться! И где же вы выкладываете основные части вроде не чего не добовляется!

            Thumb up Thumb down +1

  2. нупас:

    Hidden due to low comment rating. Click here to see.

    Poorly-rated. Like or Dislike: Thumb up Thumb down -7

  3. Антон Сергеевич:

    Не терпится продолжения. Когда же уже продолжим? :)

    Thumb up Thumb down 0

  4. Жду с нетерпением продолжения

    Thumb up Thumb down 0

Ответить

Comments

Перед отправкой формы: