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

Вниз

DelphiX, DoMove, DoCollision   Найти похожие ветки 

 
Jus   (2004-10-01 13:03) [0]

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

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


 
KilkennyCat ©   (2004-10-01 13:12) [1]

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


 
NikeOLD ©   (2004-10-01 14:32) [2]

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


 
NikeOLD ©   (2004-10-01 14:36) [3]

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


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


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

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


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

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

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


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

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


 
Servelat ©   (2004-10-01 15:59) [7]

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

Здесь.


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


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

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

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

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


 
NikeOLD ©   (2004-10-01 16:37) [9]

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

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


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

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


 
breakmaster ©   (2004-10-01 20:52) [11]

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


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

Servelat ©   (01.10.04 18:55) [10]

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


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


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

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


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

Вот класс игрока:
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, потом начнутся головняки, и закончатся где-то через месяц. Мне-бы хотябы демку сделать к этому сроку:(
Плиззз! )-;


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

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

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

Итак, хотя в 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 DoFly (InfluenceSprite: TSprite; MoveCount: Integer): Boolean; //Возвращает true, если приземлились
        Function DoJump (InfluenceSprite: TSprite; MoveCount: Integer): Boolean; //Возвращает true, если приземлились
        Procedure DoGravity (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.


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


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

А теперь немного подробнее...
Итак тут выложен целый модуль, который без лишних коментариев, вместе с реализованым на нём примером высылаю тебе в писме, извени что без предуприждения (надеюсь там есть свободных 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.


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


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


> 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(TFSfot)   (2004-10-02 20:31) [18]

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


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


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))
Проверяет не является ли данная ячейка карты лестницей...

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


 
Jus   (2004-10-03 06:16) [20]

Собственно всё понятно! Но у тебя всё в игре проверяется по массиву(идея хорошая), а можно ведь без этого. Я использовал в своей игре массив для того лишь, чтоб загружать карту и объекты по массиву, а в дальнейшем может и для поисков путей для врагов(АИ). Получается у меня, что по массиву загрузились объекты и мне массив больше не нужен, дальше я использую DoCollision и DoMove, я так хотел. Твой модуль можно использовать тоже для  гравитации. Буду делать, спасибо.


 
Jus   (2004-10-03 08:28) [21]

Какая функция округляет (обрубает) число после запятой? Сам не понял как выразился:)

Ну например:  7.25  = 7  
                       7.99  = 7
                       8.01  = 8
                       8.84  = 8


 
cyborg ©   (2004-10-03 09:37) [22]


> [20] Jus   (03.10.04 06:16)

Массив  карты в подобной игре наиболее оптимальный вариант, быстро работает и лёгок в обработке.


> [21] Jus   (03.10.04 08:28)

Trunc();


 
Jus   (2004-10-03 09:58) [23]


> Trunc();

Я уже догадался:)


> Массив  карты в подобной игре наиболее оптимальный вариант,
> быстро работает и лёгок в обработке.

Щас делал, с кирпичами чисто, всё работает, спасибо всем!:)))Всё ок!)


 
bobomen   (2004-10-03 11:06) [24]

изыди ведьма


 
Falcon(TFSoft)   (2004-10-03 16:03) [25]

>obomen   (03.10.04 11:06) [24]
изыди ведьма

???К чему это сказано???

А кгде скриншоты посмотреть можно?
Если они уже есть...


 
Jus   (2004-10-03 17:16) [26]


> Falcon(TFSoft)   (03.10.04 16:03) [25]
> >obomen   (03.10.04 11:06) [24]
> изыди ведьма
> ???К чему это сказано???

А он вроде того, он всем всегда ченибудь говорит, надоел уже. извеняюсь.


> А кгде скриншоты посмотреть можно?
> Если они уже есть...


ftp://cyborghome.ru/ScreenShots/


 
ninja ©   (2004-10-03 17:33) [27]

как там прогресс? когда играть можно будет?


 
Falcon(TFSoft)   (2004-10-03 18:07) [28]

Если нужна помощь, то обращайся... *)
да, ещё вопрос, как тебе игрулина которую я прислал?


 
Jus   (2004-10-04 05:28) [29]


> ninja ©   (03.10.04 17:33) [27]
> как там прогресс? когда играть можно будет?

Во что? Альфа версии ещё даже нет, но скоро будет:)


> Falcon(TFSoft)   (03.10.04 18:07) [28]
> Если нужна помощь, то обращайся... *)
> да, ещё вопрос, как тебе игрулина которую я прислал?

Нормально, даже больше чем. Ты б её доделал! ...?:)


 
Jus   (2004-10-04 08:24) [30]


> Щас делал, с кирпичами чисто, всё работает, спасибо всем!:)))Всё
> ок!)


Блин, я вот вчера, поспешил с заключением.
У меня игрок допустим находится в массиве(x,y) [12,7], а кирпич [12,8]. когда он идётвправо то по X он как только переходит на [13,7] начинает падать, а если идти влево, то по X он уже будет [11,7] и тоже начнёт падать. вроде ну так и надо, правильно. Но визуально ведь объект 32х32 и Х у этого объекта находится в левой части объекта, а правая часть объекта находится на 32 пикселя правей от Х. Так что получается (на экране) вправо падает нормально, а влево как только один пиксель успевает пройти за кирпич - начинает падать сквозь него. Как же мне делать, чтоб "угодить" и для движения вправо и также влево?;(


 
Jus   (2004-10-04 08:38) [31]

Фрагмент из программы создания карты по массиву [ix,iy]
...
IF ScrMap[ix,iy]=36 then  //Игрок 1
   begin
player1:=TPlayer.Create(DXSpriteEngine.Engine);
 player1.Image:=DXImagePlayer1.Items.Find("IPlayerR");
 player1.Width:=player1.Image.Width;
 player1.Height:=player1.Image.Height;
 player1.X:=ScrX;
 player1.Y:=ScrY;
 player1.Z:=2;
 player1.PixelCheck:=True;
 fplayer1:=true;// создан игрок или нет
 player1.ScanX:=ix; //
 player1.ScanY:=iY; // ScrMap[ScanX,ScanY]
 end;

...

 procedure TPlayer.DoMove(MoveCount:Integer);
var s:string; i:integer;
begin{1}
 If (ScrMap[Trunc(player1.ScanX),Trunc(player1.ScanY+1)]) and (ScrMap[Trunc(player1.ScanX+1),Trunc(player1.ScanY+1)]) =0 then falling:=true else falling:=false;
 if isRight in Form1.DXInput.States then begin MoveR:=True; l:=1;ScanX:=ScanX+0.125; x:=x+4;end;
 if IsLeft in Form1.DXInput.States then begin MoveL:=True;l:=0; x:=x-4;ScanX:=ScanX-0.125;end;
 if IsButton1 in Form1.DXInput.States then Falling:=True;
 if Falling=true then begin Y:=Y+8; ScanY:=ScanY+0.25 end;
 collision;
 end;{1}


Зы: if Falling=true then begin Y:=Y+8; ScanY:=ScanY+0.25 end;

В подчёркнутой строчке я поясню: ести бы Y:=Y+4(1/8-я часть спрайта 12.5%) то ScanY:=ScanY+0.125(переместился на 1/8-ю часть массива 12.5%)если Y+32(целая чась спрайта 100%) то ScanY+1;(... 100%).


 
cyborg ©   (2004-10-04 09:40) [32]


> [30] Jus   (04.10.04 08:24)

В этой игре игрок бегает поклеточно, а не попиксельно, следовательно обрабатывать ввод нужно только тогда, когда игрок ровно стоит в клетке. Нажали, нарипмер, клавишу влево, ставишь игроку флаг двжения, у тебя клетка карты 32х32 пикселя, вот он должен двигаться эти 32 пиксела, пока их не пройдёт. На кадр прибавляй ему по 2 или по 4 пикселя, подбери, чтобы скорость нормальная была. Проверять на падение нужно будет 1 раз, когда игрок дошёл до назначения, т.е. встал ровно в клетку, тогда и смотри что под ним. Так же с падением, ставишь флаг "падает" и крутишь цикл программы, пока не упадёт на клетку вниз, затем опять проверяй на падение или ввод клавиш управления.

Момент дохода до назначения (ну и слово :), координата игрока будет кратна 32-ум, т.е. if (X mod 32=0) and (Y mod 32 = 0) then (остановить игрока, посмотреть, есть ли под ним земля, если есть обработать ввод, если нет, то падает). А чтобы не пропустить этот момент, то прибавляй ему координаты по единице, например, если скорость у игрока = 3 пикселя на кадр, то for i:=1 to Speed do (двигай игрока на пиксель и прверяй дошёл ли он до места назначения, т.е. координаты кратны 32-ум)


 
Megabyte-ceercop ©   (2004-10-04 13:15) [33]


>  падает постоянно и следовательно со стеной,(т.к. TKirp
> это и стена и пол). Значит я нажимаю влево и он стоит как
> кол вкопанный!


Ты проверяешь столкновение объекта при его новом положении, и если это столкновение есть, ты возвращаешь предыдущее положение. Поэтому его столкновение с полом и расценивается как столкновение со стеной.

Делай так:
Измени координату X, проверь столкновения, и в случае столкновения со стеной, верни предыдущее значение координаты X.

Измени координату Y, проверь столкновения, в случае столкновения с полом или потолком, верни предыдущее значение координаты Y.

Теперь горизонтальное перемещение объекта не будет зависеть от вертикального.


 
Faclon(TFSoft)   (2004-10-04 20:45) [34]

Не хочется выступать критиком, но помоему вариант предлагаемый  ув.cyborg-ом чуть чуть не подходит.  Не потому, что приняв этот вариант Jus будет переделывать достаточно участков кода, что б этого не делать (тафтологоия какая-то ;)).
Вопервых игра будет сильно "шаговая", тоесть если шаг сделан влево, значит что б  отойти опять назад, необходио дождаться пока завершится текущий шаг, что уж говориь о прыжках. Но в этом всём есть большой плюс - просчёт столкновений упрощается в несколько раз. ведь мы точно знаем на перёд за каждый шаг где будет находится спрайт.
А что надо сделать, чтоб реализовать прыжок с отвеса ???
Во-вторых, лодерунер был всегда игрой с шагами в 1п. (ну может не в один а в 2,3 ну мах в 4 пиксела).

P.S. Простите за орфографию.


 
Faclon(TFSoft)   (2004-10-04 20:46) [35]

>Megabyte-ceercop ©

Ты всё правильно говориш, но вот незадача, если использовать "гравитацию", то по твоей технологии спрайт будет дёргатся.

Пример:
Спрайт прыгнул, полсе чего падал с некоторой скоростью dу=6, (к примеру 6), призимлился, произошёл детекшен колижен (столкновение вроде как так произносится). По товему методу необходимо вернуть спрайту предыдущее положение тоесть y=y-6. Это подбросит его на 6 пикселов вверх, после чего он снова упадёт с dу=2 или dу=1. В лутшем случае его снова подбросит на 1 пиксел, в худшем, на больше.

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

Я долго пытался выйти из этой ситуации, но мой код так и не выплыл..

И ещё раз повторюсь, если я не прав, то пожайлуста поправте меня...

с ув. Faclon


 
Faclon(TFSoft)   (2004-10-04 20:47) [36]

Я решил эту проблему следующим методом, возможно не таким прогресивным, как того хотелось бы..
Сначала на словах:
Проверка идёт по масиву карты(преобразовую координаты спрайта, в номер текущего элемента масива), если следующая "клетка" является непроходимой, то кордината спрайта просто не изменяется.
Но это не даёт хорошего результата, спрайт иногда просто "впухает", влезает и т.п в запрещённый объект. Что б решить этоту проблему в обработке столкновения проводятся дополнительные пересчёты, нормализация текущей позиции, координат спрайта.

А теперь пример (работающий, кто захочет убедится, просите вышлю ехе файл...)

Procedure TPlayer.DoMove(MoveCount: Integer);
 ***
if isLeft in MFrm.DXInput.States then
    begin
     if Map[trunc ((Y+16)/32), trunc (X/32)]<20 then
        dx := -(Speed/1000)*MoveCount;
    end;

   if isRight in MFrm.DXInput.States then
    begin
     if Map[trunc ((Y+16)/32) ,trunc ((X+32)/32)]<20 then
        dx := (Speed/1000)*MoveCount;
    end;
***
   
//==============================================================================
procedure TPlayer.DoCollision(Sprite: TSprite; var Done: Boolean);
Var
  xo, xs, yo, ys : Byte;
begin
 inherited DoCollision(Sprite,Done);

 if Sprite is TMapPiece then
  begin
     X := X + (X-Sprite.X)/32;
     Y := Y + (Y-Sprite.Y)/32;
     
//    Coord := Coord + (Coord-Sprite.Coord)/NormalizeSpeed;
  end;

 Done := True;
end;


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


 
Falcon(TFSoft)   (2004-10-05 00:49) [37]

Special to Jus:
>[30],[31]

Предлагаю ипользовать вместо player1.ScanX просто player1.X, помоему так гараздо удобнее.
Тогда координаты игрока(пл.) в пространстве игры буду типа ххх.хх (тоетсь Single), а вот что б найти текуще его положение в ячейке товей карты ты будеш использовать:
Map[trunc (player1.Y/32), trunc (player1.X/32)]
Тут 32 - величина ячеек карты 32*32, тогда не прийдётся воспользоватся дополнительной переменной ScanX. Она, я так понял дублирует player1.х.

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


procedure TPlayer.DoMove(MoveCount:Integer);
var
  dx, dy :Single;
begin{1}

   dx := 0;
   dy := 0;

   if isLeft in MFrm.DXInput.States then
    begin
    {(Y+16) - центр спрайта по оси у,      trunc ((Y+16)/32) - номер строки
     (X/32) - берём левый угол спрайта, так как идём влево

     Map[] < 20 - означает, что слева элемент, через который можно проходить,
                  к примеру сделаеш чтоб камень был 1, дерево 2 и т.д.
                  а например трава, или кусты какие-нибудь 21}
     if Map[trunc ((Y+16)/32), trunc (X/32)]<20 then
        dx := -(Speed/1000)*MoveCount;//x:=x+dx;
     DirectionX := -1;  //направление движения, возможно понадобится
     FASPos :=  s_Left  //текущая анимация - движение влево, тоже может понадобится
    end;

   if isRight in MFrm.DXInput.States then
    begin
    {
     всё тоже самое, но вместо (X/32) берём
     (X+32)/32 - тоесть правый конец спрайта, так как движемся в право.}
     if Map[trunc ((Y+16)/32) ,trunc ((X+32)/32)]<20 then
        dx := (Speed/1000)*MoveCount;
     DirectionX := 1;
     FASPos :=  s_Right
    end;

//----------------движение по лестнице-----------------
   if isUp in MFrm.DXInput.States then
    begin
     if (Map[ trunc (Y/32), trunc ((X+16)/32)]=19) and //Проверяем, лесница ли в Руках? 19=лестница
        (Map[trunc (Y/32) ,trunc ((X+16)/32)]<20)      //Нет ли чего-то непроходимого сверху?
         then
           begin
              dY :=-1.2*(Speed/1000)*MoveCount; // скорость поднятия по леснице чуть другая, нежели ход пешком
              FASPos :=  s_Up // анимация, может понадобится
           end;
    end;

   if isDown in MFrm.DXInput.States then
    begin
     if (Map[trunc ((Y+34)/32), trunc ((X+16)/32)]=19) and //Проверяем, лесница ли в ногах?, точнее в руках :)
        (Map[trunc ((Y+32)/32) ,trunc ((X+16)/32)]<20)  //Нет ли чего-то снизу?
        then
        dY :=1.2*(Speed/1000)*MoveCount;
        DirectionY := 1;
        FASPos :=  s_Down
    end;

