m_player.c
来自「著名物理引擎Hawk的源代码」· C语言 代码 · 共 330 行
C
330 行
/* M_player.c, HAWK game engine
*
* Copyright 1997-1998 by Phil Frisbie, Jr.
* for Hawk Software
*
*/
#include "G_main.h"
#include "G_math.h"
#include "M_player.h"
#define STEP 16
#define STOP_EPSILON (float)0.1
/* this is one of two test clipping functions */
void clipMove(vec3_t in, vec3_t normal, vec3_t out)
{
float backoff;
float change;
int i;
backoff = DotProduct(in, normal);
for (i=0 ; i<3 ; i++)
{
change = normal[i]*backoff;
out[i] = in[i] - change;
if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
out[i] = 0;
}
}
void clipMove2(vec3_t move, GSURFACE *surf, vec3_t end)
{
if(surf->normal[X] > 0.99f)
{
move[X] += surf->dist - end[X];
}
else if(surf->normal[Y] > 0.99f)
{
move[Y] += surf->dist - end[Y];
}
else if(surf->normal[Z] > 0.99f)
{
move[Z] += surf->dist - end[Z];
}
else
{
}
}
void playerMove(OBJECT *obj, vec3_t move)
{
vec3_t neworigin;
VectorAdd(move, obj->origin, neworigin);
/* This needs ALLOT of tweeking to get it right */
if(0)
/*if(obj->type & (O_WALLCOL|O_OBJCOL)) */
{
TRACE *tr;
vec3_t vtemp, oldorigin;
vec_t moveleft = 1.0f;
int checks = 3;
VectorCopy(obj->origin, oldorigin);
/* first add step height */
neworigin[Z] += STEP;
oldorigin[Z] += STEP;
tr = gi.TraceBBox(oldorigin, obj->mins, obj->maxs, neworigin, obj, MASK_PLAYERSOLID);
while((tr->fraction < 1.0f)&&(checks))
{
VectorCopy(tr->endpos, oldorigin);
moveleft -= moveleft * tr->fraction;
VectorScale(move, moveleft, move);
clipMove2(move, tr->surface, neworigin);
VectorAdd(move, oldorigin, neworigin);
tr = gi.TraceBBox(oldorigin, obj->mins, obj->maxs, neworigin, obj, MASK_PLAYERSOLID);
checks--;
}
/* now push down from the end point */
VectorCopy(neworigin, vtemp);
neworigin[Z] -= 2 * STEP;
tr = gi.TraceBBox(vtemp, obj->mins, obj->maxs, neworigin, obj, MASK_PLAYERSOLID);
if(tr->fraction < 1.0)
{
VectorCopy(tr->endpos, neworigin);
}
VectorCopy(neworigin, obj->origin);
}
else
{
VectorCopy(neworigin, obj->origin);
}
}
void M_PlayerUpdate(OBJECT *obj)
{
int i, frames = Frames;
vec3_t move;
float speed;
BOOL run = FALSE;
BOOL crouch = FALSE;
/* you need to do this for fast 3D cards */
if(!frames)
return;
/* Process movement events */
if(obj->event&EV_FAST)
{
if(obj->event&EV_CROUCH)
{
speed = obj->acc;
crouch = TRUE;
}
else
speed = FAST * obj->acc;
}
else
{
if(obj->event&EV_CROUCH)
{
speed = obj->acc * 0.5;
crouch = TRUE;
}
else
speed = obj->acc;
}
if(obj->event&EV_LEFT)
{
obj->strafeSpeed += frames * speed;
obj->strafeSpeed = MIN(obj->maxspeed, obj->strafeSpeed);
run = TRUE;
}
if(obj->event&EV_TURNLEFT)
obj->angles[Z] += frames * obj->turn;
if(obj->event&EV_RIGHT)
{
obj->strafeSpeed -= frames * speed;
obj->strafeSpeed = MAX(-obj->maxspeed, obj->strafeSpeed);
run = TRUE;
}
if(obj->event&EV_TURNRIGHT)
obj->angles[Z] -= frames * obj->turn;
if(obj->event&EV_FORWARD)
{
if (obj->event&EV_UP)
obj->speed= obj->maxspeed;
else
obj->speed += frames * speed;
obj->speed = MIN(obj->maxspeed, obj->speed);
run = TRUE;
}
if(obj->event&EV_BACKWARD)
{
obj->speed -= frames * speed;
obj->speed = MAX(-obj->maxspeed, obj->speed);
run = TRUE;
}
if(obj->event&EV_UP)
{
obj->vertSpeed += frames * speed;
obj->vertSpeed = MIN(obj->maxspeed, obj->vertSpeed);
}
if(obj->event&EV_DOWN)
{
obj->vertSpeed -= frames * speed;
obj->vertSpeed = MAX(-obj->maxspeed, obj->vertSpeed);
}
if(obj->event&EV_LOOKUP)
{
obj->pitch += frames * 2;
obj->pitch = MIN(89.9, obj->pitch);
}
if(obj->event&EV_LOOKDOWN)
{
obj->pitch -= frames * 2;
obj->pitch = MAX(-89.9, obj->pitch);
}
if((fabs(obj->speed) > STOPPED_LIMIT)
|| (fabs( obj->strafeSpeed ) > STOPPED_LIMIT)
|| (fabs( obj->vertSpeed ) > STOPPED_LIMIT))
{
move[X] = frames * (obj->speed * cos(RAD(obj->angles[Z]))
+ obj->strafeSpeed
* cos(RAD(obj->angles[Z] + (float)90.0)));
move[Y] = frames * (obj->speed * sin(RAD(obj->angles[Z]))
+ obj->strafeSpeed
* sin(RAD(obj->angles[Z] + (float)90.0)));
move[Z] = frames * obj->vertSpeed;
}
else
{
move[X] = move[Y] = move[Z] = 0.0;
}
/* apply friction */
if(!(obj->type & O_NOFRIC))
{
for (i = 0; i < frames; ++i)
{
obj->speed *= Level->force;
obj->strafeSpeed *= Level->force;
obj->vertSpeed *= Level->force;
}
}
/* adjust the bounding box */
if(crouch)
{
if(!obj->param[2])
obj->maxs[Z] -= 20;
}
else
{
if(obj->param[2])
obj->maxs[Z] += 20;
}
/* set the animation */
if((run == !obj->param[1])||(crouch == !obj->param[2]))
{
if(run)
{
obj->param[1] = TRUE;
if(crouch)
{
gi.AnimationSetNext(obj->animation, FRAME_crwalk1, FRAME_crwalk6, -1);
gi.AnimationSetLoop(obj->animation, TRUE);
obj->param[2] = TRUE;
}
else
{
gi.AnimationSetNext(obj->animation, FRAME_run1, FRAME_run6, -1);
gi.AnimationSetLoop(obj->animation, TRUE);
obj->param[2] = FALSE;
}
}
else
{
obj->param[1] = FALSE;
if(crouch)
{
gi.AnimationSetNext(obj->animation, FRAME_crstnd01, FRAME_crstnd19, -1);
gi.AnimationSetLoop(obj->animation, TRUE);
obj->param[2] = TRUE;
}
else
{
gi.AnimationSetNext(obj->animation, FRAME_stand01, FRAME_stand40, -1);
gi.AnimationSetLoop(obj->animation, TRUE);
obj->param[2] = FALSE;
}
}
}
playerMove(obj, move);
/* now process other effects */
obj->param[0] -= frames;
if((obj->event&EV_SHOOT)&&(obj->param[0] <=0))
{
obj->param[0] = 15;
G_objShoot(obj);
}
}
void SP_info_player_start(entity_t *entity)
{
OBJECT *player;
if(Level->view[0]->object)
{
if(ValueForKey(entity, "targetname"))
return;
}
player = gi.ObjectAdd();
/* set the player start info */
GetVectorForKey (entity, "origin", player->origin);
player->angles[Z] = FloatForKey(entity, "angle");
player->mins[X] = -16;
player->mins[Y] = -16;
player->mins[Z] = -24;
player->maxs[X] = 16;
player->maxs[Y] = 16;
player->maxs[Z] = 32;
player->pitch = 0;
player->radius = 16;
player->height = 24;
player->speed = 0;
player->maxspeed = 20;
player->strafeSpeed = 0;
player->vertSpeed = 0;
player->classname = "player";
player->turn = 2;
player->acc = 2;
player->type = O_PLAYER;
player->next = NULL;
player->model = gi.ModelLoad("players/male/tris.md2");
player->weapon = gi.ModelLoad("players/male/weapon.md2");
player->animation = gi.AnimationAdd();
gi.AnimationSetDefault(player->animation, FRAME_stand01, FRAME_stand40);
player->update = M_PlayerUpdate;
Level->view[0]->object = player;
if(Level->view[1])
Level->view[1]->object = player;
}
void SP_info_player_deathmatch (int e)
{
}
void SP_info_player_coop (int e)
{
}
void SP_info_player_intermission (int e)
{
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?