void collidePortal(vect3Df_s pr, vect3Df_s sr, portal_s* p, vect3Df_s* point) { vect3Df_s o; if(!isPortalInRectangle(pr,sr,p,&o))return; vect3Df_s v=vsubf(*point,p->position); const vect3Df_s u1=p->plane[0], u2=p->plane[1]; float xp=vdotf(v,u1)+PORTAL_WIDTH; float yp=vdotf(v,u2)+PORTAL_HEIGHT; // printf("IN PORTAL ? %f %f\n", xp, yp); if(xp<0 || yp<0 || xp>=PORTAL_WIDTH*2 || yp>=PORTAL_HEIGHT*2)return; float d1=(xp), d2=(yp), d3=PORTAL_WIDTH*2-(xp), d4=PORTAL_HEIGHT*2-(yp); if(d1<d2 && d1<d3 && d1<d4) { *point=vaddf(*point,vmulf(u1,-d1)); }else if(d2<d1 && d2<d3 && d2<d4) { *point=vaddf(*point,vmulf(u2,-d2)); }else if(d3<d1 && d3<d2 && d3<d4) { *point=vaddf(*point,vmulf(u1,d3)); }else{ *point=vaddf(*point,vmulf(u2,d4)); } // printf("YES %f %f %f %f\n",d1,d2,d3,d4); }
void collideObjectRoom(physicalPoint_s* pp, room_s* r) { if(!pp || !r)return; vect3Df_s oldPosition = pp->position; // float length=vmagf(pp->speed); bool ret=false; pp->position = vaddf(pp->position,pp->speed); ret = checkObjectCollision(pp, r); pp->contact=ret; vect3Df_s os=pp->speed; pp->speed=vect3Df(pp->position.x-oldPosition.x, pp->position.y-oldPosition.y, pp->position.z-oldPosition.z); pp->speed=vect3Df((os.x*pp->speed.x>0)?(pp->speed.x):(0),(os.y*pp->speed.y>0)?(pp->speed.y):(0),(os.z*pp->speed.z>0)?(pp->speed.z):(0)); if(pp->contact) { //floor friction vect3Df_s s=vsubf(pp->speed,vmulf(normGravityVector,vdotf(normGravityVector,pp->speed))); pp->speed=vsubf(pp->speed,vdivf(s,2)); }else{ //air friction vect3Df_s s=vsubf(pp->speed,vmulf(normGravityVector,vdotf(normGravityVector,pp->speed))); pp->speed=vsubf(pp->speed,vdivf(s,32)); } if(fabs(pp->speed.x)<0.01f)pp->speed.x=0; if(fabs(pp->speed.z)<0.01f)pp->speed.z=0; }
bool isPointInPortal(portal_s* p, vect3Df_s o, vect3Df_s *v, float* x, float* y, float* z) { if(!x || !y || !z || !v || !p)return false; *v=vsubf(o,p->position); const vect3Df_s u1=p->plane[0], u2=p->plane[1]; *x=vdotf(*v,u1); *y=vdotf(*v,u2); *z=vdotf(*v,p->normal); return !(*x<-PORTAL_WIDTH || *y<-PORTAL_HEIGHT || *x>=PORTAL_WIDTH || *y>=PORTAL_HEIGHT || *z>3.0f); }
void updatePlatform(platform_s* pf, player_s* p) { if(!pf)return; if(pf->ao.active) { if(pf->touched && p->object.position.y>pf->position.y+p->object.radius) { p->object.position=vaddf(p->object.position,pf->velocity); }else if(pf->oldTouched){ p->object.speed=vaddf(p->object.speed,pf->velocity); } if(pf->direction) { if(vdotf(vsubf(pf->position,pf->destination),pf->velocity)>0) { if(pf->backandforth) { pf->velocity=vmulf(pf->velocity,-1); pf->direction=false; }else{ pf->velocity=vect3Df(0,0,0); pf->ao.active=false; } } }else{ if(vdotf(vsubf(pf->position,pf->origin),pf->velocity)>0) { pf->velocity=vmulf(pf->velocity,-1); pf->direction=true; } } int i; for(i=0; i<NUMOBJECTS; i++) { if(objects[i].used && intersectOBBPlatform(pf, &objects[i])) { objects[i].position = vaddf(objects[i].position, pf->velocity); } } pf->position=vaddf(pf->position,pf->velocity); } if(pf->aar) { pf->aar->position = vaddf(pf->position, vect3Df(-PLATFORMSIZE, PLATFORMHEIGHT, -PLATFORMSIZE)); } pf->ao.oldActive=pf->ao.active; pf->oldTouched=pf->touched; pf->touched=false; }
bool collideRectangle(physicalPoint_s* o, vect3Df_s p, vect3Df_s s) { if(!o)return false; vect3Df_s o2 = getClosestPointRectangle(p, s, o->position); int i; for(i=0; i < NUM_PORTALS; i++) { if(portals[i].target && portals[i].open && portals[i].target->open)collidePortal(p, s, &portals[i], &o2); } vect3Df_s v = vsubf(o2, o->position); float gval = vdotf(v, normGravityVector); vect3Df_s v2 = vsubf(v, vmulf(normGravityVector, gval)); float sqd = (v2.x*v2.x)+(v2.y*v2.y)+(v2.z*v2.z)+((gval*gval)/ transY); if(sqd < o->sqRadius) { float sqd = (v2.x*v2.x)+(v2.y*v2.y)+(v2.z*v2.z)+(gval*gval)/transY; float d = sqrtf(sqd); v = vdivf(vmulf(vect3Df(v.x, v.y, v.z), -(o->radius-d)), d); o->position = vaddf(o->position, v); return true; } return false; }
vect3Df_s getClosestPointRectangle(vect3Df_s rectOrigin, vect3Df_s rectSize, vect3Df_s o) { vect3Df_s u1, u2; float x,y,sx,sy; if(rectSize.x){sx=fabs(rectSize.x);u1=vect3Df((rectSize.x>0)?(1.0f):(-(1.0f)),0,0);} else{sx=fabs(rectSize.y);u1=vect3Df(0,(rectSize.y>0)?(1.0f):(-(1.0f)),0);} if(rectSize.z){sy=fabs(rectSize.z);u2=vect3Df(0,0,(rectSize.z>0)?(1.0f):(-(1.0f)));} else{sy=fabs(rectSize.y);u2=vect3Df(0,(rectSize.y>0)?(1.0f):(-(1.0f)),0);} o=vsubf(o, rectOrigin); x=vdotf(o, u1); y=vdotf(o, u2); bool r=true; r=r && x<sx && x>=0; r=r && y<sy && y>=0; if(r)return vaddf(rectOrigin, vect3Df((x*u1.x)+(y*u2.x), (x*u1.y)+(y*u2.y), (x*u1.z)+(y*u2.z))); if(x<0) { x=0; if(y<0)y=0; else if(y>sy)y=sy; }else if(x>sx) { x=sx; if(y<0)y=0; else if(y>sy)y=sy; }else if(y<0) { y=0; if(x<0)x=0; else if(x>sx)y=sx; }else if(y>sy) { y=sy; if(x<0)x=0; else if(x>sx)x=sx; } return vaddf(rectOrigin, vect3Df((x*u1.x)+(y*u2.x), (x*u1.y)+(y*u2.y), (x*u1.z)+(y*u2.z))); }
bool collideLineRectangle(rectangle_s* rec, vect3Df_s o, vect3Df_s v, float d, float* kk, vect3Df_s* ip) { if(!rec)return false; vect3Df_s n=vect3Df(fabs(rec->normal.x),fabs(rec->normal.y),fabs(rec->normal.z)); float p1=vdotf(v,n); if(fabs(p1)>0.001f) { vect3Df_s p = convertRectangleVector(rec->position); vect3Df_s s = convertRectangleVector(rec->size); float p2=vdotf(vsubf(p,o),n); float k=p2/p1; s8 sign=((s.x>0)^(s.y<0)^(s.z>0)^(p1<0))?(-1):(1); if(kk) { *kk=k+sign; } if(k<0 || k>d){return false;} vect3Df_s i=vaddf(o,vmulf(v,k)); if(ip)*ip=i; i=vsubf(i,p); bool r=true; if(s.x) { if(s.x>0)r=r&&i.x<s.x&&i.x>=0; else r=r&&i.x>s.x&&i.x<=0; } if(s.y) { if(s.y>0)r=r&&i.y<s.y&&i.y>=0; else r=r&&i.y>s.y&&i.y<=0; } if(s.z) { if(s.z>0)r=r&&i.z<s.z&&i.z>=0; else r=r&&i.z>s.z&&i.z<=0; } return r; } return false; }
void updateEnergyBall(room_s* r, energyBall_s* eb) { if(!eb)return; vect3Df_s l=eb->position; vect3Df_s ip=l, normal; rectangle_s* col=collideGridCell(getCurrentCell(r,eb->position), eb->launcher?eb->launcher->surface:NULL, l, eb->direction, eb->speed, &ip, &normal); if(!col)col=collideGridCell(getCurrentCell(r,vaddf(eb->position,vmulf(eb->direction,eb->speed))), eb->launcher?eb->launcher->surface:NULL, l, eb->direction, eb->speed, &ip, &normal); if(col) { // printf("COL COL COL %d\n",col->collides); energyDevice_s* ed=isEnergyCatcherSurface(col); if(ed && !ed->active) { //caught md2InstanceChangeAnimation(&ed->modelInstance,2,false); md2InstanceChangeAnimation(&ed->modelInstance,1,true); killEnergyBall(eb); if(eb->launcher)eb->launcher->active=false; ed->active=true; return; } vect3Df_s v=vect3Df(0,0,0); float x, y, z; portal_s* portal=NULL; int i; for(i=0; i<NUM_PORTALS && !portal; i++) { if(isPointInPortal(&portals[i],ip,&v,&x,&y,&z))portal=&portals[i]; if(portal && fabs(z)>=0.1f)portal=NULL; } if(portal && !portal->target)portal=NULL; if(!portal) { eb->position=ip; eb->direction=vsubf(eb->direction,vmulf(normal,2*vdotf(eb->direction,normal))); eb->position=vaddf(eb->position,vmulf(eb->direction,ENERGYBALLSIZE)); }else if(portal->target && portal->open && portal->target->open){ eb->position=vaddf(eb->position,vmulf(eb->direction,eb->speed)); warpEnergyBall(portal,eb); eb->position=vaddf(eb->position,vmulf(eb->direction,eb->speed)); } }else{ eb->position=vaddf(eb->position,vmulf(eb->direction,eb->speed)); } md2InstanceUpdate(&eb->modelInstance); if(!eb->life)killEnergyBall(eb); else eb->life--; }
void updatePlayer(player_s* p, room_s* r) { if(!p)return; md2InstanceUpdate(&p->gunInstance); md2InstanceUpdate(&p->ratmanInstance); if(!p->flying) p->object.speed = vaddf(p->object.speed, vmulf(normGravityVector, 0.04f)); vect3Df_s prevPosition = p->object.position; collideObjectRoom(&p->object, r); if(p->inPortal && !p->oldInPortal)playSFX(portalEnterSFX[rand()%2]); else if(!p->inPortal && p->oldInPortal)playSFX(portalExitSFX[rand()%2]); int i; for(i=0; i < NUM_PORTALS; i++) { if(portals[i].target)checkPortalPlayerWarp(p, &portals[i]); } updateCamera(&p->camera); float alignment = -vdotf(vect3Df(p->camera.orientation[0][0],p->camera.orientation[0][1],p->camera.orientation[0][2]), normGravityVector); // printf("alignment : %f \n",alignment); { if(alignment>0.001) { if(alignment>0.125)rotateMatrixZ((float*)p->camera.orientation, -0.5f*0.15f, true); else if(alignment>0.0625)rotateMatrixZ((float*)p->camera.orientation, -0.25f*0.15f, true); else if(alignment>0.03125)rotateMatrixZ((float*)p->camera.orientation, -0.125f*0.07f, true); }else if(alignment<-0.001) { if(alignment<-0.125)rotateMatrixZ((float*)p->camera.orientation, 0.5f*0.15f, true); else if(alignment<-0.0625)rotateMatrixZ((float*)p->camera.orientation, 0.25f*0.15f, true); else if(alignment<-0.03125)rotateMatrixZ((float*)p->camera.orientation, 0.125f*0.07f, true); } } // fixMatrix(c->orientation); //compensate floating point errors p->camera.position = vaddf(p->object.position, vect3Df(0.0f, cos(p->walkCnt1)*0.14f, 0.0f)); if(vmagf(p->object.speed) < 0.03f || !p->object.contact)md2InstanceChangeAnimation(&p->ratmanInstance, 0, false); if(p->flying) p->object.speed = vect3Df(0,0,0); //TEMP p->tempAngle = vmulf(p->tempAngle, 0.65f); }
void shootPlayerGun(player_s* p, room_s* r, portal_s* portal) { if(!p)return; if(p->gunInstance.currentAnim == PORTALGUN_SHOOT)return; md2InstanceChangeAnimation(&p->gunInstance, PORTALGUN_IDLE, false); md2InstanceChangeAnimation(&p->gunInstance, PORTALGUN_SHOOT, true); vect3Df_s position; rectangle_s* rec = collideLineMapClosest(r, NULL, p->camera.position, vect3Df(-p->camera.orientation[2][0], -p->camera.orientation[2][1], -p->camera.orientation[2][2]), 1000.0f, &position, NULL); if(rec && rec->portalable) { portal_s oldPortal = *portal; vect3Df_s normal = rec->normal; vect3Df_s plane0 = vect3Df(p->camera.orientation[0][0], p->camera.orientation[0][1], p->camera.orientation[0][2]); plane0 = vnormf(vsubf(plane0, vmulf(normal, vdotf(normal, plane0)))); position = vaddf(position, vmulf(normal, -0.05f)); portal->position = position; updatePortalOrientation(portal, plane0, normal); isPortalOnWall(r, portal, true); portal->draw = true; portal->open = true; if(isPortalOnWall(r, portal, false)) { ejectPortalOBBs(portal); ejectPortalOBBs(portal->target); }else{ *portal = oldPortal; } } }