Beispiel #1
0
void GameSession::SimulateFreeElems(MR_SimulationTime pTimeToSimulate)
{
    Level *mCurrentLevel = track->GetLevel();

    // Do the simulation
    int lRoomIndex;

    // Interaction objects collection

    // Simulate element by element
    for(lRoomIndex = -1; lRoomIndex < mCurrentLevel->GetRoomCount(); lRoomIndex++) {
        // Simulate FreeElements
        MR_FreeElementHandle lElementHandle = mCurrentLevel->GetFirstFreeElement(lRoomIndex);

        while(lElementHandle != NULL) {
            MR_FreeElementHandle lNext = Level::GetNextFreeElement(lElementHandle);
            SimulateOneFreeElem(pTimeToSimulate, lElementHandle, lRoomIndex);
            lElementHandle = lNext;
        }
    }
    mCurrentLevel->FlushPermElementPosCache();
}
Beispiel #2
0
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 );
            }
        }
    }

}