📄 pmove.java
字号:
/* * 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. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * */// Created on 25.01.2004 by RST.// $Id: PMove.java,v 1.8 2006/01/21 21:53:32 salomo Exp $package jake2.qcommon;import jake2.Defines;import jake2.Globals;import jake2.game.*;import jake2.server.SV;import jake2.util.Math3D;public class PMove { // 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 public static class pml_t { public float[] origin = { 0, 0, 0 }; // full float precision public float[] velocity = { 0, 0, 0 }; // full float precision public float[] forward = { 0, 0, 0 }, right = { 0, 0, 0 }, up = { 0, 0, 0 }; public float frametime; public csurface_t groundsurface; public int groundcontents; public float[] previous_origin = { 0, 0, 0 }; public boolean ladder; } public static pmove_t pm; public static pml_t pml = new pml_t(); // movement parameters public static float pm_stopspeed = 100; public static float pm_maxspeed = 300; public static float pm_duckspeed = 100; public static float pm_accelerate = 10; public static float pm_airaccelerate = 0; public static float pm_wateraccelerate = 10; public static float pm_friction = 6; public static float pm_waterfriction = 1; public static float pm_waterspeed = 400; // try all single bits first public static int jitterbits[] = { 0, 4, 1, 2, 3, 5, 6, 7 }; public static int offset[] = { 0, -1, 1 }; /** * Slide off of the impacting object returns the blocked flags (1 = floor, 2 = step / wall) */ public static void PM_ClipVelocity(float[] in, float[] normal, float[] out, float overbounce) { float backoff; float change; int i; backoff = Math3D.DotProduct(in, normal) * overbounce; for (i = 0; i < 3; i++) { change = normal[i] * backoff; out[i] = in[i] - change; if (out[i] > -Defines.MOVE_STOP_EPSILON && out[i] < Defines.MOVE_STOP_EPSILON) out[i] = 0; } } static float[] planes[] = new float[SV.MAX_CLIP_PLANES][3]; public static void PM_StepSlideMove_() { int bumpcount, numbumps; float[] dir = { 0, 0, 0 }; float d; int numplanes; float[] primal_velocity = { 0, 0, 0 }; int i, j; trace_t trace; float[] end = { 0, 0, 0 }; float time_left; numbumps = 4; Math3D.VectorCopy(pml.velocity, primal_velocity); numplanes = 0; time_left = pml.frametime; for (bumpcount = 0; bumpcount < numbumps; bumpcount++) { for (i = 0; i < 3; i++) end[i] = pml.origin[i] + time_left * pml.velocity[i]; trace = pm.trace.trace(pml.origin, pm.mins, pm.maxs, end); if (trace.allsolid) { // entity is trapped in another solid pml.velocity[2] = 0; // don't build up falling damage return; } if (trace.fraction > 0) { // actually covered some distance Math3D.VectorCopy(trace.endpos, pml.origin); numplanes = 0; } if (trace.fraction == 1) break; // moved the entire distance // save entity for contact if (pm.numtouch < Defines.MAXTOUCH && trace.ent != null) { pm.touchents[pm.numtouch] = trace.ent; pm.numtouch++; } time_left -= time_left * trace.fraction; // slide along this plane if (numplanes >= SV.MAX_CLIP_PLANES) { // this shouldn't really happen Math3D.VectorCopy(Globals.vec3_origin, pml.velocity); break; } Math3D.VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; // modify original_velocity so it parallels all of the clip planes for (i = 0; i < numplanes; i++) { PM_ClipVelocity(pml.velocity, planes[i], pml.velocity, 1.01f); for (j = 0; j < numplanes; j++) if (j != i) { if (Math3D.DotProduct(pml.velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } if (i != numplanes) { // go along this plane } else { // go along the crease if (numplanes != 2) { // Com.printf("clip velocity, numplanes == " + numplanes + "\n"); Math3D.VectorCopy(Globals.vec3_origin, pml.velocity); break; } Math3D.CrossProduct(planes[0], planes[1], dir); d = Math3D.DotProduct(dir, pml.velocity); Math3D.VectorScale(dir, d, pml.velocity); } // if velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners if (Math3D.DotProduct(pml.velocity, primal_velocity) <= 0) { Math3D.VectorCopy(Globals.vec3_origin, pml.velocity); break; } } if (pm.s.pm_time != 0) { Math3D.VectorCopy(primal_velocity, pml.velocity); } } /** * 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? */ public static void PM_StepSlideMove() { float[] start_o = { 0, 0, 0 }, start_v = { 0, 0, 0 }; float[] down_o = { 0, 0, 0 }, down_v = { 0, 0, 0 }; trace_t trace; float down_dist, up_dist; // float [] delta; float[] up = { 0, 0, 0 }, down = { 0, 0, 0 }; Math3D.VectorCopy(pml.origin, start_o); Math3D.VectorCopy(pml.velocity, start_v); PM_StepSlideMove_(); Math3D.VectorCopy(pml.origin, down_o); Math3D.VectorCopy(pml.velocity, down_v); Math3D.VectorCopy(start_o, up); up[2] += Defines.STEPSIZE; trace = pm.trace.trace(up, pm.mins, pm.maxs, up); if (trace.allsolid) return; // can't step up // try sliding above Math3D.VectorCopy(up, pml.origin); Math3D.VectorCopy(start_v, pml.velocity); PM_StepSlideMove_(); // push down the final amount Math3D.VectorCopy(pml.origin, down); down[2] -= Defines.STEPSIZE; trace = pm.trace.trace(pml.origin, pm.mins, pm.maxs, down); if (!trace.allsolid) { Math3D.VectorCopy(trace.endpos, pml.origin); } Math3D.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 || trace.plane.normal[2] < Defines.MIN_STEP_NORMAL) { Math3D.VectorCopy(down_o, pml.origin); Math3D.VectorCopy(down_v, pml.velocity); return; } //!! Special case // if we were walking along a plane, then we need to copy the Z over pml.velocity[2] = down_v[2]; } /** * Handles both ground friction and water friction. */ public static void PM_Friction() { float vel[]; float speed, newspeed, control; float friction; float drop; vel = pml.velocity; speed = (float) (Math.sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2])); if (speed < 1) { vel[0] = 0; vel[1] = 0; return; } drop = 0; // apply ground friction if ((pm.groundentity != null && pml.groundsurface != null && 0 == (pml.groundsurface.flags & Defines.SURF_SLICK)) || (pml.ladder)) { friction = pm_friction; control = speed < pm_stopspeed ? pm_stopspeed : speed; drop += control * friction * pml.frametime; } // apply water friction if (pm.waterlevel != 0 && !pml.ladder) drop += speed * pm_waterfriction * pm.waterlevel * pml.frametime; // scale the velocity newspeed = speed - drop; if (newspeed < 0) { newspeed = 0; } newspeed /= speed; vel[0] = vel[0] * newspeed; vel[1] = vel[1] * newspeed; vel[2] = vel[2] * newspeed; } /** * Handles user intended acceleration. */ public static void PM_Accelerate(float[] wishdir, float wishspeed, float accel) { int i; float addspeed, accelspeed, currentspeed; currentspeed = Math3D.DotProduct(pml.velocity, wishdir); addspeed = wishspeed - currentspeed; if (addspeed <= 0) return; accelspeed = accel * pml.frametime * wishspeed; if (accelspeed > addspeed) accelspeed = addspeed; for (i = 0; i < 3; i++) pml.velocity[i] += accelspeed * wishdir[i]; } /** * PM_AirAccelerate. */ public static void PM_AirAccelerate(float[] wishdir, float wishspeed, float accel) { int i; float addspeed, accelspeed, currentspeed, wishspd = wishspeed; if (wishspd > 30) wishspd = 30; currentspeed = Math3D.DotProduct(pml.velocity, wishdir); addspeed = wishspd - currentspeed; if (addspeed <= 0) return; accelspeed = accel * wishspeed * pml.frametime; if (accelspeed > addspeed) accelspeed = addspeed; for (i = 0; i < 3; i++) pml.velocity[i] += accelspeed * wishdir[i]; } /** * PM_AddCurrents. */ public static void PM_AddCurrents(float[] wishvel) { float[] v = { 0, 0, 0 }; float s; // account for ladders if (pml.ladder && Math.abs(pml.velocity[2]) <= 200) { if ((pm.viewangles[Defines.PITCH] <= -15) && (pm.cmd.forwardmove > 0)) wishvel[2] = 200; else if ((pm.viewangles[Defines.PITCH] >= 15) && (pm.cmd.forwardmove > 0)) wishvel[2] = -200;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -