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

Вниз

DelphiX - Рождение и смерть спрайтов.   Найти похожие ветки 

 
jab~   (2004-02-13 15:17) [0]

За основу взял примерчик
DXSprites (http://delphigfx.mastak.ru/samples/samp17.rar)

Добавил свой класс
 TDiablo = class(TImageSprite)
 private
   procedure SetAnim(AName : String);
   procedure SetAnimAngle;
   function  FinishStep : Boolean;
   function  FinishMove : Boolean;
   function  FinishFollow : Boolean;
   function  HitBy(ASprite : TDiablo) : Boolean;
   procedure Move;
 protected
   procedure DoDraw; override;
   procedure DoMove(MoveCount: Integer); override;
   procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
 public
   FDrawE : Boolean;
   FStatus     : TStatus; // Что делаем (идём, стоим, ...)
   FTarget     : TSprite; // Кого атакуем
   FEnergy,
   FAttackRadius,         // Радиус атаки
   FDestX,                // Координаты куда
   FDestY,                // прийти
   FMapX,                 // Координаты
   FMapY,                 // на карте
   FNextX,                // Координаты
   FNextY,                // следующей клетки
   FAngle,                // Угол вектора скорости
   FSpeed      : Integer; // Скорость спрайта
   FX,
   FY          : Double;
   constructor Create(AParent: TSprite); override;
   procedure SetDest(AX, AY : Integer);
   procedure SetTarget(ATarget : TSprite);
 end;

Ну естественно в маине для клика прописал:
procedure TMainForm.DXDrawMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
// Когда я кликаю правой клавишей мыши
 If ssRight in Shift then
     If Selected<>nil then begin
           Target:=Nil;
           TCursor(MyCursor).Action:=aTarget;
           TCursor(MyCursor).Collision;
           If (Target=Nil) or (Target=Selected) then
             begin
               If Selected is TDiablo then TDiablo(Selected).SetDest(MouseMapX,MouseMapY);
               If Selected is THero then THero(Selected).SetDest(MouseMapX,MouseMapY);
             end Else
             begin
               If Selected is TDiablo then TDiablo(Selected).SetTarget(Target);
               If Selected is THero then THero(Selected).SetTarget(Target);
             end;
           Target:=Nil;
     end;
...
...

Сам класс TDiablo описал так же как и класс THero за исключением имен картинок подгружаемых (спарайтов)
Всё заработало практически сразу! У меня бегают 2 типа монстров и мочат друг друга, но вот незадача.. смерть монстра отображается не тем спрайтом. Смерть показывает именно тем кто убил, а не того кого убили...
Я думаю что нужно что то изменить в процедуре

function THero.HitBy(ASprite : THero) : Boolean;
begin
 FEnergy:=FEnergy - 1;
 If (FTarget=Nil) and (FStatus=stStop) Then SetTarget(ASprite);
 If FEnergy<0
   Then
     begin
       FStatus:=stDead;
       Collisioned:=False;
       SetAnim("Dead");
       Result:=True;
     end
   Else
     Result:=False;
end;

А начал менять то у меня ничего не вышло.... Может кто сможет помочь?


 
ZAROLF ©   (2004-02-13 15:38) [1]

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


 
jab~   (2004-02-13 17:18) [2]

ZAROLF
Уже в принципе разобрался...
Могу демку по почте выслать если интересно!?

И ещё проблемка..
Есть у меня в обработчике (таймер) такая штука

 If isButton5 in MainForm.DXInput.States
   Then
     begin
       TThin.Create(DXSpriteEngine.Engine);
     end;

Ну тут понятно всё... создаётся класс. Вот только проблемка есть, как можно немного замедлить создание, а то я не успеваю нажать на кнопку как у меня вываливается груда монстров... если ставлю sleep() то уменя вся игра замирает... Это ведь й меня основной таймер... Может что подскажеш?


 
ZAROLF ©   (2004-02-13 18:25) [3]

jab~   (13.02.04 17:18) [2]
Ну тут понятно всё... создаётся класс. Вот только проблемка есть, как можно немного замедлить создание, а то я не успеваю нажать на кнопку как у меня вываливается груда монстров... если ставлю sleep() то уменя вся игра замирает... Это ведь й меня основной таймер... Может что подскажеш?
-----------------------------------------------------------------
var speed:shortint;

If isButton5 in MainForm.DXInput.States Then
begin
if speed>0then Dec(speed);
if speed>0then Exit;
speed:=10; //задержка
TThin.Create(DXSpriteEngine.Engine);
end;

Попробуй так.


 
jab~   (2004-02-16 09:28) [4]

Что то не работает такая задержка...
Попробывал вместо шортинтеджера влепить интеджер так вообще всё подвисать стало...

*************************
К слову:
Я начал использовать Random(10)
if random(10)=1 then
begin
Тут выполняется то что мне нужно задержать.
end
Такого рода задержка конечно полный абзац, но
работает и ничего не тормозит!
*************************

Есть вопрос:
В формкреате у меня происходит наполнение имэджлиста
 ImageList.Items[0].Picture.LoadFromFile("main\Flur.bmp");
 ImageList.Items[1].Picture.LoadFromFile("fatc\Go.bmp");
 ImageList.Items[2].Picture.LoadFromFile("fatc\Stand.bmp");
 ImageList.Items[3].Picture.LoadFromFile("fatc\Attack.bmp");
 ImageList.Items[4].Picture.LoadFromFile("fatc\Dead.bmp");
 ImageList.Items[6].Picture.LoadFromFile("main\Energy.bmp");
и т.д.
И наполнению этому нет конца и края...
Каким образом выводить картинку того что происходит лоадинг?

И ещё вопрос:
Когда у меня убивается монстр, то происходит смертельный ролик из спрайтов (он падает на землю весь окровавленный) и класс этого монстра принимает статус "sDead", но вот незадача... я нарубил груду монстров и у меня начинает тормозить комп по страшному так как у меня уже накопилась куча "мертвых" классов. Если им (классам) давать Dead по смертно, то тормозов нет, но классы умирают (и картинки тоже), а я бы хотел чтоб у меня на экране оставалась посмертная картина (куча трупов, кровище, оторванные конечности). Т.е. как рисовать на общий фон последний спрайт или может есть другой способ?


 
m-AAA-d ©   (2004-02-16 09:55) [5]

попробуй перед тем как удалишь спрайт убитого монстра получив его координаты и угол поворота нарисовать прямо на DXDraw.Surface соответствующий паттерн из DXImageCollection


 
ZAROLF ©   (2004-02-16 11:05) [6]

>jab~   (16.02.04 09:28) [4]
> Что то не работает такая задержка...
> Попробывал вместо шортинтеджера влепить интеджер так вообще
> всё подвисать стало...
>

var speed:shortint;

If isButton5 in MainForm.DXInput.States Then
begin
if speed>0then Dec(speed);
if speed>0then Exit;
speed:=10; //задержка
//ну так точно должно заработать
with TThin.Create(DXSpriteEngine.Engine)do
begin
....
end;
end;

> Если им (классам) давать Dead по смертно, то тормозов нет,
> но классы умирают (и картинки тоже), а я бы хотел чтоб у
> меня на экране оставалась посмертная картина (куча трупов,
> кровище, оторванные конечности). Т.е. как рисовать на общий
> фон последний спрайт или может есть другой способ?
-----------------------------------------------------------------
Может тебе останавливать спрайт на последнем кадре(посмертный).


 
nexxiss ©   (2004-02-16 11:36) [7]

Можно к тайлу добавить свойство с дополнительным изображением или какое другое свойство, по которому можно определить тип изображения для вывода поверх тайла


 
jab~   (2004-02-17 11:05) [8]

to m-AAA-d
Хм интересная идея... я об этом задумывался, но очень понимаю как этореализовать. В общем для полноты картины приведу кусок из проги:

// Загружаю карту
constructor TFlur.Create(AParent: TSprite; AX, AY : Integer);
var
 i, j          : Integer;
begin
 inherited Create(AParent);
 SetMapSize(AX,AY);
 Image := MainForm.ImageList.Items.Find("GFlur");
 X := 0;      // Начальная координата по иксу
 Y := 0;      // Начальная координата по игрику
 Z := -2;     // Глубина
 Width := MapWidth  * Image.Width;
 Height:= MapHeight * Image.Height;
//Случайное заполнение карты
 For i:=0 to AX-1 do
   For j:=0 to AY-1 do
     Chips[i,j]:=Random(20);
end;
, где TFlur = class(TBackgroundSprite)

В общем тут всё просто.. я случайным образом заполняю фон квадратиками 32х32 (спрайтами). Указываю размер карты AX, AY : Integer

В формкреате после загрузки картинок в имэдж лист у меня выполняется:
 Flur:=TFlur.Create(DXSpriteEngine.Engine,50,50);

А после я уже играюсь со спрайтами юнитов!
Посмертно классу юнита я присваиваю статус stDead и для всех классов имеющих этот статус отрабатывает следующее:
     begin
       SetAnimAngle;
       If Round(AnimPos)=AnimCount
         then begin
             AnimSpeed:=0;
             Z:=-1;
         end;
     end;
Это просто показываю последний спрайт из посмертного ролика!
Таким образом у меня разбросану по карте куча классов монстров которые показывают последнюю картинку их смерти.

Когда у меня накапливается некоторое колличество этих классов то у меня начинает жудко тормозить комп! (ведь они сидят в оперативке), а ещё я слышал о некой кривизне DXSpriteEngine который иногда проглючивает и меня выкидывает без предупреждения (но это если у меня "мертвых" спрайтов накапливается куча)
>>>>>>>>>>>>>
Как реализовать прорисовку посмертной картинки спрайта поверх фона(карты) TFlur или может есть другой способ?
>>>>>>>>>>>>>


 
jab~   (2004-02-17 11:13) [9]

to ZAROLF
Да нет... мне не нужно:
with TThin.Create(DXSpriteEngine.Engine)do
begin
....
end;

У меня всё описано в самом креате вся внутренность..
А для куска:
If isButton5 in MainForm.DXInput.States Then
begin
if speed>0then Dec(speed);
if speed>0then Exit;
...
У меня не происходит задержки... почемуто...

>Может тебе останавливать спрайт на последнем кадре(посмертный).
Это так и реализовано:
   stDead :
     begin
       SetAnimAngle;
       If Round(AnimPos)=AnimCount
         then begin
             AnimSpeed:=0;
             Z:=-1;
         end;
     end;
Для статуса stDead я прорисовываю последнюю картинку смерти...
Вот если бы её прорисовать на карте, а спрайт командой Dead убить напроч... только я не знаю как это реализовать.


 
jab~   (2004-02-17 11:23) [10]

to nexxiss
Я так понял ты предлогаеш менят саму картинку куска карты на котором умер класс монстра или героя!?
Просто спрайт ячейки карты меньше спрайта монстра и умирая он занимает несколько кусков карты... Там картинку придется резат и раздавать... наверно есть более простой вариант...
Сам фон Z:=-10
Живой юнит Z:=2
Мертвый юнит Z:=-1

Может можно создать ещё какой то слой карты на котором будут картинки мертвых персонажей??? Если этот вариант возможен, то очень хотелось бы посмотреть на код реализации! :)

