![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
DelphiX, DoMove, DoCollision [D6, WinXP]
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]ниче не понял...