Я создаю программу для игры в дартс (чтобы использовать себя в своей комнате для игры в дартс) и хочу, чтобы пользователь мог щелкать по различным областям изображения доски для игры в дартс, чтобы зарегистрировать брошенные дротики.
ЭтоРазмер программы будет изменен, поэтому изображение дротика может изменить его размер, когда пользователь изменит размер окна программы.
Я использую список полигонов (pointF-массивов) для отображения каждой области и запуска некоторыхвычисление, чтобы увидеть, находится ли щелчок мыши внутри области многоугольников, но как правильно масштабировать эти многоугольники при изменении размера окна рисунка?Мои полигоны жестко запрограммированы для отображения области изображения на мишени для конкретного размера.
Редактировать: После действительно блестящего ответа Оливье Жако-Descombes, я исправил масштабирование с помощью функции GetScaledPoint, которая преобразует значения x и y указателя мыши в значения, соответствующие исходному размеру изображения, что позволяет легко проверять совпадения в исходных многоугольниках.Я отредактировал решение в коде ниже, если кто-то заинтересован.В этом примере Picture1 - это изображение доски для игры в дартс (например, http://quizmasters.biz/Pub%20Genius/Darts/Gfx/Dartboard_05.jpg), для которой заданы sizemode = stretch и docking = fill.
Public Class DartBoard
Dim Double20 = New PointF() {New PointF(263, 78), New PointF(275, 76), New PointF(284, 76), New PointF(293, 75), New PointF(306, 75), New PointF(319, 75), New PointF(332, 76), New PointF(330, 89), New PointF(320, 88), New PointF(309, 87), New PointF(300, 87), New PointF(289, 88), New PointF(277, 89), New PointF(267, 91), New PointF(264, 78)}
Dim Triple20 = New PointF() {New PointF(279, 154), New PointF(285, 154), New PointF(293, 154), New PointF(301, 152), New PointF(306, 152), New PointF(312, 152), New PointF(314, 151), New PointF(322, 152), New PointF(320, 167), New PointF(312, 165), New PointF(304, 164), New PointF(297, 165), New PointF(289, 166), New PointF(281, 166), New PointF(277, 154), New PointF(283, 153), New PointF(291, 153), New PointF(299, 152), New PointF(308, 152), New PointF(314, 153), New PointF(322, 153)}
Private startwidth As Integer = 0
Private startheight As Integer = 0
Public Structure DartBoardAreaStruct
Public Points As Integer
Public Area() As PointF
End Structure
Dim DartBoardAreas As New List(Of DartBoardAreaStruct)
Private Sub DartBoard_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DartBoardAreas.Add(New DartBoardAreaStruct With {.Area = Double20, .Points = 40})
DartBoardAreas.Add(New DartBoardAreaStruct With {.Area = Triple20, .Points = 60})
startwidth = PictureBox1.Width
startheight = PictureBox1.Height
End Sub
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
Dim scaledpos As PointF = GetScaledPoint(e.Location)
For Each DartBoardArea In DartBoardAreas
If Me.PolyGonHitTest(DartBoardArea.Area, scaledpos) Then
MsgBox(DartBoardArea.Points)
End If
Next
End Sub
Public Function PolyGonHitTest(ByVal polygonPoints() As PointF, ByVal mousePos As PointF) As Boolean
Dim path As New System.Drawing.Drawing2D.GraphicsPath
path.AddLines(polygonPoints)
Dim region As New Region(path)
If region.IsVisible(mousePos) Then Return True
Return False
End Function
Function GetScaledPoint(ByVal s As Point) As PointF
Dim xfactor As Double = 0
Dim yfactor As Double = 0
Dim OriginalSize As Size = New Size(startwidth, startheight)
Dim NewSize As Size = New Size(PictureBox1.Width, PictureBox1.Height)
If NewSize.Width < OriginalSize.Width Then
xfactor = OriginalSize.Width / NewSize.Width
Else
xfactor = NewSize.Width / OriginalSize.Width
End If
If NewSize.Height < OriginalSize.Height Then
yfactor = OriginalSize.Height / NewSize.Height
Else
yfactor = NewSize.Height / OriginalSize.Height
End If
Return New PointF(s.X / xfactor, s.Y / yfactor)
End Function
End Class