mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-07 13:15:01 +00:00
Anim Editor: added basic particle spawner functionality and graphic frame randomiser
This commit is contained in:
@@ -34,6 +34,11 @@ class UIControls::BaseControl < BitmapSprite
|
|||||||
return self.bitmap.height
|
return self.bitmap.height
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def visible=(value)
|
||||||
|
super
|
||||||
|
@captured_area = nil if !self.visible
|
||||||
|
end
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
def mouse_pos
|
def mouse_pos
|
||||||
@@ -83,7 +88,7 @@ class UIControls::BaseControl < BitmapSprite
|
|||||||
end
|
end
|
||||||
|
|
||||||
def busy?
|
def busy?
|
||||||
return !@captured_area.nil?
|
return self.visible && !@captured_area.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def changed?
|
def changed?
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ module GameData
|
|||||||
"EaseOut" => :ease_out
|
"EaseOut" => :ease_out
|
||||||
}
|
}
|
||||||
USER_AND_TARGET_SEPARATION = [200, -200, -100] # x, y, z (from user to target)
|
USER_AND_TARGET_SEPARATION = [200, -200, -100] # x, y, z (from user to target)
|
||||||
|
SPAWNER_TYPES = {
|
||||||
|
"None" => :none,
|
||||||
|
"RandomDirection" => :random_direction,
|
||||||
|
"RandomDirectionGravity" => :random_direction_gravity
|
||||||
|
}
|
||||||
|
|
||||||
# Properties that apply to the animation in general, not to individual
|
# Properties that apply to the animation in general, not to individual
|
||||||
# particles. They don't change during the animation.
|
# particles. They don't change during the animation.
|
||||||
@@ -62,62 +67,69 @@ module GameData
|
|||||||
# These properties cannot be changed partway through the animation.
|
# These properties cannot be changed partway through the animation.
|
||||||
# NOTE: "Name" isn't a property here, because the particle's name comes
|
# NOTE: "Name" isn't a property here, because the particle's name comes
|
||||||
# from the "Particle" property above.
|
# from the "Particle" property above.
|
||||||
"Graphic" => [:graphic, "s"],
|
"Graphic" => [:graphic, "s"],
|
||||||
"Focus" => [:focus, "e", FOCUS_TYPES],
|
"Focus" => [:focus, "e", FOCUS_TYPES],
|
||||||
"FoeInvertX" => [:foe_invert_x, "b"],
|
"FoeInvertX" => [:foe_invert_x, "b"],
|
||||||
"FoeInvertY" => [:foe_invert_y, "b"],
|
"FoeInvertY" => [:foe_invert_y, "b"],
|
||||||
"FoeFlip" => [:foe_flip, "b"],
|
"FoeFlip" => [:foe_flip, "b"],
|
||||||
|
"Spawner" => [:spawner, "e", SPAWNER_TYPES],
|
||||||
|
"SpawnQuantity" => [:spawn_quantity, "v"],
|
||||||
|
"RandomFrameMax" => [:random_frame_max, "u"],
|
||||||
# All properties below are "SetXYZ" or "MoveXYZ". "SetXYZ" has the
|
# All properties below are "SetXYZ" or "MoveXYZ". "SetXYZ" has the
|
||||||
# keyframe and the value, and "MoveXYZ" has the keyframe, duration and the
|
# keyframe and the value, and "MoveXYZ" has the keyframe, duration and the
|
||||||
# value. All have "^" in their schema. "SetXYZ" is turned into "MoveXYZ"
|
# value. All have "^" in their schema. "SetXYZ" is turned into "MoveXYZ"
|
||||||
# when compiling by inserting a duration (second value) of 0.
|
# when compiling by inserting a duration (second value) of 0.
|
||||||
"SetFrame" => [:frame, "^uu"], # Frame within the graphic if it's a spritesheet
|
"SetFrame" => [:frame, "^uu"], # Frame within the graphic if it's a spritesheet
|
||||||
"MoveFrame" => [:frame, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveFrame" => [:frame, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetBlending" => [:blending, "^uu"], # 0, 1 or 2
|
"SetBlending" => [:blending, "^uu"], # 0, 1 or 2
|
||||||
"SetFlip" => [:flip, "^ub"],
|
"SetFlip" => [:flip, "^ub"],
|
||||||
"SetX" => [:x, "^ui"],
|
"SetX" => [:x, "^ui"],
|
||||||
"MoveX" => [:x, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveX" => [:x, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetY" => [:y, "^ui"],
|
"SetY" => [:y, "^ui"],
|
||||||
"MoveY" => [:y, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveY" => [:y, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetZ" => [:z, "^ui"],
|
"SetZ" => [:z, "^ui"],
|
||||||
"MoveZ" => [:z, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveZ" => [:z, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetZoomX" => [:zoom_x, "^uu"],
|
"SetZoomX" => [:zoom_x, "^uu"],
|
||||||
"MoveZoomX" => [:zoom_x, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveZoomX" => [:zoom_x, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetZoomY" => [:zoom_y, "^uu"],
|
"SetZoomY" => [:zoom_y, "^uu"],
|
||||||
"MoveZoomY" => [:zoom_y, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveZoomY" => [:zoom_y, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetAngle" => [:angle, "^ui"],
|
"SetAngle" => [:angle, "^ui"],
|
||||||
"MoveAngle" => [:angle, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveAngle" => [:angle, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetVisible" => [:visible, "^ub"],
|
"SetVisible" => [:visible, "^ub"],
|
||||||
"SetOpacity" => [:opacity, "^uu"],
|
"SetOpacity" => [:opacity, "^uu"],
|
||||||
"MoveOpacity" => [:opacity, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveOpacity" => [:opacity, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetColorRed" => [:color_red, "^ui"],
|
"SetColorRed" => [:color_red, "^ui"],
|
||||||
"MoveColorRed" => [:color_red, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveColorRed" => [:color_red, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetColorGreen" => [:color_green, "^ui"],
|
"SetColorGreen" => [:color_green, "^ui"],
|
||||||
"MoveColorGreen" => [:color_green, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveColorGreen" => [:color_green, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetColorBlue" => [:color_blue, "^ui"],
|
"SetColorBlue" => [:color_blue, "^ui"],
|
||||||
"MoveColorBlue" => [:color_blue, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveColorBlue" => [:color_blue, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetColorAlpha" => [:color_alpha, "^ui"],
|
"SetColorAlpha" => [:color_alpha, "^ui"],
|
||||||
"MoveColorAlpha" => [:color_alpha, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveColorAlpha" => [:color_alpha, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetToneRed" => [:tone_red, "^ui"],
|
"SetToneRed" => [:tone_red, "^ui"],
|
||||||
"MoveToneRed" => [:tone_red, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveToneRed" => [:tone_red, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetToneGreen" => [:tone_green, "^ui"],
|
"SetToneGreen" => [:tone_green, "^ui"],
|
||||||
"MoveToneGreen" => [:tone_green, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveToneGreen" => [:tone_green, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetToneBlue" => [:tone_blue, "^ui"],
|
"SetToneBlue" => [:tone_blue, "^ui"],
|
||||||
"MoveToneBlue" => [:tone_blue, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveToneBlue" => [:tone_blue, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
"SetToneGray" => [:tone_gray, "^ui"],
|
"SetToneGray" => [:tone_gray, "^ui"],
|
||||||
"MoveToneGray" => [:tone_gray, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
"MoveToneGray" => [:tone_gray, "^uuiE", nil, nil, nil, INTERPOLATION_TYPES],
|
||||||
# These properties are specifically for the "SE" particle.
|
# These properties are specifically for the "SE" particle.
|
||||||
"Play" => [:se, "^usUU"], # Filename, volume, pitch
|
"Play" => [:se, "^usUU"], # Filename, volume, pitch
|
||||||
"PlayUserCry" => [:user_cry, "^uUU"], # Volume, pitch
|
"PlayUserCry" => [:user_cry, "^uUU"], # Volume, pitch
|
||||||
"PlayTargetCry" => [:target_cry, "^uUU"] # Volume, pitch
|
"PlayTargetCry" => [:target_cry, "^uUU"] # Volume, pitch
|
||||||
}
|
}
|
||||||
PARTICLE_DEFAULT_VALUES = {
|
PARTICLE_DEFAULT_VALUES = {
|
||||||
:name => "",
|
:name => "",
|
||||||
:graphic => "",
|
:graphic => "",
|
||||||
:focus => :foreground,
|
:focus => :foreground,
|
||||||
:foe_invert_x => false,
|
:foe_invert_x => false,
|
||||||
:foe_invert_y => false,
|
:foe_invert_y => false,
|
||||||
:foe_flip => false
|
:foe_flip => false,
|
||||||
|
:spawner => :none,
|
||||||
|
:spawn_quantity => 1,
|
||||||
|
:random_frame_max => 0
|
||||||
|
|
||||||
}
|
}
|
||||||
# NOTE: Particles are invisible until their first command, and automatically
|
# NOTE: Particles are invisible until their first command, and automatically
|
||||||
# become visible then. "User" and "Target" are visible from the start,
|
# become visible then. "User" and "Target" are visible from the start,
|
||||||
@@ -315,6 +327,13 @@ module GameData
|
|||||||
# The User and Target particles have hardcoded graphics/foci, so they
|
# The User and Target particles have hardcoded graphics/foci, so they
|
||||||
# don't need writing to PBS
|
# don't need writing to PBS
|
||||||
ret = nil if ["User", "Target"].include?(@particles[index][:name])
|
ret = nil if ["User", "Target"].include?(@particles[index][:name])
|
||||||
|
when "Spawner"
|
||||||
|
ret = nil if ret == :none
|
||||||
|
when "SpawnQuantity"
|
||||||
|
ret = nil if @particles[index][:spawner].nil? || @particles[index][:spawner] == :none
|
||||||
|
ret = nil if ret && ret <= 1
|
||||||
|
when "RandomFrameMax"
|
||||||
|
ret = nil if ret == 0
|
||||||
when "AllCommands"
|
when "AllCommands"
|
||||||
# Get translations of all properties to their names as seen in PBS
|
# Get translations of all properties to their names as seen in PBS
|
||||||
# animation files
|
# animation files
|
||||||
|
|||||||
@@ -524,6 +524,37 @@ AnimationEditor::SidePanes.add_property(:particle_pane, :focus, {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
AnimationEditor::SidePanes.add_property(:particle_pane, :random_frame_max, {
|
||||||
|
:new => proc { |pane, editor|
|
||||||
|
pane.add_labelled_number_text_box(:random_frame_max, _INTL("Rand. frame"), 0, 99, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
AnimationEditor::SidePanes.add_property(:particle_pane, :spawner, {
|
||||||
|
:new => proc { |pane, editor|
|
||||||
|
values = {
|
||||||
|
:none => _INTL("None"),
|
||||||
|
:random_direction => _INTL("Random direction"),
|
||||||
|
:random_direction_gravity => _INTL("Random direction gravity")
|
||||||
|
}
|
||||||
|
pane.add_labelled_dropdown_list(:spawner, _INTL("Spawner"), values, :none)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
AnimationEditor::SidePanes.add_property(:particle_pane, :spawn_quantity, {
|
||||||
|
:new => proc { |pane, editor|
|
||||||
|
pane.add_labelled_number_text_box(:spawn_quantity, _INTL("Spawn qty"), 1, 99, 1)
|
||||||
|
},
|
||||||
|
:refresh_value => proc { |control, editor|
|
||||||
|
spawner = editor.anim[:particles][editor.particle_index][:spawner]
|
||||||
|
if !spawner || spawner == :none
|
||||||
|
control.disable
|
||||||
|
else
|
||||||
|
control.enable
|
||||||
|
end
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
AnimationEditor::SidePanes.add_property(:particle_pane, :opposing_label, {
|
AnimationEditor::SidePanes.add_property(:particle_pane, :opposing_label, {
|
||||||
:new => proc { |pane, editor|
|
:new => proc { |pane, editor|
|
||||||
pane.add_label(:opposing_label, _INTL("If on opposing side..."))
|
pane.add_label(:opposing_label, _INTL("If on opposing side..."))
|
||||||
|
|||||||
@@ -148,6 +148,14 @@ class AnimationEditor::Canvas < Sprite
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show_particle_sprite?(index)
|
||||||
|
return false if index < 0 || index >= @anim[:particles].length
|
||||||
|
particle = @anim[:particles][index]
|
||||||
|
return false if !particle || particle[:name] == "SE"
|
||||||
|
return false if particle[:spawner] && particle[:spawner] != :none
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
def selected_particle=(val)
|
def selected_particle=(val)
|
||||||
return if @selected_particle == val
|
return if @selected_particle == val
|
||||||
@selected_particle = val
|
@selected_particle = val
|
||||||
@@ -411,12 +419,11 @@ class AnimationEditor::Canvas < Sprite
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get_sprite_and_frame(index, target_idx = -1)
|
def get_sprite_and_frame(index, target_idx = -1)
|
||||||
|
return if !show_particle_sprite?(index)
|
||||||
spr = nil
|
spr = nil
|
||||||
frame = nil
|
frame = nil
|
||||||
particle = @anim[:particles][index]
|
particle = @anim[:particles][index]
|
||||||
case particle[:name]
|
case particle[:name]
|
||||||
when "SE"
|
|
||||||
return
|
|
||||||
when "User"
|
when "User"
|
||||||
spr = @battler_sprites[user_index]
|
spr = @battler_sprites[user_index]
|
||||||
raise _INTL("Sprite for particle {1} not found somehow (battler index {2}).",
|
raise _INTL("Sprite for particle {1} not found somehow (battler index {2}).",
|
||||||
@@ -442,7 +449,7 @@ class AnimationEditor::Canvas < Sprite
|
|||||||
|
|
||||||
def refresh_sprite(index, target_idx = -1)
|
def refresh_sprite(index, target_idx = -1)
|
||||||
particle = @anim[:particles][index]
|
particle = @anim[:particles][index]
|
||||||
return if !particle || particle[:name] == "SE"
|
return if !show_particle_sprite?(index)
|
||||||
relative_to_index = -1
|
relative_to_index = -1
|
||||||
if particle[:focus] != :user_and_target
|
if particle[:focus] != :user_and_target
|
||||||
if GameData::Animation::FOCUS_TYPES_WITH_USER.include?(particle[:focus])
|
if GameData::Animation::FOCUS_TYPES_WITH_USER.include?(particle[:focus])
|
||||||
@@ -519,8 +526,7 @@ class AnimationEditor::Canvas < Sprite
|
|||||||
end
|
end
|
||||||
|
|
||||||
def refresh_particle_frame
|
def refresh_particle_frame
|
||||||
return if @selected_particle < 0 || @selected_particle >= @anim[:particles].length ||
|
return if !show_particle_sprite?(@selected_particle)
|
||||||
@anim[:particles][@selected_particle][:name] == "SE"
|
|
||||||
focus = @anim[:particles][@selected_particle][:focus]
|
focus = @anim[:particles][@selected_particle][:focus]
|
||||||
frame_color = AnimationEditor::ParticleList::CONTROL_BG_COLORS[focus] || Color.magenta
|
frame_color = AnimationEditor::ParticleList::CONTROL_BG_COLORS[focus] || Color.magenta
|
||||||
@sel_frame_bitmap.outline_rect(1, 1, @sel_frame_bitmap.width - 2, @sel_frame_bitmap.height - 2, frame_color)
|
@sel_frame_bitmap.outline_rect(1, 1, @sel_frame_bitmap.width - 2, @sel_frame_bitmap.height - 2, frame_color)
|
||||||
@@ -552,7 +558,7 @@ class AnimationEditor::Canvas < Sprite
|
|||||||
if GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus])
|
if GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus])
|
||||||
refresh_particle(i) # Because there can be multiple targets
|
refresh_particle(i) # Because there can be multiple targets
|
||||||
else
|
else
|
||||||
refresh_sprite(i) if particle[:name] != "SE"
|
refresh_sprite(i) if show_particle_sprite?(i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
refresh_particle_frame # Intentionally after refreshing particles
|
refresh_particle_frame # Intentionally after refreshing particles
|
||||||
@@ -708,8 +714,7 @@ class AnimationEditor::Canvas < Sprite
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_selected_particle_frame
|
def update_selected_particle_frame
|
||||||
if @selected_particle < 0 || @selected_particle >= @anim[:particles].length ||
|
if !show_particle_sprite?(@selected_particle)
|
||||||
@anim[:particles][@selected_particle][:name] == "SE"
|
|
||||||
@sel_frame_sprite.visible = false
|
@sel_frame_sprite.visible = false
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class AnimationPlayer
|
|||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
def set_up_particle(particle, target_idx = -1)
|
def set_up_particle(particle, target_idx = -1, instance = 0)
|
||||||
particle_sprite = AnimationPlayer::ParticleSprite.new
|
particle_sprite = AnimationPlayer::ParticleSprite.new
|
||||||
# Get/create a sprite
|
# Get/create a sprite
|
||||||
sprite = nil
|
sprite = nil
|
||||||
@@ -127,23 +127,25 @@ class AnimationPlayer
|
|||||||
particle_sprite.foe_flip = particle[:foe_flip]
|
particle_sprite.foe_flip = particle[:foe_flip]
|
||||||
end
|
end
|
||||||
# Find earliest command and add a "make visible" command then
|
# Find earliest command and add a "make visible" command then
|
||||||
|
delay = AnimationPlayer::Helper.get_particle_delay(particle, instance)
|
||||||
if sprite && !particle_sprite.battler_sprite?
|
if sprite && !particle_sprite.battler_sprite?
|
||||||
first_cmd = -1
|
first_cmd = AnimationPlayer::Helper.get_first_command_frame(particle)
|
||||||
particle.each_pair do |property, cmds|
|
particle_sprite.add_set_process(:visible, (first_cmd + delay) * slowdown, true) if first_cmd >= 0
|
||||||
next if !cmds.is_a?(Array) || cmds.empty?
|
# Apply random frame
|
||||||
cmds.each do |cmd|
|
if particle[:random_frame_max] && particle[:random_frame_max] > 0
|
||||||
first_cmd = cmd[0] if first_cmd < 0 || first_cmd > cmd[0]
|
particle_sprite.add_set_process(:frame, (first_cmd + delay) * slowdown, rand(particle[:random_frame_max] + 1))
|
||||||
end
|
|
||||||
end
|
end
|
||||||
particle_sprite.add_set_process(:visible, first_cmd * slowdown, true) if first_cmd >= 0
|
|
||||||
end
|
end
|
||||||
# Add all commands
|
# Add all commands
|
||||||
|
spawner_type = particle[:spawner] || :none
|
||||||
|
regular_properties_skipped = AnimationPlayer::Helper::PROPERTIES_SET_BY_SPAWNER[spawner_type] || []
|
||||||
particle.each_pair do |property, cmds|
|
particle.each_pair do |property, cmds|
|
||||||
next if !cmds.is_a?(Array) || cmds.empty?
|
next if !cmds.is_a?(Array) || cmds.empty?
|
||||||
|
next if regular_properties_skipped.include?(property)
|
||||||
cmds.each do |cmd|
|
cmds.each do |cmd|
|
||||||
if cmd[1] == 0
|
if cmd[1] == 0
|
||||||
if sprite
|
if sprite
|
||||||
particle_sprite.add_set_process(property, cmd[0] * slowdown, cmd[2])
|
particle_sprite.add_set_process(property, (cmd[0] + delay) * slowdown, cmd[2])
|
||||||
else
|
else
|
||||||
# SE particle
|
# SE particle
|
||||||
filename = nil
|
filename = nil
|
||||||
@@ -159,31 +161,77 @@ class AnimationPlayer
|
|||||||
else
|
else
|
||||||
filename = "Anim/" + cmd[2]
|
filename = "Anim/" + cmd[2]
|
||||||
end
|
end
|
||||||
particle_sprite.add_set_process(property, cmd[0] * slowdown, [filename, cmd[3], cmd[4]]) if filename
|
particle_sprite.add_set_process(property, (cmd[0] + delay) * slowdown, [filename, cmd[3], cmd[4]]) if filename
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
particle_sprite.add_move_process(property, cmd[0] * slowdown, cmd[1] * slowdown, cmd[2], cmd[3] || :linear)
|
particle_sprite.add_move_process(property, (cmd[0] + delay) * slowdown, cmd[1] * slowdown, cmd[2], cmd[3] || :linear)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
# Add spawner commands
|
||||||
|
add_spawner_commands(particle_sprite, particle, instance, delay)
|
||||||
# Finish up
|
# Finish up
|
||||||
@anim_sprites.push(particle_sprite)
|
@anim_sprites.push(particle_sprite)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_spawner_commands(particle_sprite, particle, instance, delay)
|
||||||
|
life_start = AnimationPlayer::Helper.get_first_command_frame(particle)
|
||||||
|
life_end = AnimationPlayer::Helper.get_last_command_frame(particle)
|
||||||
|
life_end = AnimationPlayer::Helper.get_duration(particles) if life_end < 0
|
||||||
|
lifetime = life_end - life_start
|
||||||
|
spawner_type = particle[:spawner] || :none
|
||||||
|
case spawner_type
|
||||||
|
when :random_direction, :random_direction_gravity
|
||||||
|
angle = rand(360)
|
||||||
|
angle = rand(360) if angle >= 180 && spawner_type == :random_direction_gravity # Prefer upwards angles
|
||||||
|
speed = rand(150, 250)
|
||||||
|
start_x_speed = speed * Math.cos(angle * Math::PI / 180)
|
||||||
|
start_y_speed = -speed * Math.sin(angle * Math::PI / 180)
|
||||||
|
start_x = (start_x_speed * 0.05) + rand(-8, 8)
|
||||||
|
start_y = (start_y_speed * 0.05) + rand(-8, 8)
|
||||||
|
# Set initial positions
|
||||||
|
[:x, :y].each do |property|
|
||||||
|
offset = (property == :x) ? start_x : start_y
|
||||||
|
particle[property].each do |cmd|
|
||||||
|
next if cmd[1] > 0
|
||||||
|
particle_sprite.add_set_process(property, (cmd[0] + delay) * slowdown, cmd[2] + offset)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Set movements
|
||||||
|
particle_sprite.add_move_process(:x,
|
||||||
|
(life_start + delay) * slowdown, lifetime * slowdown,
|
||||||
|
start_x + (start_x_speed * lifetime / 20.0), :linear)
|
||||||
|
if spawner_type == :random_direction_gravity
|
||||||
|
particle_sprite.add_move_process(:y,
|
||||||
|
(life_start + delay) * slowdown, lifetime * slowdown,
|
||||||
|
[start_y_speed / slowdown, AnimationPlayer::Helper::GRAVITY_STRENGTH.to_f / (slowdown * slowdown)], :gravity)
|
||||||
|
else
|
||||||
|
particle_sprite.add_move_process(:y,
|
||||||
|
(life_start + delay) * slowdown, lifetime * slowdown,
|
||||||
|
start_y + (start_y_speed * lifetime / 20.0), :linear)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Creates sprites and ParticleSprites, and sets sprite properties that won't
|
# Creates sprites and ParticleSprites, and sets sprite properties that won't
|
||||||
# change during the animation.
|
# change during the animation.
|
||||||
def set_up
|
def set_up
|
||||||
particles.each do |particle|
|
particles.each do |particle|
|
||||||
if GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus]) && @targets
|
qty = 1
|
||||||
one_per_side = [:target_side_foreground, :target_side_background].include?(particle[:focus])
|
qty = particle[:spawn_quantity] || 1 if particle[:spawner] && particle[:spawner] != :none
|
||||||
sides_covered = []
|
qty.times do |i|
|
||||||
@targets.each do |target|
|
if GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus]) && @targets
|
||||||
next if one_per_side && sides_covered.include?(target.index % 2)
|
one_per_side = [:target_side_foreground, :target_side_background].include?(particle[:focus])
|
||||||
set_up_particle(particle, target.index)
|
sides_covered = []
|
||||||
sides_covered.push(target.index % 2)
|
@targets.each do |target|
|
||||||
|
next if one_per_side && sides_covered.include?(target.index % 2)
|
||||||
|
set_up_particle(particle, target.index, i)
|
||||||
|
sides_covered.push(target.index % 2)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
set_up_particle(particle, -1, i)
|
||||||
end
|
end
|
||||||
else
|
|
||||||
set_up_particle(particle)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
reset_anim_sprites
|
reset_anim_sprites
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
# Methods used by both AnimationPlayer and AnimationEditor::Canvas.
|
# Methods used by both AnimationPlayer and AnimationEditor::Canvas.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
module AnimationPlayer::Helper
|
module AnimationPlayer::Helper
|
||||||
|
PROPERTIES_SET_BY_SPAWNER = {
|
||||||
|
:random_direction => [:x, :y],
|
||||||
|
:random_direction_gravity => [:x, :y]
|
||||||
|
}
|
||||||
|
GRAVITY_STRENGTH = 300
|
||||||
BATTLE_MESSAGE_BAR_HEIGHT = 96 # NOTE: You shouldn't need to change this.
|
BATTLE_MESSAGE_BAR_HEIGHT = 96 # NOTE: You shouldn't need to change this.
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
@@ -19,6 +24,39 @@ module AnimationPlayer::Helper
|
|||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the frame that the particle has its earliest command.
|
||||||
|
def get_first_command_frame(particle)
|
||||||
|
ret = -1
|
||||||
|
particle.each_pair do |property, cmds|
|
||||||
|
next if !cmds.is_a?(Array) || cmds.empty?
|
||||||
|
cmds.each do |cmd|
|
||||||
|
ret = cmd[0] if ret < 0 || ret > cmd[0]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return (ret >= 0) ? ret : 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the frame that the particle has (the end of) its latest command.
|
||||||
|
def get_last_command_frame(particle)
|
||||||
|
ret = -1
|
||||||
|
particle.each_pair do |property, cmds|
|
||||||
|
next if !cmds.is_a?(Array) || cmds.empty?
|
||||||
|
cmds.each do |cmd|
|
||||||
|
ret = cmd[0] + cmd[1] if ret < cmd[0] + cmd[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
# For spawner particles
|
||||||
|
def get_particle_delay(particle, instance)
|
||||||
|
case particle[:spawner] || :none
|
||||||
|
when :random_direction, :random_direction_gravity
|
||||||
|
return instance / 4
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
def get_xy_focus(particle, user_index, target_index, user_coords, target_coords)
|
def get_xy_focus(particle, user_index, target_index, user_coords, target_coords)
|
||||||
@@ -200,6 +238,12 @@ module AnimationPlayer::Helper
|
|||||||
ret += (end_val - start_val) * (1 - (((-2 * x) + 2) * ((-2 * x) + 2) / 2))
|
ret += (end_val - start_val) * (1 - (((-2 * x) + 2) * ((-2 * x) + 2) / 2))
|
||||||
end
|
end
|
||||||
return ret.round
|
return ret.round
|
||||||
|
when :gravity # Used by particle spawner
|
||||||
|
# end_val is [initial speed, gravity]
|
||||||
|
# s = ut + 1/2 at^2
|
||||||
|
t = now - start_time
|
||||||
|
ret = start_val + (end_val[0] * t) + (end_val[1] * t * t / 2)
|
||||||
|
return ret.round
|
||||||
end
|
end
|
||||||
raise _INTL("Unknown interpolation method {1}.", interpolation)
|
raise _INTL("Unknown interpolation method {1}.", interpolation)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user