[BB, B+, B3D] SpecialRect()

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

 

Weazle25

Betreff: [BB, B+, B3D] SpecialRect()

BeitragDi, Mai 22, 2007 14:58
Antworten mit Zitat
Benutzer-Profile anzeigen
Mit dieser Function kann man Rechtecke mit abgerundeten Ecken zeichnen.
Der Unterschied zu anderen "RoundedRect()" liegt darin das bei SpecialRect() jede Ecke einen anderen Radius haben kann.
Darüberhinaus kann auch die Breite der Outline verändert und das Rechteck mit einer Füllung (2. Farbe) versehen werden.

Die Parameter sollten selbsterklärend sein.
Die Radien:
R1 -> oben links
R2 -> oben rechts
R3 -> unten links
R4 -> unten rechts

Code: [AUSKLAPPEN]

Graphics( 800, 600, 32, 2 )
SetBuffer( BackBuffer() )
ClsColor( 150, 150, 255 )
Cls

LockBuffer( BackBuffer() )

SpecialRect( 100, 100, 200, 100, 50, 10, 10, 50, 1, $FFFFFF00, $FF0000FF, 1 )
For i = 0 To 359 Step 1
   Kreis( 350, 100, 100, 1, $FF000000, ARGB( 255, Rand( 0, 255 ), Rand( 0, 255 ), Rand( 0, 255 ) ), i, i + 1 )
Next

UnlockBuffer( BackBuffer() )

Flip

FlushKeys()
WaitKey()

Function SpecialRect( X, Y, W, H, R1, R2, R3, R4, BorderWidth, ARGB_Border = $FF0000FF, ARGB_Inner = $FFFFFFFF, Fill = 1 )
   Kreis( X, Y, R1, BorderWidth, ARGB_Border, ARGB_Inner, 0.0, 90.0, Fill )
   Kreis( X + W - R2 - R2 - 1, Y, R2, BorderWidth, ARGB_Border, ARGB_Inner, 90.0, 180.0, Fill )
   Kreis( X, Y + H - R3 - R3 - 1, R3, BorderWidth, ARGB_Border, ARGB_Inner, 270.0, 360.0, Fill )
   Kreis( X + W - R4 - R4 - 1, Y + H - R4 - R4 - 1, R4, BorderWidth, ARGB_Border, ARGB_Inner, 180.0, 270.0, Fill )
   
   For Y1 = 0 To H - 1
      X2 = 0
      W2 = W - 1
      If Y1 < R1 Then
         X2 = R1
         W2 = W - R1 - 1
      EndIf
      If Y1 > ( H - R3 - 1 ) Then
         X2 = R3
         W2 = W - R3 - 1
      EndIf
      If Y1 < R2 Then W2 = W2 - R2 - 1
      If Y1 > ( H - R4 - 1 ) Then W2 = W2 - R4 - 1
      
      For X1 = 0 To W - 1
         If X1 >= X2 And X1 <= ( X2 + W2 ) Then
            If X1 < BorderWidth Or ( W - 1 - X1 ) < BorderWidth Or Y1 < BorderWidth Or ( H - 1 - Y1 ) < BorderWidth Then
               WritePixel( X1 + X, Y1 + Y, ARGB_Border )
            Else
               If Fill = 1 Then WritePixel( X1 + X, Y1 + Y, ARGB_Inner )
            EndIf
         EndIf
      Next
   Next
End Function

Function Kreis( X, Y, Radius, BorderWidth, ARGB_Border = $FF0000FF, ARGB_Inner = $FFFFFFFF, StartSeg# = 0.0, EndSeg# = 360.0, Fill = 1 )
   Local deg#, yp, xp, r
   BorderWidth=BorderWidth-1
   StartSeg# = StartSeg# + 180.0
   EndSeg# = EndSeg# + 180.0
   
   For deg# = StartSeg# To EndSeg# Step 0.1
      For r = 0 To Radius
         yp = Int( -Sin#(deg#) * Float#( r ) * Float#( -1 ) + Float#( Y ) + Float#( Radius ) )
         xp = Int( Cos#(deg#) * Float#( r ) + Float#( X ) + Float#( Radius ) )

         If (Radius - r ) <= BorderWidth Then
            WritePixel( xp,yp, ARGB_Border )
         Else
            If Fill = 1 Then WritePixel( xp,yp, ARGB_Inner )
         EndIf
      Next
   Next
End Function

Function ARGB( A, R, G, B )
   Return A * $1000000 + R * $10000 + G * $100 + B
End Function

End


Gruss
Weazle
  • Zuletzt bearbeitet von Weazle25 am Di, Mai 22, 2007 18:28, insgesamt einmal bearbeitet

Smily

BeitragDi, Mai 22, 2007 16:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Tip für das nächste mal:
Du solltest deine Funktionen nicht einfach irgendwo mitten im Programm reinschreiben.
Schreibe sie ganz oben oder noch besser ganz unten hin. Sowas kommt besser an ^^
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org
 

Weazle25

BeitragDi, Mai 22, 2007 18:35
Antworten mit Zitat
Benutzer-Profile anzeigen
@Smily0412
Jetzt besser?
Normaler Weise habe ich meine Functionen immer in separaten Dateien.
Nur hier hatte ich mal ne Ausnahme gemacht weils ja nur ein Mini-Programm ist.


Gruss
Weazle

Smily

BeitragDi, Mai 22, 2007 18:46
Antworten mit Zitat
Benutzer-Profile anzeigen
joa so sieht es schon besser aus Wink

Leider ist die Funktion für Realtime-Effekte nich zu gebrauchen (bei mir ~3 sekunden berrechnungszeit)

vlt solltest du nur den Rand per Writepixelfast machen und größere Flächen dann mit rect füllen, das macht das ganze bestimmt schneller Wink

gruß, Smily0412
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org
 

Weazle25

BeitragDi, Mai 22, 2007 22:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Smily0412 hat Folgendes geschrieben:

joa so sieht es schon besser aus Wink

Leider ist die Funktion für Realtime-Effekte nich zu gebrauchen (bei mir ~3 sekunden berrechnungszeit)


3 Sekunden? Also bei mir ist das Proggi seeehhhrrr viel schneller.
Wie schnell kann ich Dir jetzt nicht sagen aber devinitiv weniger als 1 Sekunde.
Wenn ich aber LockBuffer( BackBuffer() ) und UnlockBuffer( BackBuffer() ) weg lasse dann braucht das Proggi auch 2-3 Sekunden.

Smily0412 hat Folgendes geschrieben:

vlt solltest du nur den Rand per Writepixelfast machen und größere Flächen dann mit rect füllen, das macht das ganze bestimmt schneller Wink

gruß, Smily0412


Ich habe das absichtlich so gemacht denn so unterstützt SpecialRect() auch Alphas so das man auch halbtransparente Rechtecke auf ne Alpha Textur zeichnen kann.
Und genau dafür brauche ich diese Function auch.
Mit Rect() ist das allerdings nicht möglich und bei WritePixelFast() gibts Probleme wenn man ausserhalb des Buffers zeichnen will.
Ich habe allerdings keine Ahnung wie ich das abfangen soll denn wie soll ich die Grösse des Buffers ermitteln wenn ich nicht weiss auf welchen Buffer gezeichnet werden soll? ( SpecialRect() sollte ja Buffer-neutral sein )

Gruss
Weazle

Smily

BeitragMi, Mai 23, 2007 14:39
Antworten mit Zitat
Benutzer-Profile anzeigen
ah mein fehler. Der Debug ist an allem schuld ^^
Zeit ohne debug: 300ms
zeit mit debug: 6000ms
Lesestoff:
gegen Softwarepatente | Netzzensur | brain.exe | Unabhängigkeitserklärung des Internets

"Wir müssen die Rechte der Andersdenkenden selbst dann beachten, wenn sie Idioten oder schädlich sind. Wir müssen aufpassen. Wachsamkeit ist der Preis der Freiheit --- Keine Zensur!"
stummi.org

PowerProgrammer

BeitragMi, Mai 23, 2007 20:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Trotzdem nicht sehr schnell, mit Rect kann man wohl noch etwas an Performance rausholen, denke ich mal.
www.xairro.com Alles für Webmaster und Programmierer! Es gibt mehr als bloß einen Counter!
 

FWeinb

ehemals "ich"

BeitragMi, Mai 23, 2007 21:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja wenn man es mit recht machen will und dann auf die Tranßperenz verzichtet aber es scheint ja nicht so als ob er das wolte ^^
"Wenn die Menschen nur über das sprächen, was sie begreifen, dann würde es sehr still auf der Welt sein." Albert Einstein (1879-1955)
"If you live each day as if it was your last, someday you'll most certainly be right." Steve Jobs
 

Weazle25

BeitragDo, Mai 24, 2007 0:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Schaut euch mal den Code etwas genauer an dann sollte euch etwas auffallen.
Nagut ich wills mal nicht so schwer machen: Das Problem sind nicht die grossen Flächen denn da wird gar nicht so viel Speed verbraten.
Die Rundungen sind das Problem!
Bei den Rundungen wird jeder Pixel separat mit sin()/Cos() berechnet was allein schon ne Menge Speed kostet.
Beim zeichnen grösserer Kreise (Radius > 40) wurden viele Pixel vergessen was ich bisher nur umgehen konnte indem ich den Kreis (und damit auch die Rundungen des SpecialRects) in 0,1° Schritten berechnen lasse.
Das hat aber den Nachteil das wesentlich mehr Pixel berechnet und gezeichnet werden müssen als eigentlich notwendig wären.

Um richtig Speed zu sparen müsste man das SpecialRect zeilenweise zeichnen.
Dann müsste man nur die äussersten Pixel berechnen und diese dann durch eine horizontale Linie verbinden.
Ich vermute mal das so auch die BB-Kreise/Ovale gezeichnet werden weil es eben die schnellste Methode ist.
Allerdings gibts dann wieder Probleme mit der Outline.
Man müsste dann also erst die Füllung zeichnen und dann die Outline drüberbügeln.

Mal schauen vielleicht bau ich SpecialRect und Kreis entsprechend um.


Gruss
Weazle

PowerProgrammer

BeitragDo, Mai 24, 2007 6:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Line-Befehl ist auch noch ziemlich langsam.
Das, was am schnellsten gezeichnet wird, sind tatsächlich Bilder, die sind quasi sofort da. Vllt wäre es schlau, ein rechteckiges Image vollständig zu füllen und dann die Ecken herauszuschneiden.
Wenn man das Teil vorberechnet, wenn man es in einer Hauptschleife nutzen möchte, dann ist es sowieso viel schneller.
Was solls, Anfänger können an deinem Code schauen, wie soetwas funktioniert und den Code für sich anpassen.
www.xairro.com Alles für Webmaster und Programmierer! Es gibt mehr als bloß einen Counter!
 

Weazle25

BeitragDo, Mai 24, 2007 11:48
Antworten mit Zitat
Benutzer-Profile anzeigen
PowerProgrammer hat Folgendes geschrieben:

Der Line-Befehl ist auch noch ziemlich langsam.


Wer redet denn von der Line-Function?
Line() versuche ich immer so weit wie möglich zu vermeiden.
Für horizontale und vertikale Linien sollte man eher Rect() WritePixel() oder WritePixelFast() benutzen.

PowerProgrammer hat Folgendes geschrieben:

Das, was am schnellsten gezeichnet wird, sind tatsächlich Bilder, die sind quasi sofort da.


Übertreib mal nicht denn Images brauchen auch ne ganze Menge Speed.
Besonders bei grossen Bildern fällt das sehr schnell auf.

PowerProgrammer hat Folgendes geschrieben:

Vllt wäre es schlau, ein rechteckiges Image vollständig zu füllen und dann die Ecken herauszuschneiden.


Und wie machst Du das dann mit der Outline?

PowerProgrammer hat Folgendes geschrieben:

Wenn man das Teil vorberechnet, wenn man es in einer Hauptschleife nutzen möchte, dann ist es sowieso viel schneller.


Eben dafür war's ja auch gedacht.
Ich arbeite gerade an einer GUI-Lib bei der künftig keine Texturen mitgeliefert werden sollen.
Statt dessen sollen die Default-Texturen bei Programmstart mit SpecialRect() gezeichnet werden.

Gruss
Weazle

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group