Pokémon Script Project Index du Forum

S’enregistrer | Rechercher | Connexion
 Information des admins 
Si vous désirez parler de PSP ou obtenir du soutient là dessus, merci d'aller faire un tour sur https://pokemonworkshop.com/forum/index.php Imbécile heureux

[Mapping]Ponts

 
Poster un nouveau sujet   Répondre au sujet    Pokémon Script Project Index du Forum -> Game Making -> Ressources techniques -> Scripts
Sujet précédent :: Sujet suivant   
Auteur Message
Ku'rei
Membre


Inscrit le: 10 Aoû 2010
Messages: 546
Adepte du NoMoreExcuses
Localisation: Chambéry
Masculin

MessagePosté le: Mar 16 Juil - 11:07 (2013)    Sujet du message: [Mapping]Ponts

Historique des mise à jours :
  • 16/07/13
    • Création du sujet
    • Modification du script pour ajouter la suppression de l'effet des carreaux obscurcissant

  • 22/07/13
    • Mise en ligne de la V2, inclue une refonte totale du script, plus propre, plus claire. L'utilisation et l'installation restent les même.





Bonjour à toutes et à tous,
Je pense que beaucoup regrette l'absence de la gestion des ponts dans rmxp. Il existe peut-être déjà des scripts les gérant, cependant, je vous propose un script facilitant grandement la création de ponts.
Les spécificités de la V2 sont ajouter en bleu.

Petite vidéo de présentation


Fonctionnalités


Fonctionnalités prise en comptes :
  • Placement automatique de pont via la commande de script :
    Code:
    placer_pont(x, y, w, h, alt_h, alt_v, map_id)

    Où :
    • x, y : Coordonnées du coin Haut-Gauche du pont,
    • w, h : Largeur et Hauteur du pont,
    • alt_h, alt_v : Altitudes d'entrées horizontale et verticale, pas véritablement utilisé par la première version du script, pourra être utilisé pour la superposition de pont, c'est pourquoi il est conseillé de respecté les altitudes,
    • map_id : numéro de la map où se trouve le pont

  • Canalisation des passages
  • Placement arbitraire des évent (au-dessus ou en dessous du pont)
    Pour ce faire : il suffit de placer une commande d'événement commentaire contenant : "OVER_BRIDGE". L'événement commencera automatiquement sur le pont. Sinon, il sera en dessous.
  • Ponts au-dessus de l'eau. Ces ponts là ne poseront aucun problèmes, ils fonctionnent comme des ponts normaux (je rappelle tout de même que PSP contient 3 types de terrains : passant, non passant et eau).
  • Les événements sont bien sur deux niveaux différents, il n'y a pas d'interaction possible entre eux si l'un d'eux est sur le pont et l'autre en dessous.
  • Suppression de l'effet des carreaux obscurcissant quand le personnage est sur un pont
  • V2 : superposition des ponts (il manque encore la superposition graphique)
  • V2 : présélection de l'altitude de départ d'un évènement


Fonctionnalités n'étant pas gérées
  • V1 : Superposition de ponts : ne vous amusez pas à empiler deux ponts, ça peut rendre je vous l'accorde mais cela causera bug sur bug...
  • Le saut à l'élastique ou tout autre type de saut depuis un pont.


Le Script


Copier/Coller le script suivant dans un nouveau script que vous appellerez "Bridge".
Code:
module Kurei
  # Key Word : Stipule si l'event commence au dessus du pont, à mettre en première place la premiere page.
  OVER_BRIDGE_WORD = "OVER_BRIDGE"
 
  #=============================================================================
  # Classe contenant les données sur les ponts du jeu
  class Bridges_Data
    def initialize
      @data = {}        # map_id => [Bridge]                      PONTS
      @data_blocks = {} #map_id =>  [[x, y, z], [x, y, z], ...]   TILE BLOQUANT PAR ALTITUDE
      @data_free = {}   # map_id => [[x, y, z], [x, y, z], ...]   TILES LIBRES PAR ALTITUDE
    end
   
    def get_bridges(map_id)
      if @data[map_id] == nil
        return []
      end
      return @data[map_id]
    end
    def [](map_id)
      return get_bridges(map_id)
    end
   
    def add_bridge(map_id, value)
      if @data[map_id]== nil
        @data[map_id] = []
      end
      @data[map_id].push(value)
    end
   
    def add_block(map_id, block = [0,0,0])
      if @data_blocks[map_id] == nil
        @data_blocks[map_id] = []
      end
      @data_blocks[map_id].push(block)
    end
   
    def add_free(map_id, block = [0,0,0])
      if @data_free[map_id] == nil
        @data_free[map_id] = []
      end
      @data_free[map_id].push(block)
    end
   
    def passable?(map_id, x, y, z)
      if @data_blocks[map_id] == nil
        return true
      end
      for block in @data_blocks[map_id]
        if block[0] == x and block[1] == y and block[2] == z
          return false
        end
      end
      return true
    end
   
    def there_free?(map_id, x, y, z)
      if @data_free[map_id] == nil
        return false
      end
      for free in @data_free[map_id]
        if free[0] == x and free[1] == y and free[2] == z
          return true
        end
      end
      return false
    end
  end
 
  #=============================================================================
  # Classe contenant le données sur Un pont
  class Bridge
    attr_accessor :x
    attr_accessor :y
    attr_accessor :width
    attr_accessor :height   #Definiton de la surface du pont
    attr_accessor :alt_h
    attr_accessor :alt_v    #Altitudes aux entrées du pont (quand on rentre horizontalement : alt_h, sinon alt_v
    attr_reader :vertical   #true si le pont est vertical, false si il est horizontal
   
    def initialize(x = 0, y = 0, w = 1, h = 1, alt_h = 1, alt_v = 0)
      @x = x
      @y = y
      @width = w
      @height = h
      @alt_h = alt_h
      @alt_v = alt_v
      @vertical = @height > @width
    end
   
    def max_alt
      return [@alt_h, @alt_v].max
    end
    def min_alt
      return [@alt_h, @alt_v].min
    end
    def vertical?
      return @alt_v > @alt_h
    end
   
    # Calcul l'altitude en fonction de l'emplacement,
    #   retourne une valeur seulement si on est sur les bords du pont
    #   les coins seront considéré selon l'allongement du pont
    # RETURN : altitude d'entrée si sur les bords du pont, -1 si à l'interieur
    #           dans tout les autres cas : -2
    def calculate_altitude(tx, ty)
      if in?(tx, ty)
        if vertical?
          #print("vert")
          if (ty == @y-1 or ty == @y+height)
            return alt_v
          elsif (tx == @x-1 or tx == @x+width)
            return alt_h
          else
            return -1
          end
        else
          #print("hori")
          if (tx == @x-1 or tx == @x+width)
            return alt_h
          elsif (ty == @y-1 or ty == @y+height)
            return alt_v
          else
            return -1
          end
        end
      end
      return -2
    end
   
    def on?(tx, ty)
      return (@x <= tx and tx < @x+width and @y <= ty and ty < @y+height)
    end
   
    def in?(tx, ty)
      return (@x-1 <= tx and tx <= @x+width and @y-1 <= ty and ty <= @y+height)
    end
  end
