Explosionsgenerator & integrierte Farbverlauf-Routine
Übersicht

![]() |
HolzchopfMeisterpackerBetreff: Explosionsgenerator & integrierte Farbverlauf-Routine |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nundenn, da ich bei meinem aktuellen Projekt bei den Grafiken, genauer gesagt bei den Explosionen, hängen blieb, hab ich mir im Handumdrehen (nagut, es dauerte schon ein weilchen ![]() Früher gab ich mich mit Algorithmus-erzeugten Grafiken nicht zufrieden, weil ich einfach zu wenig Farbe einbringen konnte - Und genau da liegt der unterschied bei diesem Explosionsgenerator. Und so Funktioniert er: Wichtig ist mal, dass es sich um eine Partikel-Explosion handelt. Jedes Partikel hat seine Grösse, seinen Platz und seine Stärke. Daraus wird sozusagen ein Schwarzweissbild einer Explosion erzeugt, je weisser, umso stärker der Pixel. Jetzt wird allerdings statt eines Algorithmus, welcher die weissen - schwarzen Pixel einfach linear von weiss nach gelb nach rot (oder gar nur gelb nach rot) umrechnet, ein Algorithmus eingesetzt, welcher die weissen - schwarzen Pixel an einem Farbverlauf anpasst, dh: die Helligkeit des Pixels bestimmt dessen Index vom Farbverlauf. Durch diese Methode lassen sich dann Explosionen zeugen, die sich gegen Schluss im Rauch auflösen ![]() Ach ja, wer will darf natürlich die Farbverlauf-Funktion aus dem Code übernehmen. Und, @Kabelbinder: Reiner Zufall, dass ich meinen Code so kurz nach deiner Farbverlauf-Routine veröffentliche. Eigentlich bin ich nur grad ins Forum gekommen um meinen Code zu veröffentlichen und da seh' ich deinen Thread. Sorry. Wenigstens haben unsere Farbverlauf-Routinen nichts gemeinsam ![]() Oooooooookey, dann will ich euch nicht länger warten lassen (lesen kann zwar jeder, so schnell wie er will): Code: [AUSKLAPPEN] ;************************************************* ; ; Rauch-& Explosions-Partikelgenerator ; ; Von Holzchopf ; ;************************************************* Graphics 400,300, 16, 2 SeedRnd MilliSecs() ; Type für die Partikel Type Partikel_Type Field X# Field Y# Field Staerke# Field Groesse# Field Bewegung# End Type ; Type für den Farbverlauf Type Farbverlauf_Type Field Index Field RGB End Type ; Type für den Grössenverlauf Type Groessenverlauf_Type Field Index Field Groesse End Type ;************************************************* ; ; Die Einstellungen für die Partikel ;================================================= ; ; Explosionen mit wenig (< 50) Partikeln ; und tiefen Werten für die Anfangs-Stärke ; ergeben schwache Explosionen (zB: Mündungs- ; Feuer). ; Mittlere Werte ( 100 Partikel, StMax 32, ; StMin 16 und mittlere Partikelgrössen) ; ergeben relativ schwache Explosionen. ; Splitter- /Gas- /Benzin-Explosionen erreicht ; man, in dem man die Werte der Stärke erhöht ; und zugleich die Partikelgrössen verringert. ; Heisse Explosionen erreicht man, in dem man ; sehr viele Partikel und/oder sehr hohe ; Werte für die Stärke einstellt. Global Anzahl_Partikel = 2000 Global Sprite_Groesse = 64 Global Partikel_Gr_Max# = 16 Global Partikel_Gr_Min# = 2 Global Partikel_StStaerke_Max = 64 Global Partikel_StStaerke_Min = 0 Global Partikel_Bewegung# = 1.0 Global Partikel_Gr_Faktor# = 0.99 ; Wie viel an Stärke die Partikel pro Frame ; verlieren (tiefer = flüssiger) Global Staerke_Abzug# = 2 ; Der Korrigierungsfaktor der Stärke, wird ; beim Malen berücksichtigt Global Staerke_Faktor# = 1 ; Sprite-Bank erstellen (für die Intensität) Global Sprite_Bank = CreateBank( Sprite_Groesse * Sprite_Groesse * 2 ) ; Anzahl Frames vorbestimmen Frames = Partikel_StStaerke_Max / Staerke_Abzug ; Image erstellen, in dem die Frames gespeichert werden Image = CreateImage( Frames * Sprite_Groesse, Sprite_Groesse ) ; Buffer zwischenspeichern B_Buffer = BackBuffer() I_Buffer = ImageBuffer( Image ) ;************************************************* ; ; Farbverlauf einlesen Global Farbverlauf.Farbverlauf_Type Restore Farbverlauf Repeat Read Index, RGB Farbverlauf.Farbverlauf_Type = New Farbverlauf_Type Farbverlauf\Index = Index Farbverlauf\RGB = RGB If Index = 255 Then Exit Forever ;************************************************* ; ; Groessenverlauf einlesen Global Groessenverlauf.Groessenverlauf_Type Restore Groessenverlauf Repeat Read Index, Groesse Groessenverlauf.Groessenverlauf_Type = New Groessenverlauf_Type Groessenverlauf\Index = Index Groessenverlauf\Groesse = Groesse If Index = 255 Then Exit Forever ;************************************************* ; ; Partikel generieren Global Partikel.Partikel_Type For a = 1 To Anzahl_Partikel Partikel.Partikel_Type = New Partikel_Type Radius = Rand( 0, ( Sprite_Groesse / 2 ) - ( Partikel_Gr_Max / 2 + 1 ) ) Winkel = Rand( 0, 359 ) Partikel\X = ( Sprite_Groesse / 2 ) + Cos( Winkel ) * Radius Partikel\Y = ( Sprite_Groesse / 2 ) + Sin( Winkel ) * Radius Partikel\Staerke = Rand( Partikel_StStaerke_Min, Partikel_StStaerke_Max ) Partikel\Groesse = Rnd( Partikel_Gr_Min, Partikel_Gr_Max ) Partikel\Bewegung = Rnd( -Partikel_Bewegung, Partikel_Bewegung ) Next ;************************************************* ; ; Sprite Generieren und zeichnen SetBuffer B_Buffer Repeat Cls ; Die Partikel berechnen und in eine Bank zeichnen PartikelBank( 255.0 / Float(Frames) * Frame ) ; Die Bank auf den Bildschirm zeichnen BankZeichnen ; Den Frame in ein Image kopieren CopyRect 10, 10, Sprite_Groesse, Sprite_Groesse, Frame * Sprite_Groesse, 0, B_Buffer, I_Buffer ; Den Farbverlauf zeichnen ZeichneFarbverlauf ; Den Grössenverlauf zeichnen ZeichneGroessenverlauf ; Die Vortschritts-Linie Zeichnen Color 0,255,255 Line 20 + ( 255.0 / Float(Frames) * Frame ) , 220, 20 + ( 255.0 / Float(Frames) * Frame ), 290 ; Die Framezahl erhöhen, wenn alle Frames gezeichnet ; wurden, Schleife verlassen Frame = Frame + 1 If Frame = Frames Then Exit Flip If KeyHit(1) Then End Forever ; Bild speichern FileName$ = "Explosion " + Frames + "_" + Sprite_Groesse + "x" + Sprite_Groesse + ".bmp" SaveImage( Image, FileName ) FreeImage Image ;************************************************* ; ; Endergebnis Zeichnen Image = LoadAnimImage( FileName, Sprite_Groesse, Sprite_Groesse, 0, Frames ) RGB = FarbverlaufFarbe( 255 ) Rot = ( RGB And $FF0000 ) Shr 16 Gruen = ( RGB And $FF00 ) Shr 8 Blau = RGB And $FF MaskImage Image, Rot, Gruen, Blau Frame = 0 ClsColor 0,255,0 Color 0,0,0 While Not KeyDown(1) Cls If MilliSecs() > S_Pause + 2000 DrawImage Image, 100, 100, Frame Frame = Frame + 1 EndIf If Frame = Frames Then S_Pause = MilliSecs() Frame = 0 EndIf Text 0,0, "Explosion generiert!" Text 0,15, "Gespeichert unter: " + FileName Text 0,30, "Frames: " + Frames Text 0,45, "Grösse: " + Sprite_Groesse + "x" + Sprite_Groesse Text 0,75, "Aktueller Frame: " + Frame Flip Wend End ;************************************************* ; ; Funktionen ; Den Farbverlauf zeichnen Function ZeichneFarbverlauf( ) For a = 0 To 255 RGB = FarbverlaufFarbe( a ) Rot = ( RGB And $FF0000 ) Shr 16 Gruen = ( RGB And $FF00 ) Shr 8 Blau = ( RGB And $FF ) Color Rot, Gruen, Blau Line 20 + a, 200, 20 + a, 210 Next End Function ;************************************************* ; Die Farbe vom Farbverlauf ermitteln ; ;================================================= ; FarbPos ist der Index der zu ermittelnden ; Farbe. ; Der Index darf nur von 0 bis 255 reichen! Function FarbverlaufFarbe( FarbPos ) For Farbverlauf = Each Farbverlauf_Type Index = Farbverlauf\Index RGB = Farbverlauf\RGB ; Falls der Index und die gewünschte Position ; übereinstimmen, kann direkt die indizierte ; Farbe zurückgegeben werden If Index = FarbPos Then Return RGB ; ... Sonst wird der Farbwert linear interpoliert ElseIf FarbPos > Index ; Nächstes Farbverlauf-Element ansteuern Farbverlauf = After Farbverlauf ; Dessen Index ermitteln Index2 = Farbverlauf\Index ; Reine Fehlerverhinderung; nur Interpolieren ; wenn nächster Index grösser ist If FarbPos < Index2 ; Dessen Farbe ermitteln RGB2 = Farbverlauf\RGB ; Die Spannweite zwischen den Indizes Spanne = Index2 - Index ; Die Entfernung zwischen Pos. und Index ermitteln Diff1 = Index2 - FarbPos Diff2 = FarbPos - Index ; Die einzelnen Farbwerte aus dem HEX-Code ermitteln Rot1 = ( RGB And $FF0000 ) Shr 16 Gruen1 = ( RGB And $FF00 ) Shr 8 Blau1 = ( RGB And $FF ) Rot2 = ( RGB2 And $FF0000 ) Shr 16 Gruen2 = ( RGB2 And $FF00 ) Shr 8 Blau2 = ( RGB2 And $FF ) ; Farbanteile von Element 1 linear angleichen Rot1 = Float( Rot1 ) / Float( Spanne ) * Float( Diff1 ) Gruen1 = Float( Gruen1 ) / Float( Spanne ) * Float( Diff1 ) Blau1 = Float( Blau1 ) / Float( Spanne ) * Float( Diff1 ) ; Farbanteile von Element 2 linear angleichen Rot2 = Float( Rot2 ) / Float( Spanne ) * Float( Diff2 ) Gruen2 = Float( Gruen2 ) / Float( Spanne ) * Float( Diff2 ) Blau2 = Float( Blau2 ) / Float( Spanne ) * Float( Diff2 ) ; Farbanteile zusammenrechnen und Überlauf verhindern Rot = Rot1 + Rot2 If Rot > 255 Then Rot = 255 Gruen = Gruen1 + Gruen2 If Gruen > 255 Then Gruen = 255 Blau = Blau1 + Blau2 If Blau > 255 Then Blau = 255 ; "HEX-Code" erzeugen RGB = ( Rot Shl 16 ) + ( Gruen Shl 8 ) + Blau Return RGB EndIf ; Wieder das aktuelle Element ansteuern (sonst ; überspringt die For-Next Schleife eins) Farbverlauf = Before Farbverlauf EndIf Next End Function ;************************************************* ; Den Grössenverlauf zeichnen Function ZeichneGroessenverlauf( ) alt_y = 0 Color 0,0,255 Line 20, 230, 20, 290 Line 10, 280, 275, 280 For a = 0 To 255 y = GroessenverlaufGroesse( a ) * 50 If a = 0 Then alt_y = y Color 0, 255, 0 Line 20 + a - 1, 280 - alt_y, 20 + a, 280 - y alt_y = y Next End Function ;************************************************* ; Die Grösse vom Grössenverlauf ermitteln ; ;================================================= ; GrPos ist der Index des zu ermittelnden ; Grössenfaktors (Rückgabewert 0 - 1 ). ; Der Index darf nur von 0 bis 255 reichen! Function GroessenverlaufGroesse#( GrPos ) For Groessenverlauf = Each Groessenverlauf_Type ; Index und Grösse des aktiven Elementes ermitteln Index = Groessenverlauf\Index Groesse = Groessenverlauf\Groesse ; Falls die gewünschte Position mit dem Index über- ; einstimmt, den Grössenfaktor zurückgeben If Index = GrPos Then Return Float( Groesse / 255.0 ) ; ... Sonst wird der Grössenfaktor linear interpoliert ElseIf GrPos > Index ; Nächstes Element ansteuern Groessenverlauf = After Groessenverlauf ; Dessen Index ermitteln Index2 = Groessenverlauf\Index If GrPos < Index2 ; Dessen Grösse ermitteln Groesse2 = Groessenverlauf\Groesse ; Die Spannweite zwischen den Indizes ermitteln Spanne = Index2 - Index ; Die Entfernung von Pos. zu Index ermitteln Diff1 = Index2 - GrPos Diff2 = GrPos - Index ; Grösse von Element 1 und 2 linear angleichen Groesse1 = Float( Groesse ) / Float( Spanne ) * Float( Diff1 ) Groesse2 = Float( Groesse2 ) / Float( Spanne ) * Float( Diff2 ) ; Die Grössen zusammenrechnen und Überlauf verhindern Groesse = Groesse1 + Groesse2 If Groesse > 255 Then Groesse = 255 ; Den Grössenfaktor zurückgeben Return Float( Groesse / 255.0 ) EndIf ; Wieder das aktuelle Element ansteuern Groessenverlauf = Before Groessenverlauf EndIf Next End Function ;************************************************* ; Die Partikel in eine Bank zeichnen (so kann auf ; die ReadPixel-Befehle verzichtet werden) Function PartikelBank( GR_Index ) For Partikel = Each Partikel_Type ; X- Und Y-Position ermitteln X# = Partikel\X Y# = Partikel\Y ; Stärke und Grösse ermitteln Staerke# = Partikel\Staerke Groesse# = Partikel\Groesse ; Radius ausrechnen Radius# = Groesse / 2.0 ; Arbeits-Radius und -Grösse errechnen ; (muss aufgerundet werden, damit alle ; Pixel berücksichtigt werden) A_Radius = Ceil( Radius ) A_Groesse = A_Radius * 2 ; Die Distanz vom Partikel zum Spritemittelpunkt ermitteln XDiff# = X - Sprite_Groesse / 2 YDiff# = Y - Sprite_Groesse / 2 Rad# = Sqr( XDiff * XDiff + YDiff * YDiff ) ; Den Winkel vom Partikel zum Spritemittelpunkt ermitteln Winkel# = ( ATan2 ( Y - Sprite_Groesse / 2, X - Sprite_Groesse / 2 ) + 360 ) Mod 360 ; Den Grössenfaktor für die ganze Explosion aus dem Grössenfaktor ermitteln VerlGroesse# = GroessenverlaufGroesse#( GR_Index ) ; Die Partikelposition mit dem Grössenfaktor angleichen X = Sprite_Groesse / 2 + Cos( Winkel ) * Rad * VerlGroesse Y = Sprite_Groesse / 2 + Sin( Winkel ) * Rad * VerlGroesse ; Die Bildpunkte, in denen das Partikel liegt ; abarbeiten For a_y = 0 To A_Groesse For a_x = 0 To A_Groesse ; Zwischenvariable für die Intensität ; des einzelnen Pixels Intens = 0 ; Die effektive Position vom Pixel zum ; Sprite-Nullpunkt Eff_X = Int(X) - Int(A_Radius) + a_x Eff_Y = Int(Y) - Int(A_Radius) + a_y ; Nur Pixel im Sprite abarbeiten If Eff_X < Sprite_Groesse And Eff_Y < Sprite_Groesse ; Jeden Bildpunkt Vierteln und von ; jedem Teil abfragen, ob dieser im ; Kreis liegt For h_y = 1 To 10 Step 5 For h_x = 1 To 10 Step 5 ; Distanz des Pixelviertels ermitteln Abfrage_X# = a_x - A_Radius + ( h_x / 10.0 ) - 0.05 Abfrage_Y# = a_y - A_Radius + ( h_y / 10.0 ) - 0.05 Abfrage_Dist# = Sqr( Abfrage_X * Abfrage_X + Abfrage_Y * Abfrage_Y ) ; Liegt der Pixelviertel im Kreis, wird die Intensität ; des ganzen Pixels erhöt If Abfrage_Dist <= Radius Then Intens = Intens + 1 Next Next ; Die neue Stärke des Pixels wird berechnet, in dem die Alte Intensität zur neuen addiert wird Akt_Staerke = PeekShort( Sprite_Bank, Eff_Y * Sprite_Groesse * 2 + Eff_X * 2 ) + Staerke / 4.0 * Intens ; Die neue Intensität des Pixels wird gespeichert PokeShort Sprite_Bank, Eff_Y * Sprite_Groesse * 2 + Eff_X * 2, Akt_Staerke EndIf Next Next ; Die Stärke des Partikels wird vermindert Staerke = Staerke - Staerke_Abzug If Staerke < 0 Then Staerke = 0 Partikel\Staerke = Staerke ; Die Grösse des Partikels wird geändert Partikel\Groesse = Groesse * Partikel_Gr_Faktor ; Das Partikel wird um den Spritemittelpunkt bewegt Winkel# = Winkel + Partikel\Bewegung Partikel\X = Sprite_Groesse / 2 + Cos( Winkel ) * Rad Partikel\Y = Sprite_Groesse / 2 + Sin( Winkel ) * Rad Next End Function ;************************************************* ; Die Bank auslesen und zeichnen Function BankZeichnen() LockBuffer For y = 0 To Sprite_Groesse - 1 For x = 0 To Sprite_Groesse - 1 ; Stärke ermitteln und um den Stärkefaktor korrigieren Staerke = 255 - PeekShort( Sprite_Bank, y * Sprite_Groesse * 2 + x * 2 ) * Staerke_Faktor If Staerke < 0 Then Staerke = 0 ; Die Farbe für den Pixel aus dem Farbverlauf ; auslesen, die Stärke dient hier als Index RGB = FarbverlaufFarbe( Staerke ) ; Pixel zeichnen WritePixelFast 10 + x, 10 + y, RGB ; Bei der Gelegenheit die Bank leeren PokeShort Sprite_Bank, ( y * Sprite_Groesse + x ) * 2, 0 Next Next UnlockBuffer End Function ;************************************************* ; ; Farbverlauf .Farbverlauf ;================================================= ; ; .- Position / Index ( 0...255 ) ; | Wichtig: Index 0 und 255 müssen ; | belegt sein! ; | ; | .- HEX-Farbcode ; | | ; /¯\ /¯¯¯¯¯\ Data 0 , $FFFFFF Data 16 , $FFFF00 Data 96 , $FF8000 Data 128 , $FF0000 Data 180 , $800000 Data 254 , $808080 Data 255 , $0000FF ; Hintergrundfarbe ;************************************************* ; ; Grössenverlauf .Groessenverlauf ;================================================= ; ; .- Position / Index ( 0...255 ) ; | Wichtig: Index 0 und 255 müssen ; | belegt sein! ; | ; | .- Grösse der Explosion ; | | ; /¯\ /¯\ Data 0 , 64 Data 12 , 180 Data 24 , 230 Data 48 , 255 Data 128 , 255 Data 255 , 192 Ich hoffe ihr könnt damit was Anfangen, ich hab den Code schliesslich mühsam auskommentiert - und das nur für euch ![]() MfG PS: Hach, dieses dumme Forum, wandelt Tabs in 3 Leerschläge um, damit geht natürlich die ganze Formatierung flöten (ist aber nicht schlimm, nur unten bei den Verläufen wärs mit perfekter Formatierung schöner ![]() |
||
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BY ♫ BinaryBorn - Yogurt ♫ (31.10.2018) Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm |
- Zuletzt bearbeitet von Holzchopf am So, Feb 06, 2005 21:37, insgesamt einmal bearbeitet
![]() |
Blatolo |
![]() Antworten mit Zitat ![]() |
---|---|---|
Schönes Programm.
Allerdings treten bei mir Fehler auf sobald die SPritegröße 128 oder mehr beträgt. Das generieren funzt noch einwandfrei und wird korrekt angezeigt nur sobald es dann als Bild gespeichert wird treten Grafik Fehler auf |
||
![]() |
HolzchopfMeisterpacker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmm, was für Grafikfehler???
Habs eben nochmal getestet, bei 128 und 256 als Spritegrösse gibts keine Fehler, auch mit was schrägem wie 155 gehts.... Probiers sonst mal mit 32Bit Farbtiefe... |
||
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BY ♫ BinaryBorn - Yogurt ♫ (31.10.2018) Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm |
![]() |
Blatolo |
![]() Antworten mit Zitat ![]() |
---|---|---|
Bei 32 bit passiert das gleiche.
Beim generieren ist noch alles richtig aber das gespeicherte Bild ist fast komplett schwarz mit irgendwelchen Grafikfehlern drauf edit: http://blatolo.tim-koepsel.de/explosion.GIF Sowas kommt dabei raus. Bei 127 funzt noch alles einwandfrei. |
||
![]() |
jungle |
![]() Antworten mit Zitat ![]() |
---|---|---|
wow,
ich bin froh hier im forum gelandet zu sein. bei mir funktioniert der soure einwandfrei - 16 und 32bit. 288x288 wunderbar ; alles was größer wird ist beschnitten. 599x599 lief auch OHNE bildfehler durch. @holzchopf, als (noch) b3d rookie lerne ich natürlich am anfang viel aus offenen sourcen. dein rauch-& explosions-partikelgenerator kommt mir da sehr gelegen ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group