З/Ы я не очень здорово разбираюсь с DelphiX и если какой код есть, то коментарии к нему мне очень помогут! :)


 
jab~   (2004-02-17 11:28) [11]

И ещё если можно, примерчик по подсветке персонажей!
При наводке на персонажа мышы чтоб он обводился по контуру зеленой или красной канвой в зависимости от статуса агресивности.

А при хождении героя по карте чтоб он просвечивал стену за которой стоит (чтоб его можно было видеть сквозь стену и кликать на нем) как к примеру это в fallout или джагет алиансе и им подобных игрушек.

Оочень хочется смотреть реальные примеры а не просто на словах... :):):)


 
ZAROLF ©   (2004-02-17 11:49) [12]

>jab~   (17.02.04 11:13) [9]
>Для статуса stDead я прорисовываю последнюю картинку смерти...
>Вот если бы её прорисовать на карте, а спрайт командой Dead >убить напроч... только я не знаю как это реализовать.
-----------------------------------------------------------------
Ну попробуй при удалении спрайта, задать координаты(см. ниже) для
вывода простого image, соответственно и ресурсов будет жрать меньше, если конечно монстров будет не 1000.

X:=Self.X+Self.Width-10;
Y:=Self.Y+Self.Height-10;
Image:=MainForm.ImageList.Items.Find("Trup"); //простой пример

А вообще Delphix для данной цели не годиться.


 
jab~   (2004-02-17 11:55) [13]

to ZAROLF
Просто я хочу сделать игру по типу мысорубки...
Груда трупов, кровища, кишки, конечности...
..ладно, это всё из-за трудовых будней! :)


 
nexxiss ©   (2004-02-17 12:21) [14]

RE: Я так понял ты предлогаеш менят саму картинку куска карты на котором умер класс монстра или героя!?
Просто спрайт ячейки карты меньше спрайта монстра и умирая он занимает несколько кусков карты... Там картинку придется резат и раздавать... наверно есть более простой вариант...


Ничего резать не надо, дастаточно просто вывести картинку мертвого унита поверх тайла. Так тебе не нужно будет хранить объекты мертвых унитов, соответсвенно расход памяти меньше.
пример:

type

TAddedImage = record
 ...
 ...
 ...
 dX,
 dY,
 ID: integer;
end;
 
...
...
...

TTile = record
 ...
 ...
 ...
 AddedImage: TAddedImage;
 
end;

При создании карты AddedImage каждого тайла присваиваем несуществующий ID ( например -1), а при выводе тайла проверяем на наличие данного ID. Если <>-1, тогда выводим картинку мертвого юнита с индексом ID и смещением dX,dY.
Это только лишь идея по решению данной проблемы. Немного подумав, можно создать более оптимальный способ.


 
jab~   (2004-02-17 12:34) [15]

