Clonk Engine (BB zu Lahm?/Ich zu doof?)
Übersicht

MrJackBetreff: Clonk Engine (BB zu Lahm?/Ich zu doof?) |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hi erstmal, ich habe mich schon ewig gefragt, wie die Engine von dem klassiker Klonk funktioniert? Und zwar dass z.b. der Boden aus einzelnen Pixeln zusammengesetzt wird.. dabei gibt es noch eine Wasserphysik.
Ich habe mal versucht das anhand eines einfachen beispiels nachzubauen. Aber es scheitert mit der geschwindigkeit schon an einfachem Schnee (sehr einfach). Aslo habt ihr Tipps wie ich das Ganze schneller machen kann? (Hab den Code leider noch nicht kommentiert) Code: [AUSKLAPPEN] Graphics 320,240 SetBuffer BackBuffer() ClsColor 119,164,177 ;Arrayerklärung ; ,0=X-Position ; ,1=Y-Position ; ,2=Am Boden?(0/1) ; ,3=Existiert? (0/1) ; ,4=Speedx ; ,5=Speedy Dim part#(76800,5) ;Partikel Dim grounds(320) ;Boden Global Frames Global ZaehlStart Global FramesJeSekunde part_count=76800 ;Max Partikel a=255 r=255 g=255 b=255 rgb=a*$1000000 + r*$10000 + g*$100 + b Const ground=240-1 ;Anfänglicher Boden for i=0 to 320 grounds(i)=ground Next pc=0 While Not KeyHit(1)=1 Cls zahl=Rand(0,100) if zahl >60 and pc<part_count part(pc,0)=Rand(1,319) part(pc,3)=1 part(pc,4)=0 part(pc,5)=1 pc=pc+1 EndIf For p=0 to pc If part(p,3)=1 If part(p,2)=0 If part(p,1)<grounds(part(p,0)) and part(p,5)>0 part(p,1)=part(p,1)+part(p,5) Else part(p,2)=1 part(p,5)=0 If grounds(part(p,0))>=part(p,1) And grounds(part(p,0))>0 grounds(part(p,0))=grounds(part(p,0))-1 EndIf EndIf EndIf Punkt(part(p,0),part(p,1),rgb) EndIf Next ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;TEXTAUSGABE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FPS Text 0,20,pc+" Partikel" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Beenden wenn Frames < 10 If FramesJeSekunde<20 and FramesJeSekunde>10 Cls Text 160,120,"Sie haben "+pc+" Partikel erreicht!",1,1 Flip WaitKey() End EndIf ;Beenden Wenn Maximale Partikelanzahl erreicht If pc=part_count Cls Text 160,120,"Sie haben den Test Bestanden!",1,1 Flip WaitKey() End EndIf Flip Wend Function Punkt(x,y,rgb) LockBuffer BackBuffer() WritePixelfast x,y,rgb UnlockBuffer BackBuffer() End function Function FPS() Frames=Frames+1 If ZaehlStart + 1001 <MilliSecs() then FramesJeSekunde = Frames Frames=0 ZaehlStart=MilliSecs() EndIf Text 0,10, FramesJeSekunde+" FPS" End Function |
||
getlose |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
die Pixel die schon gefallen sind solltest du in ein Image zeichnen,
und das eigentliche Pixel kannst du löschen. |
||
MrJack |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Gute Idee werds mal ausprobieren... ![]() |
||
getlose |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Zitat: Dim part#(76800,5) ;Partikel ![]() mit ist gerade aufgefallen das du da grundlegend ein bisschen was falsch gemacht hast ![]() Code: [AUSKLAPPEN] Global gw=320,gh=240,img,rgb=255*$1000000+255*$10000+255*$100+255 Graphics gw,gh,32,2 img=CreateImage (gw,gh) Dim map(gw-1) For t=0 To gw-1 map(t)=gh-1 Next Type pixel Field x Field y End Type SetBuffer BackBuffer() While Not KeyHit(1) Cls mx=MouseX() my=MouseY() If MouseDown(1) Then CreatePixel(mx+Rnd(-3,3),my+Rnd(-3,3)) SetPixels DrawPixels DrawImage img,0,0 If ac = 1 st = MilliSecs(); fs = ic; ac = 0 EndIf If MilliSecs()>=st+1000 fps=ic-fs ac =1 EndIf Text 0,0,"FPS: "+fps ic = ic + 1 Flip Wend Function CreatePixel(x,y) If map(x)>y Then p.pixel=New pixel p\x=x p\y=y Else Return 0 EndIf End Function Function SetPixels() For p.pixel=Each pixel p\y=p\y+1 If p\y>map(p\x) Then map(p\x)=map(p\x)-1 DrawIntoImage(p\x,p\y-1) Delete p.pixel EndIf Next End Function Function DrawIntoImage(x,y) SetBuffer ImageBuffer(img) Plot x,y SetBuffer BackBuffer() End Function Function DrawPixels() LockBuffer BackBuffer() For p.pixel=Each pixel WritePixelFast p\x,p\y,rgb Next UnlockBuffer BackBuffer() End Function |
||
![]() |
Travis |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmm? Die Haufen die sich da bilden sehen aber ein bisschen unrealistisch aus oder? ![]() Ich hatte selbst auch mal sowas gemacht. Leider bildet sich auf einer Seite immer so ein Komischer Trichter, in dem einige Lücken vorhanden sind. Das hängt irgendwie mit dem Wind zusammen. Ist aber trotzdem mal 'nen Blick wert. Code: [AUSKLAPPEN] ; ------------------------ ; - Schneefall by Travis - ; - 2. Version - ; -------------------------------- ; - Simulation von Schneeflocken - ; --------------------------------------- ; - Copyright (C) Aug 2004, DanielNobis - ; --------------------------------------- SeedRnd MilliSecs() Global ResX = 640 Global ResY = 480 Global Gravitation# = .1 Global Wind# = Rnd(.1,-.1) Global Flocken Graphics ResX,ResY,16,2 ; --- Terrain erstellen --- Global Map = CreateImage(ResX,ResY) SetBuffer ImageBuffer(Map) Font1 = LoadFont("Verdana", 42, 1, 0, 0) SetFont Font1 Color 100,100,150 Text 120,200, "Schneefall by Travis" Rect 0,ResY-100, ResX, 100,1 ; Boden FreeFont Font1 SetBuffer BackBuffer() ; --- Terrain erstellen --- ; --- Kollisions Map erstellen --- w = ImageWidth(Map) h = ImageHeight(Map) Dim KollisionMap(w,h) SetBuffer ImageBuffer(Map) LockBuffer ImageBuffer(Map) For y = 0 To h For x = 0 To w rgb = ReadPixelFast(x,y) If rgb = -16777216 Then KollisionMap(x,y) = 0 If rgb <> -16777216 Then KollisionMap(x,y) = 1 Next Next UnlockBuffer ImageBuffer(Map) SetBuffer BackBuffer() ; --- Kollisions Map erstellen --- Repeat Cls DrawImage Map, 0, 0 If KeyHit(28) Then ViewKollisionMap(): Delay 1000 If MilliSecs()-Timer1 > 1 Then x = Rnd(ResX) y = Rnd(0) NewFlocke(x,y) EndIf UpdateFlocken() Text 0,0, "Flocken: " + Flocken Text 0,10, "FPS: " + FPS() Flip 0 Until KeyHit(1) End Flip WaitKey End ; --- Neue Flocke erstellen --- Type Flocke Field x#,y#,status,col,masse End Type Function NewFlocke(x,y) f.flocke = New flocke f\x = x f\y = y f\status = 1 R = Rnd(150,255) f\col = a*$1000000 + R*$10000 + R*$100 + R f\masse = Rnd(1,3) Flocken = Flocken + 1 End Function ; --- Neue Flocke erstellen --- ; --- Flocken aktualisieren --- Function UpdateFlocken() LockBuffer BackBuffer() For f.flocke = Each flocke tx# = f\x# ty# = f\y# If KollisionMap(f\x# + Wind#, f\y#) = 0 Then f\x# = f\x# + Wind# ; Ist neben der Flocke frei If KollisionMap(f\x#, f\y + Gravitation# * f\masse#) = 0 Then ; Ist unter der Flocke frei f\y# = f\y# + Gravitation# * f\masse# Else If KollisionMap(f\x+1, f\y+1) = 0 Then f\x = f\x+1: f\y = f\y + 1: Goto NextFlocke ; Floche rutscht zur Seite If KollisionMap(f\x-1, f\y+1) = 0 Then f\x = f\x-1: f\y = f\y + 1: Goto NextFlocke WritePixelFast(f\x,f\y,f\col,ImageBuffer(Map)) ; Flocke in den Hintergrund integrieren KollisionMap(f\x,f\y) = 1 Delete f Flocken = Flocken - 1 Goto NextFlocke EndIf WritePixelFast(f\x,f\y,f\col,BackBuffer()) .NextFlocke Next UnlockBuffer BackBuffer() End Function ; --- Kollisions Map zur Kontrolle anzeigen --- Function ViewKollisionMap() w = ImageWidth(Map) h = ImageHeight(Map) TestMap = CreateImage(w,h) SetBuffer ImageBuffer(TestMap) LockBuffer ImageBuffer(TestMap) For y = 0 To h For x = 0 To w If KollisionMap(x,y) = 1 Then WritePixelFast(x,y,$CC0000) Next Next UnlockBuffer ImageBuffer(TestMap) SetBuffer BackBuffer() Cls DrawImage TestMap, 0,0 Color 255,255,0 Text 0,0, "Kollisions Map" Flip End Function ; --- Kollisions Map zur Kontrolle anzeigen --- ; --- Frames per Second --- Global FPSSEC = MilliSecs(), FPS, FRAMES Function FPS() FRAMES = FRAMES + 1 If MilliSecs() - FPSSEC => 1000 Then FPS = FRAMES FRAMES = 0 FPSSEC = MilliSecs() EndIf Return FPS End Function ; --- Frames per Second --- |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
x.Force |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Array index out of bounds @ travis | ||
AMD Athlon XP 2000+ | 1024mb DDR-Ram | Asus Radeon 9600XT | BENQ FP757 17°Zoll TFT Was kümmert mich mein Geschwätz von gestern? (Konrad Adenauer) -.- |
![]() |
Travis |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mach mal den Debugger aus. Mit dem geht es bei mir auch nicht. ![]() |
||
www.funforge.org
Ich hasse WASD-Steuerung. Man kann alles sagen, man muss es nur vernünftig begründen können. |
![]() |
tft |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi....
der gravirenste fehler ist wohl, das du alles unnötig in Functionen gepackt hast und das LockBuffer in der Function für jedes Pixsel aufgerufen wird. Und das Image Scrolling fehlt. Aber lass dich von solchen fehlversuchen nicht abschrecken. Jeder hir hat mal so angefangen. Fiehl Spass noch....... |
||
TFT
https://www.sourcemagic.ch Monkey,HTML5,CSS3,W 10 64 Bit, 32 GB Ram, GTX Titan, W8 ist Müll !!!!!! |
Timo |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hi!
MrJack hat Folgendes geschrieben: Dim part#(76800,5) ;Partikel
sehe ich das richtig, das du 76801 * 6 * 8Byte = 3686448Bytes benötigst? Das sind 3.5 GB!! Könnte ein Grund dafür sein warum es so langsam ist ![]() |
||
![]() |
TheShadowModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
76801 * 6 * 4Byte = 1.843.224=1,8MB | ||
AMD64 3500+ | GeForce6600GT 128MB | 1GB DDR | WinXPsp2 |
Timo |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Oh - stimmt bei mir dürften nicht GB stehen sondern Mb ![]() Na ok, dann wirds daran wohl nicht liegen... ![]() |
||
![]() |
Peer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Geh auf Clonk.de und lad dir den code runter ^^ (steht da frei zum Download).
Sry für den sakassmus aber Blitz ist da net die richtige sprache für. In C++ wird glaube ich ein Bild genommen und getiled aber dann nur da als Bild gemalt wo in einem array der schneewert eingetragen ist. Also schon von der Grafikarte net mehr im code. Clonk rules ![]() |
||
junky |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
bin seit Jahren begeisterter Clonker...
aber ich glaub nicht, dass es mit Blitz nicht gehen sollte kann nun nicht beurteilen, ob das Travis in seinem BspCode schon so macht (habn nit richtig durchgearbeitet), aber ich schreib einfach mal ![]() mal doch z.b. deine Schneeflocken auf ein von dir selbst gebuffertes Bild, welches den ganzen Bildschirm umfasst und immer eingezeichnet wird... so brauchst du nicht unendlich von kleinen Schneeflocken abzubilden, sondern kannst sie, wenn sie z.b. bereits in einer unbeweglichen Position am Boden liegen, vernachlässigen ![]() und wenn ich so ein Bild bei mir übern ganzen Bildschirm zeichnen lasse ( 1024, 768, 32) hab ich immerhin noch 450fps --- PS: is nur ne Idee - habs noch nit selbst ausprobiert (werds aber mal bei Gelegenheit) - ne Idee is aber immer noch besser als garnix ![]() |
||
gestern stand ich noch vorm Abgrund
heute bin ich einen Schritt weiter... |
![]() |
tft |
![]() Antworten mit Zitat ![]() |
---|---|---|
HI...
ich denke da must du noch mal ganz von forne anfangen. Der gesamte ansatz zu diesem problem ist Falsch. Hir einige hinweise. Erzeuge Image mit Schneeflocke. Lass dieses zufälig oben in der X achse erzeugen. For next Schleife mit anzahl flocken. Flocken nach unten bewegen. Flocken auf Coli testen Wenn nötig aus For next schleife entfernen. Für diese aufgabe kanst du am besten Types einsetzen. Da diese sich Löschen lassen und du nicht sortieren must. |
||
TFT
https://www.sourcemagic.ch Monkey,HTML5,CSS3,W 10 64 Bit, 32 GB Ram, GTX Titan, W8 ist Müll !!!!!! |
junky |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
wow, muss dich leider enttäuschen tft ![]() writepixelfast is bei ner gewissen Flockenanzahl eindeutig schneller ( da wir schon en bisl Schnee haben wollen, hab ich einfach ma 1000 eingestellt ) wenn ich alle Flocken als Images dargestellt hab, gab es richtige Performanceeinbußen ... gn8 @ all |
||
gestern stand ich noch vorm Abgrund
heute bin ich einen Schritt weiter... |
![]() |
tft |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi
Diesen Code habe ich gerade zusammen geschustert. Noch nicht ganz astrein aber bei mir 400 FPS bei durchgehend 1300 Flocken. Code: [AUSKLAPPEN] Graphics3D 640,420,32,2 SetBuffer BackBuffer() Dim x(4000) Dim y(4000) Global anz_flocken=0 t=MilliSecs()+300 Const anz_p=4 im=CreateImage(640,420) SetBuffer ImageBuffer(im) Cls Color $FF,0,0 Line 0,300,640,400 SetBuffer BackBuffer() Repeat DrawBlock(im,0,0) If t<MilliSecs() t=MilliSecs()+1 For i=1 To anz_p anz_flocken=anz_flocken+1 x(anz_flocken)=Rnd(1,639) y(anz_flocken)=0 Next EndIf If anz_flocken>0 LockBuffer BackBuffer() For i=1 To anz_flocken y(i)=y(i)+1 RGB=ReadPixelFast(x(i),y(i)) r=(RGB And $FF0000)/$10000 ;g=(RGB And $FF00)/$100 ;b=RGB And $FF If r=0 WritePixelFast(x(i),y(i),$ffffff) Else SetBuffer ImageBuffer(im) WritePixel(x(i),y(i)-1,$ffffff) SetBuffer BackBuffer() If i<>anz_flocken x(i)=x(anz_flocken) y(i)=y(anz_flocken) EndIf anz_flocken=anz_flocken-1 EndIf Next UnlockBuffer BackBuffer() Text 10,10,anz_flocken EndIf Frames=Frames+1 If ZaehlStart + 1001 <MilliSecs() Then FramesJeSekunde = Frames Frames=0 ZaehlStart=MilliSecs() EndIf Text 10,20, FramesJeSekunde+" FPS" ;Delay(1) Flip 0 Until KeyHit(1) End |
||
TFT
https://www.sourcemagic.ch Monkey,HTML5,CSS3,W 10 64 Bit, 32 GB Ram, GTX Titan, W8 ist Müll !!!!!! |
![]() |
tft |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi...
damit das ganze nicht so eckig aussieht. Code: [AUSKLAPPEN] Graphics3D 640,420,32,2 SetBuffer BackBuffer() Dim x(8000) Dim y(8000) Global anz_flocken=0 t=MilliSecs()+300 Const anz_p=20 im=CreateImage(640,420) SetBuffer ImageBuffer(im) Cls Color $FF,0,0 Line 0,300,640,400 Line 0,301,640,401 Line 0,302,640,402 SetBuffer BackBuffer() Repeat DrawBlock(im,0,0) If t<MilliSecs() t=MilliSecs()+1 For i=1 To anz_p anz_flocken=anz_flocken+1 x(anz_flocken)=Rnd(1,639) y(anz_flocken)=0 Next EndIf If anz_flocken>0 LockBuffer BackBuffer() For i=1 To anz_flocken y(i)=y(i)+1 RGB=ReadPixelFast(x(i),y(i)) r=(RGB And $FF0000)/$10000 ;g=(RGB And $FF00)/$100 ;b=RGB And $FF If r=0 WritePixelFast(x(i),y(i),$ffffff) Else RGB=ReadPixelFast(x(i)-1,y(i)+1) r=(RGB And $FF0000)/$10000 If r>0 RGB=ReadPixelFast(x(i)+1,y(i)+1) r=(RGB And $FF0000)/$10000 If r>0 SetBuffer ImageBuffer(im) WritePixel(x(i),y(i)-1,$ffffff) SetBuffer BackBuffer() If i<>anz_flocken x(i)=x(anz_flocken) y(i)=y(anz_flocken) EndIf anz_flocken=anz_flocken-1 Else x(i)=x(i)+1 y(i)=y(i)+1 WritePixelFast(x(i),y(i),$ffffff) EndIf Else x(i)=x(i)-1 y(i)=y(i)+1 WritePixelFast(x(i),y(i),$ffffff) EndIf EndIf Next UnlockBuffer BackBuffer() Text 10,10,anz_flocken EndIf Frames=Frames+1 If ZaehlStart + 1001 <MilliSecs() Then FramesJeSekunde = Frames Frames=0 ZaehlStart=MilliSecs() EndIf Text 10,20, FramesJeSekunde+" FPS" ;Delay(1) Flip 0 Until KeyHit(1) End |
||
TFT
https://www.sourcemagic.ch Monkey,HTML5,CSS3,W 10 64 Bit, 32 GB Ram, GTX Titan, W8 ist Müll !!!!!! |
![]() |
Peer |
![]() Antworten mit Zitat ![]() |
---|---|---|
So dass interessiert mich aber wirklich. Clonk ist schlichtweg genial. Wenn man sone Engine hinbekommen würde und die noch mit einer Abwandling von Blitz Virtual Mashine verbinden würde könnte man sicher ein geniales Spiel entwickeln.
Fürs Terrain: Ein 2 Dimensionales Array von der Maximalen Mapgröße (bei 10 bildschirmbreiten ungefähr 10000 x 10000 x 4 byte = 400 MB (gibt leider keine Byte Arrays)). Dies wird nur für abfragen (Ob z.B. Steine im Weg sind) benutzt. Zur Grafischen Darstellung: Für Festen Boden (Erde, Steine, Granit, Kohle etc.) also alles was sich nicht bewegt (ausnahme beim buddeld oder Granitflints) getilete Bilder von ca. 800 x 800 Pixel (Für eine Maximale Auflösung von 1600x1024. So braucht man nicht immer 10000x10000 pixel bilder zu malen sondern immer nur 4 800 x 800 Pixel bilder. Das benötigt eigentlich keine Performance (4 Bilder). Bei bewegten Objekten (Schnee (Lavinen), Wasser, Öl etc.) wird ein 2. Array benötigt oder besser in das erste Integriert (1 byte für boden, 1 byte für flüssigkeiten). Gemalt wird in die Tilebilder des Festen Bodens. Wenn sich ein wassertropfen verschiebt wird er an seiner ursprungsposition mit der Transparentfarbe übermalt, und an seiner neuen position mit seiner normalen farbe gemahlt. Für die berechnung der Bewegung muss be jedem wassertropfen in der Linie ein Posel unter ihm geprüft werden, ob es links oder rechts ein freier Pixel besteht und er muss dann hinbewegt werden. Dies muss aber nur gemacht werden wenn sich etwas im letzten Frame bewegt hat (Ein lochh gesprengt wurde, Das wasser noch am fließen ist etc.) Also jeder Wasserpixel muss bei einer Bewegung ein Pixel nach unten und beliebig viele pixel nach links oder rechts oder direkt runter. Schnee und ähnliches muss bei jeder Bewegug eins runter und NUR 1 nach links oder rechts. Das macht den unterschied auß. Diese routinen müssen dann natürlich optimiert werden weil sie sonst schlichtweg zu langsam währen. Ich arbeite im Moment leider selber an einem großen projekt und kann daher selber nicht viel beisteuern (Codemäßig). Aber logistisch helfe ich gerne weiter da mich Clonk sehr interessiert und ich mich über einen Nachbau in BB sehr freuen würde (sry dass ich letztes mal so pessemistisch war ![]() Was man auf keinen fall machen darf ist bei jedem Frame alle pixel mit write/readpixel zu malen oder auszulesen weil es schlichweg zu langsam ist. Malt sie lieber einmal in ein Bild und nur bei veränderungen mit writepixelfast arbeiten. Fals jemand etwas aus meinem gebrabel net versteht fragt einfach ^^ |
||
junky |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
ehm ![]() lasst mich wissen, wenn ich jetz totalen schrott zusammenschreib - thx ![]() ich bezweifel dass das echt clonk auf ner auflösung von 1600x1200 überhaupt noch flüssig läuft ... - deshalb rechne ich mit ner max Auflösung von 1024x800 1024 x 800 x 4Byte = 3.276.800Bytes / Bildschirm 3.276.800Bytes x 10 Bildschirme = 32.768.000 Bytes = 31,25 Mb |
||
gestern stand ich noch vorm Abgrund
heute bin ich einen Schritt weiter... |
![]() |
Peer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja aber die Maps sind ja scrollbar. Und ne riesige map hat schon 10000-50000 pixel breite | ||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group