physics.cpp

Go to the documentation of this file.
00001 
00002 //
00003 // Das Tank - Copyright (C) 2006, 2007 Windsor Schmidt <windsor@windsorworld.net>
00004 //
00005 // This program is free software; you can redistribute it and/or modify it
00006 // under the terms of the GNU General Public License as published by the Free
00007 // Software Foundation; either version 2 of the License, or (at your option)
00008 // any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful, but WITHOUT
00011 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
00013 // more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along with
00016 // this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017 // Place, Suite 330, Boston, MA 02111-1307 USA
00018 //
00020 
00021 
00022 #ifndef STDAFX
00023 #include "stdafx.h"
00024 #endif
00025 
00026 
00033 void PhysicsUpdate(CWorld * ThisWorld)
00034 {
00035        Vector vTemp(0,0,0);
00036 
00037        // we'll be using a couple of object pointers for loops / comparison frequently here, so use these:
00038        CObject * Current = ThisWorld->Objects;
00039        CObject * Other = ThisWorld->Objects;
00040 
00041        // save the object positions
00042        while(Current != NULL)
00043        {
00044               Current->OldPosition = Current->Position; // save last position in case we need to move back
00045 
00046               Current = Current->Next;
00047        }
00048 
00050        // handle input from player(s)
00052        static int iX;
00053        for(iX = 0; iX < NUM_PLAYERS; iX++)
00054        {
00055               // only fire if the player doesn't own any other objects
00056               if(ThisWorld->Player[iX]->iInput[INPUT_FIRE] == true && ThisWorld->Player[iX]->iOwnCount == 0)
00057               {
00058                      GameLogicFire(ThisWorld->Player[iX]);
00059                      ThisWorld->Player[iX]->iInput[INPUT_FIRE] = false;
00060               }
00061 
00062               if(ThisWorld->Player[iX]->iInput[INPUT_LEFT] == true)
00063               {
00064                      ThisWorld->Player[iX]->fAngle += 2;
00065                      ThisWorld->Player[iX]->fSubAngle += 2; // rotate turret also
00066               }
00067 
00068               if(ThisWorld->Player[iX]->iInput[INPUT_RIGHT] == true)
00069               {
00070                      ThisWorld->Player[iX]->fAngle -= 2;
00071                      ThisWorld->Player[iX]->fSubAngle -= 2; // rotate turret also
00072               }
00073 
00074               if(ThisWorld->Player[iX]->iInput[INPUT_UP] == true)
00075               {
00076                      vTemp.x = 0.002;
00077                      vTemp.y = 0.0;
00078                      ThisWorld->Player[iX]->Velocity += VRotate2D(DegreesToRadians(ThisWorld->Player[iX]->fAngle),vTemp);
00079               }
00080 
00081               if(ThisWorld->Player[iX]->iInput[INPUT_DOWN] == true)
00082               {
00083                      vTemp.x = 0.002;
00084                      vTemp.y = 0.0;
00085                      ThisWorld->Player[iX]->Velocity -= VRotate2D(DegreesToRadians(ThisWorld->Player[iX]->fAngle),vTemp);
00086               }
00087        }
00088 
00090        // update position of world objects
00092        Current = ThisWorld->Objects;
00093        while(Current != NULL)
00094        {
00095               UpdateBody(Current, .1);
00096 
00097               // move object based on velocity **THIS IS A HACK - FIX ME**
00098               Current->Position.x += Current->Velocity.x;
00099               Current->Position.y += Current->Velocity.y;
00100 
00101               // bounce objects as they hit the playfield bounds **THIS IS A HACK - FIX ME**
00102               if(Current->Position.x + Current->fBBLeft < 0) // left wall
00103               {
00104                      Current->Position.x = Current->fBBRight;
00105                      Current->Velocity.x = Current->Velocity.x * -1;
00106                      if(Current->iType != TYPEID_TANK) PlaySound(SOUNDID_REFLECT); // play a sound effect
00107               }
00108 
00109               if(Current->Position.x + Current->fBBRight > PLAYFIELD_SIZE) // right wall
00110               {
00111                      Current->Position.x = PLAYFIELD_SIZE + Current->fBBLeft;
00112                      Current->Velocity.x = Current->Velocity.x * -1;
00113                      if(Current->iType != TYPEID_TANK) PlaySound(SOUNDID_REFLECT); // play a sound effect
00114               }
00115 
00116               if(Current->Position.y  + Current->fBBBottom < 0) // bottom wall
00117               {
00118                      Current->Position.y = Current->fBBTop;
00119                      Current->Velocity.y = Current->Velocity.y * -1;
00120                      if(Current->iType != TYPEID_TANK) PlaySound(SOUNDID_REFLECT); // play a sound effect
00121               }
00122 
00123               if(Current->Position.y + Current->fBBTop > PLAYFIELD_SIZE) // top wall
00124               {
00125                      Current->Position.y = PLAYFIELD_SIZE + Current->fBBBottom;
00126                      Current->Velocity.y = Current->Velocity.y * -1;
00127                      if(Current->iType != TYPEID_TANK) PlaySound(SOUNDID_REFLECT); // play a sound effect
00128               }
00129 
00130               Current = Current->Next; // traverse the list to operate on the next object
00131        }
00132 }
00133 
00134 
00141 void PhysicsDampedCollision(CObject * ObjA, CObject * ObjB)
00142 {
00143 }
00144 
00145 
00152 void PhysicsElasticCollision(CObject * ObjA, CObject * ObjB)
00153 {
00154 }
00155 
00156 
00162 void PhysicsStop(CObject * ObjA, CObject * ObjB)
00163 {
00164        int biteX, biteY; // X and Y delta of the object's positions. reflect whichever is greater
00165        biteX = biteY = 0;
00166 
00167        if(ObjA->Velocity.x < 0) // ObjA going left
00168        {
00169               biteX = ObjA->Position.x - ObjB->Position.x;
00170        }
00171        
00172        if(ObjA->Velocity.x > 0) // ObjA going right
00173        {
00174               biteX = ObjB->Position.x - ObjA->Position.x;
00175        }
00176        
00177        if(ObjA->Velocity.y > 0) // ObjA going up
00178        {
00179               biteY = ObjB->Position.y - ObjA->Position.y;
00180        }
00181        
00182        if(ObjA->Velocity.y < 0) // ObjA going down
00183        {
00184               biteY = ObjA->Position.y - ObjB->Position.y;
00185        }
00186 
00187        if(biteX >= biteY)
00188        {
00189               ObjA->Velocity.x = 0;
00190               ObjA->Position.x = ObjA->OldPosition.x;
00191               return;
00192        }
00193        else
00194        {
00195               ObjA->Velocity.y = 0;
00196               ObjA->Position.y = ObjA->OldPosition.y;
00197               return;
00198        }
00199 }
00200 
00201 
00209 void PhysicsReflect(CWorld * ThisWorld, CObject * ObjA, CObject * ObjB)
00210 {
00211        CEffect * NewEffect;
00212 
00213        // special cases based on object type
00214        switch(ObjA->iType)
00215        {
00216        case TYPEID_BOUNCY_SHOT:
00217               NewEffect = new CEffect(EFFECTID_MINISHOCK);
00218               NewEffect->MShock = new MiniShock(ObjA->Position, 1);
00219               NewEffect->MShock->SetColor(0.8, 0.3, 0.6);
00220               ThisWorld->AddEffect(NewEffect);
00221               break;
00222        }
00223 
00224        int biteX, biteY; // X and Y delta of the object's positions. reflect whichever is greater
00225        biteX = biteY = 0;
00226 
00227        if(ObjA->Velocity.x < 0) // ObjA going left
00228        {
00229               biteX = ObjA->Position.x - ObjB->Position.x;
00230        }
00231        
00232        if(ObjA->Velocity.x > 0) // ObjA going right
00233        {
00234               biteX = ObjB->Position.x - ObjA->Position.x;
00235        }
00236        
00237        if(ObjA->Velocity.y > 0) // ObjA going up
00238        {
00239               biteY = ObjB->Position.y - ObjA->Position.y;
00240        }
00241        
00242        if(ObjA->Velocity.y < 0) // ObjA going down
00243        {
00244               biteY = ObjA->Position.y - ObjB->Position.y;
00245        }
00246 
00247        if(biteX > biteY)
00248        {
00249               ObjA->Velocity.x *= -1;
00250               return;
00251        }
00252        else
00253        {
00254               ObjA->Velocity.y *= -1;
00255               return;
00256        }
00257        
00258        if(biteX == biteY) // hit a corner
00259        {
00260               ObjA->Velocity.x *= -1;
00261               ObjA->Velocity.y *= -1;
00262               return;
00263        }
00264 }
00265 
00266 
00273 void UpdateBody(CObject * body, float timeDelta)
00274 {
00275        float xproj = 0;
00276        float yproj = 0;
00277        Vector perp;
00278        Vector medialFriction;
00279        Vector lateralFriction;
00280        Vector heading(1,0,0);
00281 
00282        switch(body->iType)
00283        {
00284        case TYPEID_TANK:
00285               heading = VRotate2D(DegreesToRadians(body->fAngle), heading);
00286               xproj = body->Velocity * heading;
00287               medialFriction = heading * -(xproj * TANK_FCR_MEDIAL);
00288 
00289               perp.x = -heading.y;
00290               perp.y = heading.x;
00291               perp.z = 0;
00292 
00293               yproj = body->Velocity * perp;
00294               
00295               lateralFriction = perp * -(yproj * TANK_FCR_LATERAL);
00296 
00297               body->Velocity += medialFriction + lateralFriction;
00298 
00299               if(body->Velocity.Magnitude() > MAX_TANK_SPEED)
00300               {
00301                      body->Velocity *= .9;
00302               }
00303               break;
00304 
00305        case TYPEID_WOOD_BLOCK:
00306               body->Velocity *= .95;
00307               break;
00308        }
00309 }
00310 
00311 
00319 void DamageRadius(CWorld * ThisWorld, Vector pos, float rad, float dam)
00320 {
00321        CObject * Current = ThisWorld->Objects;
00322        Vector vDist(0,0,0);
00323 
00324        while(Current != NULL)
00325        {
00326               if(Current->iType != TYPEID_WALL_BLOCK)
00327               {
00328                      vDist = Current->Position - pos;
00329                      if(vDist.Magnitude() < rad)
00330                      {
00331                             Current->iHealth -= (dam - (vDist.Magnitude()/dam));
00332                             Current->Velocity += vDist * (dam - (vDist.Magnitude()/dam)) * .002;
00333                      }
00334               }
00335               Current = Current->Next;
00336        }
00337 }

 

Copyright Windsor Schmidt 2006 - All rights reserved.