end



class Game_Map
  attr_accessor :bridges
  def initialize
    @map_id = 0
    @display_x = 0
    @display_y = 0
    @bridges = Kurei::Bridges_Data.new
  end
 
  def tiles_passable?(x, y)
    for i in [2, 1, 0]
      # タイル ID を取得
      tile_id = data[x, y, i]
      # タイル ID 取得失敗
      if tile_id == nil
        # 通行不可
        return false
      # 全方向の障害物ビットがセットされている場合
      elsif @passages[tile_id] & 0x0f == 0x0f
        # 通行不可
        return false
      # それ以外で プライオリティが 0 の場合
      elsif @priorities[tile_id] == 0
        # 通行可
        return true
      end
    end
    # 通行可
    return true
  end
 
  #Overidding original methods to add a nil return if there's no event 
  def check_event(x, y, z = nil) 
    for event in $game_map.events.values 
      if event.x == x and event.y == y
        return event.id 
      end 
    end 
    return nil 
  end
 
  def tileset_id
    return @map.tileset_id
  end
 
  def passable?(x, y, d, self_event = nil, z = nil)
    # 与えられた座標がマップ外の場合
    unless valid?(x, y)
      # 通行不可
      return false
    end
    # 方向 (0,2,4,6,8,10) から 障害物ビット (0,1,2,4,8,0) に変換
    bit = (1 << (d / 2 - 1)) & 0x0f
    # すべてのイベントでループ
    for event in events.values
      # 自分以外のタイルと座標が一致した場合
      if event.tile_id >= 0 and event != self_event and
         event.x == x and event.y == y and not event.through
        if self_event != nil
          if !event.check_altitude(event, self_event)
            next
          end
        end
        # 障害物ビットがセットされている場合
        if @passages[event.tile_id] & bit != 0
          # 通行不可
          return false
        # 全方向の障害物ビットがセットされている場合
        elsif @passages[event.tile_id] & 0x0f == 0x0f
          # 通行不可
          return false
        # それ以外で プライオリティが 0 の場合
        elsif @priorities[event.tile_id] == 0
          # 通行可
          return true
        end
      end
    end
   
    # Surf
    if self_event != nil
      #print($game_map.terrain_tag(x, y), ", ", self_event.terrain_tag)
      if $game_map.terrain_tag(x, y) == 7 and self_event.terrain_tag != 7
        return false
      end
      if $game_map.terrain_tag(x, y) != 7 and self_event.terrain_tag == 7
        if self_event.type == Game_Player
          # Retour au skin normal
          $game_temp.common_event_id = POKEMON_S::Skill_Info.map_use(POKEMON_S::Skill_Info.id("SURF"))
        end
        return false
      end
    end
   
    # レイヤーの上から順に調べるループ
    for i in [2, 1, 0]
      # タイル ID を取得
      tile_id = data[x, y, i]
      # タイル ID 取得失敗
      if tile_id == nil
        # 通行不可
        return false
      # 障害物ビットがセットされている場合
      elsif @passages[tile_id] & bit != 0
        # 通行不可
        return false
      # 全方向の障害物ビットがセットされている場合
      elsif @passages[tile_id] & 0x0f == 0x0f
        # 通行不可
        return false
      # それ以外で プライオリティが 0 の場合
      elsif @priorities[tile_id] == 0
        # 通行可
        return true
      end
    end
    # 通行可
    return true
  end
end




