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.