Sichtfeld auf Tilemap

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Shoker

Betreff: Sichtfeld auf Tilemap

BeitragSa, März 14, 2009 1:26
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, März 14, 2009 1:32
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, März 14, 2009 1:35
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Smile

Silver_Knee

BeitragSa, März 14, 2009 2:00
Antworten mit Zitat
Benutzer-Profile anzeigen
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])

hectic

Sieger des IS Talentwettbewerb 2006

BeitragSa, März 14, 2009 3:10
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, März 14, 2009 8:22
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, März 14, 2009 11:40
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, März 14, 2009 13:56
Antworten mit Zitat
Benutzer-Profile anzeigen
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. Very Happy

BladeRunner

Moderator

BeitragSa, März 14, 2009 13:59
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSa, März 14, 2009 14:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Okay, Danke für eure Antworten Smile Schaue es mir an.

SpionAtom

BeitragSa, März 14, 2009 20:58
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, März 15, 2009 12:11
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Very Happy

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

BeitragSo, März 15, 2009 13:00
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragSo, März 15, 2009 17:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Bresenham hätte ich jetzt auch gesagt Smile
Play Satyr!
 

Shoker

BeitragMo, März 16, 2009 16:58
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Wink

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group