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 08.02.2010, 23:53   #1
_Matrix
Neuling
 
Benutzerbild von _Matrix
 
Registriert seit: 01.10.2009
Beiträge: 41
Beitrag verbessertes Collisions-check-Script

Maker-Version: XP
Skript-Version 1.3
*Update-infos siehe unten.*

Ok, da ich mal austesten wollte, wie viel besser es wäre, wenn es eine Tabelle gibt, die die Position aller Events enthält hab ich mich mal dran gesetzt.

Das Ergebnis sind 38 fps bei 360 bewegten Events statt den vorher nur 10 fps.

Das Script erneuret alle Funktionen, die Event-Positionen prüfen oder ändern.
(Hoffe, ich hab keine Übersehen)

Code:
#==============================================================================
# ** Collision 1.3
#------------------------------------------------------------------------------
#  Scripted by TheWhiteShadow
#==============================================================================
GHOST_FLAG = "ghost" # Kannste ändern, wenn ghost nicht gefällt oder so.^^

class Game_Map
  #--------------------------------------------------------------------------
  # * Setup
  #     map_id : map ID
  #--------------------------------------------------------------------------
  def setup(map_id)
    # Put map ID in @map_id memory
    @map_id = map_id
    # Load map from file and set @map
    @map = load_data(sprintf("Data/Map%03d.rxdata", @map_id))
    # erstelle eine Wegtabelle
    @paths = Table.new(width, height * 2)
    # - Ungerade Y-Werte enthalten horizontale Wege
    # - Gerade Y-Werte enthalten vertikale Wege
    # erstelle eine Positionstabelle
    @positions = Table.new(width, height)
    @overlay = {}
    # set tile set information in opening instance variables
    tileset = $data_tilesets[@map.tileset_id]
    @tileset_name = tileset.tileset_name
    @autotile_names = tileset.autotile_names
    @panorama_name = tileset.panorama_name
    @panorama_hue = tileset.panorama_hue
    @fog_name = tileset.fog_name
    @fog_hue = tileset.fog_hue
    @fog_opacity = tileset.fog_opacity
    @fog_blend_type = tileset.fog_blend_type
    @fog_zoom = tileset.fog_zoom
    @fog_sx = tileset.fog_sx
    @fog_sy = tileset.fog_sy
    @battleback_name = tileset.battleback_name
    @passages = tileset.passages
    @priorities = tileset.priorities
    @terrain_tags = tileset.terrain_tags
    # Initialize displayed coordinates
    @display_x = 0
    @display_y = 0
    # Clear refresh request flag
    @need_refresh = false
    # Set map event data
    @events = {}
    for i in @map.events.keys
      @events[i] = Game_Event.new(@map_id, @map.events[i])
    end
    # Set common event data
    @common_events = {}
    for i in 1...$data_common_events.size
      @common_events[i] = Game_CommonEvent.new(i)
    end
    # Initialize all fog information
    @fog_ox = 0
    @fog_oy = 0
    @fog_tone = Tone.new(0, 0, 0, 0)
    @fog_tone_target = Tone.new(0, 0, 0, 0)
    @fog_tone_duration = 0
    @fog_opacity_duration = 0
    @fog_opacity_target = 0
    # Initialize scroll information
    @scroll_direction = 2
    @scroll_rest = 0
    @scroll_speed = 4
    # fülle die Wegtabelle
    for y in 0..(height * 2 - 2)
      for x in 0..(width - 1)
        @paths[x, y] = set_path(x, y) # 0 = Unpassierbar / >0 = Passierbar
      end
    end
  end
  #--------------------------------------------------------------------------
  def set_path(x, y)
    d = y % 2 == 0 ? 6 : 2
    y /= 2
    new_x = x + (d == 6 ? 1 : 0)
    new_y = y + (d == 2 ? 1 : 0)
    bit = (1 << (d / 2 - 1)) & 0x0f
    # Loop searches in order from top of layer
    for i in [2, 1, 0]
      tile_id = data[x, y, i]
      if tile_id == nil
        return 0
      else
        return 0 if not valid?(new_x, new_y) or @passages[tile_id] & bit == bit
        return check_second(new_x, new_y, 10-d) if @priorities[tile_id] == 0
      end
    end
    return check_second(new_x, new_y, 10-d)
  end
  #--------------------------------------------------------------------------
  # Prüfe den Rückweg vom Folgetile 
  def check_second(x, y, d)
    new_x = x + (d == 4 ? -1 : 0)
    new_y = y + (d == 8 ? -1 : 0)
    bit = (1 << (d / 2 - 1)) & 0x0f
    # Loop searches in order from top of layer
    for i in [2, 1, 0]
      tile_id = data[x, y, i]
      if tile_id == nil
        return 0
      else
        return 0 if @passages[tile_id] & bit == bit
        return 1 if @priorities[tile_id] == 0
      end
    end
    return 1
  end
  #--------------------------------------------------------------------------
  # * gibt ein unpasierbares Event auf x/y zurück
  #--------------------------------------------------------------------------
  def collision_on(x, y, self_event)
    return nil unless valid?(x, y)
    case @positions[x, y] <=> 0
    when 1 # einfach belegt
      return $game_player if @positions[x, y] == 1
      ev = @events[@positions[x, y] - 1]
      return ev unless ev.through or ev == self_event
    when -1 # mehrfach belegt
      @overlay[y * width + x].each do |i|
        return $game_player if i == 1
        ev = @events[i-1]
        return ev unless ev.through or ev == self_event
      end
    end
    return nil
  end
  #--------------------------------------------------------------------------
  # * fügt der Positionsliste ein Event hinzu
  #--------------------------------------------------------------------------
  def add_position(x, y, id)
    x %= $game_map.width
    y %= $game_map.height
    id += 1 # damit auch der Spieler erkannt wird
    if @positions[x, y] == 0 # nicht belegt
      @positions[x, y] = id
    elsif @positions[x, y] > 0 # einfach belegt
      @overlay[y * width + x] = [@positions[x, y], id]
      @positions[x, y] = -1
    else # mehrfach belegt
      @overlay[y * width + x].push(id)
    end
  end
  #--------------------------------------------------------------------------
  # * entfernt ein Event aus der Positionsliste
  #--------------------------------------------------------------------------
  def remove_position(x, y, id)
    id += 1
    if @positions[x, y] == id # einfach belegt
      @positions[x, y] = 0
    elsif @positions[x, y] == -1 # mehrfach belegt
      @overlay[y * width + x].delete(id)
      if @overlay[y * width + x].size == 1
        @positions[x, y] = @overlay[y * width + x][0]
        @overlay.delete(y * width + x)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Get all Events on position x/y
  #--------------------------------------------------------------------------
  def events_on(x, y)
    events = []
    if valid?(x, y) or @positions[x, y] == -2
      case @positions[x, y] <=> 0
      when 1 # einfach belegt
        events.push(@events[@positions[x, y] - 1]) if @positions[x, y] != 1
      when -1 # mehrfach belegt
        @overlay[y * width + x].each do |i|
          next if i == 1
          events.push(@events[i - 1])
        end
      end
    end
    return events
  end
  #--------------------------------------------------------------------------
  # * Determine if Passable
  #     x          : x-coordinate
  #     y          : y-coordinate
  #     d          : direction (0,2,4,6,8,10)
  #                  *  0,10 = determine if all directions are impassable
  #     self_event : Self (If event is determined passable)
  # - Änderung: Eventdurchlauf auf relevantes Feld beschränkt
  #--------------------------------------------------------------------------
  def passable?(x, y, d, self_event = nil)
    # If coordinates given are outside of the map
    unless valid?(x, y)
      # impassable
      return false
    end
    # Change direction (0,2,4,6,8,10) to obstacle bit (0,1,2,4,8,0)
    bit = (1 << (d / 2 - 1)) & 0x0f
    event = collision_on(x, y, self_event)
    if event != nil
      # If tiles other than self are consistent with coordinates
      if event.tile_id >= 0 and event != self_event
        # If obstacle bit is set
        if @passages[event.tile_id] & bit != 0
          # impassable
          return false
        # If obstacle bit is set in all directions
        elsif @passages[event.tile_id] & 0x0f == 0x0f
          # impassable
          return false
        # If priorities other than that are 0
        elsif @priorities[event.tile_id] == 0
          # passable
          return true
        end
      end
    end
    # Loop searches in order from top of layer
    for i in [2, 1, 0]
      # Get tile ID
      tile_id = data[x, y, i]
      # Tile ID acquistion failure
      if tile_id == nil
        # impassable
        return false
      # If obstacle bit is set
      elsif @passages[tile_id] & bit != 0
        # impassable
        return false
      # If obstacle bit is set in all directions
      elsif @passages[tile_id] & 0x0f == 0x0f
        # impassable
        return false
      # If priorities other than that are 0
      elsif @priorities[tile_id] == 0
        # passable
        return true
      end
    end
    # passable
    return true
  end
  #--------------------------------------------------------------------------
  def tile_passable?(tile_id, d)
    # If tiles other than self are consistent with coordinates
    if tile_id > 0
      # Change direction (0,2,4,6,8,10) to obstacle bit (0,1,2,4,8,0)
      bit = (1 << (d / 2 - 1)) & 0x0f
      # If obstacle bit is set
      if @passages[tile_id] & bit != 0
        # impassable
        return false
      # If obstacle bit is set in all directions
      elsif @passages[tile_id] & 0x0f == 0x0f
        # impassable
        return false
      # If priorities other than that are 0
      elsif @priorities[tile_id] == 0
        # passable
        return true
      end
    end
    return true
  end
  #--------------------------------------------------------------------------
  def path_exist?(x, y, d)
    return false unless @paths[x, y]
    y *= 2
    if d == 2 or d == 8
      y -= 1
      y += 2 if d == 2
    else
      x -= 1 if d == 4
    end
    return @paths[x, y] > 0
  end
end

class Game_Character
  attr_reader :ghost # verhindert das Ein/Austragen in der Kollisionstabelle
  def ghost=(value)
    @ghost = value
    $game_map.remove_position(@x, @y, @id)
  end
  #--------------------------------------------------------------------------
  # * change x-position
  #--------------------------------------------------------------------------
  def new_x(x)
    $game_map.remove_position(@x, @y, @id) unless @ghost
    @x = x
    $game_map.add_position(@x, @y, @id) unless @ghost
  end
  #--------------------------------------------------------------------------
  # * change y-position
  #--------------------------------------------------------------------------
  def new_y(y)
    $game_map.remove_position(@x, @y, @id) unless @ghost
    @y = y
    $game_map.add_position(@x, @y, @id) unless @ghost
  end
  #--------------------------------------------------------------------------
  # * change x/y-position
  #--------------------------------------------------------------------------
  def new_pos(x, y)
    $game_map.remove_position(@x, @y, @id) unless @ghost
    @x = x
    @y = y
    $game_map.add_position(@x, @y, @id) unless @ghost
  end
  #--------------------------------------------------------------------------
  # * Move to Designated Position
  #     x : x-coordinate
  #     y : y-coordinate
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def moveto(x, y)
    new_pos(x % $game_map.width, y % $game_map.height)
    @real_x = @x * 128
    @real_y = @y * 128
    @prelock_direction = 0
  end
  #--------------------------------------------------------------------------
  # * Determine if Passable
  #     x : x-coordinate
  #     y : y-coordinate
  #     d : direction (0,2,4,6,8)
  #         * 0 = Determines if all directions are impassable (for jumping)
  # - Änderung: Diverses
  #--------------------------------------------------------------------------
  def passable?(x, y, d)
    # Get new coordinates
    new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
    new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
    # existiert das neue Feld nicht?
    unless $game_map.valid?(new_x, new_y)
      # impassable
      return false
    end
    # If through is ON
    if @through
      # passable
      return true
    end
    full_test = false
    # Event-Tile hier vorhanden?
    event = $game_map.collision_on(x, y, self)
    if event != nil
      full_test = true
    end
    # Event-Tile dort vorhanden?
    event = $game_map.collision_on(new_x, new_y, self)
    if event != nil
      if event.character_name != "" or self != $game_player
        # impassable
        return false
      elsif event.tile_id >= 0
        full_test = true
      end
    end
    #print("$game_map.path_exist?")
    # existiert der Weg zum Zielfeld nicht?
    if full_test
      return false unless $game_map.passable?(x, y, d, self)
      return false unless $game_map.passable?(new_x, new_y, 10 - d, self)
    else
      return false unless $game_map.path_exist?(x, y, d)
    end
    # passable
    return true
  end
  #--------------------------------------------------------------------------
  # * Move Down
  #     turn_enabled : a flag permits direction change on that spot
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_down(turn_enabled = true)
    # Turn down
    if turn_enabled
      turn_down
    end
    # If passable
    if passable?(@x, @y, 2)
      # Turn down
      turn_down
      # Update coordinates
      new_y(@y + 1)
      # Increase steps
      increase_steps
    # If impassable
    else
      # Determine if touch event is triggered
      check_event_trigger_touch(@x, @y+1)
    end
  end
  #--------------------------------------------------------------------------
  # * Move Left
  #     turn_enabled : a flag permits direction change on that spot
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_left(turn_enabled = true)
    # Turn left
    if turn_enabled
      turn_left
    end
    # If passable
    if passable?(@x, @y, 4)
      # Turn left
      turn_left
      # Update coordinates
      new_x(@x - 1)
      # Increase steps
      increase_steps
    # If impassable
    else
      # Determine if touch event is triggered
      check_event_trigger_touch(@x-1, @y)
    end
  end
  #--------------------------------------------------------------------------
  # * Move Right
  #     turn_enabled : a flag permits direction change on that spot
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_right(turn_enabled = true)
    # Turn right
    if turn_enabled
      turn_right
    end
    # If passable
    if passable?(@x, @y, 6)
      # Turn right
      turn_right
      # Update coordinates
      new_x(@x + 1)
      # Increase steps
      increase_steps
    # If impassable
    else
      # Determine if touch event is triggered
      check_event_trigger_touch(@x+1, @y)
    end
  end
  #--------------------------------------------------------------------------
  # * Move up
  #     turn_enabled : a flag permits direction change on that spot
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_up(turn_enabled = true)
    # Turn up
    if turn_enabled
      turn_up
    end
    # If passable
    if passable?(@x, @y, 8)
      # Turn up
      turn_up
      # Update coordinates
      new_y(@y - 1)
      # Increase steps
      increase_steps
    # If impassable
    else
      # Determine if touch event is triggered
      check_event_trigger_touch(@x, @y-1)
    end
  end
  #--------------------------------------------------------------------------
  # * Move Lower Left
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_lower_left
    # If no direction fix
    unless @direction_fix
      # Face down is facing right or up
      @direction = (@direction == 6 ? 4 : @direction == 8 ? 2 : @direction)
    end
    # When a down to left or a left to down course is passable
    if (passable?(@x, @y, 2) and passable?(@x, @y + 1, 4)) or
       (passable?(@x, @y, 4) and passable?(@x - 1, @y, 2))
      # Update coordinates
      new_pos(@x - 1, @y + 1)
      # Increase steps
      increase_steps
    end
  end
  #--------------------------------------------------------------------------
  # * Move Lower Right
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_lower_right
    # If no direction fix
    unless @direction_fix
      # Face right if facing left, and face down if facing up
      @direction = (@direction == 4 ? 6 : @direction == 8 ? 2 : @direction)
    end
    # When a down to right or a right to down course is passable
    if (passable?(@x, @y, 2) and passable?(@x, @y + 1, 6)) or
       (passable?(@x, @y, 6) and passable?(@x + 1, @y, 2))
      # Update coordinates
      new_pos(@x + 1, @y + 1)
      # Increase steps
      increase_steps
    end
  end
  #--------------------------------------------------------------------------
  # * Move Upper Left
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_upper_left
    # If no direction fix
    unless @direction_fix
      # Face left if facing right, and face up if facing down
      @direction = (@direction == 6 ? 4 : @direction == 2 ? 8 : @direction)
    end
    # When an up to left or a left to up course is passable
    if (passable?(@x, @y, 8) and passable?(@x, @y - 1, 4)) or
       (passable?(@x, @y, 4) and passable?(@x - 1, @y, 8))
      # Update coordinates
      new_pos(@x - 1, @y - 1)
      # Increase steps
      increase_steps
    end
  end
  #--------------------------------------------------------------------------
  # * Move Upper Right
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def move_upper_right
    # If no direction fix
    unless @direction_fix
      # Face right if facing left, and face up if facing down
      @direction = (@direction == 4 ? 6 : @direction == 2 ? 8 : @direction)
    end
    # When an up to right or a right to up course is passable
    if (passable?(@x, @y, 8) and passable?(@x, @y - 1, 6)) or
       (passable?(@x, @y, 6) and passable?(@x + 1, @y, 8))
      # Update coordinates
      new_pos(@x + 1, @y - 1)
      # Increase steps
      increase_steps
    end
  end
  #--------------------------------------------------------------------------
  # * Jump
  #     x_plus : x-coordinate plus value
  #     y_plus : y-coordinate plus value
  # - Änderung: Positionsänderung über Funktionsaufruf
  #--------------------------------------------------------------------------
  def jump(x_plus, y_plus)
    # If plus value is not (0,0)
    if x_plus != 0 or y_plus != 0
      # If horizontal distnace is longer
      if x_plus.abs > y_plus.abs
        # Change direction to left or right
        x_plus < 0 ? turn_left : turn_right
      # If vertical distance is longer, or equal
      else
        # Change direction to up or down
        y_plus < 0 ? turn_up : turn_down
      end
    end
    # Calculate new coordinates
    new_x = @x + x_plus
    new_y = @y + y_plus
    # If plus value is (0,0) or jump destination is passable
    if (x_plus == 0 and y_plus == 0) or passable?(new_x, new_y, 0)
      # Straighten position
      straighten
      # Update coordinates
      new_pos(new_x, new_y)
      # Calculate distance
      distance = Math.sqrt(x_plus * x_plus + y_plus * y_plus).round
      # Set jump count
      @jump_peak = 10 + distance - @move_speed
      @jump_count = @jump_peak * 2
      # Clear stop count
      @stop_count = 0
    end
  end
