Exemplo n.º 1
0
void Missile::ApplyEffect(const MR_ContactEffect * pEffect, MR_SimulationTime pTime, MR_SimulationTime pDuration, BOOL pValidDirection, MR_Angle pHorizontalDirection, MR_Int32 /*pZMin */ , MR_Int32 /*pZMax */ , Model::Level * /*pLevel */ )
{
	MR_ContactEffect *lEffect = (MR_ContactEffect *) pEffect;
	const MR_PhysicalCollision *lPhysCollision = dynamic_cast < MR_PhysicalCollision * >(lEffect);

	if((lPhysCollision != NULL) && pValidDirection) {

		if(lPhysCollision->mWeight < MR_PhysicalCollision::eInfiniteWeight) {
			if(mLived >= cIgnitionTime) {
				// Hitted a free object
				// Must died
				mLived = cLifeTime + cStopTime;
			}
		}
		else {
			// Hitted structure..make a perfect bounce
			MR_Angle lDiff = MR_NORMALIZE_ANGLE(pHorizontalDirection - mOrientation + MR_PI);

			if((lDiff < (MR_PI / 2)) || (lDiff > (MR_PI + MR_PI / 2))) {
				mOrientation = MR_NORMALIZE_ANGLE(pHorizontalDirection + lDiff);
				mBounceSoundEvent = TRUE;
			}
		}
	}
}
Exemplo n.º 2
0
void InertialMoment::ComputeCollision(const InertialMoment *pObstacle,
	MR_Angle pHorizontalDirection)
{

	// Compute the speed component in the direction of the Impact direction

	MR_Int32 lDirectionSpeed = (mXSpeed * MR_Cos[pHorizontalDirection] / MR_TRIGO_FRACT) + (mYSpeed * MR_Sin[pHorizontalDirection] / MR_TRIGO_FRACT);
	MR_Int32 lObjDirectionSpeed = (pObstacle->mXSpeed * MR_Cos[pHorizontalDirection] / MR_TRIGO_FRACT) + (pObstacle->mYSpeed * MR_Sin[pHorizontalDirection] / MR_TRIGO_FRACT);

	if(lObjDirectionSpeed > lDirectionSpeed) {
		double lKeepRatio = (mWeight - pObstacle->mWeight) / (mWeight + pObstacle->mWeight);
		double lReceivedRatio = (2 * mWeight) * pObstacle->mWeight / ((mWeight + pObstacle->mWeight) * mWeight);

		lDirectionSpeed = MR_Int32(lDirectionSpeed * lKeepRatio);
		lObjDirectionSpeed = MR_Int32(lObjDirectionSpeed * lReceivedRatio);

		MR_Int32 lXBounceSpeed = (MR_Int32) lDirectionSpeed * MR_Cos[pHorizontalDirection] / MR_TRIGO_FRACT + (MR_Int32) lObjDirectionSpeed * MR_Cos[pHorizontalDirection] / MR_TRIGO_FRACT;
		MR_Int32 lYBounceSpeed = (MR_Int32) lDirectionSpeed * MR_Sin[pHorizontalDirection] / MR_TRIGO_FRACT + (MR_Int32) lObjDirectionSpeed * MR_Sin[pHorizontalDirection] / MR_TRIGO_FRACT;

		MR_Angle lPerpendicularAngle = MR_NORMALIZE_ANGLE(pHorizontalDirection + MR_PI / 2);
		MR_Int32 lPerpendicularSpeed = (mXSpeed * MR_Cos[lPerpendicularAngle] / MR_TRIGO_FRACT) + (mYSpeed * MR_Sin[lPerpendicularAngle] / MR_TRIGO_FRACT);

		MR_Int32 lXPerpendicularSpeed = lPerpendicularSpeed * MR_Cos[lPerpendicularAngle] / MR_TRIGO_FRACT;
		MR_Int32 lYPerpendicularSpeed = lPerpendicularSpeed * MR_Sin[lPerpendicularAngle] / MR_TRIGO_FRACT;

		mXSpeed = lXPerpendicularSpeed + lXBounceSpeed;
		mYSpeed = lYPerpendicularSpeed + lYBounceSpeed;
	}

}
Exemplo n.º 3
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 );
            }
        }
    }

}