Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

DelphiX - Рождение и смерть спрайтов. [Delphi, Windows]


Страницы:   1 2

jab~ ©   (2004-02-13 15:17:00) 

За основу взял примерчик
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;

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


nexxiss   (2004-02-23 13:16:00) [1]

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


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

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-20 16:11:00) [3]

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


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

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

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-19 18:18:00) [5]

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


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

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

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


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

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

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


nexxiss   (2004-02-19 12:23:00) [8]

Можно по-другому:
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 09:13:00) [9]

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-18 17:00:00) [10]

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

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-17 16:48:00) [11]

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

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


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

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


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

В общем так!

Создал я класс:
 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;
Он будет у меня отображать дохлых юнитов в виде картинки!
Но каким образом мне узнать какую картинку подгружать?


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

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


nexxiss   (2004-02-17 12:21:00) [15]

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 11:55:00) [16]

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


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

>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:28:00) [18]

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

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

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


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

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

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

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


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

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 убить напроч... только я не знаю как это реализовать.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо