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

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

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

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 09.02.2008, 17:40   #31
Sibedir
Тот ещё
Старожил
 
Аватар для Sibedir
 
Регистрация: 14.11.2007
Сообщений: 2,242
По умолчанию

Цитата:
Почему же кто Вам мешает например сделать в цикле смещение позиций и строк битмапа, и заполнять каждый цвет ( несколько байт ) тем которым надо и будет Вам таже линия, кружки и т.д. так можно свой мини-движок сделать Просто манипулирую X, Y-ом.
Да, нет спасибо. . И наврят ли это будет работать быстрее чем API. Там наверняка задействованы низкоуровневые механизмы вплоть до механизмов, реализованных на уровне железа.
Sibedir вне форума Ответить с цитированием
Старый 09.02.2008, 22:23   #32
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию Делимся опытом 1

Господа, и вот вы наконец подошли к необходимости использования GDI, и это верно, если OGL и DirX не в счет, то быстрее способов нет. Как же Canvas? ...он работает быстрее, чем вам кажется, вот только применять его нужно знаючи. Поделюсь опытом, конкретно по пунктам, что нужно проводить в циклах, и как организовать быструю прорисовку кадра.

Сначала структурно:
1) Готовим буфер заднего плана в памяти (выполняется по требованию), он всегда хранит задник;
2) Записываем в кадр буфер через Canvas (кадр - переменная TBitmap);
3) Рисуем в кадр объекты (в памяти);
4) Отображаем кадр (модифицированный в памяти) через Canvas.
...все.
Мерцание исключено, т.к. отображение выполняется только последним пунктом, в Image или PaintBox отображаются только следующие друг за другом готовые кадры, никаких стираний в момент отображения.

Этот алгоритм у меня рисует поле 1024х768 24 кадра в секунду, послойно, объектов много, анимированные и статичные, качество 24 бита, BMP с масками альфа-канала, загрузка процессора 4% , ОЗУ 64М, ну это из за хранения в памяти текстур анимации (275х250 пкс).

Не претендую на авторство методов, если кто-то узнает свои строки, им низкий поклон.

1) Как создать в памяти буфер под TBitmap

Подготовка. Запишем нужные переменные прямо вот так:
Код:
type
  TForm1 = class(TForm)
....
  private
    ZoneBitmap, BufBitmap: TBitmap;
    Scr, Scr2: Pointer; // указатели
    SX, SY: Word; // размеры
  end;

// тип представления пикчела по RGB
type
  PRGB = ^TRGB;
  tagRGB = packed record
    R: Byte;
    B: Byte;
    G: Byte;
  end;
  TRGB = tagRGB;

Var  
  x, y: Integer;// Счетчики циклов
  TexPointer, MapPointer, ZonePointer: Pointer; // Указатели на строки пикселов
  TexPixel, MapPixel, ZonePixel: PRGB; // Указатели на 24-битные пиксели
  MscrT, MscrM, MscrZ: Integer; // количество пикселей в строке
Перед процедурой создания буфера нужно определить его размеры W и H, также можно изменить битность буфера на приемлимое, т.е. записываем в BInfo.bmiHeader.biBitCount значение 8, 16, 24, 32. Кроме того освобождая память под буфер, нужно указывать правильный множитель ZeroMemory(Scr2,SX*SY*{множитель}) , 1, 2, 3, 4 , соответственно по числу байт на пиксел.
Код:
procedure TForm1.CreateBitmap;
var
  BInfo: tagBITMAPINFO;
begin
  SX:=W;
  SY:=H;
  BInfo.bmiHeader.biSize:=sizeof(tagBITMAPINFOHEADER);
  BInfo.bmiHeader.biWidth:=SX;
  BInfo.bmiHeader.biHeight:=SY;
  BInfo.bmiHeader.biPlanes:=1;
  BInfo.bmiHeader.biBitCount:=24;
  BInfo.bmiHeader.biCompression:=BI_RGB;
  ZoneBitmap:=TBitmap.Create();
ZoneBitmap.Handle:=CreateDIBSection(Canvas.Handle,BInfo,DIB_RGB_COLORS,Scr,0,0);
  ZeroMemory(Scr,SX*SY*3);
  BufBitmap:=TBitmap.Create();
BufBitmap.Handle:=CreateDIBSection(Canvas.Handle,BInfo,DIB_RGB_COLORS,Scr2,0,0);
  ZeroMemory(Scr2,SX*SY*3);
