Войти
ПрограммированиеФорумФизика

Физика игрока FPS (в ODE): как создать игрока, как сделать движение вверх по лестнице и т.д.?

#0
7:25, 22 июля 2006

Я загрузил уровень Q3, сделал TriMesh geom из этого, поэтому уровень сейчас представляет собой "пол". Теперь мне нужно создать игрока FPS. Как это сделать?
Я подумал, что можно создать его из двух сфер, соединённых скользящим суставом (slider joint), чтобы игрок мог приседать. Я хочу поместить камеру в верхнюю сферую.
Но тогда будет существовать дыра в "середине" игрока, что приведёт к странным столкновениям.
Как лучше всего создать игрока?

И как двигаться вверх по лестнице? Совершенно не знаю. Должен ли я измерять высоту ступеньки и, если она достаточно мала, двигаться на следующую?

Спасибо.


#1
9:59, 22 июля 2006

kornerr
Посмотри тут: http://www.codesampler.com/ - найдешь часть ответов и много еще полезного...

#2
14:33, 26 июля 2006

Где то была тема, полтора месяца назад.
Там была сфера, как тело для колизии, лучше использовать капсулу

#3
14:48, 26 июля 2006

Вобщем чтобы сделать хождение по карте:
в nearCallBack определяешь какие обькты сталкиваются (ну обычный код, с условиями)
если одно из тел - игрок (запиши указатель на класс в userData), то у контакта сделай силу трения 0, bounce где-то 0.1

procedure nearCallback(data: pointer; o1, o2: PdxGeom); cdecl;

var
  b1, b2: PdxBody;
  i, NumC: Integer;
  Contact: array[0..c_colMax-1] of TdContact;
  c: TdJointID;

begin

  b1:=dGeomGetBody(o1);
  b2:=dGeomGetBody(o2);

  if Assigned(b1) and Assigned(b2) and (dAreConnected(b1, b2) <> 0) then
    Exit;

  if (o1=Player.FSphere.FGeom) or (o2=Player.FSphere.FGeom) then for i:=0 to c_colMax-1 do begin
    Contact[i].surface.mode:=dContactBounce;//dContactMotion1;//dContactBounce;
    Contact[i].surface.bounce:=0.1;
    Contact[i].surface.mu:=0;
    //Contact[i].surface.bounce:=v_bounce;
    //Contact[i].surface.bounce_vel:=v_bounce_vel;

  end else for i:=0 to c_colMax-1 do begin

    Contact[i].surface.mode:=dContactBounce;
    Contact[i].surface.mu:=v_mu;
    //Contact[i].surface.mu2:=v_mu2;
    Contact[i].surface.bounce:=v_bounce;
    Contact[i].surface.bounce_vel:=v_bounce_vel;
  end;


  NumC:=dCollide(o1, o2, c_colMax, Contact[0].geom, SizeOf(TdContact));
  //if ((o1=Player.FGeom) or (o2=Player.FGeom)) and (NumC>0) then
    //Beep;

  if NumC>0 then for i:=0 to NumC-1 do begin
    c:=dJointCreateContact(PhysicWorld.FWorld, PhysicWorld.FContGroup, @Contact[i]);
    dJointAttach(c, b1, b2);
    if (o1=Player.FSphere.FGeom) or (o2=Player.FSphere.FGeom) then begin
      Player.FJump:=True;
      Inc(v_playerC);
    end;
  end;
end;

Этот пример немного не подойдет, потому что используются глобальный обьект Player, но можно исправить :)

У игрока все так
Если физическое тело игрока ни с чем не соприкосается (например в прыжке), то его скорость не обнуляется, а если... ну тут должно дойти
В качалке была дема, за код не ругайте

procedure TPlayer.Progress(deltaTime: Double);
var
  IsMoving: Boolean;
  vperp: TVector;
begin
  FCamera.Pos:=Pos;
  if mouseDown_ then begin
    camera.Aim((Mouse.CursorPos.X - lastCP.X)/5, (Mouse.CursorPos.Y - lastCP.Y)/5);
    GetCursorPos(lastCP);
  end;
  IsMoving:=False;
  if v_playerC>0 then begin
//------------------------------------
  if not (IsKeyDown('w') and IsKeyDown('s')) then begin

    if IsKeyDown('w') then begin
      IsMoving:=True;
      vperp:=VectorCrossProduct(Camera.Up, Camera.Right);
      ScaleVector(vperp, c_moveSpeed);
      dBodySetLinearVel(FSphere.FBody, vperp[0], vperp[1], vperp[2]);
    end;

    if IsKeyDown('s') then begin
      IsMoving:=True;
      vperp:=VectorCrossProduct(Camera.Up, Camera.Right);
      ScaleVector(vperp, -c_moveSpeed);
      dBodySetLinearVel(FSphere.FBody, vperp[0], vperp[1], vperp[2]);
    end;
  end;

  if not (IsKeyDown('a') and IsKeyDown('d')) then begin
    if IsKeyDown('a') then begin
      IsMoving:=True;
      vperp:=FCamera.Right;
      ScaleVector(vperp, -c_moveSpeed);
      dBodySetLinearVel(FSphere.FBody, vperp[0], vperp[1], vperp[2]);
    end;
    if IsKeyDown('d') then begin
      IsMoving:=True;
      vperp:=FCamera.Right;
      ScaleVector(vperp, c_moveSpeed);
      dBodySetLinearVel(FSphere.FBody, vperp[0], vperp[1], vperp[2]);
    end;
  end;