Хм... так так... есть пару мыслей... счас буду проверять.


 
jab~   (2004-02-17 14:46) [16]

В общем так!

Создал я класс:
 TDead = class(TImageSprite)
 protected
 public
   constructor Create(AParent: TSprite); override;
 end;

constructor TDead.Create(AParent: TSprite);
begin
 inherited Create(AParent);
 Image := MainForm.ImageList.Items.Find("??????");
 X := 10;
 Y := 10;
 Z := -1;
 Width := Image.Width;
 Height := Image.Height;
end;
Он будет у меня отображать дохлых юнитов в виде картинки!
Но каким образом мне узнать какую картинку подгружать?


 
nexxiss ©   (2004-02-17 14:52) [17]

А это задавай уже в живом юните. Когда он умирает, соответственно выбирается нужное изображение для дохлого


 
jab~   (2004-02-17 16:48) [18]

Вроде вышло... Полностью избавится от создания "мертвого" класса не вышло. Оказалось что просто так нарисовать картинку на карте не выходит... Пришлось создать облегченный класс с анимацией смерти. Таким образом во время смерти юнита я вызываю махонький классик в который передаю координаты смерти + угол разворота + тип юнита. Здохни злобный монстр... :):):) Таким образом я удовлетворил свою кровожаднось.... :):):) Теперь на экране запросто вмещается пару сотен трупов в различных позах (навалом), всё в крови и комп практически не тормозит.. так немножко заметно падение FPS но не сильно.

>>>>>>>>>>>>>>>>>>>>
Как мне создать экран загрузки..
Ну типа когда игра грузится, чтоб отображалась шкала на фоне какой то картинки (а то у меня сейчас просто черный экран), а после загрузки показывалось меню!?
>>>>>>>>>>>>>>>>>>>>


 
nexxiss ©   (2004-02-18 17:00) [19]

Заводим следующее дело:

type
 TGameState = set of [ gs_Play, gs_Pause, gs_MainMenu, gs_InGameMenu, gs_Active ];

...
...

var
 GameState: TGameState;

...
...

begin
 GameState:=[gs_Active];
...
...

в процедуре вывода графики:

if not (gs_Active in GameState) then exit; // если приложение не активно то ничего не делаем
if gs_Play in GameState then <Играем дальше>
if gs_Pause in GameState then <Пауза>

и так далее


 
jab~   (2004-02-19 09:13) [20]

to nexxiss
Идея достойная! Наверно так буду делать.
Но тогда позникает опять таки не решенная проблема с этими дурацкими isButton"ami

procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
begin
 if not DXDraw.CanDraw then exit;

 If isButton1 in MainForm.DXInput.States
   Then
     begin
       GameState:=[gs_Pause];
     end;
// Таким образом мне нужно писать ещё один клик
 If isButton2 in MainForm.DXInput.States
   Then
     begin
       GameState:=[gs_Play];
     end;

end;
То есть у меня как бы 2 клавиши... одна ставит паузу, а другая её снимает, а как это в других играх реализовано на одной клавише?

Просто isButton сабака сробатыват до тех пор пока удержываеш клавишу... если бы было для него что то вроде KeyUp - KeyDown то можно было бы запросто переключать режимы. В данном случае просто KeyPress :(
А с задержкой описанной выше ничего не вышло.


 
nexxiss ©   (2004-02-19 12:23) [21]

Можно по-другому:
if isButton in MainForm.DXInput.States then
 if gs_Pause in GameState then GameState:=GameState-[gs_Pause]
                          else GameState:=GameState+[gs_Pause];
вроде как таким образом, а gs_Play это для главного меню игры, т.е. если игра начата, тогда этот флаг есть, если нет, то нету


 
jab~   (2004-02-19 15:00) [22]

to nexxiss
У тебя if isButton in MainForm.DXInput.States then ...
устанавливает и снимает этот флаг?

процедура
procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
отрабатывает 40 раз в секунду! .. соответственно этот влаг установится и снимется по 20 раз... и в конечном итоге не известно что получится.


 
jab~   (2004-02-19 18:02) [23]

Вот выложил:
http://gauss2k.narod.ru/mb.rar

Исправте кто то кривизну кода, а то я уже не знаю как это можно...


 
nexxiss ©   (2004-02-19 18:18) [24]

Это работать будет только в случае нажатия на кнопку, соответсвенно вызовов не будет 20-40, а только 1.


 
jab~   (2004-01-23 13:36) [25]

to nexxiss
Что то наверно не так, но у меня не получилось обьявить тип твоим способом...

Получилось так:
type
TGameState = (gs_Play, gs_Pause, gs_MainMenu, gs_InGameMenu, gs_Active );


 
jab~   (2004-02-20 15:33) [26]

Мда и ещё...
Если я прирываю вывод графики

if GameState=gs_Pause then begin

If isButton3 in MainForm.DXInput.States
then begin
 GameState:=gs_Play;
end;

exit;
end;

или сворачиваю окно Alt+Tab то потом даже если возобнавляю (возвращаюсь в окно), то оно у меня не продолжает отрисовывать...
Что делать?


 
nexxiss ©   (2004-02-20 16:11) [27]

Хм, я пытался скачать твои исходники, но с narod.ru скорость совсем никакая, вышли на меил. Заодно гляну, что у тебя там выходит в общем. Тип не получается объявить, т.к. значения не определены
Высылай сурскод.


 
jab~   (2004-02-23 09:02) [28]

to nexxiss

Это автоматически сгенерированное сообщение почтового сервера UkrNet.

Посланное Вами сообщение не может быть доставлено одному или нескольким
получателям. Следующие адреса не были обработаны:

 nexxiss@one.lv
   SMTP error from remote mailer after end of data:
   host mail2.one.lv [62.85.54.8]: 552 Mailbox <nexxiss@one.lv> does not have
enough space

------ Это копия сообщения, включая все заголовки. ------
------ Размер сообщения был 1179051 байт; только первые
------ 16384 байт показаны ниже.


 
nexxiss ©   (2004-02-23 13:16) [29]

Тогда попробуй отправить на nexxiss@mail.ru
У меня на том майле места не осталось, поэтому такая беда вышла



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

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

Наверх




Память: 0.56 MB
Время: 0.044 c
14-1086349024
DSKalugin
2004-06-04 15:37
2004.06.20
Уязвимость Firebird


1-1086216041
hiperLogun
2004-06-03 02:40
2004.06.20
XP Menu


6-1082982090
WinLamka
2004-04-26 16:21
2004.06.20
мониторинг шаров.


6-1082634294
Aleksandr
2004-04-22 15:44
2004.06.20
Кто портит сообщения по мылу?


1-1086636595
Duk
2004-06-07 23:29
2004.06.20
Потоки





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский