⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 g_phys.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): g_phys.c                                                          }
{ Content: physics logic                                                     }
{                                                                            }
{ Initial conversion by : MathD (matheus@tilt.net                            }
{ Initial conversion on : 05-Feb-2002                                        }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ This program is free software; you can redistribute it and/or              }
{ modify it under the terms of the GNU General Public License                }
{ as published by the Free Software Foundation; either version 2             }
{ of the License, or (at your option) any later version.                     }
{                                                                            }
{ This program is distributed in the hope that it will be useful,            }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of             }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       }
{                                                                            }
{ See the GNU General Public License for more details.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Updated on :                                                               }
{ Updated by :                                                               }
{                                                                            }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{ none                                                                       }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ 1.) A few functions need to be translated                                  }
{ 2.) Give it a test                                                         }
{                                                                            }
{----------------------------------------------------------------------------}
{ * NOTES:                                                                   }
{                                                                            }
{ translated the pointers to records as specified in message board           }
{ edict_t = record;                                                          }
{ editc_p = ^edict_p                                                         }
{----------------------------------------------------------------------------}

unit g_phys;

{pushmove objects do not obey gravity, and do not interact with each other or 
trigger fields, but block normal movement and push normal objects when they move.

onground is set for toss objects when they come to a complete rest.  it is set 
for steping or walking objects 

doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
corpses are SOLID_NOT and MOVETYPE_TOSS
crates are SOLID_BBOX and MOVETYPE_TOSS
walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY

solid_edge items only clip against bsp models.}

interface

{delphi-note: completed functions}
function SV_TestEntityPosition(ent: edict_p): edict_p;
procedure SV_CheckVelocity (ent: edict_p);
function SV_RunThink (ent: edict_p): qboolean;
procedure SV_Impact(e1: edict_p; trace: trace_p);
function ClipVelocity(_in, normal, _out: vec3_t; overbounce: single): integer;
function SV_FlyMove(ent: edict_p; time: single; mask: integer): integer;
procedure SV_AddGravity(ent: edict_p);
function SV_PushEntity(ent: edict_p; push: vec3_t): trace_t;
procedure SV_Physics_None(ent: edict_p);
procedure SV_Physics_Noclip (ent: edict_p);
procedure SV_Physics_Toss(ent: edict_p);
procedure SV_AddRotationalFriction(ent: edict_p)

{delphi-note: not completed functions}
function SV_Push(pushed: edict_p, _move, amove: vec3_t): qboolean;
procedure SV_Physics_Pusher(ent: edict_p);
procedure SV_Physics_Step(ent: edict_p);

implementation

{/*
============
SV_TestEntityPosition

============
*/}
function SV_TestEntityPosition(ent: edict_p): edict_p;
var
trace: trace_t;
mask: integer;
begin	
  if ent^.clipMask then 
    mask:= ent^.clipMask
  else
    mask:= MASK_SOLID;

  trace:= gi.trace(ent^.s.origin, ent^.mins, ent^.maxs, ent^.s.origin, ent, mask);
  
  if (trace.startsolid) then begin
    result:= g_edicts;
    exit;
  end;

  result:= nil;
end;


{/*
================
SV_CheckVelocity
================
*/}

procedure SV_CheckVelocity (ent: edict_p);
var
i: integer;
begin
  //
  // bound velocity
  //
  i:= 0;
  for i:= 0 to 2 do begin
    if (ent^.velocity[i] > sv_maxvelocity^.value) then
      ent^.maxvelocity[i]:= sv_maxvelocity^.value
    else if (ent^.velocity[i] < -sv_maxvelocity^.value) then
      ent^.velocity[i]:= -sv_maxvelocity^.value;  
  end;
end;


{/*
=============
SV_RunThink

Runs thinking code for this frame if necessary
=============
*/}
function SV_RunThink (ent: edict_p): qboolean;
var
thinktime: single;
begin
  thinktime:= ent^.nextthink;
  if (thinktime <= 0) then begin
    result:= true;
    exit;
  end;
  if (thinktime : level.time + 0.001) then begin
    result:= true;
    exit;
  end;

  ent^.nextthink:= 0;
  if (ent^.think = false) then gi.error('NIL ent^.think');
  ent^.think(ent);
  result:= false;
end;


{/*
==================
SV_Impact

Two entities have touched, so run their touch functions
==================
*/}
procedure SV_Impact(e1: edict_p; trace: trace_p);
var
e2: edict_p;
backplane: cplane_p;
begin
  e2:= trace^.ent;
  
  {delphi-note: maybe this should be}
  {if ((ei^.touch and e1^.solid) <> SOLID_NOT)}
  if (ei^.touch and e1^.solid <> SOLID_NOT) then
    e1^.touch(e1, e2, @trace^.plane, trace^.surface);

  {delphi-note: same as above}  
  if (e2^.touch and e2^.solid <> SOLID_NOT then 
    e2^.touch(e2, e1, nil, nil);
end;

	

{/*
==================
ClipVelocity

Slide off of the impacting object
returns the blocked flags (1 = floor, 2 = step / wall)
==================
*/}
const STOP_EPSILON = 0.1;

function ClipVelocity(_in, normal, _out: vec3_t; overbounce: single): integer;
var
backoff, change: single;
i, blocked: integer;
begin
  blocked:= 0;
  if (normal[2] > 0) then blocked:= blocked or 1; //floor

  {delphi-note: check this out. Not quite sure..}
  if (normal[2] = 0) then blocked:= blocked or 2; //step
  
  backoff:= DotProduct(_in, normal) * overbounce;

  for i:= 0 to 2 do begin
    change:= normal[i] * backoff;
    _out[i]:= _in[i] - change;
    if (_out[i] > -STOP_EPSILON) and (_out[i] < STOP_EPSILON) then _out[i]:= 0;
  end;

  result:= blocked;
end;

  	
{/*
============
SV_FlyMove

The basic solid body movement clip that slides along multiple planes
Returns the clipflags if the velocity was modified (hit something solid)
1 = floor
2 = wall / step
4 = dead stop
============
*/}
const MAX_CLIP_PLANES = 5;

function SV_FlyMove(ent: edict_p; time: single; mask: integer): integer;
var
hit: edict_p;
bumpcount, numbumps: integer;
dir: vect3_t;
d: single;
numplanes: integer;
planes: array[0..MAX_CLIP_PLANES -1] of vec3_t;
primal_velocity, original_velocity, new_velocity: vec3_t;
i, j: integer;
trace: trace_t;
_end: vec3_t;
time_left: single;
blocked: integer;
begin
  numbumps:= 4;
  blocked:= 0;
  VectorCopy(ent^.velocity, original_velocity);
  VectorCopy(ent^.velocity, primal_velocity);

  time_left:= time;
  ent^.groundentity:= nil;
  for bumpcount:= 0 to numbumps -1 do begin
    for i:= 0 to 2 do _end[i]:= ent^.s.origin[i] + time_left * ent^.velocity[i];
    trace:= gi.trace(ent^.origin, ent^.mins, ent^.maxs, _end, ent, mask);

    if (trace.allsolid) then begin
      //entity is trapped in another solid
      VectorCopy(vec3_origin, ent^.velocity);
      result:= 3;
      exit;
    end;

    if (trace.fraction > 0) then begin
      //actually covered some distance
      VectorCopy(trace,endpos, ent^.s.origin);
      VectorCopy(ent^.velocity, original_velocity);
      numplanes:= 0;
    end;

    if (trace.fraction = 1) then break; //moved the entire distance

    hit:= trace.ent;

    if (trace.plane.normal[2] > 0.7) then begin
      blocked:= blocked or 1; //floor;

      if (hit^.solid == SOLID_BSP) then begin
        ent^.groundentity:= hit;
        ent^.groundentity_linkcount:= hit^.linkcount;
      end;

      if not trace.plane.normal[2] then blocked:= blocked or 2; //step      
    end;

//
// run the impact function
//
    SV_Impact(ent, @trace);
    if not ent^.inuse then break;

    time_left:= timeleft - (time_left * trace.fraction);
    //cliped to another plane
    if (numplanes >= MAX_CLIP_PLANES then begin
      //this shouldn't really happen
      VectorCopy(vec3_origin, ent^.velocity);
      result:= 3;
      exit;
    end;

    VectorCopy(trace.plane.normal, planes[numplanes]);
    inc(numplanes);

//
// modify original_velocity so it parallels all of the clip planes
//
    for i:= 0 to numplanes -1 do begin
      ClipVelocity(original_velocity, planes[i], new_velocity, 1);

      for j:= 0 to numplanes -1 do begin
        if (j <> i) then begin
          if (DotProduct(new_velocity, planes[j]) < 0) then break; //not ok
      end;
      
      if j = numplanes then break;
    end;
    
    if (i <> numplanes) then VectorCopy(new_velocity, ent^.velocity) //go along this plane   
    else begin
      if (numplanes <> 2) then begin //go along the crease
        //gi.dprintf('clip velocity, numplanes = %i #13#10', numplanes);
        VectorCopy(vec3_origin, ent^.velocity);
        result:= 7;
        exit;
      end;
      
      CrossProduct(planes[0], planes[1], dir);
      d:= DotProduct(dir, ent^.velocity);
      VectorScale(dir, d, ent^.velocity);
    end;

//
// if original velocity is against the original velocity, stop dead

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -