RPG-Maker Quartier

Hier dreht sich alles um die RPG-Maker-Reihe von ASCII/Enterbrain. Der RPG-Maker ist ein Tool, mit dem du dir dein eigenes kleines Rollenspiel erstellen kannst. Du findest hier alles, was du dazu brauchst. Aber natürlich umfasst die Community noch mehr!
Aktuelle Zeit: Di Mär 03, 2020 0:43

Alle Zeiten sind UTC + 1 Stunde



Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste



Ein neues Thema erstellen Auf das Thema antworten  [ 1 Beitrag ] 
Autor Nachricht

 Betreff des Beitrags: Verbessertes Collisions-Script
BeitragVerfasst: So Okt 10, 2010 14:50 
Maker-Version: XP
Skript-Version: 1.3

Heute veröffentliche ich die neuste Version meines verbessterten Kollisions-Erkennungsskripts.
Es ist minimal schneller, als der Vorgänger. (38 statt 8 Frames)

Das Script erneuret alle Funktionen, die Event-Positionen prüfen oder ändern.

Events, die "ghost" im Namen tragen werden als Ghost-Objekt gehandelt.

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.
Event-Tiles oder Vögel, welche keinerlei Interaktionen benötigen erleichtern somit anderen Events die Kollisionsabfragen.

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


Benutzung:
Code ins Script oberhalb der Main-Funktion einfügen.

Vergesst den Crediteintrag nicht.

mfg TWS


Nach oben
  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 1 Beitrag ] 

Alle Zeiten sind UTC + 1 Stunde


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de