From d1f4c1fd83c724188015244ef1ae089193665259 Mon Sep 17 00:00:00 2001 From: Rafael Barreto Date: Wed, 18 Aug 2010 23:50:56 +0000 Subject: [PATCH] reverting player collision, adding bot changing direction after collision, fixing slow motion when walking on corners, better balance teams evaluation git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@5655 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/src/geom.h | 4 +++ source/src/physics.cpp | 74 +++++++++++++++++++++++++----------------- source/src/server.cpp | 4 +-- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/source/src/geom.h b/source/src/geom.h index 0672f199..898e665e 100644 --- a/source/src/geom.h +++ b/source/src/geom.h @@ -81,7 +81,10 @@ struct vec vec &sub(const vec &o) { x -= o.x; y -= o.y; z -= o.z; return *this; } float squaredlen() const { return x*x + y*y + z*z; } + float sqrxy() const { return x*x + y*y; } + float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z; } + float dotxy(const vec &o) const { return x*o.x + y*o.y; } float magnitude() const { return sqrtf(squaredlen()); } vec &normalize() { div(magnitude()); return *this; } @@ -101,6 +104,7 @@ struct vec bool reject(const vec &o, float max) const { return x>o.x+max || xo.y+max || ystate!=CS_ALIVE || !o->cancollide) return false; - const float r = o->radius+d->radius, dx = o->o.x-d->o.x, dy = o->o.y-d->o.y; + const float r = o->radius+d->radius; + const vec dr = vec(o->o.x-d->o.x,o->o.y-d->o.y,0); const float deyeheight = d->eyeheight, oeyeheight = o->eyeheight; - if(d->type==ENT_PLAYER && o->type==ENT_PLAYER ? dx*dx + dy*dy < r*r : fabs(dx)type==ENT_PLAYER && o->type==ENT_PLAYER ? dr.sqrxy() < r*r : fabs(dr.x)vel) >= 0.0f) { if(d->o.z-deyeheighto.z-oeyeheight) { if(o->o.z-oeyeheighto.z-oeyeheight-1; } else if(o->o.z+o->aboveeye>lo) lo = o->o.z+o->aboveeye+1; @@ -162,7 +163,7 @@ bool objcollide(physent *d, const vec &objpos, float objrad, float objheight) // // drop & rise are supplied by the physics below to indicate gravity/push for current mini-timestep static int cornersurface = 0; -bool collide(physent *d, bool spawn, float drop, float rise, int level) +bool collide(physent *d, bool spawn, float drop, float rise, int level) // levels 1 = map, 2 = players, 4 = models, default: 1+2+4 { cornersurface = 0; const float fx1 = d->o.x-d->radius; // figure out integer cube rectangle this entity covers in map @@ -523,38 +524,53 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime) pl->o.z -= f*d.z; break; } - if(pl->type==ENT_PLAYER && hitplayer) + if(pl->type!=ENT_BOUNCE && hitplayer) { - float dx = hitplayer->o.x-pl->o.x, dy = hitplayer->o.y-pl->o.y, - push = (dx*d.x + dy*d.y)/max(dx*dx + dy*dy, 1e-3f), - px = fabs(f*push*dx*10.0f), py = fabs(f*push*dy*10.0f); - physent *hp = hitplayer; - pl->o.x -= px*d.x; - pl->o.y -= py*d.y; - bool plc = collide(pl, false, drop, rise, 2); - if( !collide(pl, false, drop, rise, 5) && ( !plc || (plc && push < 0 && hp==hitplayer) ) ) continue; - hitplayer->vel.add(d); // this works fine in singleplayer, and we need to test it better in multiplayer - pl->o.x += px*d.x; - pl->o.y += py*d.y; + vec dr(hitplayer->o.x-pl->o.x,hitplayer->o.y-pl->o.y,0); + float dist = dr.ufmagxy(), + push = (dist > 0.1f ? dr.dotxy(d)*1.1f/dist : dr.dotxy(d) * 11.0f); + + pl->o.x -= f*d.x*push; + pl->o.y -= f*d.y*push; + if(i==0 && pl->type==ENT_BOT) pl->yaw += (dr.cxy(d)>0 ? 2:-2); // force the bots to change direction + if( !collide(pl, false, drop, rise) ) continue; + pl->o.x += f*d.x*push; + pl->o.y += f*d.y*push; } - // player stuck, try slide along y axis - pl->o.x -= f*d.x; - if(!collide(pl, false, drop, rise)) + if (cornersurface) { - d.x = 0; - if(pl->type==ENT_BOUNCE) { pl->vel.x = -pl->vel.x; pl->vel.mul(0.7f); } - continue; + float ct2f = (cornersurface == 2 ? -1.0 : 1.0); + float diag = f*d.ufmagxy()*2; + vec vd = vec((d.y*ct2f+d.x >= 0.0f ? diag : -diag), (d.x*ct2f+d.y >= 0.0f ? diag : -diag), 0); + pl->o.x -= f*d.x; + pl->o.y -= f*d.y; + + pl->o.x += vd.x; + pl->o.y += vd.y; + if(!collide(pl, false, drop, rise)) + { + d.x = vd.x; d.y = vd.y; + continue; + } + pl->o.x -= vd.x; + pl->o.y -= vd.y; } - pl->o.x += f*d.x; -// still stuck, try x axis - pl->o.y -= f*d.y; - if(!collide(pl, false, drop, rise)) + else { - d.y = 0; - if(pl->type==ENT_BOUNCE) { pl->vel.y = -pl->vel.y; pl->vel.mul(0.7f); } - continue; +#define WALKALONGAXIS(x,y) \ + pl->o.x -= f*d.x; \ + if(!collide(pl, false, drop, rise)) \ + { \ + d.x = 0; \ + if(pl->type==ENT_BOUNCE) { pl->vel.x = -pl->vel.x; pl->vel.mul(0.7f); } \ + continue; \ + } \ + pl->o.x += f*d.x; + // player stuck, try slide along y axis + WALKALONGAXIS(x,y); + // still stuck, try x axis + WALKALONGAXIS(y,x); } - pl->o.y += f*d.y; // try just dropping down pl->o.x -= f*d.x; pl->o.y -= f*d.y; diff --git a/source/src/server.cpp b/source/src/server.cpp index ccbe8e84..59900611 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -1533,7 +1533,7 @@ bool balanceteams(int ftr) // pro vs noobs never more if(mastermode != MM_OPEN || totalclients < 3 ) return true; int tsize[2] = {0, 0}, tscore[2] = {0, 0}; int totalscore = 0, nplayers = 0; - int flagmult = (m_ctf ? 20 : (m_htf ? 10 : 5)); + int flagmult = (m_ctf ? 25 : (m_htf ? 12 : 6)); loopv(clients) if(clients[i]->type!=ST_EMPTY) { @@ -1545,7 +1545,7 @@ bool balanceteams(int ftr) // pro vs noobs never more tsize[c->team]++; // effective score per minute, thanks to wtfthisgame for the nice idea // in a normal game, normal players will do 500 points in 10 minutes - c->eff_score = c->state.points * 60 * 1000 / time + c->state.points / 10 + c->state.flagscore * flagmult; + c->eff_score = c->state.points * 60 * 1000 / time + c->state.points / 8 + c->state.flagscore * flagmult; tscore[c->team] += c->eff_score; nplayers++; totalscore += c->state.points;