mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
587 lines
14 KiB
Ruby
587 lines
14 KiB
Ruby
# Particle Engine, Peter O., 2007-11-03
|
|
# Based on version 2 by Near Fantastica, 04.01.06
|
|
# In turn based on the Particle Engine designed by PinkMan
|
|
class Particle_Engine
|
|
def initialize(viewport=nil,map=nil)
|
|
@map = (map) ? map : $game_map
|
|
@viewport = viewport
|
|
@effect = []
|
|
@disposed = false
|
|
@firsttime = true
|
|
@effects = {
|
|
# PinkMan's Effects
|
|
"fire" => Particle_Engine::Fire,
|
|
"smoke" => Particle_Engine::Smoke,
|
|
"teleport" => Particle_Engine::Teleport,
|
|
"spirit" => Particle_Engine::Spirit,
|
|
"explosion" => Particle_Engine::Explosion,
|
|
"aura" => Particle_Engine::Aura,
|
|
# BlueScope's Effects
|
|
"soot" => Particle_Engine::Soot,
|
|
"sootsmoke" => Particle_Engine::SootSmoke,
|
|
"rocket" => Particle_Engine::Rocket,
|
|
"fixteleport" => Particle_Engine::FixedTeleport,
|
|
"smokescreen" => Particle_Engine::Smokescreen,
|
|
"flare" => Particle_Engine::Flare,
|
|
"splash" => Particle_Engine::Splash,
|
|
# By Peter O.
|
|
"starteleport" => Particle_Engine::StarTeleport
|
|
}
|
|
end
|
|
|
|
def dispose
|
|
return if disposed?
|
|
for particle in @effect
|
|
next if particle.nil?
|
|
particle.dispose
|
|
end
|
|
@effect.clear
|
|
@map = nil
|
|
@disposed = true
|
|
end
|
|
|
|
def disposed?
|
|
return @disposed
|
|
end
|
|
|
|
def add_effect(event)
|
|
@effect[event.id] = pbParticleEffect(event)
|
|
end
|
|
|
|
def remove_effect(event)
|
|
return if @effect[event.id].nil?
|
|
@effect[event.id].dispose
|
|
@effect.delete_at(event.id)
|
|
end
|
|
|
|
def realloc_effect(event,particle)
|
|
type = pbEventCommentInput(event, 1, "Particle Engine Type")
|
|
if type.nil?
|
|
particle.dispose if particle
|
|
return nil
|
|
end
|
|
type = type[0].downcase
|
|
cls = @effects[type]
|
|
if cls.nil?
|
|
particle.dispose if particle
|
|
return nil
|
|
end
|
|
if !particle || !particle.is_a?(cls)
|
|
particle.dispose if particle
|
|
particle = cls.new(event,@viewport)
|
|
end
|
|
return particle
|
|
end
|
|
|
|
def pbParticleEffect(event)
|
|
return realloc_effect(event,nil)
|
|
end
|
|
|
|
def update
|
|
if @firsttime
|
|
@firsttime = false
|
|
for event in @map.events.values
|
|
remove_effect(event)
|
|
add_effect(event)
|
|
end
|
|
end
|
|
for i in 0...@effect.length
|
|
particle = @effect[i]
|
|
next if particle.nil?
|
|
if particle.event.pe_refresh
|
|
event = particle.event
|
|
event.pe_refresh = false
|
|
particle = realloc_effect(event,particle)
|
|
@effect[i] = particle
|
|
end
|
|
particle.update if particle
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class ParticleEffect
|
|
attr_accessor :x, :y, :z
|
|
|
|
def initialize
|
|
@x = 0
|
|
@y = 0
|
|
@z = 0
|
|
end
|
|
|
|
def update; end
|
|
def dispose; end
|
|
end
|
|
|
|
|
|
|
|
class ParticleSprite
|
|
attr_accessor :x, :y, :z, :ox, :oy, :opacity, :bitmap, :blend_type
|
|
|
|
def initialize(viewport)
|
|
@viewport = viewport
|
|
@sprite = nil
|
|
@x = 0
|
|
@y = 0
|
|
@z = 0
|
|
@ox = 0
|
|
@oy = 0
|
|
@opacity = 255
|
|
@bitmap = nil
|
|
@blend_type = 0
|
|
@minleft = 0
|
|
@mintop = 0
|
|
end
|
|
|
|
def dispose
|
|
@sprite.dispose if @sprite
|
|
end
|
|
|
|
def bitmap=(value)
|
|
@bitmap = value
|
|
if value
|
|
@minleft = -value.width
|
|
@mintop = -value.height
|
|
else
|
|
@minleft = 0
|
|
@mintop = 0
|
|
end
|
|
end
|
|
|
|
def update
|
|
w = Graphics.width
|
|
h = Graphics.height
|
|
if !@sprite && @x>=@minleft && @y>=@mintop && @x<w && @y<h
|
|
@sprite = Sprite.new(@viewport)
|
|
elsif @sprite && (@x<@minleft || @y<@mintop || @x>=w || @y>=h)
|
|
@sprite.dispose
|
|
@sprite = nil
|
|
end
|
|
if @sprite
|
|
@sprite.x = @x if @sprite.x!=@x
|
|
@sprite.x -= @ox
|
|
@sprite.y = @y if @sprite.y!=@y
|
|
@sprite.y -= @oy
|
|
@sprite.z = @z if @sprite.z!=@z
|
|
@sprite.opacity = @opacity if @sprite.opacity!=@opacity
|
|
@sprite.blend_type = @blend_type if @sprite.blend_type!=@blend_type
|
|
@sprite.bitmap = @bitmap if @sprite.bitmap!=@bitmap
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class ParticleEffect_Event < ParticleEffect
|
|
attr_accessor :event
|
|
|
|
def initialize(event,viewport=nil)
|
|
@event = event
|
|
@viewport = viewport
|
|
@particles = []
|
|
@bitmaps = {}
|
|
end
|
|
|
|
def setParameters(params)
|
|
@randomhue,@leftright,@fade,
|
|
@maxparticless,@hue,@slowdown,
|
|
@ytop,@ybottom,@xleft,@xright,
|
|
@xgravity,@ygravity,@xoffset,@yoffset,
|
|
@opacityvar,@originalopacity = params
|
|
end
|
|
|
|
def loadBitmap(filename,hue)
|
|
key = [filename,hue]
|
|
bitmap = @bitmaps[key]
|
|
if !bitmap || bitmap.disposed?
|
|
bitmap = AnimatedBitmap.new("Graphics/Fogs/"+filename,hue).deanimate
|
|
@bitmaps[key] = bitmap
|
|
end
|
|
return bitmap
|
|
end
|
|
|
|
def initParticles(filename,opacity,zOffset=0,blendtype=1)
|
|
@particles = []
|
|
@particlex = []
|
|
@particley = []
|
|
@opacity = []
|
|
@startingx = self.x + @xoffset
|
|
@startingy = self.y + @yoffset
|
|
@screen_x = self.x
|
|
@screen_y = self.y
|
|
@real_x = @event.real_x
|
|
@real_y = @event.real_y
|
|
@filename = filename
|
|
@zoffset = zOffset
|
|
@bmwidth = 32
|
|
@bmheight = 32
|
|
for i in 0...@maxparticless
|
|
@particlex[i] = -@xoffset
|
|
@particley[i] = -@yoffset
|
|
@particles[i] = ParticleSprite.new(@viewport)
|
|
@particles[i].bitmap = loadBitmap(filename, @hue) if filename
|
|
if i==0 && @particles[i].bitmap
|
|
@bmwidth = @particles[i].bitmap.width
|
|
@bmheight = @particles[i].bitmap.height
|
|
end
|
|
@particles[i].blend_type = blendtype
|
|
@particles[i].y = @startingy
|
|
@particles[i].x = @startingx
|
|
@particles[i].z = self.z+zOffset
|
|
@opacity[i] = rand(opacity/4)
|
|
@particles[i].opacity = @opacity[i]
|
|
@particles[i].update
|
|
end
|
|
end
|
|
|
|
def x; return ScreenPosHelper.pbScreenX(@event); end
|
|
def y; return ScreenPosHelper.pbScreenY(@event); end
|
|
def z; return ScreenPosHelper.pbScreenZ(@event); end
|
|
|
|
def update
|
|
if @viewport &&
|
|
(@viewport.rect.x >= Graphics.width ||
|
|
@viewport.rect.y >= Graphics.height)
|
|
return
|
|
end
|
|
selfX = self.x
|
|
selfY = self.y
|
|
selfZ = self.z
|
|
newRealX = @event.real_x
|
|
newRealY = @event.real_y
|
|
@startingx = selfX + @xoffset
|
|
@startingy = selfY + @yoffset
|
|
@__offsetx = (@real_x==newRealX) ? 0 : selfX-@screen_x
|
|
@__offsety = (@real_y==newRealY) ? 0 : selfY-@screen_y
|
|
@screen_x = selfX
|
|
@screen_y = selfY
|
|
@real_x = newRealX
|
|
@real_y = newRealY
|
|
if @opacityvar>0 && @viewport
|
|
opac = 255.0/@opacityvar
|
|
minX = opac*(-@xgravity*1.0 / @slowdown).floor + @startingx
|
|
maxX = opac*(@xgravity*1.0 / @slowdown).floor + @startingx
|
|
minY = opac*(-@ygravity*1.0 / @slowdown).floor + @startingy
|
|
maxY = @startingy
|
|
minX -= @bmwidth
|
|
minY -= @bmheight
|
|
maxX += @bmwidth
|
|
maxY += @bmheight
|
|
if maxX<0 || maxY<0 || minX>=Graphics.width || minY>=Graphics.height
|
|
# echo "skipped"
|
|
return
|
|
end
|
|
end
|
|
particleZ = selfZ+@zoffset
|
|
for i in 0...@maxparticless
|
|
@particles[i].z = particleZ
|
|
if @particles[i].y <= @ytop
|
|
@particles[i].y = @startingy + @yoffset
|
|
@particles[i].x = @startingx + @xoffset
|
|
@particlex[i] = 0.0
|
|
@particley[i] = 0.0
|
|
end
|
|
if @particles[i].x <= @xleft
|
|
@particles[i].y = @startingy + @yoffset
|
|
@particles[i].x = @startingx + @xoffset
|
|
@particlex[i] = 0.0
|
|
@particley[i] = 0.0
|
|
end
|
|
if @particles[i].y >= @ybottom
|
|
@particles[i].y = @startingy + @yoffset
|
|
@particles[i].x = @startingx + @xoffset
|
|
@particlex[i] = 0.0
|
|
@particley[i] = 0.0
|
|
end
|
|
if @particles[i].x >= @xright
|
|
@particles[i].y = @startingy + @yoffset
|
|
@particles[i].x = @startingx + @xoffset
|
|
@particlex[i] = 0.0
|
|
@particley[i] = 0.0
|
|
end
|
|
if @fade == 0
|
|
if @opacity[i] <= 0
|
|
@opacity[i] = @originalopacity
|
|
@particles[i].y = @startingy + @yoffset
|
|
@particles[i].x = @startingx + @xoffset
|
|
@particlex[i] = 0.0
|
|
@particley[i] = 0.0
|
|
end
|
|
else
|
|
if @opacity[i] <= 0
|
|
@opacity[i] = 250
|
|
@particles[i].y = @startingy + @yoffset
|
|
@particles[i].x = @startingx + @xoffset
|
|
@particlex[i] = 0.0
|
|
@particley[i] = 0.0
|
|
end
|
|
end
|
|
calcParticlePos(i)
|
|
if @randomhue == 1
|
|
@hue += 0.5
|
|
@hue = 0 if @hue >= 360
|
|
@particles[i].bitmap = loadBitmap(@filename, @hue) if @filename
|
|
end
|
|
@opacity[i] = @opacity[i] - rand(@opacityvar)
|
|
@particles[i].opacity = @opacity[i]
|
|
@particles[i].update
|
|
end
|
|
end
|
|
|
|
def calcParticlePos(i)
|
|
@leftright = rand(2)
|
|
if @leftright == 1
|
|
xo = -@xgravity*1.0 / @slowdown
|
|
else
|
|
xo = @xgravity*1.0 / @slowdown
|
|
end
|
|
yo = -@ygravity*1.0 / @slowdown
|
|
@particlex[i] += xo
|
|
@particley[i] += yo
|
|
@particlex[i] -= @__offsetx
|
|
@particley[i] -= @__offsety
|
|
@particlex[i] = @particlex[i].floor
|
|
@particley[i] = @particley[i].floor
|
|
@particles[i].x = @particlex[i]+@startingx+@xoffset
|
|
@particles[i].y = @particley[i]+@startingy+@yoffset
|
|
end
|
|
|
|
def dispose
|
|
for particle in @particles
|
|
particle.dispose
|
|
end
|
|
for bitmap in @bitmaps.values
|
|
bitmap.dispose
|
|
end
|
|
@particles.clear
|
|
@bitmaps.clear
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Fire < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,1,20,40,0.5,-64,
|
|
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-13,30,0])
|
|
initParticles("particle",250)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Smoke < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,0,80,20,0.5,-64,
|
|
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-15,5,80])
|
|
initParticles("smoke",250)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Teleport < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([1,1,1,10,rand(360),1,-64,
|
|
Graphics.height,-64,Graphics.width,0,3,-8,-15,20,0])
|
|
initParticles("wideportal",250)
|
|
for i in 0...@maxparticless
|
|
@particles[i].ox = 16
|
|
@particles[i].oy = 16
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Spirit < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([1,0,1,20,rand(360),0.5,-64,
|
|
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-13,30,0])
|
|
initParticles("particle",250)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Explosion < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,1,20,0,0.5,-64,
|
|
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-13,30,0])
|
|
initParticles("explosion",250)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Aura < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,1,20,0,1,-64,
|
|
Graphics.height,-64,Graphics.width,2,2,-5,-13,30,0])
|
|
initParticles("particle",250)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Soot < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,0,20,0,0.5,-64,
|
|
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-15,5,80])
|
|
initParticles("smoke",100,0,2)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::SootSmoke < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,0,30,0,0.5,-64,
|
|
Graphics.height,-64,Graphics.width,0.5,0.10,-5,-15,5,80])
|
|
initParticles("smoke",100,0)
|
|
for i in 0...@maxparticless
|
|
@particles[i].blend_type = rand(6) < 3 ? 1 : 2
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Rocket < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,0,60,0,0.5,-64,
|
|
Graphics.height,-64,Graphics.width,0.5,0,-5,-15,5,80])
|
|
initParticles("smoke",100,-1)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::FixedTeleport < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([1,0,1,10,rand(360),1,
|
|
-Graphics.height,Graphics.height,0,Graphics.width,0,3,-8,-15,20,0])
|
|
initParticles("wideportal",250)
|
|
for i in 0...@maxparticless
|
|
@particles[i].ox = 16
|
|
@particles[i].oy = 16
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
# By Peter O.
|
|
class Particle_Engine::StarTeleport < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,1,10,0,1,
|
|
-Graphics.height,Graphics.height,0,Graphics.width,0,3,-8,-15,10,0])
|
|
initParticles("star",250)
|
|
for i in 0...@maxparticless
|
|
@particles[i].ox = 48
|
|
@particles[i].oy = 48
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Smokescreen < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,0,250,0,0.2,-64,
|
|
Graphics.height,-64,Graphics.width,0.8,0.8,-5,-15,5,80])
|
|
initParticles(nil,100)
|
|
for i in 0...@maxparticless
|
|
rnd = rand(3)
|
|
@opacity[i] = (rnd==0) ? 1 : 100
|
|
filename = (rnd==0) ? "explosionsmoke" : "smoke"
|
|
@particles[i].bitmap = loadBitmap(filename, @hue)
|
|
end
|
|
end
|
|
|
|
def calcParticlePos(i)
|
|
if @randomhue==1
|
|
filename = (rand(3)==0) ? "explosionsmoke" : "smoke"
|
|
@particles[i].bitmap = loadBitmap(filename, @hue)
|
|
end
|
|
multiple = 1.7
|
|
xgrav = @xgravity*multiple/@slowdown
|
|
xgrav = -xgrav if (rand(2)==1)
|
|
ygrav = @ygravity*multiple/@slowdown
|
|
ygrav = -ygrav if (rand(2)==1)
|
|
@particlex[i] += xgrav
|
|
@particley[i] += ygrav
|
|
@particlex[i] -= @__offsetx
|
|
@particley[i] -= @__offsety
|
|
@particlex[i] = @particlex[i].floor
|
|
@particley[i] = @particley[i].floor
|
|
@particles[i].x = @particlex[i]+@startingx+@xoffset
|
|
@particles[i].y = @particley[i]+@startingy+@yoffset
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Flare < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,1,30,10,1,-64,
|
|
Graphics.height,-64,Graphics.width,2,2,-5,-12,30,0])
|
|
initParticles("particle",255)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Particle_Engine::Splash < ParticleEffect_Event
|
|
def initialize(event,viewport)
|
|
super
|
|
setParameters([0,0,1,30,255,1,-64,
|
|
Graphics.height,-64,Graphics.width,4,2,-5,-12,30,0])
|
|
initParticles("smoke",50)
|
|
end
|
|
|
|
def update
|
|
super
|
|
for i in 0...@maxparticless
|
|
@particles[i].opacity = 50
|
|
@particles[i].update
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
class Game_Event < Game_Character
|
|
attr_accessor :pe_refresh
|
|
|
|
alias nf_particles_game_map_initialize initialize
|
|
def initialize(map_id,event,map=nil)
|
|
@pe_refresh = false
|
|
begin
|
|
nf_particles_game_map_initialize(map_id, event, map)
|
|
rescue ArgumentError
|
|
nf_particles_game_map_initialize(map_id, event)
|
|
end
|
|
end
|
|
|
|
alias nf_particles_game_map_refresh refresh
|
|
def refresh
|
|
nf_particles_game_map_refresh
|
|
@pe_refresh = true
|
|
end
|
|
end
|