/* Copyright (C) 2000 Xavier Hosxe 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 */ #include #include #include "tank.hpp" #include "scene.hpp" #include "fire.hpp" int Tank::numberOfTanks_=0; int Tank::m_nBigCubeList; int Tank::m_nLittleCubeList; Tank::Tank(List *list, int x, int shield) : Sprite(list,TYPE_TANK ,x,.5,70) { state_=NORMAL; sizex_ = 1.2; sizey_ = 1; sizez_ = 1.2; tetay1_=0; tetay2_=-90; shield_ = shield; chaine1_=0; chaine2_=0; numberOfTanks_++; bRealEnemy=true; // printf("numberOfTanks_ %d\n", numberOfTanks_); } Tank::~Tank() { numberOfTanks_--; // printf("numberOfTanks-- = %d\n", numberOfTanks_); } void Tank::drawShadowable() { glDisable(GL_CULL_FACE); glPushMatrix(); glTranslatef(x_,y_,z_); glRotatef(tetay1_,0,1,0); glTranslatef(0,-y_,0); glBegin(GL_TRIANGLE_STRIP); { glNormal3f(0,0,-1); glTexCoord2f(0, 0+chaine1_); glVertex3f(.3 , .2 , -.6); glTexCoord2f(.5, 0+chaine1_); glVertex3f(.6, .2, -.6); glTexCoord2f(0,1+chaine1_); glVertex3f(.3 , 0.02 , -.6); glTexCoord2f(.5, 1+chaine1_); glVertex3f(.6, 0.02, -.6); glNormal3f(0,-1,0); glTexCoord2f(0, 6+chaine1_); glVertex3f(.3 , 0.02 , .6); glTexCoord2f(.5, 6+chaine1_); glVertex3f(.6, 0.02, .6); glNormal3f(0,0,1); glTexCoord2f(0, 7+chaine1_); glVertex3f(.3 , .2 , .6); glTexCoord2f(.5, 7+chaine1_); glVertex3f(.6, .2, .6); glNormal3f(0,1,0); glTexCoord2f(0, 13+chaine1_); glVertex3f(.3 , .2 , -.6); glTexCoord2f(.5, 13+chaine1_); glVertex3f(.6, .2, -.6); } glEnd(); glBegin(GL_TRIANGLE_STRIP); { glNormal3f(0,0,-1); glTexCoord2f(0, 0+chaine2_); glVertex3f(-.3 , .2 , -.6); glTexCoord2f(.5, 0+chaine2_); glVertex3f(-.6, .2, -.6); glTexCoord2f(0,1+chaine2_); glVertex3f(-.3 , 0.02 , -.6); glTexCoord2f(.5, 1+chaine2_); glVertex3f(-.6, 0.02, -.6); glNormal3f(0,-1,0); glTexCoord2f(0, 6+chaine2_); glVertex3f(-.3 , 0.02 , .6); glTexCoord2f(.5, 6+chaine2_); glVertex3f(-.6, 0.02, .6); glNormal3f(0,0,1); glTexCoord2f(0, 7+chaine2_); glVertex3f(-.3 , .2 , .6); glTexCoord2f(.5, 7+chaine2_); glVertex3f(-.6, .2, .6); glNormal3f(0,1,0); glTexCoord2f(0, 13+chaine2_); glVertex3f(-.3 , .2 , -.6); glTexCoord2f(.5, 13+chaine2_); glVertex3f(-.6, .2, -.6); } glEnd(); glTranslatef(0,+.2,0); /* =========== Gros cube ============ */ glCallList(m_nBigCubeList); /* ========= petit cube ============= */ glTranslatef(0,.5,0); glRotatef(tetay2_+90,0,1,0); glCallList(m_nLittleCubeList); /* ============ CANON ============== */ glBegin(GL_QUAD_STRIP); { glVertex3f(.05,.05,-.2); glVertex3f(.05,.05,-1); glVertex3f(-.05,.05,-.2); glVertex3f(-.05,.05,-1); glVertex3f(-.05,-.05,-.2); glVertex3f(-.05,-.05,-1); glVertex3f(.05,-.05,-.2); glVertex3f(.05,-.05,-1); glVertex3f(.05,.05,-.2); glVertex3f(.05,.05,-1); } glEnd(); glPopMatrix(); glEnable(GL_CULL_FACE); } void Tank::draw() { glDisable(GL_CULL_FACE); glPushMatrix(); glTranslatef(x_,y_,z_); glRotatef(tetay1_,0,1,0); glTranslatef(0,-y_,0); glBindTexture(GL_TEXTURE_2D, GLvar->texture_chaine); glBegin(GL_TRIANGLE_STRIP); { glNormal3f(0,0,-1); glTexCoord2f(0, 0+chaine1_); glVertex3f(.3 , .2 , -.6); glTexCoord2f(.5, 0+chaine1_); glVertex3f(.6, .2, -.6); glTexCoord2f(0,1+chaine1_); glVertex3f(.3 , 0.02 , -.6); glTexCoord2f(.5, 1+chaine1_); glVertex3f(.6, 0.02, -.6); glNormal3f(0,-1,0); glTexCoord2f(0, 6+chaine1_); glVertex3f(.3 , 0.02 , .6); glTexCoord2f(.5, 6+chaine1_); glVertex3f(.6, 0.02, .6); glNormal3f(0,0,1); glTexCoord2f(0, 7+chaine1_); glVertex3f(.3 , .2 , .6); glTexCoord2f(.5, 7+chaine1_); glVertex3f(.6, .2, .6); glNormal3f(0,1,0); glTexCoord2f(0, 13+chaine1_); glVertex3f(.3 , .2 , -.6); glTexCoord2f(.5, 13+chaine1_); glVertex3f(.6, .2, -.6); } glEnd(); glBegin(GL_TRIANGLE_STRIP); { glNormal3f(0,0,-1); glTexCoord2f(0, 0+chaine2_); glVertex3f(-.3 , .2 , -.6); glTexCoord2f(.5, 0+chaine2_); glVertex3f(-.6, .2, -.6); glTexCoord2f(0,1+chaine2_); glVertex3f(-.3 , 0.02 , -.6); glTexCoord2f(.5, 1+chaine2_); glVertex3f(-.6, 0.02, -.6); glNormal3f(0,-1,0); glTexCoord2f(0, 6+chaine2_); glVertex3f(-.3 , 0.02 , .6); glTexCoord2f(.5, 6+chaine2_); glVertex3f(-.6, 0.02, .6); glNormal3f(0,0,1); glTexCoord2f(0, 7+chaine2_); glVertex3f(-.3 , .2 , .6); glTexCoord2f(.5, 7+chaine2_); glVertex3f(-.6, .2, .6); glNormal3f(0,1,0); glTexCoord2f(0, 13+chaine2_); glVertex3f(-.3 , .2 , -.6); glTexCoord2f(.5, 13+chaine2_); glVertex3f(-.6, .2, -.6); } glEnd(); glBindTexture(GL_TEXTURE_2D, GLvar->texture_camouflage); glTranslatef(0,+.2,0); /* =========== Gros cube ============ */ glColor3f(1,1,1); glCallList(m_nBigCubeList); glTranslatef(0,.5,0); glRotatef(tetay2_+90,0,1,0); glCallList(m_nLittleCubeList); /* ========= petit cube ============= */ glDisable(GL_TEXTURE_2D); /* ============ CANON ============== */ glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,GLvar->bleu_diffuse); glBegin(GL_QUAD_STRIP); { glVertex3f(.05,.05,-.2); glVertex3f(.05,.05,-1); glVertex3f(-.05,.05,-.2); glVertex3f(-.05,.05,-1); glVertex3f(-.05,-.05,-.2); glVertex3f(-.05,-.05,-1); glVertex3f(.05,-.05,-.2); glVertex3f(.05,-.05,-1); glVertex3f(.05,.05,-.2); glVertex3f(.05,.05,-1); } glEnd(); glPopMatrix(); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,GLvar->blanc_diffuse); } void Tank::move() { switch(state_) { case NORMAL: dz_=-.1; if (z_<4) { dz_ = (float)(random()%2)/100+.01; state_ = MOVING; } /* if ((GLvar->myRandom(200)) || (z_<0)) { state_ = TURNING; } */ if (GLvar->myRandom(300)) { // printf("0x%x NORMAL->PREPARE_SHOT\n", this); state_ = PREPARE_SHOOT; } break; case PREPARE_SHOOT: { float pos; Sprite *current; toShot = NULL; if (mlist->mfirst) { current=(Sprite*)mlist->mfirst; do { if (((Sprite *)mlist->mcurrent)->getType()==TYPE_MY_SPACE_SHIP) toShot = (Sprite *)mlist->mcurrent; break; current = (Sprite*)current->GetNext(); } while (current!=NULL); } if (toShot==NULL) { state_=NORMAL; break; } // printf("0x%x PREPARE_SHOT->TURNING_TOURELLE\n", this); state_ = TURNING_TOURELLE; if ((toShot->getX() - x_) != 0.0) { float DX = (-toShot->getX() + x_)>0?(-toShot->getX() + x_):-(-toShot->getX() + x_); float DZ = (toShot->getZ() - z_)>0?(toShot->getZ() - z_):-(toShot->getZ() - z_); tetay2_goal = (atan(DZ/DX))/6.2831852*360; if (-toShot->getX() < -x_) { tetay2_goal = 180-tetay2_goal; } if (toShot->getZ() < z_) { tetay2_goal = -tetay2_goal; } } else { if (toShot->getZ() > z_) tetay2_goal = 90; else tetay2_goal = -90; } pos = tetay2_- tetay2_goal; if (pos<0) { pos+=360; } if (pos>180) dtetay2_ = 3.5*GLvar->global_timeadjustment; else dtetay2_ = -3.5*GLvar->global_timeadjustment; } break; case MOVING: /* if (dz_ == 0) { dz_ = (float)(random()%2)/100+.01; }*/ if (GLvar->myRandom(100) || (z_>65)) { state_=NORMAL; } break; case TURNING: dz_=0; tetay1_ +=5; if ((GLvar->myRandom(60)) || (z_<7)) { state_=MOVING; } break; case TURNING_TOURELLE: dz_=0; if (abs((int)(tetay2_-tetay2_goal)) < 2.5* GLvar->global_timeadjustment) { // printf("0x%x TURNING_TOURELLE->SHOOTING\n", this); state_=SHOOTING; cpt_=0; } else { tetay2_ += dtetay2_; if (tetay2_> 180) tetay2_-=360; if (tetay2_< -180) tetay2_+=360; } break; case SHOOTING: cpt_+=GLvar->global_timeadjustment; if (cpt_>10) { // printf("0x%x SHOOTING !!!!!!!!!!\n", this); TankFire *newFire; float dirx; float dirz; tetay2_ = tetay2_goal; dirx = -cos(tetay2_/360*6.2831852)/5; dirz = sin(tetay2_/360*6.2831852)/5; x_-=dirx; if (x_>11) { x_=11; } if (x_<-11) { x_=-11; } z_-=dirz; newFire= new TankFire(mlist,this,x_+dirx*6,.7,z_+dirz*6,dirx,dirz,tetay2_); mlist->Add(newFire); dz_=0; state_=MOVING; // printf("0x%x SHOOTING->MOOVING\n", this); } break; } chaine1_ += (dz_+.05)*GLvar->global_timeadjustment*1.4; if (chaine1_>1) chaine1_-=1; chaine2_ += (dz_+.05)*GLvar->global_timeadjustment*1.4; if (chaine2_>1) chaine2_-=1; Sprite::move(); } void Tank::collision(Sprite*contact) { static Explosion * explode; switch(contact->getType()) { case TYPE_MY_FIRE2: shield_ = 0; case TYPE_MY_FIRE4: shield_-=2; case TYPE_MY_FIRE1: case TYPE_SPIRALE: case TYPE_MY_SPACE_SHIP: { shield_--; if ((shield_<=0) && (dead_==0)) { explode = new Explosion(this,8); mlist->Add(explode); contact->score(400); dead_=1; } else { if (state_ != SHOOTING && state_ != PREPARE_SHOOT) { state_ = PREPARE_SHOOT; // printf("0x%x AOUCH!!!!!!!! ->PREPARE_SHOOTING\n", this); } } break; } case TYPE_TANK: float tx = ((x_-contact->getX()) / ((sizex_ + contact->getSizeX())/2)) ; float tz = ((z_-contact->getZ()) / ((sizez_ + contact->getSizeZ())/2)) ; x_ += tx/2; z_ += tz/2; break; } } void Tank::initList() { m_nBigCubeList = scene->createCube(.6); m_nLittleCubeList = scene->createCube(.5); } /* +================================+ | TankFire | +================================+ */ TankFire::TankFire(List *list, Tank *tank, float x, float y, float z,float dx, float dz,float rotated) : Sprite(list,TYPE_FIRE_TANK ,x,y,z) { sizez_=.2; sizey_=.2; sizex_=.2; dx_=dx*1.2; dz_=dz*1.2; tetay_=0; rotated_ = rotated; } void TankFire::drawShadowable() { glPushMatrix(); glTranslatef(x_,y_,z_); glRotatef(rotated_,0,1,0); glBegin(GL_TRIANGLE_FAN); { glVertex3f(-.1,0,0); glVertex3f(.6+(float)(random()%128)/256.0,.1,0); glVertex3f(.4,0,.1); glVertex3f(.6+(float)(random()%128)/256.0,-.1,0); glVertex3f(.4,-.1,0); glVertex3f(.6+(float)(random()%128)/256.0,0,-.1); glVertex3f(.4,.1,0); } glEnd(); glPopMatrix(); } void TankFire::draw() { glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glPushMatrix(); glTranslatef(x_,y_,z_); glRotatef(rotated_,0,1,0); glBegin(GL_TRIANGLE_FAN); glColor4f(1,1,1,1); glVertex3f(-.1,0,0); glColor4f(.8,.5,0,.3); glVertex3f(.6+(float)(random()%128)/256.0,.1,0); glVertex3f(.4,0,.1); glVertex3f(.6+(float)(random()%128)/256.0,-.1,0); glVertex3f(.4,-.1,0); glVertex3f(.6+(float)(random()%128)/256.0,0,-.1); glVertex3f(.4,.1,0); glEnd(); glPopMatrix(); glDisable(GL_BLEND); glEnable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glColor4f(1,1,1,1); } void TankFire::move() { Sprite::move(); tetay_ +=(5*GLvar->global_timeadjustment)>20?20:(10*GLvar->global_timeadjustment); if (tetay_>90) tetay_-=90; if ((z_<0) || (z_>70) || (x_<-11.8) || (x_>11.8)) { dead_=1; } } void TankFire::collision(Sprite*contact) { switch(contact->getType()) { case TYPE_MY_FIRE2: case TYPE_MY_FIRE1: { Explosion *explode; explode= new Explosion(this,2,1,0); mlist->Add(explode); dead_=1; break; } case TYPE_MY_SPACE_SHIP: Explosion *explode; explode= new Explosion(this,2,1,0); mlist->Add(explode); dead_=1; break; } }