private void startBatch(bool allowRecycle = false) { if (hasBegun && !allowRecycle) { return; } endBatch(); int amountQuads = OsuMathHelper.Clamp(SpriteList.Count, 1, 100); if (SpriteBatch == null || SpriteBatch.Size < amountQuads) { for (int i = 0; i < SpriteBatches.Length; i++) { SpriteBatches[i] = new QuadBatch <TexturedVertex2d>(amountQuads * 2, 500); } } if (currentBlend == SpriteBlendMode.Additive) { OsuGlControl.SetBlend(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One); } else { OsuGlControl.SetBlend(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); } hasBegun = true; Current = this; NativeText.ScaleModifier = Scale; }
public HitCircleFruits(HitObjectManager hom, Vector2 startPosition, int startTime, bool newCombo, HitObjectSoundType soundType, string fruit) : base(hom) { Position = new Vector2(OsuMathHelper.Clamp(startPosition.X, 0, GameField.DEFAULT_WIDTH), 340); BasePosition = Position; StartTime = startTime; EndTime = startTime; SoundType = soundType; NewCombo = newCombo; if (hom.spriteManager != null) { SpriteHitCircle1 = new pSprite(TextureManager.Load(@"fruit-" + fruit), Fields.Gamefield, Origins.Centre, Clocks.Audio, Position, SpriteManager.drawOrderBwd(StartTime), false, Color.White); SpriteCollection.Add(SpriteHitCircle1); DimCollection.Add(SpriteHitCircle1); SpriteHitCircle1.TagNumeric = 1; SpriteHitCircle2 = new pSprite(TextureManager.Load(@"fruit-" + fruit + "-overlay"), Fields.Gamefield, Origins.Centre, Clocks.Audio, Position, SpriteManager.drawOrderBwd(StartTime - 1), false, Color.White); SpriteCollection.Add(SpriteHitCircle2); DimCollection.Add(SpriteHitCircle2); SpriteHyperDash = new pSprite(TextureManager.Load(@"fruit-" + fruit), Fields.Gamefield, Origins.Centre, Clocks.Audio, Position, SpriteManager.drawOrderBwd(StartTime + 1), false, Color.TransparentBlack); SpriteHyperDash.Additive = true; SpriteCollection.Add(SpriteHyperDash); DimCollection.Add(SpriteHyperDash); Transformation fall1 = new Transformation(new Vector2(Position.X, -100), new Vector2(Position.X, 340), StartTime - hitObjectManager.PreEmpt, StartTime); fall1.EndVector.Y += (fall1.EndVector.Y - fall1.StartVector.Y) * 0.2f; fall1.Time2 += (int)(fall1.Duration * 0.2f); float rotation = RNG.NextSingle(-0.2f, 0.2f); SpriteCollection.ForEach(s => { s.Transformations.Add(fall1); s.Rotation = rotation; }); if (ModManager.CheckActive(hitObjectManager.ActiveMods, Mods.Hidden)) { Transformation t = new Transformation(TransformationType.Fade, 1, 0, startTime - (int)(hitObjectManager.PreEmpt * 0.6), startTime - (int)(hitObjectManager.PreEmpt * 0.44)); SpriteCollection.ForEach(s => s.Transformations.Add(t)); } } }
internal pSliderBar(SpriteManager spriteManager, double min, double max, double initial, Vector2 position, int length) { Min = min; Max = max; Current = Initial = OsuMathHelper.Clamp(initial, Min, Max); Length = length; lineColour = SkinManager.NEW_SKIN_COLOUR_MAIN; lineLeft = new pSpriteSliderBarLine(GameBase.WhitePixel, position, 0.992f, lineColour, length); lineLeft.HandleInput = true; lineLeft.ExactCoordinates = true; lineLeft.VectorScale = new Vector2(length * 1.6f, 1.5f); lineRight = new pSprite(GameBase.WhitePixel, position, 0.991f, true, lineColour); lineRight.ExactCoordinates = true; lineRight.HandleInput = true; lineRight.Alpha = 0.5f; lineRight.VectorScale = new Vector2(length * 1.6f, 1.5f); Seekbar = new pSprite(TextureManager.Load(@"circle-empty", SkinSource.Osu), Fields.TopLeft, Origins.Centre, Clocks.Game, seekPosition, 0.99f, true, lineColour, null); Seekbar.HandleInput = true; Seekbar.OnUpdate += delegate { float v1 = Seekbar.drawRectangle.X - lineLeft.drawRectangle.X; float halfCircle = Seekbar.DrawWidth / 1.6f / 2; lineLeft.VectorScale.X = Math.Max(0, v1 / GameBase.WindowManager.RatioInverse); lineRight.VectorScale.X = Math.Max(0, length * 1.6f - (v1 + Seekbar.DrawWidth) / GameBase.WindowManager.RatioInverse); lineRight.Position.X = Seekbar.Position.X + halfCircle; }; SpriteCollection.Add(Seekbar); SpriteCollection.Add(lineLeft); SpriteCollection.Add(lineRight); lineLeft.OnHover += sprite_OnHover; lineLeft.OnHoverLost += sprite_OnHoverLost; if (spriteManager != null) { spriteManager.Add(Seekbar); spriteManager.Add(lineLeft); spriteManager.Add(lineRight); } updatePosition(); }
private void Explode(HitObject h) { if (ModManager.CheckActive(Mods.Cinema)) { return; } float explosionOffset = OsuMathHelper.Clamp(((HitCircleFruits)h).CatchOffset.X, -catcherWidthHalf + catchMargin * 3, catcherWidthHalf - catchMargin * 3); if (!(h is HitCircleFruitsTick)) { float scale = OsuMathHelper.Clamp(ComboCounter.HitCombo / 200f, 0.35f, 1.125f); pSprite exp1 = new pSprite(TextureManager.Load(@"scoreboard-explosion-2", SkinSource.Osu), Fields.Gamefield, Origins.CentreLeft, Clocks.Game, h.Position, 0.99f, false, h.Colour); exp1.Additive = true; exp1.Rotation = (float)(-Math.PI / 2); exp1.FadeOut(300); exp1.Transformations.Add(new Transformation(TransformationType.VectorScale, new Vector2(1, 0.9f), new Vector2(16 * scale, 1.1f), GameBase.Time, GameBase.Time + 160, EasingTypes.Out)); spriteManagerAdd.Add(exp1); exp1.IsVisible = true; exp1.InitialPosition = new Vector2(explosionOffset, 0); caughtSprites.Add(exp1); } pSprite exp2 = new pSprite(TextureManager.Load(@"scoreboard-explosion-1", SkinSource.Osu), Fields.Gamefield, Origins.CentreLeft, Clocks.Game, h.Position, 1, false, h.Colour); exp2.Rotation = (float)(-Math.PI / 2); spriteManagerAdd.Add(exp2); exp2.Additive = true; exp2.FadeOut(700); exp2.Transformations.Add(new Transformation(TransformationType.VectorScale, new Vector2(0.9f, 1), new Vector2(0.9f, 1.3f), GameBase.Time, GameBase.Time + 500, EasingTypes.Out)); exp2.IsVisible = true; exp2.InitialPosition = new Vector2(explosionOffset, 0); caughtSprites.Add(exp2); }
protected override void Read() { BindSection(@"Mania"); ReadList(@"ColumnLineWidth", ColumnLineWidth, w => w > 0f && w < 2f ? 2f : w); ReadValue(@"BarlineHeight", ref BarlineHeight); ReadValue(@"SpecialStyle", ref SpecialStyle); ReadList(@"ColumnWidth", ColumnWidth, w => OsuMathHelper.Clamp(w, 5, 100)); ReadList(@"ColumnSpacing", ColumnSpacing); for (int i = 0; i < Columns - 1; i++) { ColumnSpacing[i] = OsuMathHelper.Clamp(ColumnSpacing[i], -ColumnWidth[i + 1], float.MaxValue); // No reason to limit max } ReadList(@"LightingNWidth", LightingNWidth); ReadList(@"LightingLWidth", LightingLWidth); ReadValues(imageMap); ReadValues(colours); ReadValues(flip); ReadValues(noteBodyStyle); ReadValue(@"WidthForNoteHeightScale", ref WidthForNoteHeightScale); ReadValue(@"StageSeparation", ref StageSeparation); StageSeparation = Math.Max(StageSeparation, 5); ReadValue(@"SeparateScore", ref SeparateScore); ReadValue(@"SplitStages", ref SplitStagesFromSkin); ReadValue(@"KeysUnderNotes", ref KeysUnderNotes); ReadValue(@"ColumnStart", ref ColumnStart); ReadValue(@"ColumnRight", ref ColumnRight); ReadValue(@"JudgementLine", ref JudgementLine); ReadValue(@"HitPosition", ref HitPosition); HitPosition = Math.Max(240, Math.Min(HitPosition, 480)); ReadValue(@"LightPosition", ref LightPosition); ReadValue(@"ComboPosition", ref ComboPosition); ReadValue(@"ScorePosition", ref ScorePosition); ReadValue(@"UpsideDown", ref UpsideDown); ReadValue(@"LightFramePerSecond", ref LightFramePerSecond); if (LightFramePerSecond <= 0) { LightFramePerSecond = 24; } }
/// <summary> /// Set the mania-wide scroll speed. /// </summary> /// <param name="value">The new scroll speed value.</param> /// <param name="owned">Whether the value is owned or unowned.</param> /// <param name="type">The type of speed to set. A normal Speed or a RelativeSpeed.</param> /// <returns>If the scroll speed was changed.</returns> internal static bool SetSpeed(double value, bool owned = false, ManiaSpeedType type = ManiaSpeedType.Speed) { // unowned sets only happen when the speed is not already owned if (!owned && isSpeedOwned) { return(false); } Mods mods = InputManager.ReplayMode && InputManager.ReplayScore != null ? InputManager.ReplayScore.EnabledMods : ModManager.ModStatus; EffectiveBPM = primaryBPM * ( ModManager.CheckActive(mods, Mods.DoubleTime) ? 1.5 : ModManager.CheckActive(mods, Mods.HalfTime) ? 0.75 : 1.0); double oldRelativeSpeed = RelativeSpeed; if (type == ManiaSpeedType.RelativeSpeed) { // set RelativeSpeed and calculate Speed RelativeSpeed = value; Speed = OsuMathHelper.Clamp((int)Math.Round(RelativeSpeed * (ConfigManager.sManiaSpeedBPMScale ? 1 : EffectiveBPM / SPEED_FACTOR)), SPEED_MIN, SPEED_MAX); } else { // set Speed and calculate RelativeSpeed Speed = OsuMathHelper.Clamp((int)Math.Round(value), SPEED_MIN, SPEED_MAX); RelativeSpeed = Speed * (ConfigManager.sManiaSpeedBPMScale ? 1 : SPEED_FACTOR / Math.Max(EffectiveBPM, 1)); } if (owned) { isSpeedOwned = true; ConfigManager.sManiaSpeed.Value = Speed; if (BeatmapManager.Current != null && ConfigManager.sUsePerBeatmapManiaSpeed) { BeatmapManager.Current.ManiaSpeed = Speed; } } return(RelativeSpeed != oldRelativeSpeed); }
public override void Update() { background.HandleInput = !Player.Playing || Player.Unpausing; const float hide_delay = 1000; if (Visible && GameBase.Time - lastVisibleTime > hide_delay) { Visible = false; } if (Visible) { if (background.Alpha > 0.98f) { float aimProgress = volume.Value / 100f; if (progress.Progress != aimProgress) { float difference = progress.Progress - aimProgress; if (Math.Abs(difference) < 0.0001) { progress.Progress = aimProgress; } else { progress.Progress = OsuMathHelper.Clamp(aimProgress + difference * (float)Math.Pow(0.99, GameBase.ElapsedMilliseconds), 0, 1); } } percentageDisplay.Text = Math.Round(progress.Progress * 100) + @"%"; } } else { if (percentageDisplay.Alpha == 0) { percentageDisplay.Text = string.Empty; } } base.Update(); }
protected override void OnShown(EventArgs e) { editor = Editor.Instance; if (editor.Compose.selectedObjects.Count == 1) { HitObject h = editor.Compose.selectedObjects[0]; float x = OsuMathHelper.Clamp(h.BasePosition.X, (float)nud_x.Minimum, (float)nud_x.Maximum); float y = OsuMathHelper.Clamp(h.BasePosition.Y, (float)nud_y.Minimum, (float)nud_y.Maximum); nud_y.Value = (decimal)y; nud_x.Value = (decimal)x; cb_relative.Checked = false; } else { cb_relative.Checked = true; relativePos = new Vector2(); } base.OnShown(e); }
private void MouseHandler(RawInput data) { RawMouse m = data.Mouse; float speed = (float)ConfigManager.sMouseSpeed; AbsoluteMovement = (m.Flags & RawMouseFlags.MoveAbsolute) > 0; if (AbsoluteMovement) { if (ConfigManager.sAbsoluteToOsuWindow) { const int range = 65536; position.X = ((float)((m.LastX - range / 2) * speed) + range / 2) / range * GameBase.WindowManager.Width; position.Y = ((float)((m.LastY - range / 2) * speed) + range / 2) / range * GameBase.WindowManager.Height; } else { // Absolute coordinates need to be shifted to the osu window's position and scaled to the desktop resolution. position = ToScreenCoords(m) - new Vector2(GameBase.ClientBounds.X, GameBase.ClientBounds.Y); position.X = (position.X - GameBase.WindowManager.Width / 2) * speed + GameBase.WindowManager.Width / 2; position.Y = (position.Y - GameBase.WindowManager.Height / 2) * speed + GameBase.WindowManager.Height / 2; } } else { position.X += m.LastX * speed; position.Y += m.LastY * speed; } if (InputManager.ShallClampMouseToWindow) { position.X = OsuMathHelper.Clamp(position.X, 0, GameBase.WindowManager.Width - 1); position.Y = OsuMathHelper.Clamp(position.Y, 0, GameBase.WindowManager.Height - 1); } intermediatePositionsNextFrame.Add(position); ++amountMessages; latency += GameBase.stopWatch.ElapsedMilliseconds - lastProcessTime; }
internal void SetValue(double value, bool silent = false, bool final = false) { value = OsuMathHelper.Clamp(value, Min, Max); if (Current != value) { Current = value; if (!silent) { if (OnValueChanged != null) { OnValueChanged(final); } if (IsDragging || final) { AudioEngine.Click(null, @"sliderbar", 1 + progress * 0.2f); } } } updatePosition(); }
internal override void UpdateInput() { if (!IsInitialized || Player.Paused) { return; } int frameCheck = 0; if (!InputManager.ReplayMode) { InputManager.leftButton1 |= KeyboardHandler.IsKeyDown(BindingManager.For(Bindings.FruitsDash)); InputManager.leftButton1 |= JoystickHandler.IsKeyDown(BindingManager.For(Bindings.FruitsDash)); InputManager.leftButton1i |= InputManager.leftButton1; if (InputManager.leftButton1i) { InputManager.leftButton = ButtonState.Pressed; } } Dashing = InputManager.leftButton == ButtonState.Pressed; if (Dashing) { frameCheck += 4; } float currentMovementSpeed = baseMovementSpeed * specialMovementModifier; if (!Dashing) { currentMovementSpeed /= 2; } if (InputManager.ReplayMode || Player.Relaxing) { float newPos = InputManager.ReplayGamefieldCursor.X; if (InputManager.NewReplayFrame) { LeftPressed = catcher1.Position.X > newPos; RightPressed = catcher1.Position.X < newPos; } if (catcher1.Position.X != newPos) { #if DEBUG if (!ModManager.CheckActive(Mods.Autoplay) && (Math.Abs(catcher1.Position.X - newPos) > currentMovementSpeed * GameBase.SIXTY_FRAME_TIME)) { NotificationManager.ShowMessageMassive("Impossible movement (" + Math.Abs(catcher1.Position.X - newPos) + " vs " + (currentMovementSpeed * GameBase.SIXTY_FRAME_TIME) + ")", 1000); } #endif catcher1.FlipHorizontal = catcher1.Position.X > newPos; catcher1.Position.X = newPos; } } else { if (GameBase.ElapsedMilliseconds > 33) { return; } if (Math.Abs(catcher1.Position.X - checkPosition) > 0.01f) { catcher1.Position.X = checkPosition; CurrentScore.InvalidateSubmission(); } if ((RightPressed = KeyboardHandler.IsKeyDown(BindingManager.For(Bindings.FruitsRight)) || JoystickHandler.IsKeyDown(BindingManager.For(Bindings.FruitsRight)))) { frameCheck += 1; catcher1.Position.X = (float)(catcher1.Position.X + currentMovementSpeed * GameBase.ElapsedMilliseconds); catcher1.FlipHorizontal = false; } if ((LeftPressed = KeyboardHandler.IsKeyDown(BindingManager.For(Bindings.FruitsLeft)) || JoystickHandler.IsKeyDown(BindingManager.For(Bindings.FruitsLeft)))) { frameCheck += 2; catcher1.Position.X = (float)(catcher1.Position.X - currentMovementSpeed * GameBase.ElapsedMilliseconds); catcher1.FlipHorizontal = true; } } checkSpecialWaitingState(); importantFrame = frameCheck != importantFrameCheck; importantFrameCheck = frameCheck; catcher1.Position.X = OsuMathHelper.Clamp(catcher1.Position.X, 0, 512); checkPosition = catcher1.Position.X; }
private double validateValue(TrackBar t, double value) { return(OsuMathHelper.Clamp(value, t.Minimum, t.Maximum)); }
internal virtual void SetProgress(float progress) { progressBarForeground.VectorScale = new Vector2(OsuMathHelper.Clamp(progress, 0, 1) * length, height); }
internal void SetScrollPosition(Vector2 scrollPosition, float clamp = 0) { ScrollPosition = new Vector2(ScrollDraggerOnLeft && ScrollDragger && ScrollDraggerPadding ? -8 : 0, OsuMathHelper.Clamp(scrollPosition.Y, ClampingStartHeight, Math.Max(ClampingStartHeight, ContentDimensions.Y - ContentDisplayHeight)) * clamp + scrollPosition.Y * (1 - clamp)); if (float.IsNaN(ScrollPosition.X)) { ScrollPosition.X = 0; } if (float.IsNaN(ScrollPosition.Y)) { ScrollPosition.Y = ClampingStartHeight; } ContentSpriteManager.ViewOffset = ScrollPosition; ContentSpriteManagerBackground.ViewOffset = ScrollPosition; Children.ForEach(s => s.ScrollOffset = ScrollPosition); UpdateDragger(); }
private void InitializeTester() { if (!PREDEFINED_TEST) { return; } if (BeatmapManager.Beatmaps.Count > 0) { if (USE_LAST_PLAYED_BEATMAP) { List <Beatmap> temp = new List <Beatmap>(BeatmapManager.Beatmaps); temp.Sort((a, b) => { return(a.DateLastPlayed.CompareTo(b.DateLastPlayed)); }); BeatmapManager.Current = temp[temp.Count - 1]; } else //Choose a random beatmap { BeatmapManager.Current = BeatmapManager.Beatmaps[RNG.Next(0, BeatmapManager.Beatmaps.Count)]; } } if (MULTIPLAYER_MATCH) { if (BeatmapManager.Current == null) { NotificationManager.ShowMessage("Couldn't start in specified test mode because no beatmaps were available."); return; } BanchoClient.Start(); Mode = OsuModes.MatchSetup; const int player_count = 8; while (!BanchoClient.Connected || !BanchoClient.InitializationComplete) { Scheduler.Update(); } PresenceCache.QueryAll(); while (User.Id <= 0 || BanchoClient.Users.Count < player_count) { Scheduler.Update(); } List <User> users = BanchoClient.Users.FindAll(u => u.InitialLoadComplete && u.Id != User.Id); users.Insert(0, User); //we are the first user. MatchSetup.Match = new ClientSideMatch(new bMatch(MatchTypes.Standard, MatchScoringTypes.Score, MatchTeamTypes.TeamVs, PlayModes.Osu, @"My test game", string.Empty, player_count, BeatmapManager.Current.SortTitle, BeatmapManager.Current.BeatmapChecksum, BeatmapManager.Current.BeatmapId, MODS_TO_USE, 2, MultiSpecialModes.FreeMod )); for (int i = 0; i < player_count; i++) { MatchSetup.Match.slotId[i] = users[i].Id; MatchSetup.Match.UserSlots[i] = users[i]; MatchSetup.Match.slotStatus[i] = SlotStatus.Playing; switch (MatchSetup.Match.matchTeamType) { case MatchTeamTypes.TagTeamVs: case MatchTeamTypes.TeamVs: MatchSetup.Match.slotTeam[i] = i % 2 == 0 ? SlotTeams.Blue : SlotTeams.Red; break; } } bScoreFrame[] frames = new bScoreFrame[player_count]; for (int i = 0; i < player_count; i++) { frames[i] = new bScoreFrame { id = (byte)i, pass = true, currentHp = 200 } } ; RunBackgroundThread(delegate { Thread.Sleep(5000); for (int i = 0; i < player_count; i++) { PlayerVs.MatchPlayerSkipped(i); Thread.Sleep(100); } Thread.Sleep(2000); Player.QueueSkip(); Player.Instance?.DoSkip(); PlayerVs.AllPlayersLoaded = true; PlayerVs.AllPlayersCompleted = true; while (true) { byte player = (byte)RNG.Next(0, player_count); switch (RNG.Next(0, 30)) { default: frames[player].count300 += 1; frames[player].currentCombo++; frames[player].currentHp += 3; break; case 1: case 2: case 3: frames[player].count100 += 1; frames[player].currentCombo++; frames[player].currentHp += 2; break; case 4: case 5: frames[player].count50 += 1; frames[player].currentHp += 1; frames[player].currentCombo++; break; case 6: frames[player].countMiss += 1; frames[player].currentHp -= 50; frames[player].currentCombo = 0; break; } frames[player].currentHp = OsuMathHelper.Clamp(frames[player].currentHp, 0, 200); if (frames[player].currentHp == 0) { frames[player].pass = false; } else if (frames[player].currentHp > 100) { frames[player].pass = true; } frames[player].totalScore += frames[player].currentCombo * 300; frames[player].maxCombo = Math.Max(frames[player].maxCombo, frames[player].currentCombo); PlayerVs.MatchScoreUpdate(frames[player]); Thread.Sleep(50); } }); } switch (INITIAL_MODE) { case OsuModes.Play: if (BeatmapManager.Current == null) { NotificationManager.ShowMessage("Couldn't start in specified test mode because no beatmaps were available."); return; } ModManager.ModStatus = MODS_TO_USE; if (AUTOMATIC_SKIP) { GameBase.RunBackgroundThread(delegate { while (true) { if (Player.Instance != null && Player.Instance.Status != PlayerStatus.Busy) { Scheduler.Add(delegate { Player.Instance?.DoSkip(); }); if (Player.HasSkipped) { break; } } Thread.Sleep(200); } }); } if (AUTOPLAY) { ModManager.ModStatus |= Mods.Autoplay; } break; } QueuedMode = INITIAL_MODE; Player.Mode = INITIAL_PLAY_MODE; } }
internal static GridSizes ClampSize(GridSizes value) { return((GridSizes)OsuMathHelper.Clamp((int)value, (int)GridSizes.Tiny, (int)GridSizes.Large)); }
internal void CalculateStrains(DifficultyHitObjectFruits PreviousHitObject, double TimeRate) { // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. // See Taiko feedback thread. double TimeElapsed = (double)(BaseHitObject.StartTime - PreviousHitObject.BaseHitObject.StartTime) / TimeRate; double Decay = Math.Pow(DECAY_BASE, TimeElapsed / 1000); // Update new position with lazy movement. PlayerPositionOffset = OsuMathHelper.Clamp( PreviousHitObject.ActualNormalizedPosition, NormalizedPosition - (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError), NormalizedPosition + (NORMALIZED_HITOBJECT_RADIUS - playerPositioningError)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player. - NormalizedPosition; // Subtract HitObject position to obtain offset LastMovement = DistanceTo(PreviousHitObject); double Addition = SpacingWeight(LastMovement); if (NormalizedPosition < PreviousHitObject.NormalizedPosition) { LastMovement = -LastMovement; } HitCircleFruits previousHitCircle = PreviousHitObject.BaseHitObject as HitCircleFruits; double additionBonus = 0; double sqrtTime = Math.Sqrt(Math.Max(TimeElapsed, 25)); // Direction changes give an extra point! if (Math.Abs(LastMovement) > 0.1) { if (Math.Abs(PreviousHitObject.LastMovement) > 0.1 && Math.Sign(LastMovement) != Math.Sign(PreviousHitObject.LastMovement)) { double bonus = DIRECTION_CHANGE_BONUS / sqrtTime; // Weight bonus by how double bonusFactor = Math.Min(playerPositioningError, Math.Abs(LastMovement)) / playerPositioningError; // We want time to play a role twice here! Addition += bonus * bonusFactor; // Bonus for tougher direction switches and "almost" hyperdashes at this point if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10) { additionBonus += 0.3 * bonusFactor; } } // Base bonus for every movement, giving some weight to streams. Addition += 7.5 * Math.Min(Math.Abs(LastMovement), NORMALIZED_HITOBJECT_RADIUS * 2) / (NORMALIZED_HITOBJECT_RADIUS * 6) / sqrtTime; } // Bonus for "almost" hyperdashes at corner points if (previousHitCircle != null && previousHitCircle.DistanceToHyperDash <= 10) { if (!previousHitCircle.HyperDash) { additionBonus += 1.0; } else { // After a hyperdash we ARE in the correct position. Always! PlayerPositionOffset = 0; } Addition *= 1.0 + additionBonus * ((10 - previousHitCircle.DistanceToHyperDash) / 10); } Addition *= 850.0 / Math.Max(TimeElapsed, 25); Strain = PreviousHitObject.Strain * Decay + Addition; }
internal void Update() { float targetAlpha = backgroundIsReady && showStoryboard ? 1 : 0; float maskingTargetAlpha = WidescreenStoryboard ? 0 : targetAlpha; if (GameBase.Mode == OsuModes.Edit) { spriteManagerFG.Alpha = spriteManagerBG.Alpha = targetAlpha; spriteManagerMasking.Alpha = maskingTargetAlpha; } else { if (spriteManagerFG.Alpha != targetAlpha) { spriteManagerBG.Alpha = spriteManagerFG.Alpha = OsuMathHelper.Clamp(spriteManagerFG.Alpha + ((targetAlpha < spriteManagerFG.Alpha ? -0.07f : 0.07f) * (float)GameBase.FrameRatio), 0, 1); } if (spriteManagerMasking.Alpha != maskingTargetAlpha) { spriteManagerMasking.Alpha = OsuMathHelper.Clamp(spriteManagerMasking.Alpha + ((maskingTargetAlpha < spriteManagerMasking.Alpha ? -0.07f : 0.07f) * (float)GameBase.FrameRatio), 0, 1); } } bool breakMode = false; if (hitObjectManager.hitObjectsCount > 0) { if (beforeGameplay && AudioEngine.Time > hitObjectManager.EarliestHitObject.HittableStartTime - hitObjectManager.PreEmpt) { beforeGameplay = false; } else if (!afterGameplay && AudioEngine.Time > hitObjectManager.LatestHitObject.HittableEndTime + hitObjectManager.HitWindow50) { afterGameplay = true; } } else { beforeGameplay = true; afterGameplay = false; } if (GameBase.Mode == OsuModes.Play && (beforeGameplay || afterGameplay)) { breakMode = true; } for (int i = 0; i < eventBreaks.Count; i++) { EventBreak e = eventBreaks[i]; if (AudioEngine.Time < e.StartTime || AudioEngine.Time > e.EndTime) { continue; } breakMode = true; BreakCurrent = e; break; } if (GameBase.Mode == OsuModes.Play && Player.Passing != passingCurrent) { passingCurrent = Player.Passing; if (passingCurrent) { InvokeOnPassing(); } else { InvokeOnFailing(); } //Sprites for (int i = 0; i < storyLayerSprites[(int)StoryLayer.Fail].Count; i++) { Event e = storyLayerSprites[(int)StoryLayer.Fail][i]; e.Sprite.Bypass = passingCurrent; } //Samples for (int i = 0; i < storyLayerSamples[(int)StoryLayer.Fail].Count; i++) { EventSample e = (EventSample)storyLayerSamples[(int)StoryLayer.Fail][i]; if (passingCurrent) { AudioEngine.SampleEvents.Remove(e.SampleCache); } else { AudioEngine.SampleEvents.Add(e.SampleCache); } } if (!firstRun) { //Sprites for (int i = 0; i < storyLayerSprites[(int)StoryLayer.Pass].Count; i++) { Event e = storyLayerSprites[(int)StoryLayer.Pass][i]; e.Sprite.Bypass = !passingCurrent; } //Samples for (int i = 0; i < storyLayerSamples[(int)StoryLayer.Pass].Count; i++) { EventSample e = (EventSample)storyLayerSamples[(int)StoryLayer.Pass][i]; if (passingCurrent) { AudioEngine.SampleEvents.Add(e.SampleCache); } else { AudioEngine.SampleEvents.Remove(e.SampleCache); } } } firstRun = false; } if (GameBase.Mode == OsuModes.Play && Player.Loaded && breakMode != BreakMode && !InputManager.ReplayMode) { //toggles go here. are only run on switching mode. if (!breakMode) { NotificationManager.ClearMessageMassive(); //Clear any displaying messages when gameplay starts. } } BreakMode = breakMode; if (!breakMode) { BreakCurrent = null; } UpdateVideo(); UpdateDimming(); if (GameBase.SixtyFramesPerSecondFrame && showStoryboard) { LoadDynamic(false, true); } }