/// <summary> /// Ctor - /// </summary> /// <param name="hitObject"></param> /// <param name="type"></param> /// <param name="time"></param> /// <param name="keys"></param> public ReplayAutoplayFrame(HitObjectInfo hitObject, ReplayAutoplayFrameType type, int time, ReplayKeyPressState keys) { HitObject = hitObject; Type = type; Time = time; Keys = keys; }
/// <summary> /// Converts a key press state to a list of lanes that are active. /// </summary> /// <param name="keys"></param> /// <returns></returns> public static List <int> KeyPressStateToLanes(ReplayKeyPressState keys) { var lanes = new List <int>(); if (keys.HasFlag(ReplayKeyPressState.K1)) { lanes.Add(0); } if (keys.HasFlag(ReplayKeyPressState.K2)) { lanes.Add(1); } if (keys.HasFlag(ReplayKeyPressState.K3)) { lanes.Add(2); } if (keys.HasFlag(ReplayKeyPressState.K4)) { lanes.Add(3); } if (keys.HasFlag(ReplayKeyPressState.K5)) { lanes.Add(4); } if (keys.HasFlag(ReplayKeyPressState.K6)) { lanes.Add(5); } if (keys.HasFlag(ReplayKeyPressState.K7)) { lanes.Add(6); } return(lanes); }
/// <summary> /// Generates a perfect replay for the keys game mode. /// </summary> /// <param name="replay"></param> /// <param name="map"></param> /// <returns></returns> public static Replay GeneratePerfectReplayKeys(Replay replay, Qua map) { var nonCombined = new List <ReplayAutoplayFrame>(); foreach (var hitObject in map.HitObjects) { // Add key press frame nonCombined.Add(new ReplayAutoplayFrame(hitObject, ReplayAutoplayFrameType.Press, hitObject.StartTime, KeyLaneToPressState(hitObject.Lane))); // If LN, add key up state at end time if (hitObject.IsLongNote) { nonCombined.Add(new ReplayAutoplayFrame(hitObject, ReplayAutoplayFrameType.Release, hitObject.EndTime - 1, KeyLaneToPressState(hitObject.Lane))); } // If not ln, add key up frame 1ms after object. else { nonCombined.Add(new ReplayAutoplayFrame(hitObject, ReplayAutoplayFrameType.Release, hitObject.StartTime + 30, KeyLaneToPressState(hitObject.Lane))); } } // Order objects by time nonCombined = nonCombined.OrderBy(x => x.Time).ToList(); // Global replay state so we can loop through in track it. ReplayKeyPressState state = 0; // Add beginning frame w/ no press state. (-10000 just to be on the safe side.) replay.Frames.Add(new ReplayFrame(-10000, 0)); var startTimeGroup = nonCombined.GroupBy(x => x.Time).ToDictionary(x => x.Key, x => x.ToList()); foreach (var item in startTimeGroup) { foreach (var frame in item.Value) { switch (frame.Type) { case ReplayAutoplayFrameType.Press: state |= KeyLaneToPressState(frame.HitObject.Lane); break; case ReplayAutoplayFrameType.Release: state -= KeyLaneToPressState(frame.HitObject.Lane); break; default: throw new ArgumentOutOfRangeException(); } } //Console.WriteLine($"Added frame at: {item.Key} with state: {state}"); replay.Frames.Add(new ReplayFrame(item.Key, state)); } return(replay); }
public static Replay GenerateAutoplayReplay(Qua map) { var replay = new Replay(); replay.PlayerName = "Autoplay"; replay.Mode = map.Mode; replay.Frames = new List <ReplayFrame>(); var nonCombined = new List <ReplayAutoplayFrame>(); foreach (var hitObject in map.HitObjects) { nonCombined.Add(new ReplayAutoplayFrame(hitObject, ReplayAutoplayFrameType.Press, hitObject.StartTime, KeyLaneToPressState(hitObject.Lane))); if (hitObject.IsLongNote) { nonCombined.Add(new ReplayAutoplayFrame(hitObject, ReplayAutoplayFrameType.Release, hitObject.EndTime - 1, KeyLaneToPressState(hitObject.Lane))); } else { nonCombined.Add(new ReplayAutoplayFrame(hitObject, ReplayAutoplayFrameType.Release, hitObject.StartTime + 30, KeyLaneToPressState(hitObject.Lane))); } } nonCombined = nonCombined.OrderBy(x => x.Time).ToList(); ReplayKeyPressState state = 0; replay.Frames.Add(new ReplayFrame(-10000, 0)); var startTimeGroup = nonCombined.GroupBy(x => x.Time).ToDictionary(x => x.Key, x => x.ToList()); foreach (var item in startTimeGroup) { foreach (var frame in item.Value) { switch (frame.Type) { case ReplayAutoplayFrameType.Press: state |= KeyLaneToPressState(frame.HitObject.Lane); break; case ReplayAutoplayFrameType.Release: state -= KeyLaneToPressState(frame.HitObject.Lane); break; default: throw new ArgumentOutOfRangeException(); } } replay.Frames.Add(new ReplayFrame(item.Key, state)); } return(replay); }
/// <summary> /// Converts an input manager's binding store to a key press state. /// </summary> /// <param name="bindingStore"></param> /// <returns></returns> private static ReplayKeyPressState BindingStoreToKeyPressState(IReadOnlyList <InputBindingKeys> bindingStore) { ReplayKeyPressState state = 0; for (var i = 0; i < bindingStore.Count; i++) { if (bindingStore[i].Pressed) { state |= Replay.KeyLaneToPressState(i + 1); } } return(state); }
/// <summary> /// Gets all of the individual unique key presses during the replay. /// </summary> public List <ReplayKeyPressInfo> GetKeyPresses() { var keyPresses = new List <ReplayKeyPressInfo>(); ReplayKeyPressState previousKeys = 0; foreach (var frame in Frames) { if (frame.Keys != previousKeys) { var currentLanes = KeyPressStateToLanes(frame.Keys); var previousLanes = KeyPressStateToLanes(previousKeys); var keyDifferences = currentLanes.Except(previousLanes) .Concat(previousLanes.Except(currentLanes)) .ToList(); foreach (var key in keyDifferences) { // key was pressed in this frame. if (currentLanes.Contains(key)) { keyPresses.Add(new ReplayKeyPressInfo(KeyLaneToPressState(key + 1), frame.Time)); } // Key was released in this frame. else if (previousLanes.Contains(key)) { var foundPress = keyPresses.FindLast(x => x.Key == KeyLaneToPressState(key + 1)); foundPress.TimeReleased = frame.Time; } } } previousKeys = frame.Keys; } return(keyPresses); }
/// <summary> /// Ctor - /// </summary> /// <param name="time"></param> /// <param name="keys"></param> public ReplayFrame(int time, ReplayKeyPressState keys) { Time = time; Keys = keys; }
/// <summary> /// Adds a frame to the replay. /// </summary> public void AddFrame(int time, ReplayKeyPressState keys) => Frames.Add(new ReplayFrame(time, keys));
/// <summary> /// </summary> /// <param name="key"></param> /// <param name="timePressed"></param> /// <param name="timeReleased"></param> public ReplayKeyPressInfo(ReplayKeyPressState key, float timePressed, float timeReleased = 0) { Key = key; TimePressed = timePressed; TimeReleased = timeReleased; }
/// <summary> /// Adds a replay frame with the correct key press state. /// </summary> private void AddFrame(ReplayKeyPressState state) { var manager = Screen.Ruleset.HitObjectManager as HitObjectManagerKeys; Replay.AddFrame((int)manager.CurrentAudioPosition, state); }
/// <summary> /// </summary> /// <param name="key"></param> public VirtualReplayKeyBinding(ReplayKeyPressState key) => Key = key;
/// <summary> /// Adds a replay frame with the correct key press state. /// </summary> private void AddFrame(ReplayKeyPressState state) => Replay.AddFrame((int)Screen.Timing.Time, state);