//------------------------------------
  end;

  if not IsMoving then begin
{
    v:=TVector(Pointer(dBodyGetLinearVel(FSphere.FBody))^);
    dBodyVectorFromWorld(FSphere.FBody, v[0], v[1], v[2], TdVector3(Pointer(@v)^));
    ScaleVector(v, -1);
}
    dBodySetAngularVel(FSphere.FBody, 0, 0, 0);
    if v_playerC>0 then
      dBodySetLinearVel(FSphere.FBody, 0, 0, 0);
  end;
  FJumpTime:=FJumpTime+deltaTime;
  if IsKeyDown(VK_SPACE) and FJump then begin
    FJump:=False;
    //Form1.Caption:=FloatToStr(FJumpTime);
    //FJumpTime:=FJumpTime-(FJumpTime/c_jumpTime)*c_jumpTime;

    vperp:=Camera.Up;
    ScaleVector(vperp, 800);
    dBodyAddForce(FSphere.FBody, vperp[0],
                  vperp[1], vperp[2]);
  end;
end;
#4
15:08, 26 июля 2006


Я конечно не совсем по теме! Но все же новая версия ОДЕ_0.6
реально стабильнее предыдущей версии или нет? стоит ли его использовать вместо Newton

#5
16:50, 26 июля 2006

DimanNN, спасибо, но я там нашёл в основном по OpenGL. Хотя примеры там неплохие: mipmapping и т.д.
Gendolf, спасибо, не надеялся получить СТОЛЬ ПОДРОБНОЕ решение проблемы. Огромное спасибо!
Хотя есть у меня ещё вопросик про управление машины... создам тему.
-=freeman=-, я выбрал ODE, т.к.
1) главный разраб - чел, который работал над... мм... вот выдержка с irc.freenode.net #irrlicht:
xhrit: PhysX and ode were written by people wo both worked at teh same place.
2) впечатляет список сделанных с использованием этой библиотеки игр. Даже коммерческих.
А по стабильности они все стабильные, думаю.

#6
8:58, 30 июля 2006

никто не пробовал делать капсулу и использовать луч? не пойму ничего :/

#7
1:50, 31 июля 2006

Ох, как давно это было... Пытался точно такое сделать, опишу свой опыт:

Значит с капсулой после каждой интерации  устанавливал положение параллельное оси Z (у меня это было вертикальная ось) чтобы капсула не падала ))) на ступеньки заходил нормально но когда поднимался по наклонной на срезе (место где соеденяется спуск и лоская дорожка) капсулу подбрасывало вверх %) короче геморой, а со сферой еще хуже улетата в NAN область )))))

Вывод: пльзоваться ньютоном или physx там официально это поддерживается.

#8
17:01, 6 авг. 2006

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

#9
1:05, 29 сен. 2006

Кстати если юзаешь БСП попробуй сделать выключение части геометрии карты с помощью ПВС. Должно немного  (или  много  :-)) ускорить процесс. 

#10
3:50, 29 сен. 2006

что такое ПВС?

#11
8:44, 6 окт. 2006

kornerr
Не надо никаких "постоянного установления угла капсуле". В ODE есть фиксация объекта по конкретной оси. Т.е. чтобы капсуль всегда стоял вертикально, и крутился только вокруг определенной оси.

А насчет обработки высот. Самый простой вариант - промеряешь высоту того места куда персонаж должен переместиться, и данные заносишь
в какую-то внутренюю переменную (это в NearCallback).
А в функции итерации (которая вызывает физический апдейт, устанавливаешь персонажу данную высоту.
Тогда не будет постоянного коллижна об землю, дрожаний и т.д.

Естественно, это можно красивее сделать, ну да уж сам разберешься потом как улучшить.

С уважением,
/Loki.

#12
9:40, 6 окт. 2006

El Loki

А как к стати зафиксить объект по оси?

#13
11:58, 6 окт. 2006

Ronin

Работает такая штука только для капсул.

        dBodySetFiniteRotationMode(pBody, 1);
  dBodySetFiniteRotationAxis(pBody, 0.0, 0.0, 1.0);

Мы так фиксируем основной капсуль персонажа в файтинге. Если все остальное нормально настроено,
то работает без единой проблемы
А детали можно уже уточнить в документации к ODE.

С уважением,
/Loki.

ПрограммированиеФорумФизика

Тема в архиве.