end

class Game_Event
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     map_id : map ID
  #     event  : event (RPG::Event)
  # - Änderung: Ghost-Flag hinzugefügt
  #--------------------------------------------------------------------------
  def initialize(map_id, event)
    super()
    @map_id = map_id
    @event = event
    @id = @event.id
    @erased = false
    @starting = false
    @through = true
    @ghost = @event.name[GHOST_FLAG]
    # Move to starting position
    moveto(@event.x, @event.y)
    refresh
  end
end

class Game_Player
  #--------------------------------------------------------------------------
  # * Same Position Starting Determinant
  # - Änderung: Eventprüfung auf relevantes Feld beschränkt
  #--------------------------------------------------------------------------
  def check_event_trigger_here(triggers)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # All event loops
    for event in $game_map.events_on(@x, @y)
      # If event coordinates and triggers are consistent
      if triggers.include?(event.trigger)
        # If starting determinant is same position event (other than jumping)
        if not event.jumping? and event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # * Front Envent Starting Determinant
  # - Änderung: Eventprüfung auf relevantes Feld beschränkt
  #--------------------------------------------------------------------------
  def check_event_trigger_there(triggers)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # Calculate front event coordinates
    new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
    new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
    # All event loops
    for event in $game_map.events_on(new_x, new_y)
      # If event coordinates and triggers are consistent
      if triggers.include?(event.trigger)
        # If starting determinant is front event (other than jumping)
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    # If fitting event is not found
    if result == false
      # If front tile is a counter
      if $game_map.counter?(new_x, new_y)
        # Calculate 1 tile inside coordinates
        new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
        new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
        # All event loops
        for event in $game_map.events_on(new_x, new_y)
          # If event coordinates and triggers are consistent
          if triggers.include?(event.trigger)
            # If starting determinant is front event (other than jumping)
            if not event.jumping? and not event.over_trigger?
              event.start
              result = true
            end
          end
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # * Touch Event Starting Determinant
  # - Änderung: Eventprüfung auf relevantes Feld beschränkt
  #--------------------------------------------------------------------------
  def check_event_trigger_touch(x, y)
    result = false
    # If event is running
    if $game_system.map_interpreter.running?
      return result
    end
    # All event loops
    for event in $game_map.events_on(@x, @y)
      # If event coordinates and triggers are consistent
      if [1,2].include?(event.trigger)
        # If starting determinant is front event (other than jumping)
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
end
Dieses mal reicht ein copy-past über der Main-Funktion zum aktivieren

Meine Überlegung war zunächst ein Tableobjekt in Kartengröße zu erstellen und sich alle Events eintragen zu lassen.
Das 1. Problem kam kurz darauf:
- Felder können mehr, als ein Event enthalten. Was nun?
Ich hab jetzt ein Hash genommen, der alle "Überlappungen" als Array enthält.
Zuerst dache ich, dass dadurch die Performance sinkt, was allerdings gar nicht stimmte.


update zu Version: 1.1
Objekt-typ "Ghost".
Ghost sind alle Events, die "ghost" im Namen haben. (Auch der Spieler, hat dort aber keinen Einfluss)
Eine Interaktion mit Ghost-Events ist nicht möglich. Umgekert schon.
So kann z.B. eine Maus Wände und Events erkennen ohne, dass sie für solche ein Hindernis darstellt.

update zu Version: 1.2
Dank derula konnte die Performance extrem gesteigert werden.
Es lag nicht am Hash, sondern an dem ständigen neu erstellen und löschen von Arrays für jede Collisions-Prüfung.
Jetzt wird nur noch ein Event für die Prüfung zurückgegeben (nur die Trigger-Prüfungen vom Spieler erfordern alle Events an der zu testenden Position).
Das Projekt läuft bei mir nun wieder mit 37-38 FPS. Was will man mehr

