Zu berechnende Tiles bestimmen
Übersicht

KrischanBetreff: Zu berechnende Tiles bestimmen |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich häng mal wieder an einer kniffeligen Sache fest, daher die Frage an Euch ob Ihr mir helfen könnt. Es geht um folgendes: ich habe eine 8192x4096 grosse Map, die in 32x16 Tiles à 256x256 Pixel zerschnibbelt ist. Eine Funktion kann anhand der X/Y-Position eines Tiles dieses gezielt als Bild berechnen. Jetzt bin ich an dem Punkt, an dem diese riesige Karte auf dem Bildschirm dargestellt werden soll. Da die wenigsten einen 8192x4096er Bildschirm haben nehmen wir mal beispielsweise eine Auflösung von 800x600 an.
Zur Veranschaulichung habe ich dazu mal eine kleine Animation gebastelt: Das violette Rechteck ist der aktuell sichtbare Teil auf dem Bildschirm (die 800x600). Wir nehmen an, dass sich der Bildschirm nach unten rechts bewegen wird. Grün sind alle Tiles, die bereits berechnet sind, Blau sind die Tiles, die daher berechnet werden müssen, bevor der sichtbare Teil dorthin gelangt und rot sind die Tiles, die überflüssig geworden sind (ausserhalb der Sichtweite/Richtung) und aus dem Speicher gelöscht werden können (oder man lässt sie dort als Cache wenn genug RAM da ist). Die erste Frage dazu ist: wie finde ich heraus, welche Tiles sich innerhalb dieses 800x600 Ausschnitts befinden, also schon berechnet sein müssen, damit dieser Ausschnitt der Karte angezeigt wird und vollständig durch Tiles abgedeckt ist? Die zweite Frage dazu ist: wie stellt man anhand einer Bewegung/Vektors fest, welches die nächsten Tiles in der Bewegungsrichtung sind, die berechnet werden müssen (also die, die dann vom Screen ziemlich sicher abgedeckt werden)? Die dritte Frage dazu ist: wie stelle ich es an, dass die Karte tiletechnisch rechts/links nicht aufhört, sondern die linken/rechten Tiles in diese Berechnungen miteinbezieht aber hingegen oben und unten begrenzt ist? Hintergrund: diese Karte stellt einen Planeten dar, auf dem nachher ein Fahrzeug herumfahren soll. Da der Planet rund ist kann man also ringsherum drauf fahren (dass man Richtung Pole die Karte anhalten muss lässt sich dann halt nicht vermeiden, sonst müsste man eine 3D- Lösung bauen, auf der man direkt auf der Kugel herumfährt). Ich habe dazu einen Beispielcode gebaut, an dem Ihr ein wenig herumspielen könnt: Code: [AUSKLAPPEN] scrw=512 ; Kartengrösse X
scrh=256 ; Kartengrösse Y sw=80 ; Bildschirmgrösse X sh=60 ; Bildschirmgrösse Y tw=16 ; Tilegrösse X th=16 ; Tilegrösse Y Graphics scrw,scrh,32,2 tx=scrw/tw ; Anzahl Tiles X ty=scrh/th ; Anzahl Tiles Y Dim tiles(tx,ty) ; Tilefeld ; Bildschirm erstellen screen=CreateImage(sw,sh) SetBuffer ImageBuffer(screen) Color 255,0,255 Rect 0,0,sw,sh,1 SetBuffer BackBuffer() ; leeres Rasterfeldimage erstellen rasterleer=CreateImage(tw,th) SetBuffer ImageBuffer(rasterleer) Color 0,255,0 Rect 0,0,tw+1,th+1,0 SetBuffer BackBuffer() ; fertig berechnetes Rasterfeldimage erstellen rasterfertig=CreateImage(tw,th) SetBuffer ImageBuffer(rasterfertig) Color 0,255,0 Rect 0,0,tw,th,0 Color 0,128,0 Rect 1,1,tw,th,1 SetBuffer BackBuffer() ; zu berechnendes Rasterfeldimage erstellen rasterberechnen=CreateImage(tw,th) SetBuffer ImageBuffer(rasterberechnen) Color 0,255,0 Rect 0,0,tw,th,0 Color 0,0,255 Rect 1,1,tw,th,1 SetBuffer BackBuffer() ; zu löschendes Rasterfeldimage erstellen rasterloeschen=CreateImage(tw,th) SetBuffer ImageBuffer(rasterloeschen) Color 0,255,0 Rect 0,0,tw,th,0 Color 255,0,0 Rect 1,1,tw,th,1 SetBuffer BackBuffer() Color 255,255,255 MoveMouse scrw/2,scrh/2 While Not KeyHit(1) Cls ; Mausposition mx=MouseX() my=MouseY() ; Tileposition der Maus xx=mx/tw yy=my/th ; Bildschirm begrenzen Y If my<(sh/2) Then my=(sh/2) If my>scrh-(sh/2) Then my=scrh-(sh/2) ; Bildschirm einzeichnen DrawImage screen,mx-(sw/2),my-(sh/2) ; Alle Tiles durchgehen For x=0 To tx-1 For y=0 To ty-1 ; das Tile ist erst einmal leer / unbenötigt image=rasterleer ; es sei denn es ist schon berechnet If tiles(x,y)=1 Then image=rasterfertig ; oder ist ist noch zu berechnen If tiles(x,y)=2 Then image=rasterberechnen ; oder ist ist ueberfluessig und kann gelöscht werden If tiles(x,y)=4 Then image=rasterloeschen ; Tile einzeichnen DrawImage image,x*tw,y*th Next Next ; Ausgabe Mausposition Text 0,0,mx+","+my ; Ausgabe Tileposition der Maus Text 0,15,xx+","+yy Flip 0 Wend End Ich hänge seit Tagen an diesem Problem fest, zu Hilfe!!! |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: Die dritte Frage dazu ist: wie stelle ich es an, dass die Karte tiletechnisch rechts/links nicht aufhört, sondern...
Wenn Du die Tiles in einem Array gespeichert hast: gegeben sei Array(32,16) und zu berechnender Bereich(sx,sy,w,h) zu prüfendes x ist (sx+w)mod 32. Beispiel: Kartenausscnitt ist (29,11 / 6,4). 29+6 ergibt 35, was ja größer als die Karte ist. Mod 32 ergibt 3, was auch stimmt, denn das Tile ragt ja 3 stellen von links wieder rein. Daher ist dies ein valides Tile zum einzeichnen, wenn der Kartenausschnitt bei x=29 beginnt. Die Position auf dem Bildschirm musst du allerdings noch anhand der Ausschnittswerte ohne mod lassen: Ausgabe: Code: [AUSKLAPPEN] for breite = sx to sx+w
X = (breite*256)-(sx*256) ... ... drawimage tile(breite mod 32,y),X,Y next Ich hoffe das hilft. |
||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zur ersten Frage: Man zeichnet immer nur ''direkt auf dem Bildschirm'' und lediglich der Datenzugriff wird variiert. Siehe dazu Code unten.
Zur zweiten Frage: Hab ich erst nach dem 5. lesen verstanden, was gemeint ist. Dazu einfach den ''sichtbaren Breich'' vergrößern. Dieser schliesst dann bereits kommende Dateninhalte mit ein. Zur dritten Frage: Hat bereits BladeRunner geklärt. Ich habe es allerdings in den Code mit eingebaut. Sonst hätte ich einfach auf die FAQ verlinkt, da aus disem der Code verändert werden mußte. Code: [AUSKLAPPEN] Graphics 600,600,0,2
SetBuffer BackBuffer() Const TILESIZE=40 Local Timer=CreateTimer(60) Local GetX,GetY Local X,Y,Block Local MapXPos Local MapYPos Dim Map(9,9) ;EINE ZUFALLS-MAP ERSTELLEN For Y=0 To 9 For X=0 To 9 Map(X,Y)=Rand(X) Next Next While Not KeyDown(1) MapXPos=MouseX() MapYPos=MouseY() ;DIE SICHTBARE MAP EINGRENZEN For Y=1 To 14 For X=1 To 14 ;DIE TILE-ID (HIER FARBE) ZWISCHENSPEICHERN GetX=(X+MapXPos/TILESIZE) Mod 10 GetY=(Y+MapYPos/TILESIZE) Mod 10 Block=Map(GetX,GetY) ;WENN DIE TILE-ID GÜLTIG IST (ALSO VORHANDEN) If Block>0 Then ;IN DIESEM FALL (WEIL KEIN BILD GELADEN) DIE FARBE ANPASSEN Color Block*20,0,0 ;IN DIESEM FALL (WEIL KEIN BILD GELADEN) EIN RECT EINZEICHNEN Rect (Int(MapXPos/TILESIZE)*TILESIZE)-MapXPos+X*TILESIZE,(Int(MapYPos/TILESIZE)*TILESIZE)-MapYPos+Y*TILESIZE,TILESIZE,TILESIZE,1 End If Next Next WaitTimer Timer Flip 0 Cls Wend End Ich hoffe es hilft. Es ist - wie du sehen kannst - eine unendlich scrollende Map. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
SpionAtom |
![]() Antworten mit Zitat ![]() |
---|---|---|
Falls es noch aktuell ist, Beispiel 2 sollte ganz gut passen:
Steuern mit der Maus per Drag&Drop. https://www.blitzforum.de/foru...829#310829 Sämtliche Werte am Anfang ließen sich anpassen. |
||
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080 |
![]() |
DerHase |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hier hat´s auch noch was von mir *Klick*. Leider geschlossen deshalb hab ich dit nicht weitergeführt. | ||
Play Satyr! |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group