class Game_Character
  attr_accessor :altitude   #Altitude de pont
  attr_accessor :bridge     #pont courant
  attr_accessor :z_alt      #Altitude à ajouter
  attr_reader :bridge
 
  def passable?(x, y, d)
    # 新しい座標を求める
    new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
    new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
    # 座標がマップ外の場合
    unless $game_map.valid?(new_x, new_y)
      # 通行不可
      return false
    end
   
    # すり抜け ON の場合
    if @through
      # 通行可
      return true
    end
   
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標が移動先と一致した場合
      if event.x == new_x and event.y == new_y and check_altitude(event, self)
        # すり抜け OFF なら
        unless event.through
          # 自分がイベントの場合
          if self != $game_player
            # 通行不可
            return false
          end
          # 自分がプレイヤーで、相手のグラフィックがキャラクターの場合
          if event.character_name != ""
            # 通行不可
            return false
          end
        end
      end
    end
    # プレイヤーの座標が移動先と一致した場合
    if $game_player.x == new_x and $game_player.y == new_y and check_altitude($game_player, self)
      # すり抜け OFF なら
      unless $game_player.through
        # 自分のグラフィックがキャラクターの場合
        if @character_name != ""
          # 通行不可
          return false
        end
      end
    end
   
    @last_altitude = @altitude
    @bridge = nil
    for bridge in $game_map.bridges[$game_map.map_id]
      new_alt = bridge.calculate_altitude(new_x, new_y)
      old_alt = bridge.calculate_altitude(@x, @y)
     
      #En dehors du pont
      if new_alt == -2 and old_alt == -2
        next
      end
     
      @bridge = bridge
      if old_alt >= 0 and new_alt == -1
        #print "Set altitude : ", old_alt
        @altitude = old_alt
      end
     
      if old_alt == -1
        if new_alt == @altitude
          #print "Reset altitude"
          @altitude = -2
        elsif new_alt != @altitude and new_alt != -1
          #print("Collision")
          return false
        end
      end
    end
   
    if @bridge == nil
      @z_alt = 0
    else
      if (@bridge.on?(new_x, new_y) or @bridge.on?(@x, @y)) and (@altitude == @bridge.max_alt or @last_altitude == @bridge.max_alt)
        @z_alt = 32*3
      else
        @z_alt = 0
      end
    end
   
    if $game_map.bridges.there_free?($game_map.map_id, new_x, new_y, @altitude)
      return true
    end
    if $game_map.bridges.there_free?($game_map.map_id,@x, @y, @last_altitude)
      return true
    end
   
    # 移動元のタイルから指定方向に出られない場合
    unless $game_map.passable?(x, y, d, self, @last_alt)
      # 通行不可
      return false
    end
    # 移動先のタイルに指定方向から入れない場合
    unless $game_map.passable?(new_x, new_y, 10 - d, self, @altitude)
      # 通行不可
      return false
    end
     
    # 通行可
    return true
   
  end
 
  def screen_z(height = 0)
    # 最前面に表示フラグが ON の場合
    if @always_on_top
      # 無条件に 999
      return 999
    end
    # 実座標とマップの表示位置から画面座標を求める
    z = (@real_y - $game_map.display_y + 3) / 4 + 32  + (@z_alt == nil ? 0 : @z_alt)    # タイルの場合
    if @tile_id > 0
      # タイルのプライオリティ * 32 を足す
      return z + $game_map.priorities[@tile_id] * 32
    # キャラクターの場合
    else
      # 高さが 32 を超えていれば 31 を足す
      return z + ((height > 32) ? 31 : 0)
    end
  end
 
  def check_event_trigger_touch(x, y)
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return
    end
    # トリガーが [イベントから接触] かつプレイヤーの座標と一致した場合
    if @trigger == 2 and x == $game_player.x and y == $game_player.y and check_altitude($game_player, self)
      # ジャンプ中以外で、起動判定が正面のイベントなら
      if not jumping? and not over_trigger?
        start
      end
    end
  end
 
  def move_down(turn_enabled = true)
    # 下を向く
    if turn_enabled
      turn_down
    end
    # 通行可能な場合
    if passable?(@x, @y, 2)
      # 下を向く
      turn_down
      # 座標を更新
      @y += 1
      # 歩数増加
      increase_steps
    # 通行不可能な場合
    else
      # 接触イベントの起動判定
      check_event_trigger_touch(@x, @y+1)
    end
  end
  #--------------------------------------------------------------------------
  # ● 左に移動
  #     turn_enabled : その場での向き変更を許可するフラグ
  #--------------------------------------------------------------------------
  def move_left(turn_enabled = true)
    # 左を向く
    if turn_enabled
      turn_left
    end
    # 通行可能な場合
    if passable?(@x, @y, 4)
      # 左を向く
      turn_left
      # 座標を更新
      @x -= 1
      # 歩数増加
      increase_steps
    # 通行不可能な場合
    else
      # 接触イベントの起動判定
      check_event_trigger_touch(@x-1, @y)
    end
  end
  #--------------------------------------------------------------------------
  # ● 右に移動
  #     turn_enabled : その場での向き変更を許可するフラグ
  #--------------------------------------------------------------------------
  def move_right(turn_enabled = true)
    # 右を向く
    if turn_enabled
      turn_right
    end
    # 通行可能な場合
    if passable?(@x, @y, 6)
      # 右を向く
      turn_right
      # 座標を更新
      @x += 1
      # 歩数増加
      increase_steps
    # 通行不可能な場合
    else
      # 接触イベントの起動判定
      check_event_trigger_touch(@x+1, @y)
    end
  end
  #--------------------------------------------------------------------------
  # ● 上に移動
  #     turn_enabled : その場での向き変更を許可するフラグ
  #--------------------------------------------------------------------------
  def move_up(turn_enabled = true)
    # 上を向く
    if turn_enabled
      turn_up
    end
    # 通行可能な場合
    if passable?(@x, @y, 8)
      # 上を向く
      turn_up
      # 座標を更新
      @y -= 1
      # 歩数増加
      increase_steps
    # 通行不可能な場合
    else
      # 接触イベントの起動判定
      check_event_trigger_touch(@x, @y-1)
    end
  end
 
  def check_altitude(event, event2)
    z1 = event.altitude
    z2 = event2.altitude
   
    min1 = event.bridge != nil ? event.bridge.min_alt : -2
    min2 = event2.bridge != nil ? event2.bridge.min_alt : -2
   
    if z1==z2
      return true
    end
   
    if( (z1 == -2 and z2 == min2) or (z1 == min1 and z2 == -2) )
      return true
    end
   
    #print(z1, ", ", z2, " ; ", min1, ", ", min2, " ; ", $game_player.bridge != nil ? $game_player.bridge.min_alt : nil)
    return false
  end
 
  def bush_depth
    # タイルの場合、または最前面に表示フラグが ON の場合
    if @tile_id > 0 or @always_on_top
      return 0
    end
   
    if $game_system.map_interpreter.on_bridge?(self) 
      return 0 
    end
   
    # ジャンプ中以外で茂み属性のタイルなら 12、それ以外なら 0
    if @jump_count == 0 and $game_map.bush?(@x, @y)
      return 12
    else
      return 0
    end
  end
 