update zu Version: 1.3
Es wird nun vorher eine Wegliste erstellt, damit nicht jedesmal alle 3 Tileebenen geprüft werden müssen.
Das Ändern des ghost-sysmbols lässt sich nun über eine Konstante regeln.

Vergesst den Crediteintrag nicht.
__________________
Mein Projekt: Legend of Midor
Status: 2.Demo in Arbeit.

Geändert von _Matrix (10.10.2010 um 15:50 Uhr). Grund: Versions-Update
_Matrix ist offline   Mit Zitat antworten
Alt 09.02.2010, 16:30   #2
derula Männlich
23
 
Benutzerbild von derula
 
Registriert seit: 03.02.2003
Alter: 29
Beiträge: 3.068
Blog-Einträge: 67
Standard

Erstmal: auf den ersten Blick wieder ein sehr gutes Skript.

Zitat:
Zitat von _Matrix Beitrag anzeigen
- Felder können mehr, als ein Event enthalten. Was nun?
Ich habe das mit folgendem Gedanken "gelöst": Wenn ein Feld 2 Events enthält, ist eines davon auf "through" gestellt ich trage es in eine Extra-Tabelle für through-Events ein (so: wenn für ein Event through umgeschaltet wird, wechselt es die Tabelle). Das stimmt natürlich nicht immer: So können 2 Through-Events an derselben Stelle mit selber Passierbarkeit stehen. Die "Lösung" dafür ist bei mir einfach, solche Situationen auf der Entwicklerseite zu verbieten (sprich: keine bewegenden Through-Events, keine 2 nicht-through-Events die sich überschneiden).

