Kamikaze Board



Zurück   Kamikaze Board > RPG Maker > RPG Maker Ressourcen & Material > RGSS-Scripts

RGSS-Scripts Postet hier die Scripts die ihr im Script-Editor selbst erstellt oder gefunden habt. Gefundene Scripts jedoch mit Quellenangabe posten!

Antwort
 
Themen-Optionen
Alt 07.02.2010, 20:20   #1
_Matrix
Neuling
 
Benutzerbild von _Matrix
 
Registriert seit: 01.10.2009
Beiträge: 41
Beitrag View-Range-Script (Prüft Sichtbarkeit mit Hindernissen)

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
Modifikation für mein Verbessertes-Collisions-Skript:


Verwendungsbeispiel in einem Event:
Code:
@>Conditional Branch: Script: player_in_sicht?(@event_id, 75, 8)
   "Aktion, wenn Spieler entdeckt wurde"
 : Branch End
* "@event_id" zeigt auf die ID des eigenen Event.

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!
__________________
Mein Projekt: Legend of Midor
Status: 2.Demo in Arbeit.

Geändert von _Matrix (10.02.2010 um 18:58 Uhr). Grund: Kompatiblität zum Collisions-Script V 1.2
_Matrix ist offline   Mit Zitat antworten
Alt 08.02.2010, 17:28   #2
derula Männlich
23
 
Benutzerbild von derula
 
Registriert seit: 03.02.2003
Alter: 29
Beiträge: 3.068
Blog-Einträge: 67
Standard

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
derula ist offline   Mit Zitat antworten
Alt 08.02.2010, 21:15   #3
_Matrix
Neuling
 
Benutzerbild von _Matrix
 
Registriert seit: 01.10.2009
Beiträge: 41
Standard

Zitat:
Was natürlich wahnsinnig ist, ist, dass er in jedem Schritt der Verbindungslinie... alle Events einzeln durchgeht
Klar ist das ein Problem, aber für eine halbe Stunde arbeit finde ich das Ergebnis nicht schlecht. Es reicht für meine Anforderungen.
Davon abgesehen benutzt man so etwas hauptsächlich bei Schleichaktionen oder im Kampf. In beidem sollte die Eventanzahl nicht übermäßig groß sein.

Zitat:
Du hast das ja in 4 verschiedene Blöcke aufgeteilt.
Das lag hauptsächlich daran, dass ich schnell den Überblick verliere, wenn sich zu viele Variablen ständig ändern. Also hab ich es erst einmal für eine Richtung erstellt, dann die Nächste...

Jedenfalls werde ich mich bei Gelegenheit noch mal drum kümmern die Blöcke zu "fusionieren".
__________________
Mein Projekt: Legend of Midor
Status: 2.Demo in Arbeit.
_Matrix ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Stichworte
script, sichtkegel, view-range


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.

Gehe zu

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Near´s "View Range"-Script v2 Phantom RGSS-Scripts 1 24.01.2007 14:41


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:46 Uhr.


Powered by vBulletin® Version 3.8.7 (Deutsch)
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.
RPGA.info