设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 83|回复: 2
打印 上一主题 下一主题

[原创发布] 敌人受击后飙血特效

[复制链接]

Lv3.寻梦者

梦石
1
星屑
370
在线时间
24 小时
注册时间
2023-9-8
帖子
10
跳转到指定楼层
1

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x

#==============================================================================
# ** 敌人受击飙血特效
#------------------------------------------------------------------------------
#  作者:Ruigi
#  版本:1.0
#  功能:敌人受击时显示可定制的血液特效,包括固定和飞溅效果
#==============================================================================

module BloodEffect
  # 血液精灵的Z轴位置(在角色上方,特效下方)
  BLOOD_Z = 298
  
  # 基础持续时间(帧数)
  DURATION = 90
  
  # 血液痕迹持续时间(帧数)
  TRACE_DURATION = 300
  
  # 血液缩放范围 [最小, 最大]
  SCALE_RANGE = [0.2, 0.2]
  
  # 飞溅效果数量
  SPLASH_COUNT = 5
  
  # 痕迹基础透明度
  TRACE_OPACITY = 20
  
  # 血液贴图文件名前缀
  BLOOD_PREFIX = "blood_"
  
  # 从敌人备注获取血液颜色
  def self.blood_color(enemy)
    # 默认红色
    return Color.new(255, 0, 0) unless enemy.note =~ /<血液颜色:\s*(\d+)\s*\.\s*(\d+)\s*\.\s*(\d+)\s*>/i
    Color.new($1.to_i, $2.to_i, $3.to_i)
  end
  
  # 获取随机血液贴图 [bitmap, is_splash]
  def self.random_blood_sprite
    files = Dir.glob("Graphics/System/#{BLOOD_PREFIX}*.png", File::FNM_CASEFOLD)
    return nil if files.empty?
   
    file = files.sample
    is_splash = file.downcase.include?("_splash")
    begin
      filename = File.basename(file)
      bitmap = Cache.system(filename)
      [bitmap, is_splash]
    rescue
      nil
    end
  end
end

#==============================================================================
# ** Sprite_Blood
#------------------------------------------------------------------------------
#  血液特效精灵
#==============================================================================

class Sprite_Blood < Sprite
  attr_accessor :duration, :is_trace
  
  def initialize(viewport, bitmap, is_splash, color)
    super(viewport)
    self.bitmap = bitmap
    self.color = color
    self.blend_type = 0  # 使用加减法混合
    self.z = BloodEffect::BLOOD_Z
   
    # 飞溅效果随机位置和大小
    if is_splash
      self.x = rand(Graphics.width)
      self.y = rand(Graphics.height)
      scale = rand(BloodEffect::SCALE_RANGE[1] - BloodEffect::SCALE_RANGE[0]) + BloodEffect::SCALE_RANGE[0]
      self.zoom_x = scale
      self.zoom_y = scale
      self.angle = rand(200)
      @duration = BloodEffect::DURATION / 1 + rand(BloodEffect::DURATION / 1)
    else
      # 固定效果
      @duration = BloodEffect::DURATION
    end
   
    @is_trace = false
    @fade_start = [@duration - 30, 0].max  # 提前30帧开始淡出
  end
  
  def update
    super
    @duration -= 1
   
    # 淡出逻辑
    if @duration <= 30 && @duration > 0
      self.opacity = (@duration / 30.0) * 255
      # 痕迹保持最低透明度
      self.opacity = BloodEffect::TRACE_OPACITY if @is_trace && self.opacity < BloodEffect::TRACE_OPACITY
    elsif @duration <= 0
      self.opacity = 0
    end
   
    # 转换为痕迹
    if @duration <= 0 && !@is_trace
      @is_trace = true
      @duration = BloodEffect::TRACE_DURATION
      self.opacity = BloodEffect::TRACE_OPACITY
    end
  end
  
  def dispose
    bitmap.dispose if bitmap
    super
  end
end

#==============================================================================
# ** Spriteset_Battle
#------------------------------------------------------------------------------
#  战斗精灵组 - 添加血液特效支持
#==============================================================================

