Форум: "Игры";
Текущий архив: 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.047 c