Ist natürlich eine Einschränkung, aber zugunsten der Geschwindigkeit. Gut zu sehen, dass du auch eine "richtige" Lösung dafür gefunden hast

(Obiges ist natürlich nicht ganz exakt, da event.character_name == "" ebenfalls wie through behandelt werden muss, aber ich wollts mal verkürzt schreiben.)

(Mein Problem bei S.E.-Pantheon ist allerdings, dass ich mit Viertelfeldern arbeite, d.h. Events stehen auf 9 Feldern gleichzeitig. Tabellenupdates bereiten mir daher noch Probleme, und der Player rennt manchmal in unsichtbare Wände, falls da vorher ein Event langlief ^^)

Kleine Anmerkungen beim Überfliegen:

Code:
  def events_on(x, y)
    if @positions[x, y] > 0 # einfach belegt
      return [] if @events[@positions[x, y]] == nil
      return [@events[@positions[x, y]]]
    elsif @positions[x, y] < 0 # mehrfach belegt
      event = []
      for ev in @overlay[y * width + x]
        event.push(@events[ev]) unless @events[ev] == nil
      end
      return event
    else # nicht belegt
      return []
    end
  end
Könnte man ersetzen durch

Code:
  def events_on(x, y)
    case @positions[x, y] <=> 0
    when 1 then # einfach belegt
      @events[@positions[x, y]] ? [@events[@positions[x, y]]] : []
    when -1 then # mehrfach belegt
      @overlay[y * width + x].collect!{ |ev| @events[ev] }.compact
    else # nicht belegt
      []
    end
  end
(vielleicht der eine oder andere Syntaxfehler drin)

Hat natürlich nicht soo große Vorteile, außer, dass es kürzer ist. Vielleicht minimal schneller. Oder langsamer xD

Ansonsten würde mich interessieren: hast du mal ausprobiert, ob es schneller / langsamer ist (wahrscheinlich zweiteres), wenn du in @overlay Arrays mit x- und y-Werten als Schlüssel nimmst?
__________________
"So, und jetzt Schluss mit dem Lamentieren - lasst uns etwas Kunst machen!!!" - GS_Raphael
derula ist offline   Mit Zitat antworten
Alt 09.02.2010, 17:38   #3
_Matrix
Neuling
 
Benutzerbild von _Matrix
 
Registriert seit: 01.10.2009
Beiträge: 41
Standard

zunächst danke für das Lob,

Zitat:
Ich habe das mit folgendem Gedanken "gelöst": Wenn ein Feld 2 Events enthält, ist eines davon auf "through" gestellt ich trage es in eine Extra-Tabelle für through-Events ein (so: wenn für ein Event through umgeschaltet wird, wechselt es die Tabelle). Das stimmt natürlich nicht immer: So können 2 Through-Events an derselben Stelle mit selber Passierbarkeit stehen. Die "Lösung" dafür ist bei mir einfach, solche Situationen auf der Entwicklerseite zu verbieten (sprich: keine bewegenden Through-Events, keine 2 nicht-through-Events die sich überschneiden).
Schön und gut, aber ich finde nicht, dass das eine gute Lösung ist, den User einzuschränken. Gerade Through-Events wie z.B. Vögel, sind dafür da, sich zu bewegen.
Ich habe mir vorher ähnliches überlegt. Gerade dafür sollte der Hash ja da sein, um überschneidungen zu ermöglichen.
Und wie schon erwänt:
Zitat:
So lange kein Feld mehrfach benutz wird, wird auch der Hash nicht benutzt
Somit bleibt für die "meißten" Fälle der Hash einfach leer.

Mit meiner neuen Änderung über Ghost-Events können diese Fälle weiter minimiert werden. Allerdings bringt es der Performance nicht viel, eröffnet aber dafür eine weitere Möglichkeit, die der Maker von sich aus nicht hat.
Wie viel das jetzt bringt sei mal dahingestellt.

Zitat:
Ansonsten würde mich interessieren: hast du mal ausprobiert, ob es schneller / langsamer ist (wahrscheinlich zweiteres), wenn du in @overlay Arrays mit x- und y-Werten als Schlüssel nimmst?
Nein, hab ich nicht.
Eine Integerzahl ist kleiner als 2. Die Größe des Hash ändert sich dadurch aber nicht. Deshalb schätze ich auch, dass es nur langsamer werden würde.
__________________
Mein Projekt: Legend of Midor
Status: 2.Demo in Arbeit.

Geändert von _Matrix (09.02.2010 um 17:42 Uhr).
_Matrix ist offline   Mit Zitat antworten
Alt 10.02.2010, 11:08   #4
derula Männlich
23
 
Benutzerbild von derula
 
Registriert seit: 03.02.2003
Alter: 29
Beiträge: 3.068
Blog-Einträge: 67
Standard

Zitat:
Zitat von _Matrix Beitrag anzeigen
Schön und gut, aber ich finde nicht, dass das eine gute Lösung ist, den User einzuschränken. Gerade Through-Events wie z.B. Vögel, sind dafür da, sich zu bewegen.
Das ist natürlich richtig, und im allgemeinen ist deine Lösung auch besser, klar.

Zitat:
Zitat von _Matrix Beitrag anzeigen
Somit bleibt für die "meißten" Fälle der Hash einfach leer.
Vielleicht würde es etwas bringen, wenn in diesem Fall auch kein Array sondern nur ein Event zurück gegeben wird. Das bräuchte zwar eine zusätzliche Abfrage, aber es würden weniger Array-Objekte erstellt, die nachher vom Garbage Collector gelöscht werden müssen.

Zitat:
Zitat von _Matrix Beitrag anzeigen
Nein, hab ich nicht.
Eine Integerzahl ist kleiner als 2. Die Größe des Hash ändert sich dadurch aber nicht. Deshalb schätze ich auch, dass es nur langsamer werden würde.
Hä? Das kapier ich nun nicht. Aber ich glaube auch, dass es langsamer werden würde, einfach aus dem Grund, dass viel mehr Array-Objekte erstellt werden müssen.
__________________
"So, und jetzt Schluss mit dem Lamentieren - lasst uns etwas Kunst machen!!!" - GS_Raphael
derula ist offline   Mit Zitat antworten
Alt 10.02.2010, 18:19   #5
_Matrix
Neuling
 
Benutzerbild von _Matrix
 
Registriert seit: 01.10.2009
Beiträge: 41
Standard

Zitat:
Vielleicht würde es etwas bringen, wenn in diesem Fall auch kein Array sondern nur ein Event zurück gegeben wird. Das bräuchte zwar eine zusätzliche Abfrage, aber es würden weniger Array-Objekte erstellt, die nachher vom Garbage Collector gelöscht werden müssen.
Vielen dank für den Hinweis.
Es lag gar nicht am Hash sondern an den "unnötigen Arrays".
Ohne dich hätte ich das vermutlich gar nicht bemerkt.
Mein Test-Projekt läuft wieder mit 38 fps. Was will man mehr. *freu*

Arrays sind in Ruby echt langsam.
__________________
Mein Projekt: Legend of Midor
Status: 2.Demo in Arbeit.
_Matrix ist offline   Mit Zitat antworten
Alt 11.02.2010, 15:18   #6
derula Männlich
23
 
Benutzerbild von derula
 
Registriert seit: 03.02.2003
Alter: 29
Beiträge: 3.068
Blog-Einträge: 67
Standard

Zitat:
Zitat von _Matrix Beitrag anzeigen
Arrays sind in Ruby echt langsam.
Arrays sind langsam, in der Tat, aber das Hauptproblem ist wohl (behaupte ich), dass viele Objekte erstellt werden, die von der Garbage Collection gelöscht werden müssen.

Hmm, wenn das so viel ausmacht, sollte ich hie und da vielleicht auch weniger Arrays benutzen ^^

Schöne Sache jedenfalls, damit wäre "RMXP ist langsam" erstmal ein bisschen wegdiskutiert (das Vorurteil wird natürlich weiter bleiben, da dein Skript leider nicht Standard ist und es noch viele andere schlechte, langsame Skripte gibt :P)
__________________
"So, und jetzt Schluss mit dem Lamentieren - lasst uns etwas Kunst machen!!!" - GS_Raphael
derula ist offline   Mit Zitat antworten
Antwort

Lesezeichen


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
Internet Check UP shadowninja Small-Talk 11 30.01.2006 18:31


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