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

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

DelphiX, DoMove, DoCollision [D6, WinXP]


Страницы:   1 2 3

Jus ©   (2004-10-01 13:03:00) 

Помогите, как мне сделать? Вот есть у меня игрок, он появляется в начале игры над "кирпичами"(Кирпич - это объект TKirp) в воздухе и как делать дальше в DoMove и DoCollision?! Я начал вроде, что у плеера по умолчанию стоит свойство Falling:=True; при Player1.DoCollision пишу
If (Sprite is Tkirp) and (Player1.Falling=True) then Falling:=False;А как потом игрок поймёт, что надо опять падать?

Если можно, приведити пример со столкновением с кирпичём (ЛЕВО ПРАВО ВЕРХ ВНИЗ), учитывая то, что есть ещё гравитация. Плиз!


Falcon(TFSfot)   (2004-10-02 20:40:00) [41]


with InfluenceSprite do
  begin  
        if (Map[trunc (Y/32), trunc ((X+16)/32)]<20) and
           (Map[trunc ((Y+25)/32), trunc ((X+16)/32)]<20-ord(LadderSens))
   then
           begin


Ок. Слушай....
Сначала мы глабальные координаты преобразовываем в координаты масива карты trunc (Y/32), trunc ((X+16)/32), тоесть получаем значение i,j (Map[i,j]), после чего проверяем что это за элемент <20
Тут 20 - означает что это воздух и все остальные элементы через которые можно прлетать, земли(их много типов) например имеет индкексы <10, лестница 19
Эта строчка проверяет выше описанное
Map[trunc (Y/32), trunc ((X+16)/32)]<20)
А эта
(Map[trunc ((Y+25)/32), trunc ((X+16)/32)]<20-ord(LadderSens))
Проверяет не является ли данная ячейка карты лестницей...

Дальше собственно идёт "физика" прыжка, вот и всё...


Falcon(TFSfot)   (2004-10-02 20:31:00) [42]

Ты всё правильно понял.
InfluenceSprite- спрайт над которым проводятся действия по гравитации.
Ты используеш процедуру DOGravity только у тех объектов, у которых ты хочеш проявить силу гравитации... и всё, у остальных ненадо...


Jus   (2004-10-02 17:07:00) [43]


> Falcon(TFSoft)   (02.10.04 13:36) [16]

благодарю! получил модуль по почте.

InfluenceSprite - это сам персонаж, или все персонажи к которым относится гравитация?
Map[,] - это массив карты, как я понял?

> with InfluenceSprite do
>   begin  
>         if (Map[trunc (Y/32), trunc ((X+16)/32)]<20) and
>            (Map[trunc ((Y+25)/32), trunc ((X+16)/32)]<20-ord(LadderSens))
>    then
>            begin
> ...


Я так понимаю что сдесь InfluenceSprite проверяет своё место положение и прочии свойства по массиву карты.
Растолкуйте пожатуйста этот фрагмент.


Falcon(TFSoft)   (2004-10-02 13:36:00) [44]