class Spriteset_Battle
  attr_reader :blood_sprites
  
  # 安全别名定义
  alias blood_effect_initialize initialize unless method_defined?(:blood_effect_initialize)
  
  def initialize(*args)
    blood_effect_initialize(*args)
    @blood_sprites = []  # 血液精灵数组
  end
  
  # 敌人精灵访问方法
  def enemy_sprites
    @enemy_sprites || []
  end
  
  alias blood_effect_update update unless method_defined?(:blood_effect_update)
  
  def update
    blood_effect_update
    update_blood_sprites
  end
  
  alias blood_effect_dispose dispose unless method_defined?(:blood_effect_dispose)
  
  def dispose
    dispose_blood_sprites
    blood_effect_dispose
  end
  
  # 添加血液特效
  def add_blood_effect(bitmap, is_splash, color, x = nil, y = nil)
    return unless bitmap && color && @viewport2
    @blood_sprites ||= []  # 双重保障
    sprite = Sprite_Blood.new(@viewport2, bitmap, is_splash, color)
    sprite.x = x if x
    sprite.y = y if y
    @blood_sprites << sprite
  end
  
  # 更新所有血液精灵
  def update_blood_sprites
    return unless @blood_sprites
   
    # 安全删除方式
    to_delete = []
    @blood_sprites.each_with_index do |sprite, index|
      sprite.update
      if sprite.duration <= 0 && sprite.is_trace
        sprite.dispose
        to_delete << index
      end
    end
   
    # 从后往前删除避免索引错乱
    to_delete.sort.reverse.each do |index|
      @blood_sprites.delete_at(index)
    end
  end
  
  # 释放所有血液精灵
  def dispose_blood_sprites
    return unless @blood_sprites
    @blood_sprites.each(&:dispose)
    @blood_sprites.clear
  end
end

#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
#  战斗场景 - 添加受击检测和特效触发
#==============================================================================

class Scene_Battle < Scene_Base
  # 安全别名定义
  alias blood_effect_execute_action execute_action unless method_defined?(:blood_effect_execute_action)
  
  def initialize
    super
    @last_hp = {}  # 用于记录敌人受击前的HP
  end
  
  def execute_action
    # 执行动作前记录敌人HP
    if @subject && @subject.opponents_unit
      @subject.opponents_unit.members.each do |enemy|
        @last_hp[enemy] = enemy.hp
      end
    end
   
    blood_effect_execute_action
    check_blood_effect
  end
  
  # 检查是否需要显示血液特效
  def check_blood_effect
    return unless @subject && @subject.opponents_unit && @subject.current_action
    return unless @spriteset
   
    target = @subject.opponents_unit.members[@subject.current_action.target_index] rescue nil
    return unless target && target.is_a?(Game_Enemy)
   
    last_hp = @last_hp[target] || target.hp
    return unless target.hp < last_hp
   
    blood_color = BloodEffect.blood_color(target.enemy)
    return unless blood_color
   
    # 修正坐标获取方式
    if sprite = @spriteset.enemy_sprites.find { |s| s.battler == target }
      # VX ACE正确的坐标获取方式
      x = sprite.x - sprite.ox + sprite.bitmap.width / 2
      y = sprite.y - sprite.oy + sprite.bitmap.height / 2
      
      # 添加固定血液效果
      if (data = BloodEffect.random_blood_sprite)
        bitmap, is_splash = data
        @spriteset.add_blood_effect(bitmap, false, blood_color, x, y) unless is_splash
      end
      
      # 添加飞溅效果
      BloodEffect::SPLASH_COUNT.times do
        if (data = BloodEffect.random_blood_sprite)
          bitmap, is_splash = data
          @spriteset.add_blood_effect(bitmap, true, blood_color) if is_splash
        end
      end
    end
  end
end

QQ截图20250712215535.png (23.49 KB, 下载次数: 0)

QQ截图20250712215535.png

QQ截图20250712215528.png (326.78 KB, 下载次数: 0)

QQ截图20250712215528.png

QQ截图20250712215535.png (23.49 KB, 下载次数: 0)

QQ截图20250712215535.png

QQ截图20250712215418.png (338.16 KB, 下载次数: 0)

QQ截图20250712215418.png

评分

参与人数 1星屑 +50 +1 收起 理由
寂静的夜里 + 50 + 1 原创奖励

查看全部评分

Lv4.逐梦者

梦石
0
星屑
6809
在线时间
595 小时
注册时间
2017-11-10
帖子
696

极短21参与

2
发表于 昨天 08:33 | 只看该作者
很吊,这个效果感觉更像是玩家飙血
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
1
星屑
370
在线时间
24 小时
注册时间
2023-9-8
帖子
10
3
 楼主| 发表于 1 小时前 | 只看该作者
BCJT 发表于 2025-7-15 08:33
很吊,这个效果感觉更像是玩家飙血

你就当作是敌人一口老血喷玩家脸上就行了)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2025-7-16 15:58

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表