public static Vec2 CalculateForce(Vec2 a, Vec2 b, double coulomb) { Vec2 acc = a - b; acc /= acc.Length(); acc *= coulomb / (DistanceSq(a, b)); return(acc); }
private unsafe void ProcessCapture() { try { Screenshot ssht = _capture.Capture(); Image <Gray, byte> process; fixed(byte *p = ssht.Data) { IntPtr ptr = (IntPtr)p; Screen = new Image <Bgra, byte>(ssht.Width, ssht.Height, ssht.Stride, ptr) { ROI = BOX_SIZE }; process = Screen.Convert <Gray, byte>(); } ssht.Dispose(); _force = new Vec2(); // Read player position from memory _playerPos = GetPlayerPosition(); Rectangle powerDetectionROI = new Rectangle( (int)Math.Max(_playerPos.X - 100, 0), (int)Math.Max(_playerPos.Y - 75, 0), (int)Math.Min(BOX_SIZE.Width - (_playerPos.X - 100), 200), (int)Math.Min(BOX_SIZE.Height - (_playerPos.Y - 75), 100)); // Look for power process.ROI = powerDetectionROI; using (Image <Gray, float> result = process.MatchTemplate(_imgPower, TemplateMatchingType.SqdiffNormed)) { double minDistSq = double.MaxValue; int minX = 0, minY = 0; for (int y = 0; y < result.Height; y++) { for (int x = 0; x < result.Width; x++) { if (result.Data[y, x, 0] < 0.20) { double dist = (x - _playerPos.X) * (x - _playerPos.X) + (y - _playerPos.Y) * (y - _playerPos.Y); if (dist < minDistSq) { minDistSq = dist; minX = x; minY = y; } } } } if (minDistSq != double.MaxValue) { Rectangle match = new Rectangle(minX + process.ROI.X, minY + process.ROI.Y, _imgPower.Width, _imgPower.Height); if (DO_DRAWING) { Screen.Draw(match, new Bgra(0, 255, 255, 255), 2); Screen.Draw(new LineSegment2DF(match.Location, _playerPos), new Bgra(0, 255, 255, 255), 1); } Vec2 acc = Vec2.CalculateForce( new Vec2(match.X + _imgPower.Width / 2.0, match.Y + _imgPower.Height / 2.0), new Vec2(_playerPos.X, _playerPos.Y), 4000); _force += acc; } } // Processing bounding box Rectangle bulletDetectionROI = new Rectangle( (int)Math.Max(_playerPos.X - INITIAL_DETECTION_RADIUS, 0), (int)Math.Max(_playerPos.Y - INITIAL_DETECTION_RADIUS, 0), (int)Math.Min(BOX_SIZE.Width - ((int)_playerPos.X - INITIAL_DETECTION_RADIUS), INITIAL_DETECTION_RADIUS * 2), (int)Math.Min(BOX_SIZE.Height - ((int)_playerPos.Y - INITIAL_DETECTION_RADIUS), INITIAL_DETECTION_RADIUS * 2)); process.ROI = bulletDetectionROI; if (TEST_MODE) { return; } Vec2 _playerVec = new Vec2(_playerPos.X, _playerPos.Y); var binthresh = process.SmoothBlur(3, 3).ThresholdBinary(new Gray(240), new Gray(255)); //220 // Detect blobs (bullets) on screen CvBlobs resultingImgBlobs = new CvBlobs(); uint noBlobs = _bDetect.Detect(binthresh, resultingImgBlobs); int blobCount = 0; resultingImgBlobs.FilterByArea(10, 500); foreach (CvBlob targetBlob in resultingImgBlobs.Values) { if (DO_DRAWING) { Screen.ROI = new Rectangle(process.ROI.X + BOX_SIZE.X, process.ROI.Y + BOX_SIZE.Y, process.ROI.Width, process.ROI.Height); Screen.FillConvexPoly(targetBlob.GetContour(), new Bgra(0, 0, 255, 255)); } // Find closest point on blob contour to player Point minPoint = targetBlob.GetContour()[0]; double minDist = double.MaxValue; foreach (var point in targetBlob.GetContour()) { Point adj = new Point(point.X + process.ROI.X, point.Y + process.ROI.Y); double dist = (adj.X - _playerPos.X) * (adj.X - _playerPos.X) + (adj.Y - _playerPos.Y) * (adj.Y - _playerPos.Y); if (dist < minDist) { minPoint = adj; minDist = dist; } } // Ensure the bullet is in the correct range if (minDist < _detectionRadius * _detectionRadius) { // Calculate forces Vec2 acc = Vec2.CalculateForce(new Vec2(minPoint.X, minPoint.Y), _playerVec, -5000); _force += acc; if (DO_DRAWING) { Screen.ROI = BOX_SIZE; Screen.Draw(new LineSegment2DF(_playerPos, minPoint), new Bgra(0, 255, 128, 255), 1); } blobCount++; } } Screen.ROI = BOX_SIZE; process.ROI = Rectangle.Empty; // Calculate new detection orb radius //float nRad = Math.Max(20.0f, INITIAL_DETECTION_RADIUS/(1 + blobCount*0.3f)); if (blobCount >= 1) { _detectionRadius = (_detectionRadius * 29 + 5.0f) / 30.0f; } else { _detectionRadius = (_detectionRadius * 59 + INITIAL_DETECTION_RADIUS) / 60.0f; } // Account for border force, to prevent cornering //if (BOX_SIZE.Width - _playerPos.X < 120) _force += new Vec2(Vec2.CalculateForce(BOX_SIZE.Width - _playerPos.X, -4000), 0); //if (_playerPos.X < 120) _force += new Vec2(Vec2.CalculateForce(_playerPos.X, 4000), 0); if (BOX_SIZE.Height - _playerPos.Y < 50) { _force += new Vec2(0, Vec2.CalculateForce(BOX_SIZE.Height - _playerPos.Y, -2000)); } if (_playerPos.Y < 200) { _force += new Vec2(0, Vec2.CalculateForce(_playerPos.Y, 2000)); } // Corners are the devil _force += Vec2.CalculateForce(new Vec2(BOX_SIZE.Width, BOX_SIZE.Height), _playerVec, -2000); _force += Vec2.CalculateForce(new Vec2(0, BOX_SIZE.Height), _playerVec, -2000); _force += Vec2.CalculateForce(new Vec2(0, 0), _playerVec, -2000); _force += Vec2.CalculateForce(new Vec2(BOX_SIZE.Width, 0), _playerVec, -2000); // Assist force if (ShouldAssist) { Vec2 sub = new Vec2(AssistPoint.X, AssistPoint.Y) - _playerVec; double dist = sub.Length(); _force += new Vec2(sub.X / dist * 2, sub.Y / dist * 2); } //imageToShow.Draw("BLOB_AREA: " + percBlob, new Point(10, 20), FontFace.HersheyPlain, 1, new Bgra(255, 255, 255, 255), 1); if (DO_DRAWING) { Screen.Draw( new Rectangle((int)(_playerPos.X - 3), (int)(_playerPos.Y - 3), 6, 6), new Bgra(0, 255, 0, 255), 2); Screen.Draw(new CircleF(_playerPos, _detectionRadius), new Bgra(0, 255, 255, 255), 1); if (ShouldAssist) { Screen.Draw( new LineSegment2DF(_playerPos, AssistPoint), new Bgra(128, 0, 255, 255), 2); Screen.Draw("ASSIST", new Point(10, 40), FontFace.HersheyPlain, 1, new Bgra(0, 255, 0, 255), 1); } // Draw force vector Screen.Draw( new LineSegment2DF(_playerPos, new PointF((float)(_playerPos.X + _force.X), (float)(_playerPos.Y + _force.Y))), new Bgra(0, 128, 255, 255), 5); Screen.Draw(powerDetectionROI, new Bgra(255, 255, 0, 255), 1); Screen.Draw(bulletDetectionROI, new Bgra(0, 0, 255, 255), 1); if (DoMovement) { Screen.Draw("DO_MOVEMENT", new Point(10, 20), FontFace.HersheyPlain, 1, new Bgra(0, 255, 0, 255), 1); } _form.imageBox.Image = Screen; } process.Dispose(); } catch (Exception e) { Console.WriteLine(e.ToString()); } }