Problikávání obrázku   otázka

VB.NET, WinForms

Dobrý den,

Vytvořil jsem začátek jednoduché 2D hry v rozhraní GDI+. Mám hotovou asi tak desetinu a objekt, který se má posouvat na formuláři ovládáním šipek problikává a toto chci odstranit, jenomže nevím jak. Časovač Timer jsem nastavil na jednu milisekundu až je objekt rychlý. Taky mám vytvořený objekt ImageList1. Zde je kód:

Public Class Form1
    'směry pohybu stíhačky
    Enum SMERY
        Nahoru = 1
        Dolu = 2
        Doleva = 3
        Doprava = 4
        Zadne = 5
    End Enum

    'souřadnice
    Structure XY
        Dim x As Integer
        Dim y As Integer
    End Structure

    'směry stíhačky
    Dim Smer As SMERY

    'součastná pozice stíhačky
    Dim Space As XY

    Private Sub Form1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode
            Case Keys.Up
                Smer = SMERY.Nahoru
            Case Keys.Down
                Smer = SMERY.Dolu
            Case Keys.Right
                Smer = SMERY.Doprava
            Case Keys.Left
                Smer = SMERY.Doleva
        End Select
    End Sub

    Private Sub Form1_KeyUp(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
        Select Case e.KeyCode
            Case Keys.Up
                Smer = SMERY.Zadne
            Case Keys.Down
                Smer = SMERY.Zadne
            Case Keys.Right
                Smer = SMERY.Zadne
            Case Keys.Left
                Smer = SMERY.Zadne
        End Select
    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Timer1.Enabled = True

        'nastavení pozice stíhačky
        Space.x = 12 * 30
        Space.y = 20 * 30

    End Sub

    Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        'pozadí vybarvit na bílou barvu
        e.Graphics.Clear(Color.White)

        'vykreslit stíhačku
        e.Graphics.DrawImage(ImageList1.Images(0), 12 * 30, 20 * 30)

    End Sub

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        'nadeklarovat g jako kreslící plátno
        Dim g As Graphics = PictureBox1.CreateGraphics

        g.FillRectangle(Brushes.White, Space.x, Space.y, 30, 30)

        Select Case Smer
            Case SMERY.Nahoru
                Space.y = Space.y - 1
            Case SMERY.Dolu
                Space.y = Space.y + 1
            Case SMERY.Doprava
                Space.x = Space.x + 1
            Case SMERY.Doleva
                Space.x = Space.x - 1
            Case SMERY.Zadne
                Space.x = Space.x
                Space.y = Space.y
        End Select

        g.DrawImage(ImageList1.Images(0), Space.x, Space.y)
    End Sub
End Class

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Problém je,

že zbytečně vytváříte objekt graphics v každém ticku timeru.

Ve Form.Load udělejte toto:

dim b = new bitmap(šířka, výška)
dim g = graphics.fromimage(b)
picturebox1.image=b

a v Ticku:

g.drawimage... 'vykreslení herní scény
picturebox1.invalidate 'obnovit vykresleni obrazku v pictureboxu

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Vedle, do globálních definic, přímo do třídy dejte Dim b As Bitmap a Dim g As Graphics a do Form.Load pak

b='viz výše
g='viz výše

Jinak by proměnné b,g byli jen v rámci metody Load a Tick timeru by je neviděl

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Nechci Vás zklamat, ale nefunguje to. Formulář se mi sice vykreslí, ale objekt nejde dát do pohybu, když mačkám šipky. Programuju ve VB.net 2010, jestli to pomůže.

Zde je upravený kód :

Public Class Form1
    Dim b As Bitmap
    Dim g As Graphics

    'směry pohybu stíhačky
    Enum SMERY
        Nahoru = 1
        Dolu = 2
        Doleva = 3
        Doprava = 4
        Zadne = 5
    End Enum

    'souřadnice
    Structure XY
        Dim x As Integer
        Dim y As Integer
    End Structure

    'směry stíhačky
    Dim Smer As SMERY

    'součastná pozice stíhačky
    Dim Space As XY

    Private Sub Form1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode
            Case Keys.Up
                Smer = SMERY.Nahoru
            Case Keys.Down
                Smer = SMERY.Dolu
            Case Keys.Right
                Smer = SMERY.Doprava
            Case Keys.Left
                Smer = SMERY.Doleva
        End Select
    End Sub

    Private Sub Form1_KeyUp(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
        Select Case e.KeyCode
            Case Keys.Up
                Smer = SMERY.Zadne
            Case Keys.Down
                Smer = SMERY.Zadne
            Case Keys.Right
                Smer = SMERY.Zadne
            Case Keys.Left
                Smer = SMERY.Zadne
        End Select
    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Timer1.Enabled = True

        b = New Bitmap(750, 750)
        g = Graphics.FromImage(b)
        PictureBox1.Image = b

        'nastavení pozice stíhačky
        Space.x = 12 * 30
        Space.y = 20 * 30

    End Sub

    Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        'pozadí vybarvit na bílou barvu
        e.Graphics.Clear(Color.White)

        'vykreslit stíhačku
        e.Graphics.DrawImage(ImageList1.Images(0), 12 * 30, 20 * 30)

    End Sub

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        PictureBox1.Invalidate() 'obnovit vykresleni obrazku v pictureboxu

        g.FillRectangle(Brushes.White, Space.x, Space.y, 30, 30)

        Select Case Smer
            Case SMERY.Nahoru
                Space.y = Space.y - 1
            Case SMERY.Dolu
                Space.y = Space.y + 1
            Case SMERY.Doprava
                Space.x = Space.x + 1
            Case SMERY.Doleva
                Space.x = Space.x - 1
            Case SMERY.Zadne
                Space.x = Space.x
                Space.y = Space.y
        End Select

        g.DrawImage(ImageList1.Images(0), Space.x, Space.y)
    End Sub
End Class

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Zkuste vyjít z tohoto, zkoušel jsem teď něco takového napsat sám:

Public Class Form1

    Dim bitmap As Bitmap
    Dim canvas As Graphics
    Dim players As New List(Of Player)

    Class Player
        Public Property Bitmap As Bitmap
        Public Property Location As Point
        Public Property Direction As Directions
        Public Sub New(bitmap As Bitmap, location As Point, direction As Directions)
            Me.Bitmap = bitmap
            Me.Location = location
            Me.Direction = direction
        End Sub
    End Class

    Enum Directions
        None = 0
        Left = 1
        Up = 2
        Right = 3
        Down = 4
    End Enum

    Private Sub Form1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode
            Case Keys.Left
                players(0).Direction = Directions.Left
            Case Keys.Up
                players(0).Direction = Directions.Up
            Case Keys.Right
                players(0).Direction = Directions.Right
            Case Keys.Down
                players(0).Direction = Directions.Down
        End Select
    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Bitmap = New Bitmap(250, 250)
        canvas = Graphics.FromImage(Bitmap)
        players.Add(New Player(ImageList1.Images(0), New Point(100, 100), Directions.None))
        PictureBox1.Image = Bitmap
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        canvas.Clear(Color.White)
        For Each player In players
            Select Case player.Direction
                Case Directions.Left
                    player.Location += New Point(-5, 0)
                Case Directions.Up
                    player.Location += New Point(0, -5)
                Case Directions.Right
                    player.Location += New Point(5, 0)
                Case Directions.Down
                    player.Location += New Point(0, 5)
            End Select
            canvas.DrawImage(player.Bitmap, player.Location)
        Next
        PictureBox1.Invalidate()
    End Sub

End Class

Zdá se, že jste zbytečně komplikovat Paint a Tick.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Taktiež by bolo lepšie úplne všetko vrátane toho objektu vykresľovať v handleru události Paint a na konci toho handleru zavolať na PictureBoxe .Invalidate() . To zabezpečí ďalšie prekreslenie PictureBoxu. Pre eliminovanie preblikávania potom nastavte .DoubleBuffered na True. Prípadne zavolajte Invalidate iba vtedy, ak treba prekresliť.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Souhlasim, pokud zapnete DoubleBuffering, mělo by to byt OK.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Doporučuji vykašlat se na GDI+ a použít XNA.

A řekl bych, že by měla být kategorie spíš VB.NET než VB6!

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

XNA Ano, ale na jednoduchou 2D hru je to zbytecne, na to postačí GDI+.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Díky všem za odpověď.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback