RPGツクールVX  エネミーランダム・大量出現

(^▽^)ノ やぁ
今日からQuest Mania 開発日記というシリーズをはじめます。
Quest Maniaというのは今SupponがRPGツクールVXで開発中のRPGです。
一応公式ホームページもあります。→こちら

ふと、おもたのですが、
敵グループをひとつひとつ作っていくのはめんどくさいです。(´・ω・`)
いろんな敵の組み合わせを考えると大変です。
何種類か選んだ中からランダムで、出現させるって言う方法があれば
らくなのになー。なんでないんだろ?

ということで、ここはスクリプトで解決することにしました。

やりかたは簡単、$game_troop.memberにGame_Enemyクラスの
インスタンスをpushしていけばいいだけです。
あと、スプライトを表示させるために、そっちのほうもちょっといじりますが。

エネミーの指定の仕方は、バトルイベントの中に
[出現確率, n, ID1, ID2, ID3・・・]という風に注釈として入れます。
出現確率には0~100の数字を、nには繰り返す数を、そのあとに選ぶエネミーのIDを
入れてやります。
注釈は文字列として読み取ることができるので、evalを使ってスクリプトとして適用できます。

あとは、テキトウに並ばせるようにして、
ハイ!完成!(^▽^)ノ
080413_01.jpg


これで、一個の敵グループでたくさんのエネミーの組み合わせを作ることができました。

怒涛のキングスライム12匹分のスライム登場(´・ω・)つ
080413_02.jpg


戦闘が長くなるので、ゲーム中ではこんなにたくさんはでません。( ^ω^)
(・・・たぶんね)

RGSS2備忘録その8 回避率を敏捷性依存にする

こんばんわー( ^ω^)
Quest Mania公式ホームページでは、これからクエストを作り始めますとかって
書いてありますが、実はまだぜんぜん作り始めてません(´;ω;`)スミマセン

で、今日は通常攻撃の回避率を敏捷性に依存させるって言うのをやります。
噛み砕いて言うと、もともと回避率は装備してるアイテムによって決められますが、
今回はスクリプトをいじって、敏捷性が高いほど、回避率が高くなるようにさせます。
っていうのをやります。

まずは、ヒット率の変更から

class Game_Battler

 def calc_hit(user, obj = nil)
    hit = 100
    if obj == nil                           # 通常攻撃の場合 
     elsif obj.is_a?(RPG::Skill)             # スキルの場合
      hit = obj.hit                         # 成功率を取得 
    else                                    # アイテムの場合
      hit = 100                             # 命中率を 100% とする 
    end 
    return hit
  end
end


スキル使用時だけはその成功率を適応させます。それ以外はすべて100%にします。
次に回避率の定義ですが、
回避率=(1-攻撃者の敏捷性/自分の敏捷性)×75
で、最大95%、最小5%にします。
というふうにします。
自分の敏捷性が攻撃者の敏捷性の3倍だったら半分の回避できるという計算になります。

class Game_Battler

 def calc_eva(user, obj = nil)
    user_agi = user.agi * 1.00
    user_agi /= 4 if user.reduce_hit_ratio?
    eva = (1 - (user_agi / self.agi)) * 75
    eva = [[eva, 5].max, 95].min
    unless obj == nil                       # 通常攻撃ではない場合
      eva = 0 unless obj.physical_attack    # 物理攻撃以外なら 0% とする
    end
    unless parriable?                       # 回避不可能な状態の場合
      eva = 0                               # 回避率を 0% とする
    end
    return eva
  end
end

これで敏捷性が高ければ高いほど回避率が高くなります。(^▽^)ヤッタネ
さーて、そろそろほんとうにクエストつくるかな(´・ω・`) まじで
では、またー(^▽^)ノシ

テーマ : RPGツクール
ジャンル : ゲーム

RGSS2備忘録その7 臨機応変に行動できる自動戦闘のアクター

バグが見つかったので、こちらをご覧ください。

こんばんわ(´・ω・`)
そろそろQuest Maniaのクエストを作り始めようとしているすっぽんです。
今日は臨機応変に行動できる自動戦闘のアクターって言うのをやります。

こんな場面はあまりないと思いますが、パーティ全員が自動戦闘で、誰か一人だけが
戦闘不能の状態で、全員蘇生可能なスキルをもっているとします。
この状態で、戦闘を開始すると行動可能なアクターは、全員戦闘不能のアクターを
蘇生しようとします。本来なら、一人だけ蘇生させるスキルを使って、他のアクターは
攻撃に回ればいいのですが、自動戦闘だとこのようなことも起こり得ます。

そこで、今日はこのような自動戦闘アクターの無駄な行動を避けるスクリプトを
紹介したいと思います。
自動戦闘のアクターの行動は、ターンごとの戦闘開始前に決定されます。しかし、
この場合、それぞれのアクターは、他のアクターがどのような行動をするのかという
ことをぜんぜん考えてません。なので、戦闘中、行動できる順番が回ってきたら、
再度、行動内容の評価を行い、臨機応変に行動させるようにすれば、前述した
問題を回避することができます。

やりかたは以下のとおりです。
class Battle_Sceneのprocess_actionメソッドを次のように変えてください。
  #--------------------------------------------------------------------------
  # ● 戦闘行動の処理
  #--------------------------------------------------------------------------
  def process_action
    return if judge_win_loss
    return if $game_temp.next_scene != nil
    set_next_active_battler
    if @active_battler == nil
      turn_end
      return
    end
    return if @active_battler.dead?
    @message_window.clear
    wait(5)
    @active_battler.white_flash = true
    unless @active_battler.action.forcing
      @active_battler.action.prepare
    end
    if @active_battler.actor? #★
      @active_battler.make_action if @active_battler.auto_battle
    end #★
    if @active_battler.action.valid?
      execute_action
    end
    unless @active_battler.action.forcing
      @message_window.clear
      remove_states_auto
      display_current_state
    end
    @active_battler.white_flash = false
    @message_window.clear
  end

これで、自動戦闘のアクターは臨機応変に行動できるようになったと思います。
ていうか、こうするとプレイヤーが行動を決めるよりも有利に戦闘が展開します。( ^ω^)

今日はこのへんで
でわ(^▽^)ノシ

テーマ : RPGツクール
ジャンル : ゲーム

RGSS2備忘録その6 目に優しい戦闘アニメーション

こんばんわー(^▽^)
最近、朝が寒すぎて目が覚めるSupponです。

えー、今日の本題に入る前に、やっぱり先日やった壁の上を歩行可能にする
スクリプトは完璧ではありませんでした。
小生スクリプトには、まだまだ不慣れで煩雑な構文になってしまったので、
あとで見直して、よりコンパクトにできたらまた、このブログで紹介したいと思います。
でも、そのまえに、他の人がもっといいスクリプトつくっちゃってるかもしれませんが。

では、きょうの本題に入ります。
今日は平日なので1分でできるやつを紹介します。( ^ω^)
みなさん、テストプレイしてるとなんだかすぐに目が疲れてきませんか?
俺だけですかね?
目が疲れた状態でプレイし続けると視力にも悪影響を及ぼす可能性が
あるかもしれませんよ。Σ(゚Д゚; エーッ!

で、目が疲れる原因、諸悪の根源はアニメーションのフラッシュです。
そこで今日は、アニメーションのフラッシュを無効にする目に優しいスクリプトを紹介します。

Sprite_Baseクラスのanimation_process_timing(timing)メソッドの
viewport.flash(timing.flash_color, timing.flash_duration * 4)という文を
コメントアウトしてください。
これでフラッシュはしなくなります。

これで、思う存分テストプレイしまくれます。(俺の場合)
これを発見する前までは、フルスクリーンでプレイすることもためらっていたSupponですが、
いまでは、バリバリフルスクリーンでやりまくっています。

今日はここまで、
みなさん、疲労を感じたら適度な休憩を取りましょう
でわ (^▽^)ノシ

テーマ : RPGツクール
ジャンル : ゲーム

RGSS2備忘録その5 壁の上を歩行可能にするスクリプト

こんばんわ( ^ω^)
平日は忙しくてブログが更新できませんでした。(´;ω;`)ウッ
今後は土日のみの更新になるとおもいます。
とはいえ、もうRGSSについて書くことがなくなってきましたがね。
書くことがなくなったらQuest Maniaの進捗状況でも書こうかと思います。

実は今日、以前紹介した壁の上を歩行可能にするスクリプトでは、
水平壁の端に歩行可能な上層レイヤーを置くと歩行可能になったり、
レイヤーがきちんと機能しないというご指摘を受けました。スミマセン(´;ω;`)ウッ
そこで、今日はその不具合を改善するスクリプトを紹介します。

まず、前回のスクリプトは削除していただいて、以下のスクリプトのコピーをお願いします。
class Game_Map
  #--------------------------------------------------------------------------
  # ● セットアップ
  #     map_id : マップ ID
  #--------------------------------------------------------------------------
  def setup(map_id)
    @map_id = map_id
    @map = load_data(sprintf("Data/Map%03d.rvdata", @map_id))
    @display_x = 0
    @display_y = 0
    @passages = $data_system.passages
    for m in 0..2
      for k in 0..7
        j = 5888 + 48 * k + 768 * m
        for i in 0..47
          if i < 16
            @passages[i + j] = 0x20
          elsif 16 <= i and  i <= 19
            @passages[i + j] = 0x21
          elsif 20 <= i and  i <= 23
            @passages[i + j] = 0x22
          elsif 24 <= i and  i <= 27
            @passages[i + j] = 0x24
          elsif 28 <= i and  i <= 31
            @passages[i + j] = 0x28
          elsif i == 32
            @passages[i + j] = 0x25
          elsif i == 33
            @passages[i + j] = 0x2a
          elsif i == 34 or i == 35
            @passages[i + j] = 0x23
          elsif i == 36 or i == 37
            @passages[i + j] = 0x26
          elsif i == 38 or i == 39
            @passages[i + j] = 0x2c
          elsif i == 40 or i == 41
            @passages[i + j] = 0x29
          elsif i == 42
            @passages[i + j] = 0x27
          elsif i == 43
            @passages[i + j] = 0x2b
          elsif i == 44
            @passages[i + j] = 0x2d
          elsif i == 45
            @passages[i + j] = 0x2e
          elsif i >= 46
            @passages[i + j] = 0x2f
          end
        end
      end
    end
    referesh_vehicles
    setup_events
    setup_scroll
    setup_parallax
    @need_refresh = false
  end
end

class Game_Character
  def map_passable?(x, y)
    return $game_map.passable2?(x, y, @x, @y)
  end
end

class Game_Player
  def map_passable?(x, y)
    case @vehicle_type
    when 0  # 小型船
      return $game_map.boat_passable?(x, y)
    when 1  # 大型船
      return $game_map.ship_passable?(x, y)
    when 2  # 飛行船
      return true
    else    # 徒歩
      return $game_map.passable2?(x, y, @x, @y)
    end
  end
end

class Game_Map
  def passable2?(x, y, self_x, self_y, flag = 0x01)
    wall = wall_passable?(x, y, self_x, self_y, flag)   
    for event in events_xy(x, y)            # 座標が一致するイベントを調べる
      next if event.tile_id == 0            # グラフィックがタイルではない
      next if event.priority_type > 0       # [通常キャラの下] ではない
      next if event.through                 # すり抜け状態
      pass = @passages[event.tile_id]       # 通行属性を取得
      next if pass & 0x10 == 0x10           # [☆] : 通行に影響しない
      return true if pass & flag == 0x00 and wall  # [○] : 通行可
      return false if pass & flag == flag   # [×] : 通行不可
    end
    for i in [2, 1, 0]                      # レイヤーの上から順に調べる
      tile_id = @map.data[x, y, i]          # タイル ID を取得
      return false if tile_id == nil        # タイル ID 取得失敗 : 通行不可
      pass = @passages[tile_id]
      next if pass & 0x10 == 0x10       # [☆] : 通行に影響しない
      pass = 0x00 if pass & 0x20 == 0x20
      return true if pass & flag == 0x00 and wall # [○] : 通行可
      return false if pass & flag == flag   # [×] : 通行不可
    end
    return false                            # 通行不可
  end
 
  def wall_passable?(x, y, self_x, self_y, flag = 0x01)
    return false if @map.data[x, y, 0] == nil
    pass = @passages[@map.data[x, y, 0]]         # 通行属性を取得
    self_pass = @passages[@map.data[self_x, self_y, 0]]
    if flag == 0x01
      if self_pass & 0x20 == 0x20
        if x > self_x #右を向いている
          return false if self_pass & 0x04 == 0x04
        elsif x < self_x #左を向いている
          return false if self_pass & 0x01 == 0x01
        elsif y > self_y #下を向いている
          return false if self_pass & 0x08 == 0x08
        elsif y < self_y #上を向いている
          return false if self_pass & 0x02 == 0x02
        end
      end
      if pass & 0x20 == 0x20 #★ 壁通路
        if x > self_x #右を向いている
          return false if pass & 0x01 == 0x01
        elsif x < self_x #左を向いている
          return false if pass & 0x04 == 0x04
        elsif y > self_y #下を向いている
          return false if pass & 0x02 == 0x02
        elsif y < self_y #上を向いている
          return false if pass & 0x08 == 0x08
        end
      end 
    end
    return true 
  end
end


これで、水平壁の上にレイヤーを敷いてもちゃんと機能するようになったと思います。
でも、このままだとプレイヤーの隣にいるイベントが、決定ボタンを押した場合や、
接したときにコマンドが起動するように設定してる場合、水平壁の端をまたいで
いたとしても、起動してしまいます。
この状況は避けたい場合は、以下のスクリプトもコピーしておいてください。
多少重くなるかも知れませんが(´・ω・`)

class Game_Player
  def check_event_trigger_there(triggers)
    return false if $game_map.interpreter.running?
    result = false
    front_x = $game_map.x_with_direction(@x, @direction)
    front_y = $game_map.y_with_direction(@y, @direction)
    if $game_map.passable2?(@x, @y, front_x, front_y) #★
      for event in $game_map.events_xy(front_x, front_y)
        if triggers.include?(event.trigger) and event.priority_type == 1
          event.start
          result = true
        end
      end
    end #★
    if result == false and $game_map.counter?(front_x, front_y)
      front_x = $game_map.x_with_direction(front_x, @direction)
      front_y = $game_map.y_with_direction(front_y, @direction)
      for event in $game_map.events_xy(front_x, front_y)
        if triggers.include?(event.trigger) and event.priority_type == 1
          event.start
          result = true
        end
      end
    end
    return result
  end
end

class Game_Character
  #--------------------------------------------------------------------------
  # ● 下に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  def move_down(turn_ok = true)
    if passable?(@x, @y+1)                  # 通行可能
      turn_down
      @y = $game_map.round_y(@y+1)
      @real_y = (@y-1)*256
      increase_steps
      @move_failed = false
    else                                    # 通行不可能
      turn_down if turn_ok
      if $game_map.passable2?(@x, @y+1, @x, @y) #★
        check_event_trigger_touch(@x, @y+1)   # 接触イベントの起動判定
      end #★
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # ● 左に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  def move_left(turn_ok = true)
    if passable?(@x-1, @y)                  # 通行可能
      turn_left
      @x = $game_map.round_x(@x-1)
      @real_x = (@x+1)*256
      increase_steps
      @move_failed = false
    else                                    # 通行不可能
      turn_left if turn_ok
      if $game_map.passable2?(@x-1, @y, @x, @y) #★
        check_event_trigger_touch(@x-1, @y)   # 接触イベントの起動判定
      end #★
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # ● 右に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  def move_right(turn_ok = true)
    if passable?(@x+1, @y)                  # 通行可能
      turn_right
      @x = $game_map.round_x(@x+1)
      @real_x = (@x-1)*256
      increase_steps
      @move_failed = false
    else                                    # 通行不可能
      turn_right if turn_ok
      if $game_map.passable2?(@x+1, @y, @x, @y) #★
        check_event_trigger_touch(@x+1, @y)   # 接触イベントの起動判定
      end #★
      @move_failed = true
    end
  end
  #--------------------------------------------------------------------------
  # ● 上に移動
  #     turn_ok : その場での向き変更を許可
  #--------------------------------------------------------------------------
  def move_up(turn_ok = true)
    if passable?(@x, @y-1)                  # 通行可能
      turn_up
      @y = $game_map.round_y(@y-1)
      @real_y = (@y+1)*256
      increase_steps
      @move_failed = false
    else                                    # 通行不可能
      turn_up if turn_ok
      if $game_map.passable2?(@x, @y-1, @x, @y) #★
        check_event_trigger_touch(@x, @y-1)   # 接触イベントの起動判定
      end #★
      @move_failed = true
    end
  end
end



これで問題はなくなったと思います。
もしまだ あったらすみません。(´・ω・`)

今日はもうひとつ、水平壁のマップの作り方を紹介します。
壁のタイルをマップ上に敷こうとすると、オートマップ機能で、
うまく設置できない場合があります。こういう場合は、Shiftキーをおしながら、
操作するとうまくいきます。
壁に階段やはしごを設置する場合、水平壁の端の部分は、
あらかじめ、ダミーを作っておき、それをShiftを押したままコピーし貼り付けます。
示した図のように矢印の方にコピーすればうまくいきます。
080112_01.jpg


まだ、あまりテストしてませんが、もしまだ不具合がありましたら
コメントのほうによろしくお願いいたします。
でわ( ^ω^)ノシ

テーマ : RPGツクール
ジャンル : ゲーム

プロフィール

Suppon

Author:Suppon
すっぽんでーす。(^▽^)
カルドラ鋭意制作中( ・`ω・´)
Twitter => suppon01
メールはこちらへ
suppon2008@gmail.com

Twitter...

Twitter Reload

最近のコメント
最近のトラックバック
月別アーカイブ
カテゴリー
ブログ内検索
RSSフィード
リンク
ブロとも申請フォーム

この人とブロともになる