Рисование.

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

oskolok_vatbI
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 112
Зарегистрирован: 07.07.2007 (Сб) 16:13
Откуда: г. Казань

Рисование.

Сообщение oskolok_vatbI » 21.04.2009 (Вт) 14:35

Вопрос такой: в PictureBox-е нарисован прямоугольник и окружность, которой можно управлять стрелками. Нужно чтобы окружность при пересечении с прямоугольником как бы «упиралась в стену», т.е. не заходила на него. Как это реализуется? Читаю про пересечение областей, может через них получиться? Или меня совсем не в ту сторону понесло? Спасибо.
Код: Выделить всё
Dim x As Integer = 100 : Dim y As Integer = 100
    Dim key As String

    Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
        Dim gr As Graphics = e.Graphics
        Dim rect As New Rectangle(30, 60, 60, 150)
        Dim fillregion As New Region(rect)
        gr.FillRegion(Brushes.Red, fillregion)
        gr.DrawEllipse(Pens.Blue, x, y, 20, 20)
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Select Case key
            Case "up"
                y -= 10
            Case "down"
                y += 10
            Case "left"
                x -= 10
            Case "right"
                x += 10
        End Select
        PB.Refresh()
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        If e.KeyCode = Keys.Up Then key = "up"
        If e.KeyCode = Keys.Down Then key = "down"
        If e.KeyCode = Keys.Left Then key = "left"
        If e.KeyCode = Keys.Right Then key = "right"
    End Sub

    Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
        key = Nothing
    End Sub

MIT
Мега гуру
Мега гуру
Аватара пользователя
 
Сообщения: 2211
Зарегистрирован: 17.09.2006 (Вс) 22:46

Re: Рисование.

Сообщение MIT » 21.04.2009 (Вт) 15:26

ИМХО - не туда :)
Может что-нибудь найдешь, обсуждали уже

Добавлено: хотя нет, тебе вроде таких сложностей не надо. Может просто матиматика? Например: если Х(центра окружности) + радиус больше чем Х правой линии, то стоп
Изображение
You can change your face, but can`t change your mind. No matter what you do.
Создайте еще более понятный интерфейс и мир создаст еще более тупого юзера. (с) Баш

oskolok_vatbI
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 112
Зарегистрирован: 07.07.2007 (Сб) 16:13
Откуда: г. Казань

Re: Рисование.

Сообщение oskolok_vatbI » 21.04.2009 (Вт) 16:12

Вот такой выкрутас я наваял:

Код: Выделить всё
Public Class Form1
    Dim x As Integer = 100 : Dim y As Integer = 100
    Dim key As String

    Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
        Dim gr As Graphics = e.Graphics
        Dim rect As New Rectangle(30, 60, 60, 150)
        Dim fillregion As New Region(rect)
        gr.FillRegion(Brushes.Red, fillregion)
        gr.DrawEllipse(Pens.Blue, x, y, 20, 20)

        Dim clipRegion As New [Region](rect)
        e.Graphics.SetClip(clipRegion, Drawing2D.CombineMode.Intersect)

        Select Case key
            Case "up"
                If e.Graphics.IsVisible(x, y) Then
                    y += 1
                    key = "nothing"
                Else
                    y -= 1
                End If

            Case "down"
                If e.Graphics.IsVisible(x + 20, y + 20) Then
                    y -= 1
                    key = "nothing"
                Else
                    y += 1
                End If

            Case "left"
                If e.Graphics.IsVisible(x, y) Then
                    x += 1
                    key = "nothing"
                Else
                    x -= 1
                End If

            Case "right"
                If e.Graphics.IsVisible(x + 20, y + 20) Then
                    x -= 1
                    key = "nothing"
                Else
                    x += 1
                End If
        End Select

    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        PB.Refresh()
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        If e.KeyCode = Keys.Up Then key = "up"
        If e.KeyCode = Keys.Down Then key = "down"
        If e.KeyCode = Keys.Left Then key = "left"
        If e.KeyCode = Keys.Right Then key = "right"
    End Sub

    Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
        key = "nothing"
    End Sub
End Class


В принципе, работает. Это нормальное решение ?

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Рисование.

Сообщение Nord777 » 21.04.2009 (Вт) 18:03

В принципе, работает. Это нормальное решение?

Код, выполняющий точно такие же действия.
Код: Выделить всё
Public Class Form1
   Dim x As Integer = 80 : Dim y As Integer = 215
   Dim rect As New Rectangle(50, 60, 60, 150)
   Dim AddX, AddY, Mul As Integer
   Dim key As Keys

   Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
      e.Graphics.FillRectangle(Brushes.Red, rect)
      e.Graphics.DrawEllipse(Pens.Blue, x, y, 20, 20)
   End Sub

   Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
      Dim k As Keys = e.KeyCode
      If k = Keys.Left Or k = Keys.Right Then AddX = k - 38 : AddY = 0
      If k = Keys.Up Or k = Keys.Down Then AddY = k - 39 : AddX = 0
      If k = Keys.Up Or k = Keys.Left Then Mul = 1
      If k = Keys.Down Or k = Keys.Right Then Mul = 21
      If rect.Contains(x + AddX * Mul, y + AddY * Mul) Then Exit Sub
      x += AddX : y += AddY
      PB.Refresh()
   End Sub
End Class
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

oskolok_vatbI
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 112
Зарегистрирован: 07.07.2007 (Сб) 16:13
Откуда: г. Казань

Re: Рисование.

Сообщение oskolok_vatbI » 22.04.2009 (Ср) 12:24

Большое спасибо ! Еще пара вопросов:
1. Как сделать такое для нескольких прямоугольников ? Вообще, нужно сделать что-то типа лабиринта, может его стоит рисовать по другому, а не прямоугольниками ? Попробовал создать несколько прямоугольников и для каждого сделать
Код: Выделить всё
If rect.Contains(x + AddX * Mul, y + AddY * Mul) Then Exit Sub

как-то странно, на некоторые круг не может попасть, а по некоторым "бегает" свободно...
Добавлено: решил с помощью For Each.
2. Пытался по аналогии сделать чтобы круг не "упирался в стену", а "толкал" прямоугольник перед собой:
Код: Выделить всё
Public Class Form1
    Dim x As Integer = 80 : Dim y As Integer = 215
    Dim x1 As Integer = 100 : Dim y1 As Integer = 215
    Dim rect As New Rectangle(x1, y1, 60, 150)
    Dim AddX, AddY, Mul As Integer
    Dim key As Keys

    Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
        e.Graphics.FillRectangle(Brushes.Red, x1, y1, 60, 150)
        e.Graphics.DrawEllipse(Pens.Blue, x, y, 20, 20)
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Dim k As Keys = e.KeyCode
        If k = Keys.Left Or k = Keys.Right Then AddX = k - 38 : AddY = 0
        If k = Keys.Up Or k = Keys.Down Then AddY = k - 39 : AddX = 0
        If k = Keys.Up Or k = Keys.Left Then Mul = 1
        If k = Keys.Down Or k = Keys.Right Then Mul = 21
        If rect.Contains(x + AddX * Mul, y + AddY * Mul) Then
            x1 += AddX : y1 += AddY
        End If
        x += AddX : y += AddY
        PB.Refresh()
    End Sub
End Class

Тоже не получается, сначала "толкает", а потом заезжает на него. Похоже, что я неправильно создаю прямоугольник.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Рисование.

Сообщение Nord777 » 22.04.2009 (Ср) 17:30

Код: Выделить всё
Public Class Form1
   Dim WallRect As New Rectangle(50, 60, 60, 150)
   Dim BallRect As New Rectangle(80, 215, 20, 20)
   Dim AddX, AddY As Integer

   Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
      e.Graphics.FillRectangle(Brushes.Red, WallRect)
      e.Graphics.DrawEllipse(Pens.Blue, BallRect)
   End Sub

   Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
      Dim k As Keys = e.KeyCode
      If k = Keys.Left Or k = Keys.Right Then AddX = k - 38 : AddY = 0
      If k = Keys.Up Or k = Keys.Down Then AddY = k - 39 : AddX = 0
      BallRect.X += AddX : BallRect.Y += AddY

      Dim TmpRect As New Rectangle(BallRect.X, BallRect.Y, BallRect.Width + 1, BallRect.Height + 1)
      If TmpRect.IntersectsWith(WallRect) Then
         WallRect.X += AddX : WallRect.Y += AddY
      End If
      PB.Refresh()
   End Sub
End Class

ИЛИ
Код: Выделить всё
Public Class Form1
   <System.Runtime.InteropServices.DllImport("user32.dll")> _
   Private Shared Function GetKeyboardState(ByVal keyState() As Byte) As Boolean
   End Function

   Dim WallRect As New Rectangle(50, 60, 60, 150)
   Dim BallRect As New Rectangle(80, 215, 50, 50)
   Dim AddX, AddY As Integer
   Dim BallReg As System.Drawing.Region
   Dim P As System.Drawing.Drawing2D.GraphicsPath
   Dim kState(255) As Byte

   Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
      e.Graphics.FillRectangle(Brushes.Red, WallRect)
      e.Graphics.DrawEllipse(Pens.Blue, BallRect)
   End Sub

   Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
      If Not GetKeyboardState(kState) Then Exit Sub
      Dim Up, Down, Left, Right As Boolean

      If kState(Keys.Up) >= 128 Then Up = True : AddY = -1
      If kState(Keys.Down) >= 128 Then Down = True : AddY = 1
      If kState(Keys.Left) >= 128 Then Left = True : AddX = -1
      If kState(Keys.Right) >= 128 Then Right = True : AddX = 1

      If Not (Up Or Down Or Left Or Right) Then Exit Sub
      If Not (Left Or Right) Then AddX = 0
      If Not (Up Or Down) Then AddY = 0

      BallRect.X += AddX : BallRect.Y += AddY

      P = New System.Drawing.Drawing2D.GraphicsPath
      P.AddArc(BallRect, 0, 359)
      BallReg = New System.Drawing.Region(P)

      If BallReg.IsVisible(WallRect) Then WallRect.X += AddX : WallRect.Y += AddY
      PB.Refresh()
   End Sub
End Class
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

oskolok_vatbI
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 112
Зарегистрирован: 07.07.2007 (Сб) 16:13
Откуда: г. Казань

Re: Рисование.

Сообщение oskolok_vatbI » 23.04.2009 (Чт) 14:01

Nord777 - большое спасибо за помощь, почти получилось. Осталась одна проблемма, немного исправив и объединив твои способы получил такое:
Код: Выделить всё
Public Class Form1
    Dim WallRect As New Rectangle(100, 200, 50, 150) 'Стена
    Dim BallRect As New Rectangle(100, 100, 20, 20)  'Мячик
    Dim BoxRect As New Rectangle(100, 130, 50, 50)   'Коробка
    Dim AddBallX, AddBallY, AddBoxX, AddBoxY As Integer
    Dim key As Keys

    Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
        e.Graphics.FillRectangle(Brushes.Red, WallRect)
        e.Graphics.FillEllipse(Brushes.Blue, BallRect)
        e.Graphics.FillRectangle(Brushes.Green, BoxRect)
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Dim k As Keys = e.KeyCode
        If k = Keys.Left Or k = Keys.Right Then AddBallX = k - 38 : AddBallY = 0
        If k = Keys.Up Or k = Keys.Down Then AddBallY = k - 39 : AddBallX = 0

        Dim tmpBallRect As New Rectangle(BallRect.X + AddBallX, BallRect.Y + AddBallY, BallRect.Width + 1, BallRect.Height + 1)
        If WallRect.IntersectsWith(tmpBallRect) Then Exit Sub

        If tmpBallRect.IntersectsWith(BoxRect) Then 'мне кажется ошибка здесь
            If k = Keys.Left Or k = Keys.Right Then AddBoxX = k - 38 : AddBoxY = 0
            If k = Keys.Up Or k = Keys.Down Then AddBoxY = k - 39 : AddBoxX = 0
            Dim TmpBoxRect As New Rectangle(BoxRect.X + AddBoxX, BoxRect.Y + AddBoxY, BoxRect.Width + 1, BoxRect.Height + 1)
            If WallRect.IntersectsWith(TmpBoxRect) Then
                If tmpBallRect.IntersectsWith(TmpBoxRect) Then Exit Sub
            Else
                BoxRect.X += AddBoxX : BoxRect.Y += AddBoxY
            End If
        End If

        BallRect.X += AddBallX : BallRect.Y += AddBallY
        PB.Refresh()
    End Sub
End Class

Идея такая - мячик не может двигаться сквозь стены, но может толкать коробку. Если коробка упирается в стену - мячик соответственно должен остановится. Не могу исправить один момент - когда движение идет сверху вниз и слева направо, мячик "прилипает" к коробке и может таскать ее за собой. Заранее благодарен.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Рисование.

Сообщение Nord777 » 23.04.2009 (Чт) 17:33

Не могу исправить один момент - когда движение идет сверху вниз и слева направо, мячик "прилипает" к коробке и может таскать ее за собой. Заранее благодарен.
Скопипастил. Проверил. Я у себя таких проблем не наблюдаю.
Сокобан пишешь?
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5

oskolok_vatbI
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 112
Зарегистрирован: 07.07.2007 (Сб) 16:13
Откуда: г. Казань

Re: Рисование.

Сообщение oskolok_vatbI » 24.04.2009 (Пт) 15:20

Да, пытаюсь сделать сокобан, думал объединю два предложенных тобой куска и все готово... Однако все сложнее. Добился работоспособности когда сундук один:
Код: Выделить всё
Dim WallRect As Rectangle() = {New Rectangle(0, 0, 40, 600), _
    New Rectangle(40, 560, 800, 40), _
    New Rectangle(760, 0, 40, 600), _
    New Rectangle(40, 0, 760, 40), _
    New Rectangle(40, 40, 40, 120), _
    New Rectangle(120, 40, 40, 120), _
    New Rectangle(80, 241, 40, 120), _
    New Rectangle(240, 240, 40, 160), _
    New Rectangle(240, 400, 200, 40), _
    New Rectangle(440, 160, 40, 360)}


    Dim BallRect As New Rectangle(280, 80, 38, 38)
    Dim BoxRect As New Rectangle(280, 160, 38, 38)
    Dim AddBallX, AddBallY, AddBoxX, AddBoxY, i As Integer
    Dim key As Keys

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Dim k As Keys = e.KeyCode
        For Me.i = 0 To 40

            If k = Keys.Left Or k = Keys.Right Then AddBallX = k - 38 : AddBallY = 0
            If k = Keys.Up Or k = Keys.Down Then AddBallY = k - 39 : AddBallX = 0

            Dim tmpBallRect As New Rectangle(BallRect.X + AddBallX, BallRect.Y + AddBallY, BallRect.Width + 1, BallRect.Height + 1)

            For Each rect In WallRect
                If rect.IntersectsWith(tmpBallRect) Then Exit Sub
            Next

            If tmpBallRect.IntersectsWith(BoxRect) Then
                If k = Keys.Left Or k = Keys.Right Then AddBoxX = k - 38 : AddBoxY = 0
                If k = Keys.Up Or k = Keys.Down Then AddBoxY = k - 39 : AddBoxX = 0

                Dim TmpBoxRect As New Rectangle(BoxRect.X + AddBoxX, BoxRect.Y + AddBoxY, BoxRect.Width + 1, BoxRect.Height + 1)

                For Each rect In WallRect
                    If TmpBoxRect.IntersectsWith(rect) Then Exit Sub
                Next

            End If
            BallRect.X += AddBallX : BallRect.Y += AddBallY
            BoxRect.X += AddBoxX : BoxRect.Y += AddBoxY
            PB.Refresh()
        Next
    End Sub

    Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
        AddBoxX = 0 : AddBoxY = 0 : AddBallX = 0 : AddBallY = 0
    End Sub

    Private Sub PB_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
        e.Graphics.FillRectangles(Brushes.Red, WallRect)
        e.Graphics.FillRectangle(Brushes.Blue, BallRect)
        e.Graphics.FillRectangle(Brushes.Green, BoxRect)
    End Sub

Не могу придумать как добавить еще сундуков, чтобы с ними можно было работать. Помогите пожалуйста, сам никак. Спасибо.

Nord777
Гуру
Гуру
Аватара пользователя
 
Сообщения: 1144
Зарегистрирован: 22.02.2004 (Вс) 13:15
Откуда: Подольск

Re: Рисование.

Сообщение Nord777 » 24.04.2009 (Пт) 18:43

Для сокобана эти методы кривы. Тут по другому надо.
Microsoft Visual Studio 2008
Microsoft .NET Framework 3.5


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 24

    TopList  
cron