А теперь немного подробнее...
Итак тут выложен целый модуль, который без лишних коментариев, вместе с реализованым на нём примером высылаю тебе в писме, извени что без предуприждения (надеюсь там есть свободных 500k).
Он позволяет делать гравитацию (`почти) одинаковой для всех объектов, не зависимо от FPS, причём гравитация по ходу дела ещё и физическая, тоесть с ускорением. Возможно не сильно реалестично но....

Чтоб воспользоватся необходимо например:

//+=========================   TEnemy_1 =======================================+
Procedure TEnemy_1.DoMove(MoveCount: Integer);
Var
  Speed : Integer;
  dy      : Real;
begin
inherited DoMove(MoveCount);

  Speed := 200;
  dx := (Speed/1000)*MoveCount;
//далее примитивная проверка на столкновение (в полученном примере это красный шарик-монстр)
  Case Direction of
     0: //Left
        Begin
           if Map[trunc ((Y+16)/32), trunc (X/32)]<20 then
                 X := X-dx
           else
               Direction := 1;
        end;
     1: //Right
        Begin
           if Map[trunc ((Y+16)/32), trunc ((X+32)/32)]<20 then
                 X := X+dx
           else
               Direction := 0;
        end;
  end;

// А вот и наша граитация!!!
  Gravity.DoGravity(Self as TSprite, MoveCount);
end;


Вот и всё!
Причём, если ты хочеш, чтоб монстр(спрайт) "прыгал" то необходимо сделать:
begin
       Gravity.Jumping    := True;
       Gravity.FlyingFinish := False;
     end;

И при вызове Gravity.DoGravity(Self as TSprite, MoveCount);спрайт подпрыгнет!

Ну вот и всё, почти тянет на статью :)
Ах, да ещё я сказал, что опишу зачем нужны некоторые переменные:

MaxJumpCount : Real;- фактически высота прыжка, только не в пиклселах а в ... каких-то относительных еденицах
LadderSens : Boolean;- говорит о том, что к объекту не будет применена гравитация, и прыжок на некоторых объектах(тафтология конечно ну ничего не поделаеш). К примеру на лестнице прыгать нельзя, но если ты падаеш, и попадаеш на лестницу то ты останавливаешся, а не "проскальзываеш" дальше.
Weight : Real;- отвеачет за вес,и соответсвенно за гравитацию, но помоему он здесь вообще не фурычит :(

И ещё одно, наверное не самое безполезное. Картра реализована как масив данных (спрайтов с набором свойств как к примеру разрушаемость), размером 32*32. Вот почему там фигурирует это число, ведь оно есть основным структурным элементом.

Ну а в остальном думаю всё понятно, если нет, то на то он и форум, что б отвечать на вопросы.

И в конце маленький примерчик реализации монстров:
unit Enemy_Movable_Unit;

interface
Uses
  DXClass, DXSprite, DXDraws,
  Gravity_Unit,
  Enemy_Unit,
  TPoints_Unit,
  TBoom_Unit;

Type
 TEnemy_1 = class (TEnemy)
   Direction       : Byte;
   dx              : Double;
   procedure DoMove(MoveCount: Integer); override;
   Constructor Create (X,Y: Double; Health,Power: Single; Hitpoints:Word);
 end;

implementation
Uses
  Main_Unit;

//+=========================   TEnemy_1 =======================================+
Constructor TEnemy_1.Create (X,Y: Double; Health,Power: Single; Hitpoints:Word);
begin
  Inherited Create(X,Y,Health,Power,Hitpoints);

  Image := MFrm.DXImageList.Items.Find('Enemy_1');
  Z:=1;
  Width := Image.Width;
  Height := Image.Height;

  Direction :=0;
end;
//==============================================================================
Procedure TEnemy_1.DoMove(MoveCount: Integer);
Var
  Speed : Integer;
  dy      : Real;
begin
if not OverlapRect(Engine.SurfaceRect, BoundsRect) then Exit; //для оптимизаци, если вне видимости, то не производить ниже идущие вычисления. помогает если монстор >25

if Self.Health<=0 then
Begin
  dead;
  exit;
end;

//вне карты - умираем
 if (X<0) or (X+32>LevelCols*32) or
    (Y<0) or (Y+32>LevelRows*32) then
    Begin
     Dead;
     Exit;
    end;

inherited DoMove(MoveCount);

  Speed := 200;
  dx := (Speed/1000)*MoveCount;

  Case Direction of
     0: //Left
        Begin
           if Map[trunc ((Y+16)/32), trunc (X/32)]<20 then
                 X := X-dx
           else
               Direction := 1;
        end;
     1: //Right
        Begin
           if Map[trunc ((Y+16)/32), trunc ((X+32)/32)]<20 then
                 X := X+dx
           else
               Direction := 0;
        end;
  end;

 
  Gravity.DoGravity(Self as TSprite, MoveCount);
end;
//+=========================   TEnemy_1 =======================================+
//+=========================     END    =======================================+
end.


Ёще не плохо было б написать копирайт, так как всё это я выдрал из игрулины своей недоделаной, но ПОЛЬЗУЙТЕСЬ на здоровье...


Falcon(TFSoft)   (2004-10-02 13:34:00) [45]

ПРивет всем!
Возможно я позно подкл. к обсуждению игры НЕ ЛОДЕ РУНЕР, но советом помогу...

Я не сильно програмёрю, поэтому приведённый ниже код сильно не критиковать(хотя программеру именно это и нужно!).

Итак, хотя в not LodeRyner игрок не прыгает но я приведу код, который позволяет создавать гравитацию на все необходимые (точнее задаваемые прогрм объекты):

unit Gravity_Unit;

interface
Uses DXSprite;

Type
  TGravityPower = class
     Public
        dy             : Real; //отвечает за текущее ускорение
        MaxJumpCount : Real; //просто необходимая переменная :)
        Jumping,   FlyingFinish : Boolean; /*ответ за текущее состояние описывать буду ниже*/
        LadderSens             : Boolean; //чувствителен ли к лестнице (или другим объектам по сценарию)?
        Weight       : Real; // вес ;)

        Constructor Create (Distance : Real);
        Function Do Fly(InfluenceSprite: TSprite; MoveCount: Integer): Boolean; //Возвращает true, если приземлились
        Function Do Jump(InfluenceSprite: TSprite; MoveCount: Integer): Boolean; //Возвращает true, если приземлились
        Procedure Do Gravity (InfluenceSprite: TSprite; MoveCount: Integer); //собственно сама гравитация, вызываемая при каждом DoMoveобъекта
     Private
        JumpCount : Real;//необходимый счётчик прыжка
end;

Var
  Gravity : Real = 200;//типа g=9,80655 :)

implementation
Uses
  Main_Unit; //подключаем модуль, в котором описывается карта и т.д. короче название модуля само за себя говорит

// конструктор
Constructor TGravityPower.Create (Distance : Real);
begin
  inherited Create;
  MaxJumpCount := Distance;
  Self.Jumping := False;
  Self.FlyingFinish := False; //???? ???? ????????, ?? ????? ?? ??? :0
  LadderSens := False;
  Weight := 1;
end;

// делаем прыжок, этой функцией
Function TGravityPower.DoJump (InfluenceSprite: TSprite; MoveCount: Integer): Boolean;
begin
with InfluenceSprite do
  begin  //????????
        if (Map[trunc (Y/32), trunc ((X+16)/32)]<20) and //?????? ?????? ???
           (Map[trunc ((Y+25)/32), trunc ((X+16)/32)]<20-ord(LadderSens))    then //????? ?????? ???  ??. +25/
           begin
              JumpCount := JumpCount + (Gravity/5000)*MoveCount*Weight;
              dy :=(MaxJumpCount*MoveCount*0.05 - 0.5*JumpCount*JumpCount)/10;
              If dy<=-4 then dy:=-4; //??? ? ?? ??????? ????? ? ????? 32?32
              Y := Y - dy;
              Result := False;              
           end
        else
           begin
              JumpCount := 0;
              Jumping := false;
              Result := True;
             //   FlyingFinish := True; //????? ????????? ? ???????
           end;
     end
end;

// делаем полёт - когда под ногами ничего нет, этой функцией
Function TGravityPower.DoFly (InfluenceSprite: TSprite; MoveCount: Integer): Boolean;
begin
with InfluenceSprite do
//34 - ???? ?? ??????? ? ????????????? ??????
  if Map[trunc ((Y+34)/32), trunc ((X+16)/32)]<20-ord(LadderSens) then //??????, ... ????? ?????? ????!
     begin
        JumpCount := JumpCount + (Gravity/5000)*MoveCount*Weight;//???????, ???? ????????, ?? FPS
        dy :=-0.5*(JumpCount*JumpCount)/10;
        If dy<-9 then dy:=-9; //??? ? ?? ??????? ????? ? ????? 32?32        
        Y := Y - dy;
        Result := False; //?? ??? ? ??????
        FlyingFinish := False;
     end
  else //????????????
     Begin
       JumpCount:=0;
       Jumping := false;   //??????? ?????
       FlyingFinish := True; //????? ????????, (??????? ??? ??????????????? ?????? ... ???????!)
       Result := True;
     end;
end;

// вообщемто эту функцию и надо вызывать, в обработке domove, и в зависимости от состояния переменных Jumping and FlyingFinish
будут производится либо прыжок, либо падение

Procedure TGravityPower.DoGravity (InfluenceSprite: TSprite; MoveCount: Integer);
begin
  if (Jumping and not FlyingFinish) then
        DoJump(InfluenceSprite, MoveCount)
  else
        DoFly(InfluenceSprite, MoveCount);
end;

end.


*-------------------------------------------------------------*


Jus   (2004-10-02 09:59:00) [46]

Вот класс игрока:
TPlayer=class(TImageSprite)
  MoveR:Boolean;
  MoveL:Boolean;
  MoveU:Boolean;
  MoveD:Boolean;
  falling:Boolean;
  DownY:Double;
  StayOnTop:Boolean;
   public
    procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
    procedure DoMove(MoveCount:Integer);override;
  end;


Falling:=True;// по умолчанию в начале игры

procedure TPlayer. DoMove(MoveCount:Integer);
var s:string;
begin{1}
 if Falling=True then DownY:=DownY+1;
 if isRight in Form1.DXInput.States then begin MoveR:=True; x:=x+1;end;
 if IsLeft in Form1.DXInput.States then begin MoveL:=True; x:=x-4;end;
collision;
 end;{1}


procedure TPlayer. DoCollision(Sprite:TSprite;var Done:Boolean);
begin
 if MoveL=True Then Begin
     If (Sprite is TKirp) and (MoveL=True) Then X:=X+4;
     MoveL:=False;
                    end;
 if MoveR=True Then Begin
     If (Sprite is TKirp) and (MoveR=True) Then X:=X-4;
     MoveR:=False;
                    end;
//  if Falling=True Then
//      If  (Sprite is TKirp) Then Begin DownY:=DownY-1; end else Falling:=True;

end;


Пожалуйстл, прошу ВАС, подумать тоже, как мне это сделать, у меня не получается, я тоже думаю над этим! :-О

Если хотите помочь мне и проекту, чтоб он реализовался быстрее, то, пожалуйсто, помогите! Кто разбирался в примере Servilatа, может нашел выход из положения?!

Зы: У меня очень сжатые сроки, до примерно 20.10.04, потом начнутся головняки, и закончатся где-то через месяц. Мне-бы хотябы демку сделать к этому сроку:(
Плиззз! )-;


Jus   (2004-10-02 08:31:00) [47]


> качать лучше FlashGet'ом или подобными, а то если просто
> - то там окна дурацкие появляются типа "вы хотите скаачть
> файл с хостинга такого-то". Во FlashGet'е без проблем.

скачал обычным способом, без проблем. спасибо!


МЯУ   (2004-10-01 21:24:00) [48]

Servelat ©   (01.10.04 18:55) [10]

хотел скачать аркаду, но, блин, не смог. DAP её не хочет, а стандартная закачка обламывается всё время на ~150kb. Не мог бы ты положить её в какое-то другое место? Посмотреть охота...


breakmaster   (2004-10-01 20:52:00) [49]

(8)Чето я не помню,чтоб в лодраннере кто-то прыгал...


Servelat   (2004-10-01 18:55:00) [50]

2 [8] Jus
Чего-то у меня письма не посылаются, наверное сервак глючит.
В общем выложил сюды:
http://www.servelat.nm.ru/arcade.zip
качать лучше FlashGet'ом или подобными, а то если просто - то там окна дурацкие появляются типа "вы хотите скаачть файл с хостинга такого-то". Во FlashGet'е без проблем.
Сразу предупреждаю: писал пару лет назад, за качество кода ответственности не несу, за отсутствие комментариев - тоже. Откуда выдрал картинки - не помню.
Тебе наверное интересны будут процедуры в модуле uSprite:
TSprite.Move;
TPlayer.Move.
Кстатим там используются не делфииксовские спрайты, а мои объекты, отдаленно их напоминающие. В общем погляди, может чем и поможет.
Удачи.


NikeOLD   (2004-10-01 16:37:00) [51]

Для общего развития: еще один вариант (по Ламоту). Но это тормоза.

Заводится еще одна поверхность (не знаю, как это в DelphiX выглядит). На ней отображаются однородным цветом непроходимые участки. Поверхность в рендеринге не участвует, но обновляется соответсвенно изменению непроходимых участков на экране. В процессе перемещения героя проводится постоянная проверка на столкновение с этим цветом, если столкнулся - стоим на месте.


Jus   (2004-10-01 16:04:00) [52]


> Servelat ©   (01.10.04 15:59) [7]
> У меня был примерчик подобный, когда я хотел какую-то аркаду
> с видом сбоку написать. Правда аркады не вышло, но мужичок
> исправно бегает и прыгает, сталкиваясь с кирпичами. А тебе
> еще проще, если герой прыгать не умеет, только падать (я
> в лоде рунер не игра никогда, так что правил не знаю). Могу
> послать на мыло, если надо.
> ЗЫ
> > Сдесь
>
> Здесь.

Давай:)!!!
hitman201@yandex.ru;

> еще проще, если герой прыгать не умеет, только падать

Он умеет перепрыгивать! Он перепрыгнуть может например расстояние с один блок 32х32.


Servelat   (2004-10-01 15:59:00) [53]

У меня был примерчик подобный, когда я хотел какую-то аркаду с видом сбоку написать. Правда аркады не вышло, но мужичок исправно бегает и прыгает, сталкиваясь с кирпичами. А тебе еще проще, если герой прыгать не умеет, только падать (я в лоде рунер не игра никогда, так что правил не знаю). Могу послать на мыло, если надо.
ЗЫ
> Сдесь

Здесь.


cyborg   (2004-10-01 15:54:00) [54]

Просто ты пошёл не по тому пути, от этого проблемы. Тебе посоветуют конечно чего нибудь, но решение скорей всего будет через зад.


Jus   (2004-10-01 15:39:00) [55]

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

Зы: Без постоянного падения получится как BOLDER DASH какой-то:)


Jus   (2004-10-01 15:33:00) [56]


> В подобных играх есть прием (это только один ИЗ вариантов
> решения).
> Игрок падает постоянно. Когда под игроком появляется объект,
> на который он должен встать, падение все равно продолжается.
> Поскольку объект никуда не исчезает мы видим, что игрок
> "стоит" на объекте. У тебя таким объектом будет кирпич,
> лестница и что там еще по сюжету.

Я так и сделал, а он скачет, и ещё при столкновении с кирпичём у меня подразумевается и пол и стены, следовалельно: он упал на кирпичи(на пол) и я нажимаю влево, чтоб идти, а при столкновении с кирпичём(левой стеной) уменя X=X+4. И что получается, он постоянно сталкивается с полом, т.к. падает постоянно и следовательно со стеной,(т.к. TKirp это и стена и пол). Значит я нажимаю влево и он стоит как кол вкопанный!


NikeOLD   (2004-10-01 14:36:00) [57]

Одним словом: нафиг переменную Falling.
В обработчике DoMove проверяешь на столкновение с объектом: да - координата Y игрока = Y объекта - высота игрока, иначе - уменьшаем Y игрока на нужную величину (т.е. падаем).


NikeOLD   (2004-10-01 14:32:00) [58]

В подобных играх есть прием (это только один ИЗ вариантов решения).
Игрок падает постоянно. Когда под игроком появляется объект, на который он должен встать, падение все равно продолжается. Поскольку объект никуда не исчезает мы видим, что игрок "стоит" на объекте. У тебя таким объектом будет кирпич, лестница и что там еще по сюжету.


KilkennyCat   (2004-10-01 13:12:00) [59]

ниче не понял...


Страницы:   1 2 3

Наверх

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