Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2004.11.07;
Скачать: [xml.tar.bz2];

Вниз

2d аркада   Найти похожие ветки 

 
Micke   (2004-07-01 15:51) [0]

Я пробую написать свою 2d аркаду на Delphi с использованием DelphiX. У меня возник рад трудностей, которые мне хотелось бы разрешить.
1. Карта в игрухе состоит из блоков (tiles), я пробовал 2 способа их отрисовки:
 1-й
     for xx:=1 to 60 do
     for yy:=1 to 30 do
     if (armap[xx,yy]<>0) then
     TilesList.Items[armap[xx,yy]].Draw(DXDraw.Surface,(xx-1)*32,(yy-1)*16,0);

2-й For j:= 1 to 60 do
 For i:= 1 to 30 do
 Begin
   with TMap1.Create(SpriteEngine.Engine) do
   begin
     Image:=TilesList.Items[armap[j,i]];
     Width := Image.Width;
     Height := Image.Height;
     x:=(j-1)*32;
     y:= (i-1)*16;
     Z := 0;
     end;
 end;


В 1-м способе игра отлично идёт бех торможения, во втором способе наблюдаются доволбно сильные тормоза, особенно при появлении на карте новых объектов. Оно и ясно, ведь во втором способе каждый кусочек(tile) является отдельным объектом. Но мне необходимо использовать второй способ, т.к. мне надо проверять Collision с картой и скролить её при движении игрока. Пули тоже являются отдельными объектами и при выстреле всё ещё больше тормозит. Как решить эту проблему?
2. Пули на большой скрорости пролетают сквозь стены. Что делать?


 
ПсихЪ_клон   (2004-07-01 16:02) [1]

Зачем ты постоянно криетишь карту?

TMap1.Create(SpriteEngine.Engine)

Неужели нельзя создать объект TMap1, инициализировать его, а затем просто выводить на его основе. Что-то типа:

var
 Map : TMap1;

begin
 Map := TMap1.Create(SpriteEngine.Engine);
end.

...

For j:= 1 to 60 do
For i:= 1 to 30 do
Begin
  with Map do
  begin
    Image:=TilesList.Items[armap[j,i]];
    Width := Image.Width;
    Height := Image.Height;
    x:=(j-1)*32;
    y:= (i-1)*16;
    Z := 0;
    end;
end;


 
Micke   (2004-07-01 16:38) [2]

Как ни странно, но это не работает. Просто не рисует карту вообще.
Вот как всё обстоит:


Tmap1 = class(TImageSprite)
   Public
   procedure DoMove(MoveCount: Integer); override;
end;
...
var
 Map:TMap1;
 armap: array [1..60,1..30] of byte;
...

procedure TMainForm.FormCreate(Sender: TObject);
begin
...
Map:= TMap1.Create(SpriteEngine.Engine);

For j:= 1 to 60 do
 For i:= 1 to 30 do
 Begin
   with Map do
   begin
     Image:=TilesList.Items[armap[j,i]];
     Width := Image.Width;
     Height := Image.Height;
     x:=(j-1)*32;
     y:= (i-1)*16;
     Z := 1;
     end;
 end;
end;


 
ПсихЪ_клон   (2004-07-01 16:42) [3]

Вообще, забей на SpriteEngine. Это по моему провал. Лучше пиши свой класс, можешь парочку нужных функций стянуть из модулей SpriteEngine"а.


 
Micke   (2004-07-01 16:48) [4]

Мне бы всётаки хотелось решить проблему с SpriteEngine. Нипонимаю почему он не хочет рисовать спрайты?


 
Micke   (2004-07-01 17:24) [5]

Что-то я не пойму. Как ты собирался таким способом вообще создать кучу тайлов. Я моём коде я создавал несколько объектов, а ты создаёшь один и просто меняешь у него Image. Таким образом мы создим самый последние тайл на карте )))
Тут надо делать что-то другое. Что бы не тормозила карта.


 
Micke   (2004-07-01 17:24) [6]

Может кто-то знает как сделать не тормозящую карту из тайлов со скролингом и Collision"ом?


 
Огромное Кулясищще ©   (2004-07-01 20:04) [7]

2 Micke:

Котлеты и мухи отдельно. Если так (т.е. настаиваешь на SpriteEngine), что то держи карту и объекты, с которыми можно столкнуться отдельно. Если не так, но выдери ту же коллизию (см. function ImageCollisionTest) и проверяй столкновение поверхностей.


 
Micke   (2004-07-01 22:28) [8]

Нельзя ли подробно объяснить. Желательно с примерами.


 
Огромное Кулясищще ©   (2004-07-02 00:08) [9]

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


 
Micke   (2004-07-02 00:22) [10]

У меня карта - это тоже спрайт. А Collision мне нужен для уничтожения пуль при столкновении с картой.


 
Огромное Кулясищще ©   (2004-07-02 01:06) [11]

2 Micke:

Я не понимаю, как пуля может столкнуться с картой? Пуля летит над картой, не трогая её.

Смотри, есть карта - она состоит из тайлов. Массив отвечает, куда какой тайл выводить. В самом начале рисования экрана выводишь карту, т.е. тайлы. Они выводятся всегда и всегда они именно квадратной (изометрия - не суть) формы. Они покрывают весь экран и всегда внизу. Карта - это паркет.


 
Micke   (2004-07-02 18:39) [12]

Какой нафиг паркет?! У меня 2d аркада с видом с боку. Ты в NFK играл?


 
ПсихЪ_клон   (2004-07-02 18:52) [13]


> Micke   (02.07.04 18:39) [12]

Ты безбожно тупишь. О том, что у тебя 2D аркада с видом "сверху" нужно было сказать с самого начала. Ибо подход тут совершенно иной. Так или иначе, у тебя есть фон (мне глубоко паралельно, как ты его выводишь, тайлами или битмэпом) и есть стены (прямоугольные блоки для которых срабатывает ДетектКолижен). Фон и стены ты хранишь отдельно. Как - сам решай.

Столкновения:
Если у тебя большие карты, то можно:
1. Разбить их на куски, для того, чтобы перед просчётом колижена для каждого блока определить кто и в каком куске карты находится и соответственно для между какими объектами этот самый коллижен проверять или не проверять.
2. Когда создаёшь карту, то контуры стен оптимизируешь в массив полигонов. И тогда столкновения определяешь с полученными полигонами. Порой даёт просто дикую оптимизацию (скорость).

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


 
Micke   (2004-07-02 19:01) [14]

Блин. Куда я попал?! Я ТУПЛЮ?! Ты читай моё сообщение!!


> У меня 2d аркада с видом с боку


Блин... Читайте пожалуйста повнимательнее.


 
ПсихЪ_клон   (2004-07-02 19:48) [15]

Чё-то я ослеп, но не вижу в твоей мессаге надписи типа: "У меня 2D-акада с видом "сбоку""...
Обычно, когда говорят про тайлы, то имеют в иду вид "сверху"...


 
Servelat ©   (2004-07-02 20:43) [16]

1. Тормозить будет, потому что DelphiX, что тут сделать - я могу только посоветовать перейти на низкоуровневый API, либо купить крутючую видюху, где даже это неоптимизированное чудо тормозить не будет.
Только то, что ты написал в посте во 2"м способе надо делать один раз (а, судя по изложению, у тебя это отрисовка и ты это по таймеру делаешь), а потом только SpriteEngine.Draw (или как-то так, давно с DelphiX не мучился) по таймеру.
2. Анимация - это обман зрителя, соответственно, при скорости пули больше размера тайла, первое положение пули может быть до столкновения с тайлом, а следующее - когда она пролетела его. DelphiX"овский Engine столкновение тогда не зафиксирует. Выход есть - писать свою проверку столкновений, например, в DoMove проверять, не врежется ли пуля при движении, а потом прибавлять к координате нужную величину.


 
Servelat ©   (2004-07-02 20:45) [17]

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


 
Micke   (2004-07-02 23:27) [18]

2 Servelat. Мне кажется, что и с DelphiX можно добиться нормальной производительности. Карта у меня рисуется один раз, при сорздании формы, не быду же я при таймере каждый раз заново рисовать карту :) Может попробоват сразу не рисовать всю карту, а только то что видит игрок, а при перемещении дорисовывать новые участки и удалять старые. Но мне кажется, что и при таком варианте будут тормоза.
Насчёт пуль ты прав. Тут надо придумывать что-то своё.
2 All. Что никто не сталкивался с этими проблемами и никто не может помочь?


 
ПсихЪ_клон   (2004-07-03 09:18) [19]

Что в твоём понимании "рисовать карту".
Лично я понимаю это как "очистить бекбуффер, вывести (отрисовать) на бекбуффер необходимые тайлы, которые хранятся в определённой структуре данных, произвести ещё какие-нибудь опирации, сделать флип праймарибуффера." Т.е. карта (целиком или какой-то её кусок) должна отрисовываться каждый раз, при перерисовке экрана. А перерисовка экрана - это, по сути и есть твои FPS. В итоге, чем чаще мы перерисовываем карту (если получается это делать чаще), тем выше FPS. Всё утрировал до нельзя, но, думаю, разберёшься.
Если хочешь готовые примеры на DelphiX, то скинь письмо на stalker2010(гы)front.ru. В теле письма напиши что-то вроде "Поделись примерами реализации карты средствами DelphiX".

Я тебе скину наработки Iso-двигла. Не пугайся, разберись со структурой карты, думаю тебе многое станет понятно.


 
Servelat ©   (2004-07-03 14:14) [20]

2 Micke
Отрисовывать надо по таймеру, создавать все - один раз, а то тебя можно не правильно понять.
DelphiX"овский Engine и так отрисовывает только те тайлы, которые на экране, другие отрисовать не возможно в принципе (невозможно программно создать изображение рядом с монитором, за его границей ;) ). Процедура Draw спрайта вызывается только если он в пределах экрана.

Насчет пуль: могу подкинуть простую идею:
у тебя в DoMove пули написано что-то вроде:
X:=X+Speed;
а ты сделай по другому:

i:=trunc(X);
while X<i+Speed do
begin
 X:=X+1;
 //тут идет проверка столкновений пули с объектами
 //В DelphiX это делает по-моему процедура Collision;
end;


Разумеется, этот код нужно еще оптимизировать и доработать, это самая простая идея, которая пришла в голову ;) . Например, в моем коде предполагается, что скорость пули - положительна, то есть пуля летит вправо. Надо еще другой вариант рассмотреть, когда пуля летит влево и Speed<0. Ну и также здесь предполагалось, что пуля летит только горизонтально, если же она может дететь под углом к горизонту, все придется делать еще сложнее.

На самом деле есть более совершенные способы решения данной проблемы, чем прибавление к координате по 1 и постоянной проверке. Но пищу для размышлений, я, надеюсь, дал.


 
Micke   (2004-07-04 12:50) [21]

2 Servelat, да. Спасибо.

2 all. И всё же, кто-нибуть сталкивался с торможением карт, на основе тайлов?!


 
Servelat ©   (2004-07-04 14:20) [22]

2 Micke
Могу предположить, что одна большая картинка рисуется быстрее, чем много маленьких. Можно попробовать рисовать все при загрузке карты на одну большую поверхность (или, в DelphiX"е на один большой DXImageList"овский Item) и потом только копировать часть этой картинки, которая в данный момент видна, на экран. Правда памяти будет жрать прилично такая картинка, зато скорость должна возрасти. При уничтожении какого-нибудь тайла, ты просто в большой картинке закрашиваешь нужный кусок прозрачным цветом.


 
ПсихЪ_клон   (2004-07-05 09:15) [23]


> Micke   (04.07.04 12:50) [21]

Вот только теперь не говори мне, что ты не тупишь. Тебе уже всё по нескольку раз объяснили, привели несколько примеров оптимизации и структуры тайловой карты, а ты сново за старое, как буд-то ничего не слышал: "И всё же, кто-нибуть сталкивался с торможением карт, на основе тайлов?!". Ты, видимо, издеваешься...


 
Darthman ©   (2004-07-05 10:32) [24]

Micke:
Если руки из зада растут - сталкивался неоднократно. Если нет, то хоть на GDI пиши ничего тормозить не будет. Тайлы это же так просто!


 
Falcon(TFSoft)   (2004-07-05 13:38) [25]

Привет всем.

Возможно я подключаюсь поздновато, к обсуждению данной темы, но кому-то возможно это будет интересно.
В примерах, которые были приведены выше всё написано правильно. Единственное лишь, что можно добавить - это отключение детколл. Так как эта процедура занимает многовато времени, и обрабатывается для массива 60х30. А вот проверка стокновения с картой производит не в классе TMap а в классе TPlayerBullet (тоесть пули).
Итак, (что б расставить все точки над i):
При инициализации уравня единожды создаём массив тайлов, у которых нет коллюжен, они просто рисуются и всё

For j:= 1 to 60 do
For i:= 1 to 30 do
Begin
  with TMapPiece.Create(SpriteEngine.Engine) do
  begin
    Image:=TilesList.Items[armap[j,i]];
    Width := Image.Width;
    Height := Image.Height;
    x:=(j-1)*32;
    y:= (i-1)*16;
    Z := 0;
    Collisioned := false;    // Вот оно
    end;
end;



А в классе пули:

Procedure TBullet.DoCollision(Sprite: TSprite; var Done: Boolean);
Begin
if Sprite Is TMapPiece then
  begin
    (Sprite as TMapPiece).DoBigBoom(Self.X, Self.Y);{Делаем к примеру взрыв, в месте cтолкновения}
    Self.Dead;
  end;

if (Sprite is TEnemy) then
  Begin
    (Sprite as TEnemy).Health :=(Sprite as TEnemy).Health - Power;
{отнимаем у врага хелсы, соответственно силе патрона}
    Self.dead;
  end;
end;


С уважением Алескей.


 
Micke   (2004-07-05 19:21) [26]

2 Falcon(TFSoft) большое спасибо.


 
Falcon(TFSoft)   (2004-07-06 01:28) [27]

2 Micke   (05.07.04 19:21) [26]
Мне чесно скзать интересно что ты за игрушку делаеш, не поделишся ли ифой про что она?
Можеш, что б не засорять форум писать на мыло...
falcon_support@ua.fm



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2004.11.07;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.038 c
1-1098515698
PURGEN
2004-10-23 11:14
2004.11.07
Хочу удалить объект!!!!


1-1098715549
Kam4atkin
2004-10-25 18:45
2004.11.07
Как правильно скопировать русский текст в буфер?


1-1098707361
}|{yk
2004-10-25 16:29
2004.11.07
Работа с двумерным вариантным массивом


1-1098283190
UVV
2004-10-20 18:39
2004.11.07
for


1-1098439005
aleshap
2004-10-22 13:56
2004.11.07
OnActivate и OnEnter





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский