/* * This code is released under the GNU General Public License. See COPYING for * details. Copyright 2003 John Spray: spray_john@users.sourceforge.net */ #include "Camera.h" #include #include #include #include #include #include #include "Vector.h" #include "Visual.h" #include "LList.h" #include "Player.h" #include "Missile.h" #include "Arena.h" #include "Ufo.h" #include "Mine.h" #include "Obstacle.h" #include "Config.h" extern Config GLOB_conf; #ifndef M_PI #define M_PI 3.14159 #endif #ifndef M_2PI #define M_2PI 6.28318 #endif Camera::Camera() { targetplayer=NULL; s=0.0f; v=0.0f; a=0.0f; bear=0; //RADIANS! pitch=0; //RADIANS! roll=0; //RADIANS bearv=0; pitchv=0; rollv=0; offset=10; viewportx=0; viewporty=0; viewportwidth=640; viewportheight=480; fov=90.0f; farclip=1000.0f; nearclip=1.0f; messagetimer=0.0f; messagetimermax=800.0f; movemode=CAMERA_MOVEMODE_CHASE; } Camera::~Camera() { } void Camera::Animate() { if(!targetplayer){ printf("Camera::Animate: targetplayer unset! Aborting.\n"); return; } Vector s_old; //use for calculating velocity s_old=s; switch(movemode){ case CAMERA_MOVEMODE_CHASE: s.x=targetplayer->s.x-sin(targetplayer->bear+targetplayer->bearv*0.001f)*offset; //s.x+=(targetplayer->s.x-sin(targetplayer->bear)*offset-s.x)*0.9f; s.z=targetplayer->s.z-cos(targetplayer->bear+targetplayer->bearv*0.001f)*offset; s.z+=(targetplayer->s.z-cos(targetplayer->bear)*offset-s.z)*0.9f; s.y=targetplayer->s.y+offset/2; pitch=-M_PI/8; bear=targetplayer->bear+targetplayer->bearv*10.0f; break; case CAMERA_MOVEMODE_CLOSE: s.x=targetplayer->s.x-4.0f*sin(targetplayer->bear); s.z=targetplayer->s.z-4.0f*cos(targetplayer->bear); s.y=targetplayer->s.y+3.0f; bear=targetplayer->bear; pitch=0.0f; break; case CAMERA_MOVEMODE_REAR: s.x=targetplayer->s.x-4.0f*sin(targetplayer->bear); s.z=targetplayer->s.z-4.0f*cos(targetplayer->bear); s.y=targetplayer->s.y+2.0f; bear=targetplayer->bear-M_PI; pitch=0.0f; break; case CAMERA_MOVEMODE_GOD: s=targetplayer->s; s.x-=15.0f*sin(targetplayer->bear); s.z-=15.0f*cos(targetplayer->bear); s.y=30+targetplayer->v.Mag()*100.0f; pitch=-M_PI/4; bear=targetplayer->bear; break; case CAMERA_MOVEMODE_FREE: bear += bearv*visual->game->dtf; pitch += pitchv*visual->game->dtf; roll += rollv*visual->game->dtf; v+=a*visual->game->dtf; s+=v*visual->game->dtf; break; default: fprintf(stderr,"Camera::Animate: Invalid movemode %d\n",movemode); break; } if(!visual->game->arena->Blocked(targetplayer->s,1.2)) /*this loop endless if the player is arena->Blocked itself * to the same radius as we're checking the camera*/ while(visual->game->arena->Blocked(s,1.0f)){ s=targetplayer->s+(s-targetplayer->s)*0.99f; } //Update the vectors used for sound face.x=sin(bear)*cos(pitch); face.z=cos(bear)*cos(pitch); face.y=sin(pitch); up.y=1.0f; up.z=up.x=0.0f; if(movemode!=CAMERA_MOVEMODE_FREE) v=(s-s_old)/visual->game->dtf; } void Camera::Draw() { int errornumber=0; glClear(GL_DEPTH_BUFFER_BIT); glViewport(viewportx, viewporty, viewportwidth, viewportheight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( fov, (float)viewportwidth/(float)viewportheight, nearclip, farclip ); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef((-roll/M_PI)*180,0.0f,0.0f,1.0f); glRotatef((-pitch/M_PI)*180,1.0f,0.0f,0.0f); glRotatef((-bear/M_PI)*180+180,0.0f,1.0f,0.0f); glTranslatef(-s.x,-s.y,-s.z); //glEnable(GL_LIGHTING); //float zero[]={0.0f,0.0f,0.0f,1.0f}; float white[]={1.0f,1.0f,1.0f,1.0f}; float ambient[]={0.7f,0.5f,0.5f,1.0f}; float diffuse[]={1.0f,0.0f,0.0f,1.0f}; float specular[]={0.0f,0.0f,0.0f,1.0f}; float pos[]={-1.0f,1.0f,-1.0f,0.0f}; glLightfv(GL_LIGHT0,GL_AMBIENT,ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,specular); glLightf(GL_LIGHT0,GL_CONSTANT_ATTENUATION,1.0f); glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,1.0f); glLightfv(GL_LIGHT0,GL_POSITION,pos); glEnable(GL_LIGHT0); /* pos[0]=-1.0f; diffuse[0]=1.0f; glLightfv(GL_LIGHT1,GL_AMBIENT,ambient); glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuse); glLightfv(GL_LIGHT1,GL_SPECULAR,specular); glLightf(GL_LIGHT1,GL_CONSTANT_ATTENUATION,1.0f); glLightf(GL_LIGHT1,GL_LINEAR_ATTENUATION,1.0f); glLightfv(GL_LIGHT1,GL_POSITION,pos); glEnable(GL_LIGHT1);*/ glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,white); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular); glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0f); DrawSky(); //DrawGrid(); DrawArena(visual->game->arena); DrawPlayer(visual->game->player); if(GLOB_conf.twoplayer) DrawPlayer(visual->game->player2); LListItem* ufoitem=visual->game->ufolist->head; while(ufoitem){ DrawUfo(&ufoitem->data); ufoitem=ufoitem->next; } LListItem* mineitem=visual->game->minelist->head; while(mineitem){ DrawMine(&mineitem->data); mineitem=mineitem->next; } LListItem* pupitem=visual->game->poweruplist->head; while(pupitem){ DrawPowerUp(&pupitem->data); pupitem=pupitem->next; } DrawMissiles(); DrawParticles(); Draw2D(); while((errornumber=glGetError())!=GL_NO_ERROR){ printf("Camera::Draw: OpenGL error: %s\n",visual->HandleGlError(errornumber)); } } void Camera::DrawPlayer(Player* player) { GLUquadricObj* quad; if(!player->alive) return; Vector vtemp1,vtemp2; float ftemp; Vector glowpos; Vector glowpostail; glBlendFunc(GL_SRC_ALPHA,GL_ONE); glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); glDepthMask(GL_FALSE); visual->UseTexture("driveparticle.png"); glColor4f(1.0f,1.0f,1.0f,1.0f); glowpos=player->s; glowpos.x-=sin(player->bear)*4.5f; glowpos.z-=cos(player->bear)*4.5f; glowpos.y-=1.0f; DrawSprite(glowpos,2.5f,(player->bouncecycle/M_PI)*180.0f); visual->UseTexture("halfdriveparticle.png"); glowpos=player->s; glowpos.x-=sin(player->bear)*4.5f; glowpos.z-=cos(player->bear)*4.5f; glowpostail=glowpos-player->v*100.0f; DrawAxisSprite(glowpos,glowpostail,2.0f); glDepthMask(GL_TRUE); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glPushMatrix(); glColor4f(1.0f,1.0f,1.0f,1.0f); glTranslatef(player->s.x,player->s.y,player->s.z); //we don't want the shadow to experience the player's tilt, //so we render it in this ugly place visual->UseTexture("shadow.png"); glPushMatrix(); //glTranslatef(sin(player->bear)*3,-player->s.y*0.99f,cos(player->bear)*3); glTranslatef(0.0f,-player->s.y*0.99f,0.0f); float shadowhw=3.0f; shadowhw-=sin(player->bouncecycle)*0.1f; glBegin(GL_QUADS); glTexCoord2f(1.0f,1.0f); glVertex3f(shadowhw,0.0f,shadowhw); glTexCoord2f(1.0f,0.0f); glVertex3f(shadowhw,0.0f,-shadowhw); glTexCoord2f(0.0f,0.0f); glVertex3f(-shadowhw,0.0f,-shadowhw); glTexCoord2f(0.0f,1.0f); glVertex3f(-shadowhw,0.0f,shadowhw); glEnd(); glPopMatrix(); vtemp1.Set3f(sin(player->bear),0.0f,cos(player->bear));//ie player's heading vector vtemp2=player->a; vtemp2.Unitize(); ftemp=vtemp1|vtemp2;//ie the proportion of the acceleration that's parallel to the heading if(ftemp<0) ftemp*=-1.0f; glRotatef((player->bear/M_PI)*180.0f,0.0f,1.0f,0.0f); glRotatef((-player->strafea*0.05f*(1.0f-ftemp))*180.0f,0.0f,0.0f,1.0f); //glRotatef(90.0f,0.0f,0.0f,1.0f); visual->DrawMesh("player.mesh"); if(player->shieldeffect||(player->powerup==POWERUP_SUPERSHIELD&&player->poweruptimer>0.0f)){ float frac_shieldeffect=player->shieldeffect/player->maxshieldeffect; glPushMatrix(); quad=gluNewQuadric(); gluQuadricNormals(quad,GL_SMOOTH); gluQuadricTexture(quad,GL_TRUE); glDepthMask(GL_FALSE); glDisable(GL_LIGHTING); visual->UseTexture("shield.png"); //Different behaviour for if we're here because of //a powerup or a Hurt if(player->shieldeffect) glColor4f(1.0f,1.0f,1.0f,frac_shieldeffect); else glColor4f(1.0f,1.0f,1.0f,1.0f); glScalef(1.0f,0.45f,1.0f); glRotatef((player->bouncecycle/(float)M_PI)*90.0f,0.0f,0.0f,1.0f); if(player->shieldeffect){ gluQuadricOrientation(quad,GLU_OUTSIDE); gluSphere(quad,player->collideradius+player->collideradius* 0.25f*(1.0f-frac_shieldeffect),20,10); gluQuadricOrientation(quad,GLU_INSIDE); gluSphere(quad,player->collideradius+player->collideradius* 0.25f*(1.0f-frac_shieldeffect),20,10); } else{ gluQuadricOrientation(quad,GLU_OUTSIDE); gluSphere(quad,player->collideradius,20,10); gluQuadricOrientation(quad,GLU_INSIDE); gluSphere(quad,player->collideradius,20,10); } glDepthMask(GL_TRUE); glEnable(GL_LIGHTING); gluDeleteQuadric(quad); glPopMatrix(); } /* if(player->collideflag){ quad=gluNewQuadric(); gluQuadricOrientation(quad,GLU_OUTSIDE); glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glColor4f(0.0f,1.0f,0.0f,0.5f); gluSphere(quad,player->collideradius,20,10); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); gluDeleteQuadric(quad); }*/ glPopMatrix(); if(player->cannonfiring && player->cannonwait>player->cannonperiod/2.0f){ glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); glDepthMask(GL_FALSE); Vector p1,p2; p1=player->s; p1.x+=sin(player->bear)*player->collideradius; p1.z+=cos(player->bear)*player->collideradius; p2=p1+player->tracer; glColor4f(1.0f,1.0f,1.0f,0.35f); visual->UseTexture("tracer.png"); DrawAxisSprite(p1,p2,0.1f); p1=player->s; p1.x+=sin(player->bear)*player->collideradius*0.5; p1.z+=cos(player->bear)*player->collideradius*0.5; p2=player->s; p2.x+=sin(player->bear)*player->collideradius*1.5f; p2.z+=cos(player->bear)*player->collideradius*1.5f; visual->UseTexture("muzzleflash.png"); glColor4f(1.0f,1.0f,1.0f,player->cannonwait/player->cannonperiod); DrawAxisSprite(p1,p2,1.0f); glDepthMask(GL_TRUE); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); } } void Camera::DrawGrid() { float x,y,z; glDisable(GL_TEXTURE_2D); glPointSize(5); glBegin(GL_POINTS); for(x=-500;x<=500;x+=10){ for(y=-100;y<=100;y+=10){ for(z=-500;z<=500;z+=10){ glColor4f(x,y,z,1.0f); glVertex3f(x,y,z); } } } glEnd(); glEnable(GL_TEXTURE_2D); } void Camera::DrawArena(Arena* arena) { float arenahalfwidth=arena->halfwidth; float arenawallheight=arena->wallheight; //--------------------- /* glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); Vector p1,p2; p1.z=arenahalfwidth; p1.y=5.0f; p2.z=-arenahalfwidth; p2.y=5.0f; v=p1-p2; Vector h=PerpLinePoint(p1,p2,s); Vector d=h-s; d.Unitize(); //printf("d.mag2=%f,d|v=%f,h.Mag=%f\n",d.Mag2(),d|v,h.Mag()); glColor4f(0.0f,1.0f,0.0f,1.0f); glBegin(GL_LINES); glVertex3f(h.x-2,h.y,h.z); glVertex3f(h.x+2,h.y,h.z); glVertex3f(h.x,h.y-2,h.z); glVertex3f(h.x,h.y+2,h.z); glVertex3f(h.x,h.y,h.z-2); glVertex3f(h.x,h.y,h.z+2); glEnd(); Vector v1,v2,v3,v4; v1=-d*0.5f; v2=d*0.5f; v3=(p2-p1)+d*0.5f; v4=(p2-p1)-d*0.5f; glTranslatef(p1.x,p1.y,p1.z); glRotatef(90.0f,v.x,v.y,v.z); glBegin(GL_QUADS); //glVertex3f(10.0f,5.0f,arenahalfwidth); //glVertex3f(-10.0f,5.0f,arenahalfwidth); //glVertex3f(-10.0f,5.0f,-arenahalfwidth); //glVertex3f(10.0f,5.0f,-arenahalfwidth); glColor4f(1.0f,0.0f,0.0f,0.5f); glVertex3f(v1.x,v1.y,v1.z); glColor4f(0.0f,1.0f,0.0f,0.5f); glVertex3f(v2.x,v2.y,v2.z); glColor4f(0.0f,0.0f,1.0f,0.5f); glVertex3f(v3.x,v3.y,v3.z); glColor4f(1.0f,1.0f,0.0f,0.5f); glVertex3f(v4.x,v4.y,v4.z); glEnd(); glRotatef(-90.0f,v.x,v.y,v.z); glTranslatef(-p1.x,-p1.y,-p1.z); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); */ //--------------------- glColor4f(1.0f,1.0f,1.0f,1.0f); visual->UseTexture("arenabase.png"); glBegin(GL_QUADS); glNormal3f(0.0f,1.0f,0.0f); glTexCoord2f(arenahalfwidth/5,arenahalfwidth/5); glVertex3f(arenahalfwidth,-5.0f,arenahalfwidth); glTexCoord2f(arenahalfwidth/5,0.0f); glVertex3f(arenahalfwidth,-5.0f,-arenahalfwidth); glTexCoord2f(0.0f,0.0f); glVertex3f(-arenahalfwidth,-5.0f,-arenahalfwidth); glTexCoord2f(0.0f,arenahalfwidth/5); glVertex3f(-arenahalfwidth,-5.0f,arenahalfwidth); glEnd(); visual->UseTexture("arenawall.png"); glBegin(GL_QUADS); glTexCoord2f(arenahalfwidth/5,arenawallheight/10); glVertex3f(arenahalfwidth,-5.0f,arenahalfwidth); glTexCoord2f(arenahalfwidth/5,0.0f); glVertex3f(arenahalfwidth,arenawallheight,arenahalfwidth); glTexCoord2f(0.0f,0.0f); glVertex3f(arenahalfwidth,arenawallheight,-arenahalfwidth); glTexCoord2f(0.0f,arenawallheight/10); glVertex3f(arenahalfwidth,-5.0f,-arenahalfwidth); glEnd(); glBegin(GL_QUADS); glTexCoord2f(arenahalfwidth/5,arenawallheight/10); glVertex3f(-arenahalfwidth,-5.0f,arenahalfwidth); glTexCoord2f(0.0f,arenawallheight/10); glVertex3f(-arenahalfwidth,-5.0f,-arenahalfwidth); glTexCoord2f(0.0f,0.0f); glVertex3f(-arenahalfwidth,arenawallheight,-arenahalfwidth); glTexCoord2f(arenahalfwidth/5,0.0f); glVertex3f(-arenahalfwidth,arenawallheight,arenahalfwidth); glEnd(); glBegin(GL_QUADS); glTexCoord2f(arenahalfwidth/5,arenawallheight/10); glVertex3f(arenahalfwidth,-5.0f,-arenahalfwidth); glTexCoord2f(arenahalfwidth/5,0.0f); glVertex3f(arenahalfwidth,arenawallheight,-arenahalfwidth); glTexCoord2f(0.0f,0.0f); glVertex3f(-arenahalfwidth,arenawallheight,-arenahalfwidth); glTexCoord2f(0.0f,arenawallheight/10); glVertex3f(-arenahalfwidth,-5.0f,-arenahalfwidth); glEnd(); glBegin(GL_QUADS); glTexCoord2f(arenahalfwidth/5,arenawallheight/10); glVertex3f(arenahalfwidth,-5.0f,arenahalfwidth); glTexCoord2f(0.0f,arenawallheight/10); glVertex3f(-arenahalfwidth,-5.0f,arenahalfwidth); glTexCoord2f(0.0f,0.0f); glVertex3f(-arenahalfwidth,arenawallheight,arenahalfwidth); glTexCoord2f(arenahalfwidth/5,0.0f); glVertex3f(arenahalfwidth,arenawallheight,arenahalfwidth); glEnd(); visual->UseTexture("arenamesh.png"); glBegin(GL_QUADS); glNormal3f(0.0f,1.0f,0.0f); glTexCoord2f(arenahalfwidth/5,arenahalfwidth/5); glVertex3f(arenahalfwidth,0.0f,arenahalfwidth); glTexCoord2f(arenahalfwidth/5,0.0f); glVertex3f(arenahalfwidth,0.0f,-arenahalfwidth); glTexCoord2f(0.0f,0.0f); glVertex3f(-arenahalfwidth,0.0f,-arenahalfwidth); glTexCoord2f(0.0f,arenahalfwidth/5); glVertex3f(-arenahalfwidth,0.0f,arenahalfwidth); glEnd(); //and draw the buildings LListItem* obstacleitem=arena->obstaclelist.head; while(obstacleitem){ DrawObstacle(&obstacleitem->data); obstacleitem=obstacleitem->next; } } void Camera::DrawSky(){ float halfwidth=5.0f; float halfheight=5.0f; float texy=1.0f; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( fov, (float)viewportwidth/(float)viewportheight, 0.1, halfwidth+10.0f ); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(s.x,s.y,s.z); glColor4f(1.0f,1.0f,1.0f,1.0f); glDepthMask(GL_FALSE); glDisable(GL_LIGHTING); visual->UseTexture("skyfront.png"); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(-halfwidth,-halfheight,halfwidth); glTexCoord2f(0.0f,texy); glVertex3f(-halfwidth,halfheight,halfwidth); glTexCoord2f(1.0f,texy); glVertex3f(halfwidth,halfheight,halfwidth); glTexCoord2f(1.0f,0.0f); glVertex3f(halfwidth,-halfheight,halfwidth); glEnd(); visual->UseTexture("skyback.png"); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(-halfwidth,-halfheight,-halfwidth); glTexCoord2f(1.0f,0.0f); glVertex3f(halfwidth,-halfheight,-halfwidth); glTexCoord2f(1.0f,texy); glVertex3f(halfwidth,halfheight,-halfwidth); glTexCoord2f(0.0f,texy); glVertex3f(-halfwidth,halfheight,-halfwidth); glEnd(); visual->UseTexture("skyleft.png"); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(halfwidth,-halfheight,-halfwidth); glTexCoord2f(1.0f,0.0f); glVertex3f(halfwidth,-halfheight,halfwidth); glTexCoord2f(1.0f,texy); glVertex3f(halfwidth,halfheight,halfwidth); glTexCoord2f(0.0f,texy); glVertex3f(halfwidth,halfheight,-halfwidth); glEnd(); visual->UseTexture("skyright.png"); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(-halfwidth,-halfheight,-halfwidth); glTexCoord2f(0.0f,texy); glVertex3f(-halfwidth,halfheight,-halfwidth); glTexCoord2f(1.0f,texy); glVertex3f(-halfwidth,halfheight,halfwidth); glTexCoord2f(1.0f,0.0f); glVertex3f(-halfwidth,-halfheight,halfwidth); glEnd(); visual->UseTexture("skyup.png"); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(-halfwidth,halfheight,-halfwidth); glTexCoord2f(1.0f,00.0f); glVertex3f(halfwidth,halfheight,-halfwidth); glTexCoord2f(1.0f,1.0f); glVertex3f(halfwidth,halfheight,halfwidth); glTexCoord2f(0.0f,1.0f); glVertex3f(-halfwidth,halfheight,halfwidth); glEnd(); visual->UseTexture("skydown.png"); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(-halfwidth,-halfheight,-halfwidth); glTexCoord2f(0.0f,1.0f); glVertex3f(-halfwidth,-halfheight,halfwidth); glTexCoord2f(1.0f,1.0f); glVertex3f(halfwidth,-halfheight,halfwidth); glTexCoord2f(1.0f,0.0f); glVertex3f(halfwidth,-halfheight,-halfwidth); glEnd(); glDepthMask(GL_TRUE); glEnable(GL_LIGHTING); glPopMatrix(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective( fov, (float)viewportwidth/(float)viewportheight, nearclip, farclip ); glMatrixMode(GL_MODELVIEW); } void Camera::DrawParticles(){ LListItem* item; glDepthMask(GL_FALSE); glDisable(GL_LIGHTING); item=visual->particlelist.head; while(item){ visual->UseTexture(item->data.texfile); glColor4f(1.0f,1.0f,1.0f,(float)(item->data.life)*1/(float)(item->data.startlife)); glBlendFunc(GL_SRC_ALPHA,item->data.blendmode); glMatrixMode(GL_MODELVIEW); if(item->data.drawmode==PARTICLE_DRAW_SIMPLE){ DrawSprite(item->data.s,item->data.rad, ((float)item->data.life/(float)item->data.startlife) *360.0f*item->data.spindir+item->data.spinoffset); } else if(item->data.drawmode==PARTICLE_DRAW_MOTION){ Vector p1; Vector p2; p1=item->data.s; p2=item->data.s+item->data.v*40.0f; DrawAxisSprite(p1,p2,item->data.rad); } item=item->next; } glDepthMask(GL_TRUE); glEnable(GL_LIGHTING); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); } void Camera::DrawMissiles(){ LListItem* item; float radius=2.0f; Vector p1,p2; glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA,GL_ONE); glMatrixMode(GL_MODELVIEW); glColor4f(1.0f,1.0f,1.0f,1.0f); visual->UseTexture("missiletrail.png"); item=visual->game->missilelist->head; while(item){ p1=item->data.s-item->data.v*20.0f; p2=item->data.s+item->data.v*20.0f; DrawAxisSprite(p1,p2,radius); DrawSprite(item->data.s,radius,0.0f); item=item->next; } glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glDepthMask(GL_TRUE); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); } void Camera::Draw2D(){ int i; glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); float scale=(float)viewportwidth/800; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(0,viewportwidth,0,viewportheight); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glColor4f(1.0f,1.0f,1.0f,1.0f); glLineWidth(1.0f); //countdown strip if the player's got a powerup------ if(targetplayer->poweruptimer){ glDisable(GL_TEXTURE_2D); float left=0.3f,right=0.7f,width; float top=0.99f,bottom=0.95f,height; float powerup_frac; left*=visual->game->screen->w; right*=visual->game->screen->w; width=right-left; top*=visual->game->screen->h; bottom*=visual->game->screen->h; height=top-bottom; powerup_frac=1.0f; glBegin(GL_TRIANGLES); glColor4f(0.5f,0.0f,0.0f,0.5f); glVertex2f(left,top); glColor4f(0.5f-powerup_frac*0.5f,powerup_frac*0.5f,0.0f,0.5f); glVertex2f(left+width*powerup_frac,top-height*powerup_frac); glVertex2f(left+width*powerup_frac,top); glEnd(); powerup_frac=(targetplayer->poweruptimer/targetplayer->maxpoweruptimer); glBegin(GL_TRIANGLES); glColor4f(1.0f,0.0f,0.0f,0.7f); glVertex2f(left,top); glColor4f(1.0f-powerup_frac,powerup_frac,0.0f,0.7f); glVertex2f(left+width*powerup_frac,top-height*powerup_frac); glVertex2f(left+width*powerup_frac,top); glEnd(); glEnable(GL_TEXTURE_2D); } //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //draw life icons:----------------------- glPushMatrix(); glTranslatef(20.0f*scale,20.0f*scale,0); visual->UseTexture("lifeicon.png"); float iconsize=37.5f*scale; float iconspacing=1.25*iconsize; if((int)targetplayer->highlightlives%200>100) glColor4f(0.0f,1.0f,0.0f,1.0f); else glColor4f(1.0f,1.0f,1.0f,1.0f); glBegin(GL_QUADS); for(i=0;ilives;i++){ glTexCoord2f(0.0f,0.0f); glVertex2f(0.0f,0.0f+i*iconspacing); glTexCoord2f(1.0f,0.0f); glVertex2f(iconsize,0.0f+i*iconspacing); glTexCoord2f(1.0f,1.0f); glVertex2f(iconsize,iconsize+i*iconspacing); glTexCoord2f(0.0f,1.0f); glVertex2f(0.0f,iconsize+i*iconspacing); } glEnd(); glPopMatrix(); //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX //draw health bar:------------------------------ float hpbarwidth=26.0f*scale; float hpbarheight=160.0f*scale; glPushMatrix(); glTranslatef(viewportwidth-20.0f*scale-hpbarwidth,20.0f*scale,0); glColor4f(1-targetplayer->hp,0.0f,targetplayer->hp,0.8f); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); glVertex2f(0.0f,0.0f); glVertex2f(hpbarwidth,0.0f); glVertex2f(hpbarwidth,targetplayer->hp*hpbarheight); glVertex2f(0.0f,targetplayer->hp*hpbarheight); glEnd(); glColor4f(1.0f,1.0f,1.0f,0.4f); glBegin(GL_LINES); glVertex2f(0.0f,0.0f); glVertex2f(hpbarwidth,0.0f); glVertex2f(hpbarwidth,hpbarheight); glVertex2f(0.0f,hpbarheight); glVertex2f(hpbarwidth,0.0f); glVertex2f(hpbarwidth,hpbarheight); glVertex2f(0.0f,0.0f); glVertex2f(0.0f,hpbarheight); glEnd(); glEnable(GL_TEXTURE_2D); glPopMatrix(); //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX SDL_Surface* text; SDL_Color color = {255,255,255,0}; GLfloat texcoords[4]; int gltex; char str[128]; //draw score counter: if(scorefont){ //enjoy the segfault if you try and render text with an invalid font pointer glPushMatrix(); glTranslatef(10.0f*scale,viewportheight-40.0f*scale,0.0f); sprintf(str,"Score: %d",visual->score); text=TTF_RenderText_Blended(scorefont,str,color); gltex=visual->SDL_GL_LoadTexture(text,texcoords); scale=(float)viewportheight/600.0f; glDisable(GL_TEXTURE_2D); glColor4f(0.0f,0.0f,0.0f,0.5f); glBegin(GL_QUADS); glVertex2f(0.0f,text->h*scale); glVertex2f(0.0f,0.0f); glVertex2f(text->w*scale,0.0f); glVertex2f(text->w*scale,text->h*scale); glEnd(); glEnable(GL_TEXTURE_2D); glColor4f(1.0f,0.0f,0.0f,0.6f+0.4f*((visual->game->score-visual->score)/50.0f)); glBegin(GL_QUADS); glTexCoord2f(texcoords[0],texcoords[1]); glVertex2f(0.0f,text->h*scale); glTexCoord2f(texcoords[0],texcoords[3]); glVertex2f(0.0f,0.0f); glTexCoord2f(texcoords[2],texcoords[3]); glVertex2f(text->w*scale,0.0f); glTexCoord2f(texcoords[2],texcoords[1]); glVertex2f(text->w*scale,text->h*scale); glEnd(); SDL_FreeSurface(text); glDeleteTextures(1,(GLuint*)&gltex); glPopMatrix(); //Draw messages as appropriate glPushMatrix(); if(!targetplayer->alive && targetplayer->lives){ if(visual->game->player->SafeToRespawn()){ text=TTF_RenderText_Blended(scorefont,"Press Return to Respawn",color); } else{ text=TTF_RenderText_Blended(scorefont,"Wait...",color); glColor4f(1.0f,0.0f,0.0f,0.7f); } } else if(messagetimer>0.0f){ messagetimer-=visual->game->dtf; text=TTF_RenderText_Blended(scorefont,message.c_str(),color); glColor4f(1.0f,0.0f,0.0f,0.1f+0.9f*(messagetimer/messagetimermax)); } else text=NULL; if(text){ gltex=visual->SDL_GL_LoadTexture(text,texcoords); glTranslatef(viewportwidth/2-text->w*scale/2,viewportheight/2-text->h*scale/2,0.0f); glBegin(GL_QUADS); glTexCoord2f(texcoords[0],texcoords[1]); glVertex3f(0.0f,text->h*scale,0.0f); glTexCoord2f(texcoords[0],texcoords[3]); glVertex3f(0.0f,0.0f,0.0f); glTexCoord2f(texcoords[2],texcoords[3]); glVertex3f(text->w*scale,0.0f,0.0f); glTexCoord2f(texcoords[2],texcoords[1]); glVertex3f(text->w*scale,text->h*scale,0.0f); glEnd(); SDL_FreeSurface(text); glDeleteTextures(1,(GLuint*)&gltex); } glPopMatrix(); //Draw fps reading if(GLOB_conf.drawfps){ glPushMatrix(); glColor4f(0.0f,1.0f,0.0f,0.7f); sprintf(str,"%.0f",1000.0f/visual->game->dtf); text=TTF_RenderText_Blended(scorefont,str,color); gltex=visual->SDL_GL_LoadTexture(text,texcoords); glTranslatef(viewportwidth-text->w,viewportheight-text->h,0.0f); glBegin(GL_QUADS); glTexCoord2f(texcoords[0],texcoords[1]); glVertex3f(0.0f,text->h,0.0f); glTexCoord2f(texcoords[0],texcoords[3]); glVertex3f(0.0f,0.0f,0.0f); glTexCoord2f(texcoords[2],texcoords[3]); glVertex3f(text->w,0.0f,0.0f); glTexCoord2f(texcoords[2],texcoords[1]); glVertex3f(text->w,text->h,0.0f); glEnd(); SDL_FreeSurface(text); glDeleteTextures(1,(GLuint*)&gltex); glPopMatrix(); } } //draw radar GLUquadric* quadr; float compx,compy,complen; complen=viewportheight*0.12f; compx=viewportwidth-complen*1.1f; compy=viewportheight*0.87f; quadr=gluNewQuadric(); glPushMatrix(); glTranslatef(compx,compy,0); glColor4f(0.1f,0.3f,0.1f,0.8f); gluDisk(quadr,0,complen,40,2); glColor4f(0.0f,0.3f,0.0f,0.3f); gluDisk(quadr,complen,complen+2,40,2); glColor4f(0.0f,0.3f,0.0f,0.2f); gluDisk(quadr,complen+2,complen+3,40,2); glColor4f(0.0f,0.3f,0.0f,0.1f); gluDisk(quadr,complen+3,complen+4,40,2); glRotatef(-visual->game->player->bear*180/M_PI,0,0,1); glColor4f(0.3f,0.5f,0.3f,0.5f); glBegin(GL_LINES); glVertex2f(complen,0.0f); glVertex2f(-complen,0.0f); glVertex2f(0.0f,complen); glVertex2f(0.0f,-complen); glEnd(); glColor4f(0.3f,0.5f,0.3f,0.9f); glLineWidth(2.0f); glBegin(GL_LINES); glVertex2f(0.0f,complen); glVertex2f(0.0f,0.0); glEnd(); glLineWidth(1.0f); LListItem* ufo_item; LListItem* powerup_item; Vector relpos; Vector arrowarm; //float theta; glPointSize(2.0f); for(ufo_item=visual->game->ufolist->head;ufo_item;ufo_item=ufo_item->next){ relpos=visual->game->player->s-ufo_item->data.s; relpos.z*=-1.0f; //account for ogl coordinate sys relpos.y=0.0f; if(relpos.Mag2()game->player->radarrange* visual->game->player->radarrange){ relpos*=complen/visual->game->player->radarrange; glColor4f(1.0f,0.0f,0.0f,1.0f); glBegin(GL_POINTS); glVertex2f(relpos.x,relpos.z); glEnd(); } else{ relpos.Unitize(); relpos*=complen; arrowarm.Set3f(0.0f,1.0f,0.0f); arrowarm=arrowarm^relpos; arrowarm.Unitize(); arrowarm*=complen*0.08f; glColor4f(0.6f,0.0f,0.0f,1.0f); glLineWidth(2.0f); glBegin(GL_LINES); glVertex2f(relpos.x,relpos.z); glVertex2f(relpos.x-arrowarm.x,relpos.z-arrowarm.z); glVertex2f(relpos.x,relpos.z); glVertex2f(relpos.x+arrowarm.x,relpos.z+arrowarm.z); glEnd(); /* relpos.Unitize(); relpos*=complen; theta=atan(relpos.z/relpos.x); arrowarm.x=5.0f*cos(theta+3.14*0.3f); arrowarm.z=5.0f*sin(theta+3.14*0.3f); glColor4f(0.6f,0.0f,0.0f,1.0f); glBegin(GL_LINES); glVertex2f(relpos.x,relpos.z); glVertex2f(relpos.x-arrowarm.x,relpos.z-arrowarm.z); glEnd(); arrowarm.x=5.0f*cos(theta-3.14*0.3f); arrowarm.z=5.0f*sin(theta-3.14*0.3f); glBegin(GL_LINES); glVertex2f(relpos.x,relpos.z); glVertex2f(relpos.x-arrowarm.x,relpos.z-arrowarm.z); glEnd();*/ } } for(powerup_item=visual->game->poweruplist->head;powerup_item;powerup_item=powerup_item->next){ relpos=visual->game->player->s-powerup_item->data.s; relpos.z*=-1.0f; //account for ogl coordinate sys relpos.y=0.0f; if(relpos.Mag2()game->player->radarrange* visual->game->player->radarrange){ relpos*=complen/visual->game->player->radarrange; if(powerup_item->data.nature==POWERUP_LIFE) glColor4f(1.0f,0.0f,1.0f,1.0f); else glColor4f(0.8f,0.8f,1.0f,1.0f); glBegin(GL_POINTS); glVertex2f(relpos.x,relpos.z); glEnd(); } else{ relpos.Unitize(); relpos*=complen; arrowarm.Set3f(0.0f,1.0f,0.0f); arrowarm=arrowarm^relpos; arrowarm.Unitize(); arrowarm*=5.0f; if(powerup_item->data.nature==POWERUP_LIFE) glColor4f(1.0f,0.0f,1.0f,1.0f); else glColor4f(0.8f,0.8f,1.0f,1.0f); glLineWidth(2.0f); glBegin(GL_LINES); glVertex2f(relpos.x,relpos.z); glVertex2f(relpos.x-arrowarm.x,relpos.z-arrowarm.z); glVertex2f(relpos.x,relpos.z); glVertex2f(relpos.x+arrowarm.x,relpos.z+arrowarm.z); glEnd(); } } glPopMatrix(); gluDeleteQuadric(quadr); //finish up: glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); } void Camera::DrawUfo(Ufo* ufo) { glPushMatrix(); glTranslatef(ufo->s.x,ufo->s.y,ufo->s.z); glRotatef((ufo->bear/M_PI)*180.0f,0.0f,1.0f,0.0f); glScalef(1-ufo->spawneffect/ufo->maxspawneffect,1-ufo->spawneffect/ufo->maxspawneffect,1-ufo->spawneffect/ufo->maxspawneffect); visual->DrawMesh("ufo.mesh"); glPopMatrix(); } void Camera::DrawMine(Mine* mine) { float spawnfrac=mine->spawneffect/mine->maxspawneffect; glPushMatrix(); glTranslatef(mine->s.x,mine->s.y,mine->s.z); glRotatef((mine->spin/M_PI)*180.0f,0.0f,1.0f,0.0f); glScalef(1-spawnfrac,1-spawnfrac,1-spawnfrac); visual->DrawMesh("mine.mesh"); glPopMatrix(); } void Camera::DrawPowerUp(PowerUp* powerup) { GLUquadricObj *quad; float scalefactor; glPushMatrix(); visual->UseTexture("powerupshell.png"); glColor4f(1.0f,1.0f,1.0f,1.0f); glTranslatef(powerup->s.x,powerup->s.y+sin(powerup->bouncecycle)*0.3f,powerup->s.z); glRotatef(powerup->spincycle*(180.0f/M_PI),0.0f,1.0f,0.0f); scalefactor=1-powerup->spawneffect/powerup->maxspawneffect; glScalef(scalefactor,scalefactor,scalefactor); glLineWidth(4.0f); if(powerup->nature==POWERUP_TRIPLESHOT){ glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); glVertex3f(0.0f,-1.25f,0.0f); glVertex3f(0.0f,1.25f,0.0f); glVertex3f(0.0f,-1.25f,0.0f); glVertex3f(0.0f,1.25f,1.5f); glVertex3f(0.0f,-1.25f,0.0f); glVertex3f(0.0f,1.25f,-1.5f); glEnd(); glEnable(GL_TEXTURE_2D); } if(powerup->nature==POWERUP_GUIDANCE){ glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); glVertex3f(0.0f,-1.25f,0.0f); glVertex3f(0.0f,1.25f,0.0f); glVertex3f(0.0f,1.25f,0.0f); glVertex3f(0.0f,1.25f,1.5f); glEnd(); glEnable(GL_TEXTURE_2D); } if(powerup->nature==POWERUP_LIFE){ glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); glVertex3f(0.0f,-1.5f,0.0f); glVertex3f(0.0f,1.5f,0.0f); glVertex3f(0.0f,0.0f,1.5f); glVertex3f(0.0f,0.0f,-1.5f); glEnd(); glEnable(GL_TEXTURE_2D); } if(powerup->nature==POWERUP_SUPERSHIELD){ glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); glVertex3f(0.0f,-1.5f,-1.5f); glVertex3f(0.0f,1.5f,-1.5f); glVertex3f(0.0f,1.5f,1.5f); glVertex3f(0.0f,-1.5f,1.5f); glEnd(); glEnable(GL_TEXTURE_2D); } quad=gluNewQuadric(); gluQuadricNormals(quad,GL_SMOOTH); gluQuadricTexture(quad,GL_TRUE); gluSphere(quad,3,10,10); gluDeleteQuadric(quad); glPopMatrix(); } void Camera::DrawObstacle(Obstacle* obstacle) { /* Quad* quad; quad=visual->game->arena->GetLastQuad(); if(quad){ glDisable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); glColor4f(0.0f,1.0f,0.0f,1.0f); glBegin(GL_QUADS); glNormal3f(quad->n.x,quad->n.y,quad->n.z); glTexCoord2f(0.0f,0.0f); glVertex3f(quad->v1.x,quad->v1.y,quad->v1.z); glTexCoord2f(0.0f,1.0f); glVertex3f(quad->v2.x,quad->v2.y,quad->v2.z); glTexCoord2f(1.0f,1.0f); glVertex3f(quad->v3.x,quad->v3.y,quad->v3.z); glTexCoord2f(1.0f,0.0f); glVertex3f(quad->v4.x,quad->v4.y,quad->v4.z); glEnd(); glEnable(GL_TEXTURE_2D); glEnable(GL_CULL_FACE); }*/ glPushMatrix(); glTranslatef(obstacle->s.x,obstacle->s.y,obstacle->s.z); //glLineWidth(5.0f); glColor4f(1.0f,1.0f,1.0f,1.0f); visual->UseTexture("skyscraper.png"); glBegin(GL_QUADS); glNormal3f(0.0f,0.0f,-1.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(0.0f,0.0f,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(0.0f,obstacle->w.y,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(obstacle->w.x,obstacle->w.y,0.0f); glTexCoord2f(1.0f,0.0f); glVertex3f(obstacle->w.x,0.0f,0.0f); glNormal3f(0.0f,0.0f,1.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(0.0f,0.0f,obstacle->w.z); glTexCoord2f(1.0f,0.0f); glVertex3f(obstacle->w.x,0.0f,obstacle->w.z); glTexCoord2f(1.0f,1.0f); glVertex3f(obstacle->w.x,obstacle->w.y,obstacle->w.z); glTexCoord2f(0.0f,1.0f); glVertex3f(0.0f,obstacle->w.y,obstacle->w.z); glNormal3f(-1.0f,0.0f,0.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(0.0f,0.0f,0.0f); glTexCoord2f(1.0f,0.0f); glVertex3f(0.0f,0.0f,obstacle->w.z); glTexCoord2f(1.0f,1.0f); glVertex3f(0.0f,obstacle->w.y,obstacle->w.z); glTexCoord2f(0.0f,1.0f); glVertex3f(0.0f,obstacle->w.y,0.0f); glNormal3f(1.0f,0.0f,0.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(obstacle->w.x,0.0f,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(obstacle->w.x,obstacle->w.y,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(obstacle->w.x,obstacle->w.y,obstacle->w.z); glTexCoord2f(1.0f,0.0f); glVertex3f(obstacle->w.x,0.0f,obstacle->w.z); glEnd(); glDisable(GL_TEXTURE_2D); glColor4f(1.0f,1.0f,1.0f,1.0f); glBegin(GL_QUADS); glNormal3f(0.0f,1.0f,0.0f); glTexCoord2f(0.0f,0.0f); glVertex3f(0.0f,obstacle->w.y,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(0.0f,obstacle->w.y,obstacle->w.z); glTexCoord2f(1.0f,1.0f); glVertex3f(obstacle->w.x,obstacle->w.y,obstacle->w.z); glTexCoord2f(1.0f,0.0f); glVertex3f(obstacle->w.x,obstacle->w.y,0.0f); glEnd(); glEnable(GL_TEXTURE_2D); glPopMatrix(); } void Camera::SetMessage(string newmessage) { message=newmessage; messagetimer=messagetimermax; } void Camera::DrawSprite(Vector s_sprite,float radius,float spin) { glPushMatrix(); glTranslatef(s_sprite.x,s_sprite.y,s_sprite.z); glRotatef((bear/M_PI)*180,0.0f,1.0f,0.0f); glRotatef(-(pitch/M_PI)*180,1.0f,0.0f,0.0f); glRotatef(spin,0.0f,0.0f,1.0f); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(-radius,-radius,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(-radius,radius,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(radius,radius,0.0f); glTexCoord2f(1.0f,0.0f); glVertex3f(radius,-radius,0.0f); glEnd(); glPopMatrix(); } void Camera::DrawAxisSprite(Vector p1,Vector p2,float radius) { Vector v_=p1-p2; Vector h=PerpLinePoint(p1,p2,s); Vector d=h-s; d.Unitize(); Vector v1,v2,v3,v4; v1=-d*radius; v2=d*radius; v3=-v_+d*radius; v4=-v_-d*radius; glPushMatrix(); glTranslatef(p1.x,p1.y,p1.z); glRotatef(90.0f,v_.x,v_.y,v_.z); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(v1.x,v1.y,v1.z); glTexCoord2f(1.0f,0.0f); glVertex3f(v2.x,v2.y,v2.z); glTexCoord2f(1.0f,1.0f); glVertex3f(v3.x,v3.y,v3.z); glTexCoord2f(0.0f,1.0f); glVertex3f(v4.x,v4.y,v4.z); glEnd(); glPopMatrix(); }