![]() |
|
|||||||
| RGSS-Scripts Postet hier die Scripts die ihr im Script-Editor selbst erstellt oder gefunden habt. Gefundene Scripts jedoch mit Quellenangabe posten! |
![]() |
|
|
Themen-Optionen |
07.02.2010, 20:20
|
#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 |
|
|
08.02.2010, 17:28
|
#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 |
|
|
08.02.2010, 21:15
|
#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 | |
|
|
Ähnliche Themen
|
||||
| Thema | Autor | Forum | Antworten | Letzter Beitrag |
| Near´s "View Range"-Script v2 | Phantom | RGSS-Scripts | 1 | 24.01.2007 14:41 |