//--------------Прыжки...------------------------------
//нажаиа ли клавиша, и призимлился ли я, что б начать прыгать снова :)
   if ((isButton1 in MFrm.DXInput.States) and (Gravity.FlyingFinish)) then
     begin
      //выставляем переменный для прыжка :)
       Gravity.Jumping    := True;
       Gravity.FlyingFinish := False;
       //убараем автоматическое нажатие клавиши, (как у Авт. Калаш. одиночные выстрелы)
       Mfrm.DXInput.States := Mfrm.DXInput.States - [isButton1];
     end;
     
     
{   далее на своё усмотрение...
   if (isButton2 in MFrm.DXInput.States) then  Weapon.Fire;
   if (isButton3 in MFrm.DXInput.States) then ***
}
  //Собственно вызываем гравитацию
  Gravity.DoGravity(Self as TSprite, MoveCount);
  Сollision;
end;{1}


И вот это ещё, что б не влезал в запретные 32*32.
(Я уже писал, но это лишним здесь не будет)

//==============================================================================
procedure TPlayer.DoCollision(Sprite: TSprite; var Done: Boolean);
begin
inherited DoCollision(Sprite,Done);

if Sprite is TMapPiece then
 begin
    X := X + (X-Sprite.X)/32;
    Y := Y + (Y-Sprite.Y)/32;

//    Coord := Coord + (Coord-Sprite.Coord)/NormalizeSpeed;
 end;

Done := True;
end;


Ну вот приблезительно так смотрится мне управление.
(увы, ... я всё подмял под свою теорию, увы ...)


 
Falcon(TFSoft)   (2004-10-05 01:15) [38]

to Megabyte-ceercop ©

Смотрел твой проэк CeerCop, класная штука. Можно подсесть надолго, только вот 32bit рисунки которые ты кажется говорил, что там используеш очень много весят. А так графа на высоком кровне :))

И метод движения тоже очень неплохой!
Опиши его подробнее здесь, что б Jus, да и другие могли б использовать его в своих наработках.


 
Megabyte-ceercop ©   (2004-10-05 06:11) [39]


> Спрайт прыгнул, полсе чего падал с некоторой скоростью dу=6,
> (к примеру 6), призимлился, произошёл детекшен колижен (столкновение
> вроде как так произносится). По товему методу необходимо
> вернуть спрайту предыдущее положение тоесть y=y-6. Это подбросит
> его на 6 пикселов вверх, после чего он снова упадёт с dу=2
> или dу=1. В лутшем случае его снова подбросит на 1 пиксел,
> в худшем, на больше.


Не прав :)

Во первых не нужно делать y=y-6 а нужно делать Y = Y_old
Те присваивать ранее запомненое значение координаты, но запомненое не в предыдущем цикле, а в этом.
Пороядок цикла такой:
//Запомнил координату.
Old_Y = Y;
//Наростил её в соответствии со скоростью ускорения вниз:
Y = Y + SpeedDown;
//Проверил колизию, и если что, то востановил старую координату
If (doColision) then Y = Old_Y;

Draw;

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


 
Jus   (2004-10-05 06:35) [40]

Megabyte-ceercop ©   (05.10.04 06:11) [39]

> Draw;
> Скакать не будет, потому как если спрайт провалился в землю,
> то он даже не отрисуется, пока не окажется на поверхности.

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



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

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

Наверх




Память: 0.63 MB
Время: 0.084 c
3-1103404096
Shamansky
2004-12-19 00:08
2005.01.23
Как совместить Dbgrid и dbcheckbox


1-1105377770
Ivan Pashkov
2005-01-10 20:22
2005.01.23
Есть у кого dcc32.exe для Delphi 2005?


1-1104406951
den303
2004-12-30 14:42
2005.01.23
TButton+Glyph


1-1105223958
WhiteGuy
2005-01-09 01:39
2005.01.23
Move It!


14-1105114572
Andrewp
2005-01-07 19:16
2005.01.23
Домовой.





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