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

📄 pmoveunit.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 3 页
字号:
{$ALIGN ON}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): QCommon.h (part), PMove.c                                         }
{ Content: Quake2\QCommon\ PLAYER MOVEMENT CODE                              }
{                                                                            }
{ Initial conversion by : Clootie (Alexey Barkovoy) - clootie@reactor.ru     }
{ Initial conversion on : 25-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:                                                                 }
{                                                                            }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{                                                                            }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{----------------------------------------------------------------------------}

unit PMoveUnit;

interface

uses
  q_shared_add,
  q_shared;

{*
==============================================================

PLAYER MOVEMENT CODE

Common between server and client so prediction matches

==============================================================
*}

var
  pm_airaccelerate: Single = 0;

procedure Pmove(pmove: pmove_p); cdecl;

implementation

uses
  Common;

const
  STEPSIZE = 18;

// all of the locals will be zeroed before each
// pmove, just to make damn sure we don't have
// any differences when running on client or server

type
  pml_p = ^pml_t;
  pml_t = record
    origin: vec3_t;                     // full float precision
    velocity: vec3_t;                   // full float precision

    forward, right, up: vec3_t;
    frametime: Single;

    groundsurface: csurface_p;
    groundplane: cplane_t;
    groundcontents: Integer;

    previous_origin: vec3_t;
    ladder: qboolean;
  end;

var
  pm: pmove_p;
  pml: pml_t;

  // movement parameters
  pm_stopspeed: Single = 100;
  pm_maxspeed: Single = 300;
  pm_duckspeed: Single = 100;
  pm_accelerate: Single = 10;
  //  pm_airaccelerate      : Single = 0; // - in interface part
  pm_wateraccelerate: Single = 10;
  pm_friction: Single = 6;
  pm_waterfriction: Single = 1;
  pm_waterspeed: Single = 400;

{*

  walking up a step should kill some velocity

*}

