Beispiel #1
0
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;
}
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 );
            }
        }
    }

}