![]() |
|
RGSS-Scripts Postet hier die Scripts die ihr im Script-Editor selbst erstellt oder gefunden habt. Gefundene Scripts jedoch mit Quellenangabe posten! |
![]() |
|
Themen-Optionen |
![]() |
#1 |
Neuling
![]() Registriert seit: 01.10.2009
Beiträge: 41
|
![]() Hallo zusammen.
Vielleicht gibt es zwar schon so ein Script, aber hier im Forum hab ich für den XP keins Gefunden. Das Skript gibt an, ob sich ein Event im Sichtkegel eines anderen befindet. Dabei berücksichtigt es alle Hindernisse, die: - Unpassierbare Events mit sprites sind. - einen Terraintag im "WALL_TAG"-Array (Skript-Zeile 3) haben, welches beliebig angepasset werden kann. Es wird kein kompletter Sichtkegel berechnet, was sich positiv auf die Performance auswirkt. Benutzen lässt es sich am besten über die Scriptfunktion vom "Conditional Branch..." Funktionen: in_sicht?(ev1, ev2, winkel , dist) ev1: Event-ID des sehenden Events ev2: Event-ID des gesehenden Events winkel: Sichtwinkel in Grad (60-90 sind optimal) dist: Maximale Entfernung in Feldern player_in_sicht?(ev, winkel, dist) ev: Event-ID des sehenden Events winkel: Sichtwinkel in Grad (60-90 sind optimal) dist: Maximale Entfernung in Feldern Die Funktionen sind so in der Interpreter-Klasse vorhanden. Code:
class Game_Character # Terrain-tags für undurchsichtig WALL_TAG = [1, 2] #-------------------------------------------------------------------------- # * prüft ob der Spieler im Sichtkegel liegt #-------------------------------------------------------------------------- def player_in_sicht?(winkel, dist) return (in_sight_cone?($game_player.x, $game_player.y, winkel, dist) and visible?($game_player.x, $game_player.y, dist)) end #-------------------------------------------------------------------------- # * prüft ob ein Event im Sichtkegel liegt #-------------------------------------------------------------------------- def in_sicht?(ev, winkel , dist) return (in_sight_cone?(ev.x, ev.y, winkel, dist) and visible?(ev.x, ev.y, dist)) end #-------------------------------------------------------------------------- # * prüft ob ein Event im Sichtkegel liegt #-------------------------------------------------------------------------- def in_sight_cone?(x, y, winkel, dist) winkel = winkel * Math::PI / 360 sx = (x - @x) sy = (y - @y) abs_sx = sx.abs abs_sy = sy.abs # Entfernung ist größer als Sichtkegel if Math.sqrt(abs_sx * abs_sx + abs_sy * abs_sy) > dist return false end case (@direction) when 2 # unten return abs_sx <= sy * Math.tan(winkel) when 4 # links return abs_sy <= -sx * Math.tan(winkel) when 6 # rechts return abs_sy <= sx * Math.tan(winkel) when 8 # oben return abs_sx <= -sy * Math.tan(winkel) end end #-------------------------------------------------------------------------- # * prüft ob ein Event verdeckt wird #-------------------------------------------------------------------------- def visible?(x, y, dist) sx = (x - @x) sy = (y - @y) # Entfernung ist 0 if sx == 0 and sy == 0 return false # da man sich nicht selbst sehen kann end abs_sx = sx.abs abs_sy = sy.abs # Entfernung ist größer als Sichtkegel if Math.sqrt(abs_sx * abs_sx + abs_sy * abs_sy) > dist return false end if abs_sx >= abs_sy # Scanne in x-Abständen dy = sy / sx.to_f r = dy / 4 if sx >= 0 for dx in 1..(sx - 1) xx = @x + dx y1 = (@y + dy * dx - r).round y2 = (@y + dy * dx + r).round unless durchsichtig?(xx, y1) return false end unless durchsichtig?(xx, y2) return false end end else for dx in (sx + 1)..-1 xx = @x + dx y1 = (@y + dy * dx - r).round y2 = (@y + dy * dx + r).round unless durchsichtig?(xx, y1) return false end unless durchsichtig?(xx, y2) return false end end end else # Scanne in y-Abständen dx = sx / sy.to_f r = dx / 4 if sy >= 0 for dy in 1..(sy - 1) yy = @y + dy x1 = (@x + dx * dy - r).round x2 = (@x + dx * dy + r).round unless durchsichtig?(x1, yy) return false end unless durchsichtig?(x2, yy) return false end end else for dy in (sy + 1)..-1 yy = @y + dy x1 = (@x + dx * dy - r).round x2 = (@x + dx * dy + r).round unless durchsichtig?(x1, yy) return false end unless durchsichtig?(x2, yy) return false end end end end return true end #-------------------------------------------------------------------------- # * prüft ob das Feld undurchsichtig ist #-------------------------------------------------------------------------- def durchsichtig?(x, y) # Vom Ziel ist das Ziel immer sichtbar if @x == x and @y == y return true end # für alle Events for event in $game_map.events.values if event.x == x and event.y == y # Event ist nicht passierbar unless event.through or event.character_name == "" return false end end end if $game_player.x == x and $game_player.y == y # Spieler ist nicht passierbar unless $game_player.through return false end end # prüfe auf unduchsichtige Wand if WALL_TAG.include?($game_map.terrain_tag(x, y)) return false end return true end end class Interpreter #-------------------------------------------------------------------------- # * prüft ob ein Event im Sichtkegel eines anderen liegt #-------------------------------------------------------------------------- def in_sicht?(ev1, ev2, winkel , dist) return $game_map.events[ev1].in_sicht?($game_map.events[ev2], winkel, dist) end #-------------------------------------------------------------------------- # * prüft ob der Spieler im Sichtkegel eines Events liegt #-------------------------------------------------------------------------- def player_in_sicht?(ev, winkel, dist) return $game_map.events[ev].player_in_sicht?(winkel , dist) end end Verwendungsbeispiel in einem Event: Code:
@>Conditional Branch: Script: player_in_sicht?(@event_id, 75, 8) "Aktion, wenn Spieler entdeckt wurde" : Branch End Das Skript ist primitiv und schnell. Falls jemand Fehler findet oder weiß wie man es verbessern kann, scheut euch um kein Kommentar. Benutzung wie immer nur Mit Crediteintrag! Geändert von _Matrix (10.02.2010 um 18:58 Uhr). Grund: Kompatiblität zum Collisions-Script V 1.2 |
![]() |
![]() |
![]() |
#2 |
23
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() Hi, hab's mal kurz überflogen, und ich hab das für S.E.-Pantheon recht ähnlich gelöst! Was natürlich wahnsinnig ist, ist, dass er in jedem Schritt der Verbindungslinie (ich nehm mal an du weißt, was ich meine) alle Events einzeln durchgeht. Das verbraucht (v.a. als Teil eines AKS und wenn viele Events sichtbar sind) viel Zeit und lässt sich nur darüber entschärfen, dass man eine Tabelle mitführt, die für jede Mapposition speichert, welches Event sich darauf befindet (das habe ich gemacht, ist aber grade noch etwas verbuggt).
Aber nochmal zu der Verbindungslinie. Du hast das ja in 4 verschiedene Blöcke aufgeteilt. Ich hatte es auch zuerst in 2 Blöcken (einen für x, einen für y), aber es geht auch in einem, indem du dx und dy einfach immer setzt, positiv / negativ, eines von beiden eben (+/-)1 setzt und als Start- und Endwert den "echten" Anfang / Ende nimmst. Vorteil: Eventuelle Bugs / Featureänderungen musst du nur einmal fixen / coden und können nicht nur für eine einzelne Richtung auftreten ![]() Ansonsten nicht schlecht!
__________________
"So, und jetzt Schluss mit dem Lamentieren - lasst uns etwas Kunst machen!!!" - GS_Raphael |
![]() |
![]() |
![]() |
#3 | ||
Neuling
![]() Registriert seit: 01.10.2009
Beiträge: 41
|
![]() Zitat:
Davon abgesehen benutzt man so etwas hauptsächlich bei Schleichaktionen oder im Kampf. In beidem sollte die Eventanzahl nicht übermäßig groß sein. Zitat:
Jedenfalls werde ich mich bei Gelegenheit noch mal drum kümmern die Blöcke zu "fusionieren". |
||
![]() |
![]() |
![]() |
Lesezeichen |
Stichworte |
script, sichtkegel, view-range |
Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1) | |
Themen-Optionen | |
|
|
![]() |
||||
Thema | Autor | Forum | Antworten | Letzter Beitrag |
Near´s "View Range"-Script v2 | Phantom | RGSS-Scripts | 1 | 24.01.2007 14:41 |