Transparenz überdeckend zeichnen mit GDI+

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von Fritschifisch.

    Transparenz überdeckend zeichnen mit GDI+

    Hi,
    ich habe folgendes Problem:
    Ich möchte eine Art Labyrinth-Spiel in 2D programmieren. Dieses soll allerdings die Einschränkung haben, dass nur der Spieler (ein Quadrat) und ein bisschen rundherum beleuchtet ist und der Rest nicht. So hab ich mir also gedacht: "Ich zeichnen die Wände, den Spieler, übermale alles mit Schwarz und mal dann über den Spieler einfach einen transparenten Kreis." (Der Spieler ist übrigens in einer PictureBox, die man halt später bewegen kann.) So, nun habe ich das Problem (was ich mir auch hätte denken können :whistling: ), dass transparent ja schwarz nicht übermalt (wie denn, auch ist ja schließlich transparent). So nun frage an euch, gibt es da eine Möglichkeit, dass Transparenz Schwarz übermalt, so, dass man da hinter halt noch die Wände, den Spieler und den Formhintergrund sieht, oder muss ich da völlig anders rangehen? Wenn ja, gebt mir doch bitte einen kleinen Stupser in die richtige Richtung ^^

    LG
    Fritschifisch

    PS: Gibt es vielleicht so was wie Ebenen?
    Drei Worte, die dein Programmieren verändern: Option Strict On

    das ist über einen GraphicsPath ganz einfach machbar...
    Du fügst einem Graphics Path ein Rectangle hinzu(das gesamte Labyrinth) und anschließend noch ein Kreis(um den Spieler) und diesen füllst du anschließend einfach(FillPath) mit Schwarz->fertig
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    okay, werde ich mal angucken ^^
    schon mal danke ;)
    EDIT:
    Ähm ja, du hast zwar geschrieben, man füllt mit FillPath, nur die Funktion finde ich nicht^^
    Ich wollte das so machen, ist das Falsch?

    VB.NET-Quellcode

    1. path.FillPath()

    Ich benutze den GraphicsPath aus System.Drawing.Drawing2D, ist das vielleicht der falsche?
    Drei Worte, die dein Programmieren verändern: Option Strict On

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

    Ich würde mit GIMP eine .png-grafik erstellen - einfach den Alpha-Kanal nutzen um Transparenz in der Mitte zu ermöglichen und zu den rändern hin wird es immer dunkler. Diese Grafik zeichnest du später einfach über alles andere drüber. Das wäre afaik in diesem Fall die "beste" möglcihkeit das ganze optisch gerecht hinzubekommen.

    Dein Spieler ist eine Picturebox? Warum zeichnest du den Spieler nicht auch mit GDI auf die Form, genau wie das Labyrinth?
    So ein Farbverlauf lässt sich mit GDI kompliziert erstellen - eine Grafik nimmt dir da viel arbeit ab. Du könntest so auch den Lichtkegel einer Taschenlampe nachbilden - da gäbe es mit GDI keine brauchbare Alternative. Da sehe ich kein Problem von wegen unsauber^^

    Erzähl mal was du mit der Picturebox meinst. Wenn du eine Picturebox hin-und-her bewegst ist das 1000mal unsauberer als alles selbst mit GDI zu zeichnen (ist ja schließlich dein Spiel und keine normale Anwendung) und für einen Lichteffekt ne grafik zu verwenden.

    edit: Graphics.FillPath(..) xD
    Bitte schön :) :

    VB.NET-Quellcode

    1. Dim path As System.Drawing.Drawing2D.GraphicsPath
    2. Dim tmpgraphics As System.Drawing.Graphics
    3. Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    4. path.AddRectangle(New Rectangle(0, 0, 700, 700))
    5. path.AddEllipse(50, 50, 300, 300)
    6. tmpgraphics.FillPath(Brushes.Black, path)
    7. End Sub
    Drei Worte, die dein Programmieren verändern: Option Strict On

    Böse Fehler^^

    VB.NET-Quellcode

    1. Dim path As new System.Drawing.Drawing2D.GraphicsPath
    2. Sub CreatePath
    3. path.AddRectangle(New Rectangle(0, 0, 700, 700))
    4. path.AddEllipse(50, 50, 300, 300)
    5. end Sub
    6. Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    7. e.graphics.FillPath(Brushes.Black, path)
    8. ' e.graphics.drawEllipse(...)
    9. End Sub


    Den Path musst du nur einmal erzeugen - ab dann kannst du ihn immer wieder zeichnen. Alternativ kannst du auch ohne ihn alles einzeln zeichnen - das musst du entscheiden. CreatePath muss natürlich im Form_Load-event aufgerufen werden bzw dann, wenn die Labirinthdaten geladen werden.
    Du hast ihn einmal deklariert - das Paint-Event wird aber sehr oft ausgeführt, es ist also unsinn dem graphicspath immer wieder neue formen hinzuzufügen. Du hast scheinbar noch nie wirklich mit GDI gearbeitet, schau doch mal in mein GDI-Tutorial rein bevor du dich an ein Spiel wagst^^
    @FreakJNS: es ist schon möglich sowas mit GDI+ zu realisieren und das gar nicht mal so schwer...
    Dafür kann man den hier verwenden:
    msdn.microsoft.com/en-us/libra…2d.pathgradientbrush.aspx

    Natürlich ist es mit einem Bild aber deshalb noch nicht unsauber ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    noch eine letzte frage ^^:
    Wie refresht man die graphics einer form, da wenn ich das neu zeichne, es sich auf der form erst ändert, wenn ich die form in der grösse verändere, mein code:

    VB.NET-Quellcode

    1. Sub reloadpath()
    2. path.Reset()
    3. path.AddRectangle(New Rectangle(0, 0, 700, 700))
    4. path.AddEllipse(100, 100, 300, 300)
    5. End Sub
    Drei Worte, die dein Programmieren verändern: Option Strict On

    Form1.Invalidate wird leitet ein neuzeichnen ein. Was du mit deinem reloadpath bewirken willst ist mir schleierhaft. Den Path würde ich nur zum zeichnen des Labirinthes benutzen - die Mauern verändern sich ja nie. Ständig den Path zu reseten und neu zusammenzusetzten ist nicht sinn der sache^^

    @ jvbsl
    Wäre eine möglichkeit^^
    der path ist ja für den lichtkegel, nicht für die mauern.

    EDIT:
    Da wir uns glaube ich Missverstanden haben, hier noch mal eine Erläuterung :) (mit Bild o.O)
    Als Anhang, wie ich mir das vorstelle (ohne Schrift ;) natürlich)
    Ich wollte das jetzt so machen, wie jvbsl es geschrieben hat. GraphicsPath erstellen, Rechteck und Kreis hinzufügen, das ganze auf die Form bringen.
    @FreakJNS

    FreakJNS schrieb:

    Den Path würde ich nur zum zeichnen des Labirinthes benutzen - die Mauern verändern sich ja nie. Ständig den Path zu reseten und neu zusammenzusetzten ist nicht sinn der sache^^
    Okay, wie würdest du es machen? :)

    @All noch mal eine Frage, gibt es eine Möglichkeit den Kreis, den ich so reingesetzt habe wie FreakJNS es beschrieben hat, in der Positon zu verändern und das ganze dann auf die Form zu bringen? Ich mach es bisher folgender Maßen, aber ich glaube das ist nicht gut:

    VB.NET-Quellcode

    1. path.Reset()
    2. path.AddRectangle(New Rectangle(0, 0, Me.ClientSize.Width, Me.ClientSize.Height))
    3. path.AddEllipse(x, y, 300, 300)
    4. Me.Invalidate()



    LG
    Fritschifisch
    Bilder
    • labyrinth.png

      4,58 kB, 100×100, 579 mal angesehen
    Drei Worte, die dein Programmieren verändern: Option Strict On

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Fritschifisch“ ()

    Ich würde es so machen, dass das gesamte Labirinth in den GraphicsPath geladen wird. Du kannst btw mittels Graphics.Transform heranzoomen, verschieben, rotieren etc - also nur einen kleinen Ausschnitt des ganzen Paths sichtbar machen. Der GraphicsPath (=> Mauern) werden zuerst gezeichnet. Dann der Spieler darüber. Erst ganz am Schluss wird die Lichtkegel-Grafik darübergezeichnet. Da dieses zur Mitte hin immer Transparenter wird scheint der Untergrund durch. (Für die Lichtkegel-Grafik eignet sich das .png-Format am besten!)

    Den Spieler musst du seperat zeichnen - er ist nicht teil des GraphicsPath! Als erstes musst du dir aber eine Sinnvolle Datenstrucktur ausdenken um das Labirinth zu speichern/laden und vor allem auswerten zu können => Kollisionserkennung etc


    Hier mal ein kleines Beispiel - habe mir bei der Grafik keine mühe gegeben, dass wirst du viel besser machen können:
    Bilder
    • untitled.JPG

      68,57 kB, 1.050×386, 129 mal angesehen
    Okay, das verstehe ich (endlich mal) :D ich muss das jetzt fragen, auch wenn das voll so klingt als wolle ich ganz viel code, aber wie legt man das bild darüber? fügt man das bild zum pfad hinzu, oder wie geht das, weil das bild ja immer neu gesetzt werden muss und das sicher schwierig, oder?
    Drei Worte, die dein Programmieren verändern: Option Strict On