{*
==================
PM_ClipVelocity

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

procedure PM_ClipVelocity(const in_, normal: vec3_t; var out_: vec3_t; overbounce: Single);
var
  backoff: Single;
  change: Single;
  i: Integer;
begin
  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;
end;

{*
==================
PM_StepSlideMove

Each intersection will try to step over the obstruction instead of
sliding along it.

Returns a new origin, velocity, and contact entity
Does not modify any world state?
==================
*}
const
  MIN_STEP_NORMAL = 0.7;                // can't step up onto very steep slopes
  MAX_CLIP_PLANES = 5;

procedure PM_StepSlideMove_;
var
  bumpcount, numbumps: Integer;
  dir: vec3_t;
  d: Single;
  numplanes: Integer;
  planes: array[0..MAX_CLIP_PLANES - 1] of vec3_t;
  primal_velocity: vec3_t;
  i, j: Integer;
  trace: trace_t;
  end_: vec3_t;
  time_left: Single;
begin
  numbumps := 4;

  VectorCopy(pml.velocity, primal_velocity);
  numplanes := 0;

  time_left := pml.frametime;

  for bumpcount := 0 to numbumps - 1 do
  begin
    for i := 0 to 2 do
      end_[i] := pml.origin[i] + time_left * pml.velocity[i];

    trace := pm.trace(pml.origin, pm.mins, pm.maxs, end_);

    if (trace.allsolid) then
    begin                               // entity is trapped in another solid
      pml.velocity[2] := 0;             // don't build up falling damage
      Exit;
    end;

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

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

    // save entity for contact
    if (pm.numtouch < MAXTOUCH) and (trace.ent <> nil) then
    begin
      pm.touchents[pm.numtouch] := trace.ent;
      Inc(pm.numtouch);
    end;

    time_left := time_left - time_left * trace.fraction;

    // slide along this plane
    if (numplanes >= MAX_CLIP_PLANES) then
    begin                               // this shouldn't really happen
      VectorCopy(vec3_origin, pml.velocity);
      Break;
    end;

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

    (*
    float		rub;

        //
        // modify velocity so it parallels all of the clip planes
        //
        if (numplanes == 1)
        {	// go along this plane
                VectorCopy (pml.velocity, dir);
                VectorNormalize (dir);
                rub = 1.0 + 0.5 * DotProduct (dir, planes[0]);

                // slide along the plane
                PM_ClipVelocity (pml.velocity, planes[0], pml.velocity, 1.01);
                // rub some extra speed off on xy axis
                // not on Z, or you can scrub down walls
                pml.velocity[0] *= rub;
                pml.velocity[1] *= rub;
                pml.velocity[2] *= rub;
        }
        else if (numplanes == 2)
        {	// go along the crease
                VectorCopy (pml.velocity, dir);
                VectorNormalize (dir);
                rub = 1.0 + 0.5 * DotProduct (dir, planes[0]);

                // slide along the plane
                CrossProduct (planes[0], planes[1], dir);
                d = DotProduct (dir, pml.velocity);
                VectorScale (dir, d, pml.velocity);

                // rub some extra speed off
                VectorScale (pml.velocity, rub, pml.velocity);
        }
        else
        {
    //			Con_Printf ("clip velocity, numplanes == %d\n",numplanes);
                VectorCopy (vec3_origin, pml.velocity);
                break;
        }

    *)
    //
    // modify original_velocity so it parallels all of the clip planes
    //
    i := 0;
    while (i < numplanes) do
    begin
      PM_ClipVelocity(pml.velocity, planes[i], pml.velocity, 1.01);
      j := 0;
      while (j < numplanes) do
      begin
        if (j <> i) then
        begin
          if (DotProduct(pml.velocity, planes[j]) < 0) then
            Break;                      // not ok
        end;
        Inc(j);
      end;

      if (j = numplanes) then
        Break;
      Inc(i);
    end;

    if (i <> numplanes) then
    begin                               // go along this plane
    end
    else
    begin                               // go along the crease
      if (numplanes <> 2) then
      begin
        //      Con_Printf ('clip velocity, numplanes == %d'#10, [numplanes]);
        VectorCopy(vec3_origin, pml.velocity);
        Break;
      end;
      CrossProduct(planes[0], planes[1], dir);
      d := DotProduct(dir, pml.velocity);
      VectorScale(dir, d, pml.velocity);
    end;
    //
    // if velocity is against the original velocity, stop dead
    // to avoid tiny occilations in sloping corners
    //
    if (DotProduct(pml.velocity, primal_velocity) <= 0) then
    begin
      VectorCopy(vec3_origin, pml.velocity);
      Break;
    end;
  end;

  if (pm.s.pm_time <> 0) then
  begin
    VectorCopy(primal_velocity, pml.velocity);
  end;
end;

{*
==================
PM_StepSlideMove

==================
*}
procedure PM_StepSlideMove;
var
  start_o, start_v: vec3_t;
  down_o, down_v: vec3_t;
  trace: trace_t;
  down_dist, up_dist: Single;
  up, down: vec3_t;
begin
  VectorCopy(pml.origin, start_o);
  VectorCopy(pml.velocity, start_v);

  PM_StepSlideMove_;

  VectorCopy(pml.origin, down_o);
  VectorCopy(pml.velocity, down_v);

  VectorCopy(start_o, up);
  up[2] := up[2] + STEPSIZE;

  trace := pm.trace(up, pm.mins, pm.maxs, up);
  if (trace.allsolid) then
    Exit;                               // can't step up

  // try sliding above
  VectorCopy(up, pml.origin);
  VectorCopy(start_v, pml.velocity);

  PM_StepSlideMove_;

  // push down the final amount
  VectorCopy(pml.origin, down);
  down[2] := down[2] - STEPSIZE;
  trace := pm.trace(pml.origin, pm.mins, pm.maxs, down);
  if not trace.allsolid then
  begin
    VectorCopy(trace.endpos, pml.origin);
  end;

  {
    VectorSubtract (pml.origin, up, delta);
    up_dist = DotProduct (delta, start_v);

    VectorSubtract (down_o, start_o, delta);
    down_dist = DotProduct (delta, start_v);
  }
  VectorCopy(pml.origin, up);

  // decide which one went farther
  down_dist := (down_o[0] - start_o[0]) * (down_o[0] - start_o[0]) +
    (down_o[1] - start_o[1]) * (down_o[1] - start_o[1]);
  up_dist := (up[0] - start_o[0]) * (up[0] - start_o[0]) +
    (up[1] - start_o[1]) * (up[1] - start_o[1]);

  if (down_dist > up_dist) or (trace.plane.normal[2] < MIN_STEP_NORMAL) then
  begin
    VectorCopy(down_o, pml.origin);
    VectorCopy(down_v, pml.velocity);
    Exit;
  end;
  //!! Special case
  // if we were walking along a plane, then we need to copy the Z over
  pml.velocity[2] := down_v[2];
end;

{*
==================
PM_Friction

Handles both ground friction and water friction
==================
*}
procedure PM_Friction_func;
var
  vel: vec3_p;
  speed, newspeed, control: Single;
  friction: Single;
  drop: Single;
begin
  vel := @pml.velocity;

  speed := sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);
  if (speed < 1) then
  begin
    vel[0] := 0;
    vel[1] := 0;
    Exit;
  end;

  drop := 0;

  // apply ground friction
  if ((pm.groundentity <> nil) and (pml.groundsurface <> nil) and (pml.groundsurface.flags and SURF_SLICK = 0)) or
    (pml.ladder) then
  begin
    friction := pm_friction;
    // control = speed < pm_stopspeed ? pm_stopspeed : speed;
    if (speed < pm_stopspeed) then
      control := pm_stopspeed
    else
      control := speed;
    drop := drop + control * friction * pml.frametime;
  end;

  // apply water friction
  if (pm.waterlevel <> 0) and (not pml.ladder) then
    drop := drop + speed * pm_waterfriction * pm.waterlevel * pml.frametime;

  // scale the velocity
  newspeed := speed - drop;
  if (newspeed < 0) then
  begin
    newspeed := 0;
  end;
  newspeed := newspeed / speed;

  vel[0] := vel[0] * newspeed;
  vel[1] := vel[1] * newspeed;
  vel[2] := vel[2] * newspeed;
end;

{*
==============
PM_Accelerate

Handles user intended acceleration
==============
*}
procedure PM_Accelerate_func(const wishdir: vec3_t; wishspeed, accel: Single);
var
  i: Integer;
  addspeed, accelspeed, currentspeed: Single;
begin
  currentspeed := DotProduct(pml.velocity, wishdir);
  addspeed := wishspeed - currentspeed;
  if (addspeed <= 0) then
    Exit;
  accelspeed := accel * pml.frametime * wishspeed;
  if (accelspeed > addspeed) then
    accelspeed := addspeed;

  for i := 0 to 2 do
    pml.velocity[i] := pml.velocity[i] + accelspeed * wishdir[i];
end;

procedure PM_AirAccelerate_func(const wishdir: vec3_t; wishspeed, accel: Single);
var
  i: Integer;
  addspeed, accelspeed, currentspeed, wishspd: Single;
begin
  wishspd := wishspeed;

  if (wishspd > 30) then
    wishspd := 30;
  currentspeed := DotProduct(pml.velocity, wishdir);
  addspeed := wishspd - currentspeed;
  if (addspeed <= 0) then
    Exit;
  accelspeed := accel * wishspeed * pml.frametime;
  if (accelspeed > addspeed) then
    accelspeed := addspeed;

⌨️ 快捷键说明

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