end;
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 09.02.2008 в 22:49.
Beermonza вне форума Ответить с цитированием
Старый 09.02.2008, 22:29   #33
Beermonza
Инженер ИС
Старожил
 
Аватар для Beermonza
 
Регистрация: 13.12.2006
Сообщений: 2,671
По умолчанию Делимся опытом 2

Мы создали в ручную две переменные TBitmap, они пустые, размером с наше игровое поле (экран игры), мы знаем где они у нас в ОЗУ.

Заполнение буфера задником бывает разное, например тайловое, ...я покажу простейшее битовое, допустим задник - картинка BMP формата, с нужной битностью:

Код:
// узнаем начало картинки в ОЗУ
TexPointer:=BitBackImage.ScanLine[0]; {картинку в BitBackImage поместили заранее обычным способом}
// узнаем начало буфера в ОЗУ
ZonePointer:=BufBitmap.ScanLine[0];
// узнаем размер строки изображения в ОЗУ
MscrT:=Integer(BitBackImage.ScanLine[1])-Integer(BitBackImage.ScanLine[0]);
For y:=0 to H-1 do
Begin
// указатели на первый пиксель в текущей строке
DWORD(TexPixel):=DWORD(TexPointer);
DWORD(ZonePixel):=DWORD(ZonePointer);
For x:=0 to W-1 do
Begin
// запись составляющих цвета из задника в буфер
ZonePixel.R := TexPixel.R;
ZonePixel.G := TexPixel.G;
ZonePixel.B := TexPixel.B;
// указатели на следующие пиксели в текущей строке
DWORD(TexPixel):=DWORD(TexPixel)+3; {прибавляется шаг равный количеству байт на пиксел (24 бит = 3 байта)}
DWORD(ZonePixel):=DWORD(ZonePixel)+3;
end;
// указатели на следующую строку
DWORD(TexPointer):=DWORD(TexPointer)+MscrT;
DWORD(ZonePointer):=DWORD(ZonePointer)-((W shl 1)+W);
end;
Все зависит от алгоритма заполнения, но принцип остается прежним.

2) Записываем в кадр буфер

Код:
ZoneBitmap.Canvas.Draw(0,0,BufBitmap);
3) Рисуем в кадр объекты

Организовываем цикл пробежки по ячейкам массива (в основе игры всегда некоторый скелет пространства, код объектов и пр.)

Код:
// указатели на первую строку текстуры, маски и фона
// узнаем размер строки изображения в ОЗУ
// цикл по-y
// указатели на первый пиксель в текущей строке
// цикл по-x
// смешивание цветов по формуле прозрачности (24 бита)
ZonePixel.R := ZonePixel.R + (TexPixel.R - ZonePixel.R) * MapPixel.R shr 8;
ZonePixel.G := ZonePixel.G + (TexPixel.G - ZonePixel.G) * MapPixel.G shr 8;
ZonePixel.B := ZonePixel.B + (TexPixel.B - ZonePixel.B) * MapPixel.B shr 8;
// указатели на следующие пиксели в текущей строке
// указатели на следующую строку
4) Отображаем кадр

Код:
DrawZone.Canvas.Draw(0,0,ZoneBitmap); // DrawZone у нас PaintBox, но можно и Image
Это в примитиве, необходимо задать много параметров на правильность наложения текстур в кадр, выход за его пределы вызывает ошибку, ведь в ОЗУ существует только ограниченное количество ячеек. Но все эти проблемы вам придется решать и в DirесеX, они по сложности такие же.

По поводу точки, кружков или прочего, ...это оч. просто рисуется однажды на канве переменной TBitmap, затем используется как картинка, ...думаю эта точка подразумевает в последствии объект более сложный.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его

Последний раз редактировалось Beermonza; 09.02.2008 в 23:08.
Beermonza вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Отбражение чисел - точки, это точки, а не запятые, обозначающие дробную часть Дикий Помощь студентам 7 12.05.2008 17:57
Принадлежность точки UnFaithful Паскаль, Turbo Pascal, PascalABC.NET 1 08.01.2008 06:16
Помогите рассчитать положение и движение точки N на отрезку DK Stark[SG!] Помощь студентам 8 14.12.2007 10:08
Блокировка точки !! ***СкаЙ*** Помощь студентам 1 13.06.2007 14:14
Help!!!Движение точки по поверхности сферы alex23xandr Помощь студентам 4 20.05.2007 14:45