2d Rotation

  • VB6

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Unknown.

    2d Rotation

    Hi!
    Ich versuche zur Zeit eine art Autorennen zu programmieren und möchte nun, dass sich auf Tastendruck eine 2d Grapfik (Auto) in einer Picturebox um z.B. jeweils 10°, möglichst schnell, weiter dreht (je nach Taste links oder rechts herum).
    Ich habe das leider nicht hingekriegt und hoffe, das mir da jemand helfen kann.
    Ich habe mich auf verschiedenen Seiten nach einen geeigneten Sourcecode umgesehen, aber meistens war das zu langsam.
    Auf www.vbfun.de habe ich das Projekt "extreme race" gedownloadet, wo genau das drin ist, was ich benötige, nur leider konnte ich den entsprechenden Teil nicht herausfiltern (Kommentare sind außerdem Tschechisch).
    Weiter unten ist ein Beispiel von Mircosoft.
    Nachteil: Drehen funktioniert bei etwas größeren Bildern nur mit flackern.
    Außerdem konnte ich nicht einprogrammieren, dass sich jetzt zum Beispiel beim drücken der Pfeiltasten das Bild um jeweils 10° in die entsprechende Richtung geht. Vielleicht kann mir ja mal jemand den code so bearbeiten, dass das geht.
    Ich bräuchte quasi mal ein gutes Beispielprogramm (gut Kommentiert) von einem Autorennen.

    <pre>
    ' Example of how to call bmp_rotate.
    Sub Command1_Click()
    Const Pi = 3.14159265359

    For angle = Pi / 6 To 2 * Pi Step Pi / 6
    Picture2.Cls
    Call bmp_rotate(Picture1, Picture2, angle)
    Next
    End Sub

    ' bmp_rotate(pic1, pic2, theta)
    ' Rotate the image in a picture box.
    ' pic1 is the picture box with the bitmap to rotate
    ' pic2 is the picture box to receive the rotated bitmap
    ' theta is the angle of rotation
    '

    Sub bmp_rotate(pic1 As Control, pic2 As Control, ByVal theta!)
    Const Pi = 3.14159265359
    Dim c1x As Integer ' Center of pic1.
    Dim c1y As Integer ' "
    Dim c2x As Integer ' Center of pic2.
    Dim c2y As Integer ' "
    Dim a As Single ' Angle of c2 to p2.
    Dim r As Integer ' Radius from c2 to p2.
    Dim p1x As Integer ' Position on pic1.
    Dim p1y As Integer ' "
    Dim p2x As Integer ' Position on pic2.
    Dim p2y As Integer ' "
    Dim n As Integer ' Max width or height of pic2.

    ' Compute the centers.
    c1x = pic1.ScaleWidth / 2
    c1y = pic1.ScaleHeight / 2
    c2x = pic2.ScaleWidth / 2
    c2y = pic2.ScaleHeight / 2

    ' Compute the image size.
    n = pic2.ScaleWidth
    If n < pic2.ScaleHeight Then n = pic2.ScaleHeight
    n = n / 2 - 1
    ' For each pixel position on pic2.
    For p2x = 0 To n
    For p2y = 0 To n
    ' Compute polar coordinate of p2.
    If p2x = 0 Then
    a = Pi / 2
    Else
    a = Atn(p2y / p2x)
    End If
    r = Sqr(1& * p2x * p2x + 1& * p2y * p2y)

    ' Compute rotated position of p1.
    p1x = r * Cos(a + theta)
    p1y = r * Sin(a + theta)

    ' Copy pixels, 4 quadrants at once.
    c0& = pic1.Point(c1x + p1x, c1y + p1y)
    c1& = pic1.Point(c1x - p1x, c1y - p1y)
    c2& = pic1.Point(c1x + p1y, c1y - p1x)
    c3& = pic1.Point(c1x - p1y, c1y + p1x)
    If c0& <> -1 Then pic2.PSet (c2x + p2x, c2y + p2y), c0&
    If c1& <> -1 Then pic2.PSet (c2x - p2x, c2y - p2y), c1&
    If c2& <> -1 Then pic2.PSet (c2x + p2y, c2y - p2x), c2&
    If c3& <> -1 Then pic2.PSet (c2x - p2y, c2y + p2x), c3&
    Next
    ' Allow pending Windows messages to be processed.
    t% = DoEvents()
    Next
    End Sub
    </pre>
    Der Vorgang dauert aber sehr lange oder ? Der geht hier jeden Pixel einzeln durch und verschiebt ihn !
    Das geht mit DirectDraw aber einfach !
    Weisst du wie man DirectDraw Initialisiert ?
    Ich hab mal irgendwann ne DirectDraw DLL geschrieben,
    hier das is ne sub um dd zu initialiseren (im Fullscreen Modus)

    <pre>
    Dim DirectX As New DirectX7
    Dim DirectDraw As DirectDraw7
    Dim SurfaceDesc As DDSURFACEDESC2
    Dim PrimarySurface As DirectDrawSurface7
    Dim BackBuffer As DirectDrawSurface7
    Dim ddClipper As DirectDrawClipper

    Sub InitDirectDrawFullscreen(handleWnd As Long, ScreenWidth As Long, ScreenHeight As Long, BitsPerPixel)

    Set DirectDraw = DirectX.DirectDrawCreate("")

    DirectDraw.SetCooperativeLevel handleWnd, DDSCL_EXCLUSIVE Or _
    DDSCL_FULLSCREEN Or _
    DDSCL_ALLOWREBOOT

    DirectDraw.SetDisplayMode ScreenWidth, ScreenHeight, BitsPerPixel, 0, DDSDM_DEFAULT

    With SurfaceDesc
    .lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT
    .ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or _
    DDSCAPS_FLIP Or _
    DDSCAPS_COMPLEX
    .lBackBufferCount = 1
    End With

    Set PrimarySurface = DirectDraw.CreateSurface(SurfaceDesc)

    SurfaceDesc.ddsCaps.lCaps = DDSCAPS_BACKBUFFER

    Set BackBuffer = PrimarySurface.GetAttachedSurface(SurfaceDesc.ddsCaps)

    End Sub

    </pre>


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Unknown“ ()

    Das ist nich ganz korrekt, du kannst viel mit BitBlt machen aber leider nicht Grafiken Drehen.

    Also wenn du mit DirectDraw arbeitestbrauchst du keine PictureBox meehr, glaub mir da arbeitets du nur noch mit Oberflächen (Surface).
    Mit denen kannst du dann sehr schnell Grafiken zwischen den verschiedenen Speichern hin und her kopieren. Ich kann dir hir nicht alles erklären, du solltest dir ein DD Tutorial für VB suchen (am besten bei google oder so) wenn du das dann druff hast,
    dann rufst du BltFX auf der DDBLTFX Struktur musst du dann den Rotationsgrad übergeben.

    (Versuch das nicht alles zu verstehen bevor du Dx bzw. DD gelernt hast ....)