private void Initialize() { const string KEY_CROP_FILENAME = "key.lvb"; const int KEY_CROP_X = 250, KEY_CROP_Y = 473, KEY_CROP_WIDTH = 524, KEY_CROP_HEIGHT = 58; const string BAR_CROP_FILENAME = "bar.lvb"; const int BAR_CROP_X = 254, BAR_CROP_Y = 518, BAR_CROP_WIDTH = 524, BAR_CROP_HEIGHT = 43; windowFinder = new WindowFinder(); imageFinder = new ImageFinder(0.9); // load all images based on Signal types. throws error if any of these are not found foreach (Signal s in Enum.GetValues(typeof(Signal))) { string subImagePath = String.Format("{0}{1}{2}", IMAGE_PATH, s.ToString(), IMAGE_EXT); imageFinder.SubImages.Add(s, new Image<Bgr, byte>(subImagePath)); } // init gamestate for (int i = 0; i < gameState.Length; i++) { gameState[i] = new Signal[KEY_COLUMNS_MAX]; } keyCropSettings = CropSettings.Load(KEY_CROP_FILENAME, KEY_CROP_X, KEY_CROP_Y, KEY_CROP_WIDTH, KEY_CROP_HEIGHT); keyCropSettings.SaveIfNotExist(KEY_CROP_FILENAME); barCropSettings = CropSettings.Load(BAR_CROP_FILENAME, BAR_CROP_X, BAR_CROP_Y, BAR_CROP_WIDTH, BAR_CROP_HEIGHT); barCropSettings.SaveIfNotExist(BAR_CROP_FILENAME); }
public void PressThread() { ImageFinder barImageFinder = new ImageFinder(THRESHOLD_BAR); InitializeImageFinder(barImageFinder, "Bar_"); // if the press-key signal is found, presses the keys found by the state thread while (_Enabled) { using (Image<Bgr, byte> bar_image_source = getCroppedBarScreenshot()) { if (bar_image_source == null) continue; Dictionary<object, Rectangle[]> matches = barImageFinder.FindAllMatches(bar_image_source, "", false); foreach (KeyValuePair<object, Rectangle[]> pairs in matches) { if (pairs.Value.Length <= 0) continue; Signal matchSignal = (Signal) pairs.Key; int barColumn = pairs.Value[0].Left / KEY_COLUMNS_WIDTH; if (barColumn == lastColumnPressed) continue; if (matchSignal == Signal.Bar_Key || matchSignal == Signal.Bar_Key_Fever) { lastColumnPressed = barColumn; PressKeys(barColumn); #if DEBUG addDebugImage(bar_image_source, pairs); #endif System.Threading.Thread.Sleep(50); break; } else // todo: check bar_space explicitly { if ( !(gameState[barColumn].Contains(Signal.Key_Space) || gameState[barColumn].Contains(Signal.Key_Space_Fever))) continue; // don't press space if there is no space to be pressed, attempt to ignore false positive lastColumnPressed = barColumn; if(matchSignal == Signal.Bar_Space_Alt) System.Threading.Thread.Sleep((pairs.Value[0].Top * 3) / 2); // inaccurate windowFinder.SendKeystroke((ushort)VirtualKeyCode.SPACE); #if DEBUG addDebugImage(bar_image_source, pairs); #endif System.Threading.Thread.Sleep(100); break; } } } } }
private void InitializeImageFinder(ImageFinder imgFinder, string startsWith = "") { foreach (Signal s in Enum.GetValues(typeof(Signal))) { if (startsWith.Length > 0 && !s.ToString().StartsWith(startsWith)) continue; string subImagePath = String.Format("{0}{1}{2}", IMAGE_PATH, s.ToString(), IMAGE_EXT); imgFinder.SubImages.Add(s, new Image<Bgr, byte>(subImagePath)); } }
public void StateThread() { ImageFinder stateImageFinder = new ImageFinder(THRESHOLD_KEY); InitializeImageFinder(stateImageFinder, "Key_"); // continously updates key state by recognizing visible keys // stopwatch used for autoready Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); while (_Enabled) { List<PhysicalSignal>[] newGameState = new List<PhysicalSignal>[KEY_COLUMNS]; for (int i = 0; i < newGameState.Length; i++) { newGameState[i] = new List<PhysicalSignal>(); } using (Image<Bgr, byte> key_image_source = getCroppedKeyScreenshot()) { if (key_image_source == null) continue; Dictionary<object, Rectangle[]> matches = stateImageFinder.FindAllMatches(key_image_source, "", false, EightKeyMode ? "" : "Key_8_"); // ignore key_8 if eight key mode is not enabled bool addedAtLeastOne = false; foreach (KeyValuePair<object, Rectangle[]> pairs in matches) { if (pairs.Value.Length <= 0) continue; foreach (Rectangle match in pairs.Value) { PhysicalSignal physicalSignal = new PhysicalSignal() { PositionX = match.Left, PositionY = match.Top, Type = (Signal) pairs.Key }; // estimate column by match location // possibility this may be off if key_image off-center int column = match.Left / KEY_COLUMNS_WIDTH; if (column > KEY_COLUMNS - 1) column = KEY_COLUMNS - 1; newGameState[column].Add(physicalSignal); addedAtLeastOne = true; } } if (addedAtLeastOne) { stopwatch.Restart(); } else if(AutoReady && stopwatch.ElapsedMilliseconds > TIME_BEFORE_AUTO_READY_MS) { windowFinder.SendKeystroke((ushort)VirtualKeyCode.F5); stopwatch.Reset(); // reset ensures bot does not auto ready more than once (un-readying). can be bad if it misses ready moment, if cooldown is too short } } Signal[][] rawGameState = new Signal[KEY_COLUMNS][]; List<PhysicalSignal>[] oldPhysicalGameState = physicalGameState; for (int i = 0; i < newGameState.Length; i++) { if (newGameState[i].Count > 0 && oldPhysicalGameState[i].Count > 1 && oldPhysicalGameState[i].Count > newGameState[i].Count) { // TEST: replaces gamestates per column if old game state had >=2 keys and this state has less, but not 0 (attempt to "fix" keys occasionally not being recognized in high bpm songs due to particles) // similar to caching // works // TODO: proper newGameState[i] = oldPhysicalGameState[i]; } PhysicalSignal[] physicalSignalArray = newGameState[i].ToArray(); Array.Sort(physicalSignalArray); rawGameState[i] = new Signal[KEY_COLUMNS_MAX]; for (int i2 = 0; i2 < physicalSignalArray.Length; i2++) { rawGameState[i][i2] = physicalSignalArray[i2].Type; } } physicalGameState = newGameState; gameState = rawGameState; } }