int GameSession::SimulateOneFreeElem(MR_SimulationTime pTimeToSimulate, MR_FreeElementHandle pElementHandle, int pRoom) { Level *mCurrentLevel = track->GetLevel(); BOOL lDeleteElem = FALSE; FreeElement *lElement = mCurrentLevel->GetFreeElement(pElementHandle); // Ask the element to simulate its movement int lNewRoom = lElement->Simulate(pTimeToSimulate, *track, pRoom); int lReturnValue = lNewRoom; if(lNewRoom == Level::eMustBeDeleted) { lDeleteElem = TRUE; lNewRoom = pRoom; } if(pRoom != lNewRoom) mCurrentLevel->MoveElement(pElementHandle, lNewRoom); // Compute interaction of the element with the environment const ShapeInterface *lContactShape = lElement->GetGivingContactEffectShape(); if(lContactShape != NULL) { // Compute contact with structural elements MR_FixedFastArray < int, 20 > lVisitedRooms; RoomContactSpec lSpec; // Do the contact treatement for that room mCurrentLevel->GetRoomContact(lNewRoom, lContactShape, lSpec); ComputeShapeContactEffects(lNewRoom, lElement, lSpec, &lVisitedRooms, 1, pTimeToSimulate); } if(lDeleteElem) mCurrentLevel->DeleteElement(pElementHandle); return lReturnValue; }
void GameSession::ComputeShapeContactEffects(int pCurrentRoom, FreeElement *pActor, const RoomContactSpec &pLastSpec, MR_FastArrayBase<int> *pVisitedRooms, int pMaxDepth, MR_SimulationTime pDuration) { Level *mCurrentLevel = track->GetLevel(); int lCounter; ContactSpec lSpec; const ShapeInterface *lActorShape = pActor->GetGivingContactEffectShape(); BOOL lValidDirection = FALSE; MR_Angle lDirectionAngle = 0; pVisitedRooms->Add(pCurrentRoom); // Compute contact with features // Not correctly done. If a collision is detected, only the floor of the // feature is assumed to be touched (directio is ok but wrong elementis selected int lNbFeatures = mCurrentLevel->GetFeatureCount(pCurrentRoom); for(lCounter = 0; lCounter < lNbFeatures; lCounter++) { int lFeatureId = mCurrentLevel->GetFeature(pCurrentRoom, lCounter); if(mCurrentLevel->GetFeatureContact(lFeatureId, lActorShape, lSpec)) { SurfaceElement *lFloor = mCurrentLevel->GetFeatureTopElement(lFeatureId); // Ok Compute the directiion of the collision if(lSpec.mZMax <= lActorShape->ZMin()) { lValidDirection = FALSE; } else if(lSpec.mZMin >= lActorShape->ZMax()) { lValidDirection = FALSE; } else { lValidDirection = mCurrentLevel->GetFeatureContactOrientation(lFeatureId, lActorShape, lDirectionAngle); } // const ContactEffectList* lActorEffectList = pActor->GetEffectList(); const ContactEffectList *lObstacleEffectList = lFloor->GetEffectList(); // Apply feature effects to the actor pActor->ApplyEffects(lObstacleEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle, lSpec.mZMin, lSpec.mZMax, *track); // Apply actor effects to the feature // if( lValidDirection ) //{ // lDirectionAngle = MR_NORMALIZE_ANGLE( lDirectionAngle+MR_PI ); // lFloor->ApplyEffects( lActorEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle ); //} } } // Compute interaction with room actors MR_FreeElementHandle lObstacleHandle = mCurrentLevel->GetFirstFreeElement(pCurrentRoom); while(lObstacleHandle != NULL) { FreeElement *lObstacleElem = Level::GetFreeElement(lObstacleHandle); if(lObstacleElem != pActor) { if(DetectActorContact(lActorShape, lObstacleElem->GetReceivingContactEffectShape(), lSpec)) { // Ok Compute the directiion of the collision if(lSpec.mZMax <= lActorShape->ZMin()) { lValidDirection = FALSE; } else if(lSpec.mZMin >= lActorShape->ZMax()) { lValidDirection = FALSE; } else { lValidDirection = GetActorForceLongitude(lActorShape, lObstacleElem->GetReceivingContactEffectShape(), lDirectionAngle); } const ContactEffectList *lActorEffectList = pActor->GetEffectList(); const ContactEffectList *lObstacleEffectList = lObstacleElem->GetEffectList(); // Apply feature effects to the actor pActor->ApplyEffects(lObstacleEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle, lSpec.mZMin, lSpec.mZMax, *track); // Apply actor effects to the feature lDirectionAngle = MR_NORMALIZE_ANGLE(lDirectionAngle + MR_PI); lObstacleElem->ApplyEffects(lActorEffectList, mSimulationTime, pDuration, lValidDirection, lDirectionAngle, lSpec.mZMin, lSpec.mZMax, *track); } } lObstacleHandle = Level::GetNextFreeElement(lObstacleHandle); } // Compute interaction with touched walls // at the same time compute interaction with other rooms for(lCounter = 0; lCounter < pLastSpec.mNbWallContact; lCounter++) { // Verify that the wall is a wall on all its height MR_Int32 lContactTop = lActorShape->ZMax(); MR_Int32 lContactBottom = lActorShape->ZMin(); int lNeighbor = mCurrentLevel->GetNeighbor(pCurrentRoom, pLastSpec.mWallContact[lCounter]); if(lNeighbor != -1) { if(!pVisitedRooms->Contains(lNeighbor)) { RoomContactSpec cspec; // Recursively call this function mCurrentLevel->GetRoomContact(lNeighbor, lActorShape, cspec); if((cspec.mDistanceFromFloor < 0) || (cspec.mDistanceFromCeiling < 0)) { lNeighbor = -1; } else { ComputeShapeContactEffects(lNeighbor, pActor, cspec, pVisitedRooms, pMaxDepth - 1, pDuration); } } } if(lNeighbor == -1) { // Apply the effect of the wall if(mCurrentLevel->GetRoomWallContactOrientation(pCurrentRoom, pLastSpec.mWallContact[lCounter], lActorShape, lDirectionAngle)) { SurfaceElement *lWall = mCurrentLevel->GetRoomWallElement(pCurrentRoom, static_cast<size_t>(pLastSpec.mWallContact[static_cast<size_t>(lCounter)])); // const ContactEffectList* lActorEffectList = pActor->GetEffectList(); const ContactEffectList *lWallEffectList = lWall->GetEffectList(); // Apply feature effects to the actor pActor->ApplyEffects(lWallEffectList, mSimulationTime, pDuration, TRUE, lDirectionAngle, lContactBottom, lContactTop, *track); // Apply actor effects to the feature // lDirectionAngle = MR_NORMALIZE_ANGLE( lDirectionAngle+MR_PI ); // lWall->ApplyEffects( lActorEffectList, mSimulationTime, pDuration, TRUE, lDirectionAngle ); } } } }