protected override void Tick(float deltaTimeSeconds) { base.Tick(deltaTimeSeconds); var angularDisplacement = GetAngularDisplacementForTick(deltaTimeSeconds); AssetLocator.MainGeometryPass._EGGHACK_ROT *= angularDisplacement; //AngularVelocity = new Vector3(angularDisplacement.RotAroundX, angularDisplacement.RotAroundY, angularDisplacement.RotAroundZ); AngularVelocity = Vector3.ZERO; //float downwardVeloComponent = Velocity.ProjectedOnto(GameCoordinator.BoardDownDir).Length; //Velocity -= GameCoordinator.BoardDownDir.WithLength(downwardVeloComponent); // OPTION 1 //var veloChangeAngle = Vector3.AngleBetween( // velocityLastFrame.ProjectedOnto(GameCoordinator.BoardDownDir), // Velocity.ProjectedOnto(GameCoordinator.BoardDownDir) //); //if (veloChangeAngle > MathUtils.PI_OVER_TWO) { // if (Vector3.AngleBetween(velocityLastFrame, GameCoordinator.BoardDownDir) < Vector3.AngleBetween(Velocity, GameCoordinator.BoardDownDir)) { // SetTranslation(lastPositions[((nextPositionSlot - 2) % lastPositions.Length)]); // Velocity = TrueVelocity; // HUDSound.UISelectNegativeOption.Play(); // } //} // OPTION 2 var downDir = GameCoordinator.BoardDownDir; Ray rollTestRay = new Ray( Transform.Translation - downDir.WithLength(GameplayConstants.EGG_COLLISION_RADIUS), downDir, GameplayConstants.EGG_COLLISION_RADIUS * 3f ); EntityModule.RayTestAllLessGarbage(rollTestRay, bulletBugRayTestReusableList, 5U); for (int i = 0; i < bulletBugRayTestReusableList.Count; ++i) { GeometryEntity touchedEntity = bulletBugRayTestReusableList[i].Entity as GeometryEntity; if (touchedEntity != null) { BulletBugRayHandle(touchedEntity); } } CheckForAndCorrectBulletBug(deltaTimeSeconds); lastPositions[(nextPositionSlot % lastPositions.Length)] = Transform.Translation; elapsedTimes[(nextPositionSlot % lastPositions.Length)] = EntityModule.ElapsedTime; ++nextPositionSlot; velocityLastFrame = Velocity; if (GameCoordinator.CurrentGameState == GameCoordinator.OverallGameState.LevelPlaying) { airtime += deltaTimeSeconds; topSpeed = Math.Max(topSpeed, TrueVelocity.Length); } }
private static void TickSound(float deltaTime) { Vector3 ballVelo = egg.Velocity; float ballSpeed = ballVelo.Length; float speedLastFrame = velocityLastFrame.Length; const int TICK_SOUND_EARLINESS_MS = 200; // Tick int adjustedTimeRemainingMs = timeRemainingMs - TICK_SOUND_EARLINESS_MS; int timeRemainingSecs = adjustedTimeRemainingMs / 1000; if (timeRemainingSecs != 0 && timeRemainingSecs != (int)(adjustedTimeRemainingMs + deltaTime * 1000f) / 1000) { int instanceId = AudioModule.CreateSoundInstance(AssetLocator.TickSound); AudioModule.PlaySoundInstance( instanceId, false, 0.2f * Config.SoundEffectVolume, adjustedTimeRemainingMs > Config.TimePitchRaiseMs ? 1f : (adjustedTimeRemainingMs > Config.TimeWarningMs ? 1.1f : 1.2f) ); } // Bounce if (velocityLastFrame != Vector3.ZERO && ballSpeed >= MIN_SPEED_FOR_DIFFERENTIAL_ANGLE_BOUNCE_SOUND && Vector3.AngleBetween(ballVelo, velocityLastFrame) >= MIN_VELO_DIFFERENTIAL_ANGLE_FOR_BOUNCE_SOUND) { if (lastBounceSoundTime - timeRemainingMs >= BOUNCE_SOUND_MIN_INTERVAL) { int instanceId = AudioModule.CreateSoundInstance(AssetLocator.ObtuseBounceSound); AudioModule.PlaySoundInstance( instanceId, false, BOUNCE_VOLUME * Config.SoundEffectVolume, RandomProvider.Next(BOUNCE_PITCH_MIN, BOUNCE_PITCH_MAX) ); instanceId = AudioModule.CreateSoundInstance(AssetLocator.ImpactSounds[RandomProvider.Next(0, AssetLocator.ImpactSounds.Length)]); AudioModule.PlaySoundInstance( instanceId, false, IMPACT_VOLUME * Config.SoundEffectVolume, RandomProvider.Next(IMPACT_PITCH_MIN, IMPACT_PITCH_MAX) ); lastBounceSoundTime = timeRemainingMs; } float speedDiff = Math.Abs(speedLastFrame - ballSpeed); int baseBitsCount = 3; if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 10f) { baseBitsCount = 13; } else if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 8f) { baseBitsCount = 11; } else if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 6f) { baseBitsCount = 7; } else if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 4f) { baseBitsCount = 5; } CollisionBitPool.DisseminateBits(egg.Transform.Translation, -boardDownDir.WithLength(speedDiff * 0.65f), baseBitsCount * (int)Config.PhysicsLevel); MaybePlayAllBounce(speedDiff); } else if (Math.Abs(ballSpeed - speedLastFrame) >= MIN_SPEED_CHANGE_FOR_BOUNCE_SOUND) // bounce in same direction { if (lastBounceSoundTime - timeRemainingMs >= BOUNCE_SOUND_MIN_INTERVAL) { int instanceId = AudioModule.CreateSoundInstance(AssetLocator.AcuteBounceSound); AudioModule.PlaySoundInstance( instanceId, false, BOUNCE_VOLUME * Config.SoundEffectVolume, RandomProvider.Next(BOUNCE_PITCH_MIN, BOUNCE_PITCH_MAX) ); instanceId = AudioModule.CreateSoundInstance(AssetLocator.ImpactSounds[RandomProvider.Next(0, AssetLocator.ImpactSounds.Length)]); AudioModule.PlaySoundInstance( instanceId, false, IMPACT_VOLUME * Config.SoundEffectVolume, RandomProvider.Next(IMPACT_PITCH_MIN, IMPACT_PITCH_MAX) ); lastBounceSoundTime = timeRemainingMs; } float speedDiff = Math.Abs(speedLastFrame - ballSpeed); int baseBitsCount = 2; if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 10f) { baseBitsCount = 13; } else if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 8f) { baseBitsCount = 11; } else if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 6f) { baseBitsCount = 7; } else if (speedDiff >= PhysicsManager.ONE_METRE_SCALED * 4f) { baseBitsCount = 3; } CollisionBitPool.DisseminateBits(egg.Transform.Translation, -boardDownDir.WithLength(speedDiff * 0.65f), baseBitsCount * (int)Config.PhysicsLevel); MaybePlayAllBounce(speedDiff); } // Roll float rollVolFraction = (ballSpeed - GameplayConstants.EGG_SPEED_FOR_MIN_ROLL_VOL) / (GameplayConstants.EGG_SPEED_FOR_MAX_ROLL_VOL - GameplayConstants.EGG_SPEED_FOR_MIN_ROLL_VOL); float rollFreqFraction = (ballSpeed - GameplayConstants.EGG_SPEED_FOR_MIN_ROLL_FREQ) / (GameplayConstants.EGG_SPEED_FOR_MAX_ROLL_FREQ - GameplayConstants.EGG_SPEED_FOR_MIN_ROLL_FREQ); Vector3 eggPos = egg.Transform.Translation; Ray rollTestRay = Ray.FromStartAndEndPoint( eggPos, eggPos + boardDownDir.WithLength(GameplayConstants.EGG_COLLISION_RADIUS + ROLL_MARGIN) ); EntityModule.RayTestAllLessGarbage(rollTestRay, reusableRayTestResultsList); bool isRolling = false; for (int i = 0; i < reusableRayTestResultsList.Count; ++i) { if (reusableRayTestResultsList[i].Entity != egg) { isRolling = true; break; } } if (isRolling) { if (unbrokenRollTime == 0) { unbrokenRollTime = (int)(deltaTime * 1000f); } else { unbrokenRollTime += lastRollTime - timeRemainingMs; } lastRollTime = timeRemainingMs; } else { if (unbrokenRollTime < UNBROKEN_ROLL_TIME_BEFORE_ROLL_SOUND || lastRollTime - timeRemainingMs > ROLL_RAY_FAIL_MAX_TIME_BEFORE_UNBROKEN_ROLL_RESET) { unbrokenRollTime = 0; } } if (unbrokenRollTime < UNBROKEN_ROLL_TIME_BEFORE_ROLL_SOUND || lastRollTime - timeRemainingMs > ROLL_RAY_FAIL_MAX_TIME_BEFORE_NO_SOUND_MS || rollVolFraction <= 0f || rollFreqFraction <= 0f) { AudioModule.SetSoundInstanceVolume(AssetLocator.RollSound.SoundInstanceIds.First(), 0f); } else { if (rollVolFraction > 1f) { rollVolFraction = 1f; } if (rollFreqFraction > 1f) { rollFreqFraction = 1f; } AudioModule.SetSoundInstanceFrequency(AssetLocator.RollSound.SoundInstanceIds.First(), ROLL_FREQ_MIN + (ROLL_FREQ_MAX - ROLL_FREQ_MIN) * rollFreqFraction); AudioModule.SetSoundInstanceVolume(AssetLocator.RollSound.SoundInstanceIds.First(), ROLL_VOLUME_MIN + (ROLL_VOLUME_MAX - ROLL_VOLUME_MIN) * rollVolFraction * Config.SoundEffectVolume); } // Highspeed if (ballSpeed >= HIGHSPEED_SOUND_MIN_SPEED) { float angleToUp = Vector3.AngleBetween(ballVelo, -boardDownDir); float angleToDown = Vector3.AngleBetween(ballVelo, boardDownDir); if (angleToUp <= MathUtils.PI_OVER_TWO * 0.5f) { if (highspeedUpMetadata.TimeAtLastSound - timeRemainingMs >= MIN_INTERVAL_BETWEEN_HIGHSPEED_SOUNDS_MS && highspeedUpMetadata.CollidedSinceLastSound && highspeedUpMetadata.SlowedSinceLastSound) { int instanceId = AudioModule.CreateSoundInstance(AssetLocator.HighSpeedUpSounds[RandomProvider.Next(0, AssetLocator.HighSpeedUpSounds.Length)]); AudioModule.PlaySoundInstance( instanceId, false, HIGHSPEED_VOLUME * Config.SoundEffectVolume, RandomProvider.Next(HIGHSPEED_PITCH_MIN, HIGHSPEED_PITCH_MAX) ); highspeedUpMetadata.CollidedSinceLastSound = highspeedUpMetadata.SlowedSinceLastSound = false; highspeedUpMetadata.TimeAtLastSound = timeRemainingMs; } } else if (angleToDown <= MathUtils.PI_OVER_TWO * 0.5f) { Ray downRay = Ray.FromStartAndEndPoint(eggPos, eggPos + boardDownDir.WithLength(PARALLEL_HIGHSPEED_DOWN_BUFFER)); bool somethingBeneath = EntityModule.RayTestAll(downRay).Any(rtc => rtc.Entity != egg); if (highspeedDownMetadata.TimeAtLastSound - timeRemainingMs >= MIN_INTERVAL_BETWEEN_HIGHSPEED_SOUNDS_MS && highspeedDownMetadata.CollidedSinceLastSound && highspeedDownMetadata.SlowedSinceLastSound && !somethingBeneath) { int instanceId = AudioModule.CreateSoundInstance(AssetLocator.HighSpeedDownSounds[RandomProvider.Next(0, AssetLocator.HighSpeedDownSounds.Length)]); AudioModule.PlaySoundInstance( instanceId, false, HIGHSPEED_VOLUME * Config.SoundEffectVolume, RandomProvider.Next(HIGHSPEED_PITCH_MIN, HIGHSPEED_PITCH_MAX) ); highspeedDownMetadata.CollidedSinceLastSound = highspeedDownMetadata.SlowedSinceLastSound = false; highspeedDownMetadata.TimeAtLastSound = timeRemainingMs; } } else if (ballSpeed >= HIGHSPEED_SOUND_MIN_SPEED + HIGHSPEED_SOUND_ADDITIONAL_SPEED_FOR_PARALLEL) { if (highspeedParallelMetadata.TimeAtLastSound - timeRemainingMs >= MIN_INTERVAL_BETWEEN_HIGHSPEED_SOUNDS_MS && highspeedParallelMetadata.CollidedSinceLastSound && highspeedParallelMetadata.SlowedSinceLastSound) { int instanceId = AudioModule.CreateSoundInstance(AssetLocator.HighSpeedParallelSounds[RandomProvider.Next(0, AssetLocator.HighSpeedParallelSounds.Length)]); AudioModule.PlaySoundInstance( instanceId, false, HIGHSPEED_VOLUME * Config.SoundEffectVolume, RandomProvider.Next(HIGHSPEED_PITCH_MIN, HIGHSPEED_PITCH_MAX) ); highspeedParallelMetadata.CollidedSinceLastSound = highspeedParallelMetadata.SlowedSinceLastSound = false; highspeedParallelMetadata.TimeAtLastSound = timeRemainingMs; } } } else { highspeedUpMetadata.SlowedSinceLastSound = highspeedDownMetadata.SlowedSinceLastSound = highspeedParallelMetadata.SlowedSinceLastSound = true; } // Countdown Timer if (!playingCountdownTimer && timeRemainingMs <= COUNTDOWN_TIMER_START_TIME_MS) { int instanceId = AudioModule.CreateSoundInstance(AssetLocator.CountdownLoopSound.File); AssetLocator.CountdownLoopSound.AddInstance(instanceId); AudioModule.PlaySoundInstance(instanceId, true, COUNTDOWN_VOLUME); playingCountdownTimer = true; } velocityLastFrame = ballVelo; }
protected override void Tick(float deltaTimeSeconds) { base.Tick(deltaTimeSeconds); if (Egg.IsDisposed || Camera.IsDisposed || GameCoordinator.CurrentGameState != GameCoordinator.OverallGameState.LevelPlaying) { return; } // Declare some variables that we'll use below Vector3 eggPos = Egg.Transform.Translation; Vector3 eggVelo = Egg.TrueVelocity; Vector3 camPos = UnalteredCamPosition; Vector3 camOrientation = UnalteredCamOrientation; Vector3 boardDownDir = GameCoordinator.BoardDownDir; Plane groundPlane = GameCoordinator.GroundPlane; Quaternion boardTilt = GameCoordinator.CurrentGameboardTilt; float flopsErrorMargin = MathUtils.FlopsErrorMargin; Vector3 verticalEggPos = eggPos.ProjectedOnto(boardDownDir); Vector3 horizontalEggPos = groundPlane.PointProjection(eggPos); Vector3 verticalEggVelo = eggVelo.ProjectedOnto(boardDownDir); Vector3 horizontalEggVelo = groundPlane.OrientationProjection(eggVelo); Vector3 verticalCamPos = camPos.ProjectedOnto(boardDownDir); Vector3 horizontalCamPos = groundPlane.PointProjection(camPos); Vector3 horizontalCamOrientation = groundPlane.OrientationProjection(camOrientation); Vector3 verticalCamOrientation = camOrientation.ProjectedOnto(boardDownDir); Vector3 curUpDir = Camera.UpDirection; Vector3 targetUpDir = -boardDownDir; Camera.Position = UnalteredCamPosition; // Find where the camera "wants" to be (only according to the egg velo) Vector3 reverseEggVelo = horizontalEggVelo.LengthSquared > GameplayConstants.MIN_EGG_SPEED_FOR_VELO_BASED_CAM_SQ ? -horizontalEggVelo : -horizontalCamOrientation; Vector3 targetPos = eggPos + reverseEggVelo.WithLength(cameraDistance); // Add the height addition to the target pos float verticalAddition = verticalEggVelo.LengthSquared > horizontalEggVelo.LengthSquared && verticalEggVelo.LengthSquared > GameplayConstants.MIN_FALL_SPEED_FOR_FALLING_CAM_SQ ? cameraHeight + GameplayConstants.CAMERA_FALLING_HEIGHT_EXTRA : cameraHeight; targetPos += -boardDownDir.WithLength(verticalAddition); // Calculate the rotation around the egg that the boom is making (in 3 dimensions!), and calculate the amount to rotate this frame Vector3 eggToTarget = targetPos - eggPos; eggToTarget *= boardTilt.Subrotation(GameplayConstants.CAM_BOARD_TILT_FACTOR); Vector3 eggToCam = camPos - eggPos; float eggToTargetLen = eggToTarget.Length; Quaternion cameraRot = Quaternion.FromVectorTransition(eggToCam.ToUnit(), eggToTarget.ToUnit()); eggToTarget = eggToCam * cameraRot.Subrotation(Math.Min(GameplayConstants.CAM_MOVE_SPEED_ANGULAR * deltaTimeSeconds, 1f)); targetPos = eggPos + (eggToTargetLen > flopsErrorMargin ? eggToTarget.WithLength(eggToTargetLen) : Vector3.ZERO); // Get the distance from the current pos to the target pos, calculate the amount to move closer this frame, and move the camera Vector3 camToTarget = targetPos - camPos; float movementDist = (float)Math.Pow(camToTarget.LengthSquared, GameplayConstants.CAM_MOVE_SPEED_EXPONENT_LINEAR) * deltaTimeSeconds; if (camToTarget.LengthSquared > flopsErrorMargin) { Camera.Move(camToTarget.WithLength(Math.Min(movementDist, camToTarget.Length))); } // Calculate the rotation of orientation, and then rotate the camera according to the rotation speed Vector3 newOrientation = (eggPos - camPos).ToUnit(); Quaternion orientRot = Quaternion.FromVectorTransition(camOrientation, newOrientation); Vector3 newCamUp; if (curUpDir == targetUpDir) { newCamUp = targetUpDir; } else { Quaternion curToTargetRot = Quaternion.FromVectorTransition(curUpDir, targetUpDir); newCamUp = curUpDir * curToTargetRot.Subrotation(GameplayConstants.CAM_UP_SUBROT_PER_SEC * deltaTimeSeconds); } Camera.Orient( camOrientation * orientRot.Subrotation(Math.Min(GameplayConstants.CAM_ORIENT_SPEED * deltaTimeSeconds, 1f)), newCamUp ); // Adjust camera orientation and position according to right-stick float xDiff = camOrientAltXTarget - camOrientAltXActual; float xDelta = xDiff * GameplayConstants.CAM_ORIENTATION_ADJUSTMENT_DELTA_FRAC_PER_SEC_X * deltaTimeSeconds; if (Math.Abs(camOrientAltXTarget) < Math.Abs(camOrientAltXActual)) { xDelta = xDiff * GameplayConstants.CAM_ORIENTATION_ADJUSTMENT_DELTA_FRAC_PER_SEC_X_STOPPING * deltaTimeSeconds; } else { xDelta = Math.Max( Math.Abs(xDelta), Math.Min( GameplayConstants.CAM_ORIENTATION_ADJUSTMENT_DELTA_ABS_MIN_PER_SEC_X * deltaTimeSeconds, Math.Abs(xDiff) ) ) * (xDiff < 0f ? -1f : 1f); } camOrientAltXActual = camOrientAltXActual + xDelta; float yDiff = camOrientAltYTarget - camOrientAltYActual; float yDelta = yDiff * GameplayConstants.CAM_ORIENTATION_ADJUSTMENT_DELTA_FRAC_PER_SEC_Y * deltaTimeSeconds; if (Math.Abs(camOrientAltYTarget) < Math.Abs(camOrientAltYActual)) { yDelta = yDiff * GameplayConstants.CAM_ORIENTATION_ADJUSTMENT_DELTA_FRAC_PER_SEC_Y_STOPPING * deltaTimeSeconds; } else { yDelta = Math.Max( Math.Abs(yDelta), Math.Min( GameplayConstants.CAM_ORIENTATION_ADJUSTMENT_DELTA_ABS_MIN_PER_SEC_Y * deltaTimeSeconds, Math.Abs(yDiff) ) ) * (yDiff < 0f ? -1f : 1f); } camOrientAltYActual = camOrientAltYActual + yDelta; unalteredCamOrientation = Camera.Orientation; Vector3 alteredOrientation = unalteredCamOrientation; Quaternion forwardToUpRot = Quaternion .FromVectorTransition(alteredOrientation, -boardDownDir) .Subrotation(GameplayConstants.MAX_CAM_ORIENTATION_ADJUSTMENT_Y * camOrientAltYActual); var verticalOrient = alteredOrientation * forwardToUpRot; var angleToFloor = new Plane(-boardDownDir, eggPos).IncidentAngleWith(new Ray(camPos, verticalOrient)); // not sure why the 0.2f is needed but it is... bool useVerticalOrient = angleToFloor >= GameplayConstants.CAM_Y_ADJUSTMENT_HORIZONTAL_BUFFER_RADIANS_BOTTOM && angleToFloor <= MathUtils.PI_OVER_TWO - GameplayConstants.CAM_Y_ADJUSTMENT_HORIZONTAL_BUFFER_RADIANS_TOP && alteredOrientation.ProjectedOnto(-boardDownDir).ToUnit() != -boardDownDir; Quaternion forwardToLeftRot = Quaternion .FromAxialRotation(-boardDownDir, -MathUtils.PI_OVER_TWO) .Subrotation(GameplayConstants.MAX_CAM_ORIENTATION_ADJUSTMENT_X * camOrientAltXActual); alteredOrientation = (useVerticalOrient ? verticalOrient : unalteredCamOrientation) * forwardToLeftRot; Camera.Orient(alteredOrientation, useVerticalOrient ? Camera.UpDirection * forwardToUpRot : Camera.UpDirection); unalteredCamPosition = Camera.Position; Vector3 alteredPosition = unalteredCamPosition.Value; Vector3 downVec = boardDownDir; Vector3 leftVec = groundPlane.OrientationProjection(unalteredCamOrientation).ToUnit() * Quaternion.FromAxialRotation(boardDownDir, -MathUtils.PI_OVER_TWO); if (useVerticalOrient) { alteredPosition += downVec.WithLength(GameplayConstants.CAM_ADJUSTMENT_TRANSLATION_MAX_Y * camOrientAltYActual); } alteredPosition += leftVec.WithLength(GameplayConstants.CAM_ADJUSTMENT_TRANSLATION_MAX_X * camOrientAltXActual); Camera.Position = alteredPosition; unalteredCamPosition = alteredPosition; unalteredCamOrientation = alteredOrientation; // Finally, make any geometry entities that are obscuring the view of the egg transparent var curLevel = GameCoordinator.CurrentlyLoadedLevel; hiddenEntityAccountingSpace.Clear(); foreach (var key in hiddenEntities.Keys) { hiddenEntityAccountingSpace.Add(key); } EntityModule.RayTestAllLessGarbage(Ray.FromStartAndEndPoint(Camera.Position, eggPos), reusableRTCList); foreach (RayTestCollision rtc in reusableRTCList) { var geomEntity = rtc.Entity as GeometryEntity; if (geomEntity == null) { continue; } if (hiddenEntities.ContainsKey(geomEntity)) { hiddenEntityAccountingSpace.Remove(geomEntity); continue; } LevelGeometryEntity entityLevelRep = curLevel.GetLevelEntityRepresentation(geomEntity); Material alphaMat = new Material(entityLevelRep.Material.Name + " + Alpha", AssetLocator.AlphaFragmentShader); alphaMat.SetMaterialConstantValue(alphaMatColorBinding, new Vector4( GameplayConstants.OBSCURING_GEOM_BRIGHTNESS, GameplayConstants.OBSCURING_GEOM_BRIGHTNESS, GameplayConstants.OBSCURING_GEOM_BRIGHTNESS, GameplayConstants.OBSCURING_GEOM_MIN_ALPHA )); ShaderResourceView texSRV = AssetLocator.LoadTexture(entityLevelRep.Material.TextureFileName).CreateView(); alphaMat.SetMaterialResource(alphaMatTextureBinding, texSRV); hiddenEntities.Add(geomEntity, new HiddenEntityMetadata( alphaMat, texSRV, entityLevelRep, alphaMatColorBinding )); geomEntity.SetModelInstance( AssetLocator.GameAlphaLayer, curLevel.GetModelHandleForGeometry(entityLevelRep.Geometry), alphaMat ); } foreach (KeyValuePair <GeometryEntity, HiddenEntityMetadata> kvp in hiddenEntities) { HiddenEntityMetadata metadata = kvp.Value; if (hiddenEntityAccountingSpace.Contains(kvp.Key)) { metadata.Alpha += GameplayConstants.OBSCURING_GEOM_ALPHA_REGAIN_SPEED * deltaTimeSeconds; if (metadata.Alpha < GameplayConstants.OBSCURING_GEOM_MAX_ALPHA) { hiddenEntityAccountingSpace.Remove(kvp.Key); } } else if (metadata.Alpha > GameplayConstants.OBSCURING_GEOM_MIN_ALPHA) { metadata.Alpha -= GameplayConstants.OBSCURING_GEOM_ALPHA_REGAIN_SPEED * deltaTimeSeconds; } } foreach (GeometryEntity hiddenEntity in hiddenEntityAccountingSpace) { var hiddenEntityMetadata = hiddenEntities.Pop(hiddenEntity); AssetLocator.UnloadTexture(hiddenEntityMetadata.LevelRepresentation.Material.TextureFileName); hiddenEntityMetadata.TexSRV.Dispose(); hiddenEntityMetadata.Material.Dispose(); hiddenEntity.SetModelInstance( AssetLocator.GameLayer, curLevel.GetModelHandleForGeometry(hiddenEntityMetadata.LevelRepresentation.Geometry), curLevel.GetLoadedMaterialForLevelMaterial(hiddenEntityMetadata.LevelRepresentation.Material) ); } }