end



class Game_Event
  attr_accessor :page
  attr_accessor :map_id
 
  def get_commentaire_command(word)
    for page in event.pages
      for command in page.list
        for par in command.parameters
          if par.is_a?(String) and par.include?(word)
            return par
          end
        end
      end
    end
    return nil
  end
 
  def initialize(map_id, event)
    super()
    @map_id = map_id
    @event = event
    @id = @event.id
    @erased = false
    @starting = false
    @through = true
    # 初期位置に移動
    moveto(@event.x, @event.y)
   
    @altitude = -2
    over = get_commentaire_command(Kurei::OVER_BRIDGE_WORD) != nil
    for bridge in $game_map.bridges[$game_map.map_id]
      new_alt = bridge.calculate_altitude(@x, @y)
     
      if new_alt == -2
        next
      end
     
      @bridge = bridge
      if over
        #print()
        @altitude = bridge.max_alt
        @z_alt = 3*32
      else
        @altitude = bridge.min_alt
        @z_alt = 0
      end
    end
   
    refresh
  end
 
  def check_event_trigger_touch(x, y)
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return
    end
    # トリガーが [イベントから接触] かつプレイヤーの座標と一致した場合
    if @trigger == 2 and x == $game_player.x and y == $game_player.y and check_altitude($game_player, self)
      # ジャンプ中以外で、起動判定が正面のイベントなら
      if not jumping? and not over_trigger?
        start
      end
    end
  end 
end




class Game_Player
 
  def initialize
    super()
    @altitude = -2
  end
 
  #--------------------------------------------------------------------------
  # ● 接触イベントの起動判定
  #--------------------------------------------------------------------------
  def check_event_trigger_touch(x, y)
    result = false
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return result
    end
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標とトリガーが一致した場合
      if event.x == x and event.y == y and [1,2].include?(event.trigger) and check_altitude(event, self)
        # ジャンプ中以外で、起動判定が正面のイベントなら
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
 
  def check_event_trigger_here(triggers)
    result = false
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return result
    end
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標とトリガーが一致した場合
      if event.x == @x and event.y == @y and triggers.include?(event.trigger) and check_altitude(event, self)
        # ジャンプ中以外で、起動判定が同位置のイベントなら
        if not event.jumping? and event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ● 正面のイベント起動判定
  #--------------------------------------------------------------------------
  def check_event_trigger_there(triggers)
    result = false
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return result
    end
    # 正面の座標を計算
    new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
    new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標とトリガーが一致した場合
      if event.x == new_x and event.y == new_y and
         triggers.include?(event.trigger) and check_altitude(event, self)
        # ジャンプ中以外で、起動判定が正面のイベントなら
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    # 該当するイベントが見つからなかった場合
    if result == false
      # 正面のタイルがカウンターなら
      if $game_map.counter?(new_x, new_y)
        # 1 タイル奥の座標を計算
        new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
        new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
        # 全イベントのループ
        for event in $game_map.events.values
          # イベントの座標とトリガーが一致した場合
          if event.x == new_x and event.y == new_y and
             triggers.include?(event.trigger) and check_altitude(event, self)
            # ジャンプ中以外で、起動判定が正面のイベントなら
            if not event.jumping? and not event.over_trigger?
              event.start
              result = true
            end
          end
        end
      end
    end
    return result
  end
end



class Interpreter
  #Ajoute le pont à la map map_id
  # x, y : position du coin haut gauche du pont
  # alt_h:Altitude à l'entrée gauche du pont
  def add_bridge(x, y, w, h, alt_h, alt_v, map_id = $game_map.map_id)
    $game_map.bridges.add_bridge(map_id, Kurei::Bridge.new(x, y, w, h, alt_h, alt_v))
  end
 
  def add_and_detect_bridge(x, y, w, h, alt_h, alt_v, map_id = $game_map.map_id)
    add_bridge(x, y, w, h, alt_h, alt_v, map_id)
   
    min = [alt_h, alt_v].min
    max = [alt_h, alt_v].max
   
    if map_id == $game_map.map_id
      map = $game_map
    else
      map = Game_Map.new
      map.setup(map_id)
      map.refresh
    end
   
    for tx in x..(x+w-1)
      for ty in y..(y+h-1)
        if map.terrain_tag(tx, ty) == 7
          $game_map.bridges.add_free(map_id, [tx, ty, max])
        elsif !map.tiles_passable?(tx, ty)
          $game_map.bridges.add_block(map_id, [tx, ty, min])
          $game_map.bridges.add_free(map_id, [tx, ty, max])
        end
      end
    end
  end
  alias placer_pont add_and_detect_bridge
 
  def on_bridge?(event)
    if event.bridge == nil
      return false
    end
   
    if event.altitude == -2
      return false
    end
   
    if event.altitude == event.bridge.min_alt
      return false
    end
   
    return true
  end
end

Code:
#=============================================================================
# - Bridges - by Ku'rei Jinwu - beginning date : 21/07/2013 -
#=============================================================================
# Script gérant les ponts.
module Kurei
  # Mot à placer dans un commentaire dans l'évent afin que l'event soit
  # automatique placer au dessus du pont.
  OVER_BRIDGES_WORD = "OVER_BRIDGE"
 
  # Mot à placer dans un commentaire dans l'évent afin que l'event commence avec
  # l'altitude passée :
  # Syntaxe :
  #     PRESET_ALTITUDE=value
  # où value est un entier
  PRESET_ALTITUDE_WORD = "PRESET_ALTITUDE"
 
  # Lorsque OVER_BRIDGE est utilisé, la détection de l'altitude maximale se fait
  # On arrete de chercher un bridge quand l'altitude de recherche atteint cette constante
  # par défaut 20
  MAX_AUTO_DETECT_ALTITUDE = 20
 
  #=============================================================================
  # Classe contenant les données sur les ponts du jeu
  class BridgesData
      # Altitude minimale de base
    UNKOWN_ALTITUDE = 0
   
    # bridges_parts   : [map_id => [x][y][index]]
      # bridges_parts[map_id][x][y][index] ->liste d'altitudes où sont des parties de ponts
    # blockers_parts  : Même principe que bridges_parts pour des blocs non passants
    # alt_modifiers   :Même structure que bridges_parts, l'Integer en bout de structure
      # représente la nouvelle altitude
     
    def initialize
      @bridges_parts  = []
      @blockers_parts = []
      @alt_modifiers  = []
    end
   
    # Indique qu'un élément de la structure donnée est à l'emplacement donné
    # IN :
    #   parts   : bool, true -> ajoutera une partie de pont, false un bloqueur
    #   map_id  : int, id de la map où il faut ajotuer l'élément
    #   x, y    : int, coordonnées du tile
    #   alt     : int, altitude où se trouve l'élément à ajouter
    def add_component(parts, map_id, x, y, alt)
      struct = (parts ? @bridges_parts : @blockers_parts)
     
      if struct[map_id] == nil
        struct[map_id] = []
      end
     
      if struct[map_id][x] == nil
        struct[map_id][x] = []
      end
     
      if struct[map_id][x][y] == nil
        struct[map_id][x][y] = []
      end
     
      struct[map_id][x][y] += [alt]
    end
   
    def add_bridge_part(map_id, x, y, alt)
      add_component(true, map_id, x, y, alt)
    end
   
    def add_blocker(map_id, x, y, alt)
      add_component(false, map_id, x, y, alt)
    end
   
    # Place un modificateur d'altitude à l'emplacement donné
    # IN :
    #   map_id  : int, id de la map où il faut ajotuer l'élément
    #   x, y    : int, coordonnées du tile
    #   alt     : int, nouvelle altitude
    def add_altitude_modifier(map_id, x, y, alt)
      struct = @alt_modifiers
     
      if struct[map_id] == nil
        struct[map_id] = []
      end
     
      if struct[map_id][x] == nil
        struct[map_id][x] = []
      end
     
      struct[map_id][x][y] = alt
    end
   
   
    def there_component?(parts, map_id, x, y, alt)
      struct = (parts ? @bridges_parts : @blockers_parts)
      if  (struct[map_id] == nil or struct[map_id][x] == nil or
          struct[map_id][x][y] == nil or not struct[map_id][x][y].include?(alt))
        return false
      end
     
      return true
    end
   
    # Retourne true si il y a une partie de pont à l'emplacement indiqué
    def there_bridge_part?(map_id, x, y, alt)
      return there_component?(true, map_id, x, y, alt)
    end
   
    #Retourne true si il y a un bloqueur à l'emplacement indiqué
    def there_blocker_part?(map_id, x, y, alt)
      return there_component?(false, map_id, x, y, alt)
    end
   
    def there_modifier?(x, y, map_id)
      return get_altitude_modifier(map_id, x, y) != nil
    end
   
    #Retourne l'atitude modifiée ou UNKOWN_ALTITUDE
    def get_altitude_modifier(map_id, x, y)
      struct = @alt_modifiers
      if  (struct[map_id] == nil or struct[map_id][x] == nil or
          struct[map_id][x][y] == nil)
        return UNKOWN_ALTITUDE
      end
     
      return struct[map_id][x][y]
    end
   
    # Calcul la nouvelle altitude lors d'un passage d'un tile à l'autre
    # IN :
    #   x, y    : coordonnées de la première case
    #   x1, y1  : coordonnées de la seconde case
    # OUT :
    #   [altitude à la seconde position, indcateur de sortie de pont, indicateur entrée sur pont]
    def get_altitude_passage(map_id, x, y, x1, y1, old_alt)
      alt_mod = get_altitude_modifier(map_id, x, y)
      alt = alt_mod
      if alt != UNKOWN_ALTITUDE and not there_bridge_part?(map_id, x1, y1, alt)
        alt = UNKOWN_ALTITUDE
      end
     
      if there_bridge_part?(map_id, x1, y1, old_alt)
        alt = old_alt
      end
     
      go_on_bridge = false
      if alt_mod != UNKOWN_ALTITUDE and there_bridge_part?(map_id, x1, y1, alt_mod)
        go_on_bridge = true
      end
     
      quit_bridge = (get_altitude_modifier(map_id, x1, y1) != UNKOWN_ALTITUDE and old_alt != alt)
     
      #print(alt, ", ", old_alt, " ; ", get_altitude_modifier(map_id, x1, y1), " ; ", alt != old_alt)
      #print [alt, quit_bridge, go_on_bridge]
      return [alt, quit_bridge, go_on_bridge]
    end
   
    #===========================================================================
    # Préfab methods
    def add_bridge(map_id, x, y, w, h, alt_h, alt_v)
      #Placement des parties de ponts
      alt = [alt_h, alt_v].max
      for tx in x..(x+w-1) 
        for ty in y..(y+h-1)
          add_bridge_part(map_id, tx, ty, alt)
        end
      end
     
      #Placement des modifieur d'altitude
      if alt_v != 0
        for tx in x-1..(x+w)
          add_altitude_modifier(map_id, tx, y-1, alt_v)
          add_altitude_modifier(map_id, tx, y+h, alt_v)
        end
      end
      if alt_h != 0
        for ty in y-1..(y+h)
          add_altitude_modifier(map_id, x-1, ty, alt_h)
          add_altitude_modifier(map_id, x+w, ty, alt_h)
        end
      end
    end
  end
