Sichtfeld auf Tilemap
Übersicht

ShokerBetreff: Sichtfeld auf Tilemap |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hey,
Ich programmiere ein 2D Rpg und bin nun zu einen Punkt gekommen, an dem ich prüfen muss ob ich mein Ziel sehe. Ich habe die entfernung und auch den Winkel bereits.. Doch leider bekomme ich es einfach nicht. Und ich habe die Felder durch die man nicht durchschauen kann in einem Dimfeld. Hab schon mehrere for schleifen versucht. Habe nur gedacht das ich mit dem Winkel und der länge herausfinden kann welche Dimfelder gerade angeschaut werden. Hoffe mir kann einer weiterhelfen. |
||
![]() |
TimBo |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi,
wenn du den WInkel hast, und ein Tilefeld ~20 pix. groß ist, dann gehe in 5er Schritten jeden Pixel durch , von Startpunkt in Richtung Endpunkt , bestimme das dazugehörige Arry-Feld , checke den Status, schaubar , nichtschaubar , wenn nichtschaubar, dann kannst du das ausgewählte Ziel nicht sehen , wenn ja , gehe wieder 5 Pixel weiter. Viele Grüße TimBo |
||
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31 hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht. |
Shoker |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
ja, genau so habe ich es auch schon versucht, leider bekomme ich da Probleme wenn ich zb 4 Felder hoch gehe und dann 1 nach links gehen muss und danach wieder 4 Felder hoch kommen ![]() |
||
![]() |
Silver_Knee |
![]() Antworten mit Zitat ![]() |
---|---|---|
Spontan fällt mir grad nix ein deshalb mal den "lahm aber geht"-weg. Mach ein Image indem Genau die Sichtlienie mit line gezeichnet wird und prüfe mit rectsoverlap die lienie gegen alle felder die in frage kommen (also blockierend und in der selben ecke [Rechts oben, links oben, rechts unten, links unten]) | ||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das ist tatsächlich ein ''Problemfall''. Mit der 5-Pixel-Taktik kann man unter umständen dann Gegner sehen, die definitiv nicht besucht werden können. Als Beispiel mal folgendes Szenario. Wenn ''1'' und ''2'' nun jeweils ein Tile sind, und A nach B geprüft werden muß, werden die beiden Gegner als ''sichtbar'' deklariert, aber mit der Unmöglichkeit zu den Gegner zu gelangen. Also ein Fehler.
Code: [AUSKLAPPEN] 11111111 B
11111111 11111111 11111111 22222222 22222222 22222222 A 22222222 Als Alternative zu Silver_Knee's sein Vorschlag, könnte man alles auf Linienkollisionen berechnen. Dazu müsste man zu jedem Tile dessen Eckpunkte mit jeweils zwei berechneten ''Linien'' kreuzen. Das würde dann in etwa wie folgt aussehen. Die berechnete Linienkollision zwischen A und B lässt keine Sichtverbindng durch. Code: [AUSKLAPPEN] \ / B
\/ /\ / \ \ / \/ /\ A / \ |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
da_poller |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
also.. ist es nicht theoretisch möglich, du kennst den winkel und die distanz. jetzt findest du mit a* oder einem anderen wegfindungs algo die kürzeste seh/begehbare route raus. ist sie länger als die direkte verbindung gehtst du zwangsweise irgendwo um die ecke und kannst dein ziel nicht sehen...
so mein halb 8 denkansatz hoffe ich konnte helfen |
||
![]() |
SpionAtom |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ist doch gar nicht so schwer:
Erst grob auf Tileebene überprüfen, ob eine direkte Sicht ausgeschlossen werden kann. Dann auf Pixelebene. |
||
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080 |
Shoker |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Also ich wollte das ganz gerne mit einer For schleife lösen.
Habe schon mehrere For schleifen probiert, komme aber einfach nicht dahinter. Algo wollte ich davor einbauen allerdings ohne erfolg. Habs noch nicht verstanden... Wenn ich die Sichtlinie habe, brauche ich auch kein Algo mehr. ![]() |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Schau mal im Internet nach Bresenham line algo, der beschreibt das prinizpielle Vorgehen. | ||
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 |
Shoker |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Okay, Danke für eure Antworten ![]() |
||
![]() |
SpionAtom |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich nahm die Herausforderung an:
Out of Sight ist nicht nur ein Film, sondern seit jetzt auch eine weitere Funktion in meinem BB-Schatz: Vielleicht sollte ich noch zwei Takte zur Funktionsweise sagen: Ich gehe tatsächlich alle Pixel der Luftlinie ab. Befindet sich ein Pixel auf einem Mauerteil, ist die Sicht unterbrochen. Findet vom einen auf den anderen Pixel ein Tile-wechsel statt - und zwar in x und y Richtung das passiert wenn man auf Position 5 steht und danach auf 1, 3, 7 oder 9. 123 456 789 - dann überprüfe ich, ob die Mauer an der Stelle geschlossen ist. Beispiel: Die Linie geht über 5 nach 7. Dann ist die Mauer geschlossen, wenn 4 und 8 ein Mauer-Tile sind. In dem Fall wäre die Sicht auch unterbrochen. Jaja klingt alles kompliziert, ist aber alles halb so wild und in einer Schleife zu lösen, die so groß ist, wie der Abstand der beiden Punkte. Code: [AUSKLAPPEN] ; outOfSight
; ; Prüft auf einer Tilemap, ob sich zwei Punkte sehen können. ; ; Linksklick - Mauer setzen ; Rechtsklick - Mauer entfernen ; Mittklick - Startpunkt neu setzen ; Tab - Debuganzeige an/aus ; ;SpionAtom - März 2oo9 Graphics 800, 800, 0, 2 SetBuffer BackBuffer() Const steps = 5 Const mapx = 0, mapy = 0, mapw = 20, maph = 20, mapg = 40 Dim map(mapw - 1, maph - 1) debug = 1 Repeat mouse_x = MouseX(): mouse_y = MouseY() ;Berechnung der MausTilekoordinaten inTileX = Floor((mouse_x - mapx) / Float(mapg)) inTileY = Floor((mouse_y - mapy) / Float(mapg)) ;Mauer setzen/löschen If MouseDown(1) Then map(inTileX, inTileY) = 1 If MouseDown(2) Then map(inTileX, inTileY) = 0 ;Spieler setzen If MouseDown(3) Then sx = inTileX: sy = inTileY: sxv = (mouse_x - mapx) Mod mapg: syv = (mouse_y - mapy) Mod mapg ;debug an/ausschalten mit Tab If KeyHit(15) Then debug = 1 - debug x1 = sx * mapg + sxv: y1 = sy * mapg + syv x2 = inTileX * mapg + (mouse_x - mapx) Mod mapg: y2 = inTileY * mapg + (mouse_y - mapy) Mod mapg Cls ;Map malen For i = 0 To mapw - 1: For j = 0 To maph - 1 If map(i, j) Then Color 0, 100, 100: Rect mapx + i * mapg, mapy + j * mapg, mapg, mapg, 1 Color 30, 30, 30: Rect mapx + i * mapg, mapy + j * mapg, mapg, mapg, 0 Next: Next If inTileX >= 0 And inTileY >= 0 Then If outOfSight(x1, y1, x2, y2, debug) Then Color 150, 0, 0: e$ = "Sicht gestört" Else Color 0, 150, 0: e$ = "Freie Sicht" End If Else Color 150, 150, 150: e$ = "Maus nicht im Feld" End If Text 0, GraphicsHeight() - 16, e$ Color 100, 100, 0: Rect mapx + inTileX * mapg, mapy + inTileY * mapg, mapg, mapg, 0 Color 100, 0, 0: Oval mapx + sx * mapg, mapy + sy * mapg, mapg, mapg, 0: Oval mapx + x1 - 2, mapy + y1 - 2, 4, 4 Color 255, 255, 255: Text 0, 0, "LINKSKLICK=Mauer setzen, RECHTSKLICK=Mauer löschen, MITTELKLICK=Spieler setzen, TAB - Debug(" + debug + ")" Text 0, 16, "Maus: " + inTileX + ", " + inTileY Flip() Until KeyDown(1) End ;Berechnet den Winkel zwischen der X-Achse und einer Geraden durch zwei Punkte Function Winkel#(x1#,y1#,x2#,y2#) Return (360+ATan2(x1#-x2#,y1#-y2#)) Mod 360 End Function ;Berechnet den Abstand zwischen zwei Punkten Function Distanz#(x1#, y1#, x2#, y2#) Return Sqr((x1-x2)^2 + (y1-y2)^2) End Function Function outOfSight(x1, y1, x2, y2, showLine = False) d# = Distanz(x1, y1, x2, y2) w# = Winkel(x1, y1, x2, y2) Text 100, 100, d ;Sichtstrahl berechnen i = 0 Repeat i = i + steps: If i > d Then i = d ;Pixelkoordinaten des aktuellen Punktes px = x1 - Sin(w) * i py = y1 - Cos(w) * i ;Tile des aktuellen Punktes inX = Floor(px / Float(mapg)) inY = Floor(py / Float(mapg)) ;Schauen, ob Strahlpunkt auf freiem Feld steht If inX >= 0 And inY >= 0 Then If map(inX, inY) Then Exit ;Schauen, ob der Strahl über einen Kreuzpunkt geht If oX <> inX And oY <> inY Then If showLine Then Color 50, 0, 50: Oval mapx + px, mapy + py, 5, 5 If map(inX, oY) = 1 And map(oX, inY) = 1 Then Exit End If If showLine Then Color 20, 20, 20: Rect mapx + inX * mapg + 1, mapy + inY * mapg + 1, mapg - 2, mapg - 2 End If oX = inX: oY = inY Until i = Int(d) e = Not(Int(px) = x2 And Int(py) = y2) If showLine Then If e Then Color 150, 0, 0 Else Color 0, 150, 0 Line mapx + x1, mapy + y1, mapx + px, mapy + py End If Return e End Function |
||
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080 |
- Zuletzt bearbeitet von SpionAtom am So, März 15, 2009 13:00, insgesamt einmal bearbeitet
![]() |
TimBo |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi,
nice Algo. Nur finde ich die Berechnung, ob 2 Linien sich kreuzen etwas lahm. Entweder ich sehe da was falsch , oder du gehst da jeden Pixel durch. Vielleicht könnte dich LineIntersect - "CodeArchiv" weiterbringen, deine Funktion zu beschleunigen. Aber im allgemeinen ein sehr nützlicher Code ![]() Viele Grüße TimBo |
||
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31 hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht. |
![]() |
SpionAtom |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Problem bei LineIntersect ist, du brauchst zwei Linien. Die Punkte für die Luftlinie hast du gegeben, Wandlinien müsste man erst aus der Tilemap rausberechnen...
Der Algo sollte aber auch noch klappen, wenn man grobschrittiger vorgeht, also nur noch alle 5 Pixel überprüft. Jo klappt noch, nach einer kleinen Anpassung, ich editier das mal oben ren. (Man wie ich das hasse, dass steps konstant sein muss bei For-Schleifen!) |
||
os: Windows 10 Home cpu: Intel Core i7 6700K 4.00Ghz gpu: NVIDIA GeForce GTX 1080 |
![]() |
DerHase |
![]() Antworten mit Zitat ![]() |
---|---|---|
Bresenham hätte ich jetzt auch gesagt ![]() |
||
Play Satyr! |
Shoker |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Okay, Habe es fast geschafft.. hab nur noch nen kleines problem mit Bresenham´s algo aber das werde ich vermutlich selbst lösen. Danke für eure hilfe ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group