end


#===============================================================================
#
# Game Class Modified
class Game_Character
  attr_accessor :altitude #altitude de jeu.
 
  # Retourne vrai si le character est sur un pont
  # OUT :
  #   bool, true si le chara est sur un pont, false sinon
  def on_bridge?
    r = (@altitude != 0 and @altitude != nil)
    return r
  end
 
  # Détermine si le passage est possible du point de vue des altitudes
  # IN :
  #   new_x, new_y  : int, coordonnées du prochain tile
  #   map_id        : int, numéro de la map
  # OUT :
  #   [bool, new_alt], passage validé ou non acompagné de la nouvelle altitude.
  def get_new_altitude(new_x, new_y, map_id = $game_map.map_id)
    if @altitude == nil
      @altitude = 0
    end
   
    pass = $data_bridges.get_altitude_passage(map_id, @x, @y, new_x, new_y, @altitude)
    new_alt = pass[0]
    quit_bridge = pass[1]
    go_on_bridge = pass[2]
   
    if new_alt == @altitude
      return [true, new_alt]
    end
   
    if quit_bridge
      return [true, Kurei::BridgesData::UNKOWN_ALTITUDE]
    end
   
    if go_on_bridge
      return [true, new_alt]
    end
   
    return [false, 0]
  end
 
  # Détermine si un character est sur la même altitude qu'un autre
  # IN :
  #   chara1, chara2  : Game_Character, chara à comparer
  #   map_id  : int, numéro de la map
  # OUT :
  #   bool, collision dans les altitudes(false) ou non(true)
  def check_event_altitude(chara1, chara2, map_id = $game_map.map_id)
    z1 = chara1.altitude
    z2 = chara2.altitude
   
    onMod1 = $data_bridges.get_altitude_modifier(map_id, chara1.x, chara1.y) != 0
    onMod2 = $data_bridges.get_altitude_modifier(map_id, chara2.x, chara2.y) != 0
   
    if z1 != z2 and not (onMod1 or onMod2)
      return false
    end
   
    return true
  end
 
  def passable?(x, y, d)
    # 新しい座標を求める
    new_x = x + (d == 6 ? 1 : d == 4 ? -1 : 0)
    new_y = y + (d == 2 ? 1 : d == 8 ? -1 : 0)
   
    # すり抜け ON の場合
    if @through
      # 通行可
      return true
    end
    # 移動元のタイルから指定方向に出られない場合
   
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標が移動先と一致した場合
      if event.x == new_x and event.y == new_y and check_event_altitude(self, event)
        # すり抜け OFF なら
        unless event.through
          # 自分がイベントの場合
          if self != $game_player
            # 通行不可
            return false
          end
          # 自分がプレイヤーで、相手のグラフィックがキャラクターの場合
          if event.character_name != ""
            # 通行不可
            return false
          end
        end
      end
    end
    # プレイヤーの座標が移動先と一致した場合
    if $game_player.x == new_x and $game_player.y == new_y and check_event_altitude(self, $game_player)
      # すり抜け OFF なら
      unless $game_player.through
        # 自分のグラフィックがキャラクターの場合
        if @character_name != ""
          # 通行不可
          return false
        end
      end
    end
   
    # Update de l'atitude
    last_alt = @altitude
    pass = get_new_altitude(new_x, new_y)
    valid = pass[0]
    new_alt = pass[1]
    if valid
      @altitude = new_alt
    else
      return false
    end
   
    if @altitude != 0 or last_alt != 0
      return true
    end
   
    # 座標がマップ外の場合
    unless $game_map.valid?(new_x, new_y)
      # 通行不可
      return false
    end
    unless $game_map.passable?(x, y, d, self)
      # 通行不可
      return false
    end
    # 移動先のタイルに指定方向から入れない場合
    unless $game_map.passable?(new_x, new_y, 10 - d, self)
      # 通行不可
      return false
    end
    # 通行可
    return true
  end
 
  def screen_z(height = 0)
    # 最前面に表示フラグが ON の場合
    if @always_on_top
      # 無条件に 999
      return 999
    end
    # 実座標とマップの表示位置から画面座標を求める
    add = 0
    if (@altitude != 0 or $data_bridges.get_altitude_modifier($game_map.map_id, x, y) != 0)
      add = 32*3
    end
    z = (@real_y - $game_map.display_y + 3) / 4 + 32 + add
    # タイルの場合
    if @tile_id > 0
      # タイルのプライオリティ * 32 を足す
      return z + $game_map.priorities[@tile_id] * 32
    # キャラクターの場合
    else
      # 高さが 32 を超えていれば 31 を足す
      return z + ((height > 32) ? 31 : 0)
    end
  end
 
  def bush_depth
    # タイルの場合、または最前面に表示フラグが ON の場合
    if @tile_id > 0 or @always_on_top
      return 0
    end
   
    if on_bridge?
      return 0
    end
    # ジャンプ中以外で茂み属性のタイルなら 12、それ以外なら 0
    if @jump_count == 0 and $game_map.bush?(@x, @y)
      return 12
    else
      return 0
    end
  end
end

class Game_Event
  # Renvoie l'expression de commande de commentaire ou nil
  # IN :
  #   keyword : string, mot-clef d'un commande de commentaire
  # OUT :
  #   string or nil, commande complète ou nil
  def event_contain_command(event, keyword)
    for page in event.event.pages
      for command in page.list
        if command.code == 108
          for parameter in command.parameters
            if parameter.include?(keyword)
              return parameter
            end
          end
        end
      end
    end
    return nil
  end
 
  def initialize(map_id, event)
    super()
    @map_id = map_id
    @event = event
    @id = @event.id
    @erased = false
    @starting = false
    @through = true
    # 初期位置に移動
    moveto(@event.x, @event.y)
   
    # Détermination de l'altitude
    @altitude = 0
    command = event_contain_command(self, Kurei::PRESET_ALTITUDE_WORD)
    if command != nil
      val = command.split("=")[1]
      @altitude = eval(val)
    end
   
    command = event_contain_command(self, Kurei::OVER_BRIDGES_WORD)
    if command != nil
      z = 0
      while not $data_bridges.there_bridge_part?(@map_id, @x, @y, z)
        #print(@map_id, ", ", @x, ", ", @y, ", ", z, ", ", $data_bridges.bridges_parts.inspect)
        z+=1
        if z >= Kurei::MAX_AUTO_DETECT_ALTITUDE
          break
        end
      end
      @altitude = (z >= Kurei::MAX_AUTO_DETECT_ALTITUDE) ? 0 : z
    end
   
    refresh
  end
 
  def check_event_trigger_touch(x, y)
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return
    end
    # トリガーが [イベントから接触] かつプレイヤーの座標と一致した場合
    if @trigger == 2 and x == $game_player.x and y == $game_player.y and $game_player.y and check_event_altitude(self, $game_player)
      # ジャンプ中以外で、起動判定が正面のイベントなら
      if not jumping? and not over_trigger?
        start
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 自動イベントの起動判定
  #--------------------------------------------------------------------------
  def check_event_trigger_auto
    # トリガーが [イベントから接触] かつプレイヤーの座標と一致した場合
    if @trigger == 2 and @x == $game_player.x and @y == $game_player.y and check_event_altitude(self, $game_player)
      # ジャンプ中以外で、起動判定が同位置のイベントなら
      if not jumping? and over_trigger?
        start
      end
    end
    # トリガーが [自動実行] の場合
    if @trigger == 3
      start
    end
  end
end

class Game_Player
  def check_event_trigger_here(triggers)
    result = false
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return result
    end
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標とトリガーが一致した場合
      if event.x == @x and event.y == @y and triggers.include?(event.trigger) and check_event_altitude(self, event)
        # ジャンプ中以外で、起動判定が同位置のイベントなら
        if not event.jumping? and event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ● 正面のイベント起動判定
  #--------------------------------------------------------------------------
  def check_event_trigger_there(triggers)
    result = false
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return result
    end
    # 正面の座標を計算
    new_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
    new_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標とトリガーが一致した場合
      if event.x == new_x and event.y == new_y and
         triggers.include?(event.trigger) and check_event_altitude(self, event)
        # ジャンプ中以外で、起動判定が正面のイベントなら
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    # 該当するイベントが見つからなかった場合
    if result == false
      # 正面のタイルがカウンターなら
      if $game_map.counter?(new_x, new_y)
        # 1 タイル奥の座標を計算
        new_x += (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
        new_y += (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
        # 全イベントのループ
        for event in $game_map.events.values
          # イベントの座標とトリガーが一致した場合
          if event.x == new_x and event.y == new_y and
             triggers.include?(event.trigger) and check_event_altitude(self, event)
            # ジャンプ中以外で、起動判定が正面のイベントなら
            if not event.jumping? and not event.over_trigger?
              event.start
              result = true
            end
          end
        end
      end
    end
    return result
  end
  #--------------------------------------------------------------------------
  # ● 接触イベントの起動判定
  #--------------------------------------------------------------------------
  def check_event_trigger_touch(x, y)
    result = false
    # イベント実行中の場合
    if $game_system.map_interpreter.running?
      return result
    end
    # 全イベントのループ
    for event in $game_map.events.values
      # イベントの座標とトリガーが一致した場合
      if event.x == x and event.y == y and [1,2].include?(event.trigger) and check_event_altitude(self, event)
        # ジャンプ中以外で、起動判定が正面のイベントなら
        if not event.jumping? and not event.over_trigger?
          event.start
          result = true
        end
      end
    end
    return result
  end
end

class Interpreter
  def add_bridge(x, y, w, h, alt_h, alt_v, map_id) 
    if alt_h != 0 and alt_v != 0
      if alt_h > alt_v
        alt_v = 0
      else
        alt_h = 0
      end
    end
    $data_bridges.add_bridge(map_id, x, y, w, h, alt_h, alt_v)
  end
  alias placer_pont add_bridge
 
  # Retourne vrai si l'évènement passé en paramètre est sur un pont
  def on_bridge?(event = $game_map.events[@event_id])
    return event.on_bridge?
  end
end

$data_bridges = Kurei::BridgesData.new

Il vous faudra modifier l'événement commun SURF (modifications entourées de rouge)


Et voici le script installé.

Utilisation


Vous pouvez utiliser ce script "à l'arrache" en créant les ponts quand vous arrivez sur la map pour la première fois mais ce n'est pas conseillé, on ne pourra prédire si les événements en contact avec les ponts seront à leurs bonne place. Je vous prie de suivre la méthode que je décris :
  • 1. Créer un événement commun en Appel chargé de créer tous les ponts du jeu en une seule fois. Il est conseillé de structurer l'événement de façon à pouvoir retrouver facilement quel pont est dans quelle map. Par exemple :

  • 2. Appel de l'événement de création des ponts. Ai-je réellement besoin de vous le dire ? Appelez cet événement commun dans la scène d'intro de votre jeu et qu'on n'en parle plus.


Quelques fonctionnalités supplémentaires
  • Placement au-dessus du pont automatique : en commentaire, dans l'événement, entrer la formule suivante :
    Code:
    OVER_BRIDGE

    cela placera l'événement au-dessus du premier pont.
  • V2, Présélection de l'altitude : en commentaire, dans l'événement, entrer la formule suivante :
    Code:
    PRESET_ALTITUDE=value

    value est la valeur présélectionnée de l'altitude. Exemple :




Il faut mettre les tiles de ponts avec une priorité de superposition de 3


Voici quelques exemples de ponts avec leurs caractéristiques ainsi que le code permettant leur création.


Les membres suivants remercient Ku'rei pour ce message :
Ле́нин (19/07/13), Koya (06/08/13), Voltix (27/08/13)


Dernière édition par Ku'rei le Mar 23 Juil - 08:10 (2013); édité 11 fois
Revenir en haut
Publicité






MessagePosté le: Mar 16 Juil - 11:07 (2013)    Sujet du message: Publicité

PublicitéSupprimer les publicités ?
Revenir en haut
Nuri Yuri
Administrateur
Administrateur


Inscrit le: 15 Oct 2008
Messages: 6 383
~Entity~
Localisation: Nancy
Non renseigné (Visible...)
ID Steam: Nuri_Yuri

MessagePosté le: Mar 16 Juil - 17:24 (2013)    Sujet du message: [Mapping]Ponts

Voilà un script qui sera super utile, il évitera les manip's de mapping/évent douteuses Gros matou qui ronronne
Revenir en haut
Facebook Twitter
Ku'rei
Membre


Inscrit le: 10 Aoû 2010
Messages: 546
Adepte du NoMoreExcuses
Localisation: Chambéry
Masculin

MessagePosté le: Mar 16 Juil - 18:27 (2013)    Sujet du message: [Mapping]Ponts

Merci,
Je viens d'ajouter la suppression de l'effet des carreaux obscurcissant quand le personnage est sur le pont.
Revenir en haut
Sphinx
Scribe
Scribe


Inscrit le: 07 Jan 2008
Messages: 9 736
Localisation: Quelque part, dans le monde... Ou peut être sur une autre planète...
ID Steam: FaQuinator

MessagePosté le: Mer 17 Juil - 21:15 (2013)    Sujet du message: [Mapping]Ponts

Imbécile heureux Ma foi, voilà une nouveauté qui va permettre d'améliorer PSP ! En plus il m'a l'air simple d'utilisation ^^

Le jour où je ferai une maj de 4G+ (c'est pas demain la veille ceci dit :!), je pense que je l'intègrerai :p
Revenir en haut
TouzaxA
Membre


Inscrit le: 27 Juil 2012
Messages: 2 669

MessagePosté le: Dim 21 Juil - 06:46 (2013)    Sujet du message: [Mapping]Ponts

C'est effectivement très sympathique. ^^
Revenir en haut
Ku'rei
Membre


Inscrit le: 10 Aoû 2010
Messages: 546
Adepte du NoMoreExcuses
Localisation: Chambéry
Masculin

MessagePosté le: Lun 22 Juil - 14:27 (2013)    Sujet du message: [Mapping]Ponts

Sphinx a écrit:
Le jour où je ferai une maj de 4G+ (c'est pas demain la veille ceci dit :!), je pense que je l’intégrerai :p

C'est trop d'honneur ^^ merci. Et comme ça j'aurais le temps d'ajouter la gestion des ponts superposés... Sacré sal***rie ces ponts...

EDIT VISIBLE :: Mise à jour du script, la version 2 est une refonte complète du script, beaucoup plus propre et claire. Elle propose quelques fonctionnalités supplémentaires notamment la gestion des ponts superposés (bien que la superposition graphique ne soit pas encore là).
Revenir en haut
Koya
Membre


Inscrit le: 16 Avr 2012
Messages: 25
Glandeuse pro
Localisation: Dans l'Eaucéan

MessagePosté le: Mar 6 Aoû - 14:59 (2013)    Sujet du message: [Mapping]Ponts

Mon nouveau dieu! Rameric après manger

J'ai galéré sur un pont qui passait au-dessus de l'eau il n'y a pas longtemps, je sens que ce script va beaucoup m'aider. <3

Je vois que la V2 gère les ponts superposés, mais par superposition graphique manquante, qu'entends-tu? La superposition des pnj avec le décor/le héros par exemple?

Et est-il possible de joindre deux ponts qui se croisent à la même altitude? Il va falloir que je teste ça de suite. =]
Revenir en haut
Visiter le site web du posteur
Ku'rei
Membre


Inscrit le: 10 Aoû 2010
Messages: 546
Adepte du NoMoreExcuses
Localisation: Chambéry
Masculin

MessagePosté le: Mer 7 Aoû - 08:05 (2013)    Sujet du message: [Mapping]Ponts

Les pont superposés sont gérés mais le personnage sera au-dessus des deux ponts tout le temps...


Koya a écrit:
Et est-il possible de joindre deux ponts qui se croisent à la même altitude? Il va falloir que je teste ça de suite. =]

En théorie oui, je te laisse essayer.
Revenir en haut
Mercury
Membre


Inscrit le: 26 Juin 2013
Messages: 258
Se débrouille comme il peut
Localisation: pas de calais
Masculin
Nintendo Network: Lareinerouge62

MessagePosté le: Mer 3 Sep - 09:04 (2014)    Sujet du message: [Mapping]Ponts

Merci, ça va beaucoup me servir Gros matou qui ronronne
Revenir en haut
Skype Facebook
Contenu Sponsorisé






MessagePosté le: Aujourd’hui à 16:55 (2017)    Sujet du message: [Mapping]Ponts

Revenir en haut
Montrer les messages depuis:   
Poster un nouveau sujet   Répondre au sujet    Pokémon Script Project Index du Forum -> Game Making -> Ressources techniques -> Scripts Toutes les heures sont au format GMT + 1 Heure
Page 1 sur 1

 
Sauter vers:  

Index | Creer un forum | Forum gratuit d’entraide | Annuaire des forums gratuits | Signaler une violation | Conditions générales d'utilisation
Powered by phpBB © 2001, 2005 phpBB Group
Thème par Thomas et l'équipe de la refonte PSP 2012 (version 1.0)
Traduction par : phpBB-fr.com