ものすごいテキトーだけどこんなことができるわけです。
require 'dxruby'
class StandardParticle < Sprite
attr_accessor :dx, :dy, :lifetime, :parent
def initialize
@dx = 0
@dy = 0
@lifetime = nil
end
def update
if @lifetime
@lifetime -= 1
if @lifetime == 0
self.vanish
return
end
end
if self.alpha > 0
self.alpha += @parent.d_alpha
self.alpha = 0 if self.alpha < 0
end
self.x += @dx
self.y += @dy
@dy += @parent.gravity
end
end
class ParticleFactory
attr_accessor :particles
@@all_objects = []
def self.step
obj = @@all_objects.map{|o|o.particles}
Sprite.update obj
Sprite.draw obj
Sprite.clean obj
@@all_objects.delete_if {|v| v.particles.empty?}
end
def initialize(particle_class)
@particle_class = particle_class
@particles = []
end
def generate(count)
flag = @particles.empty?
count.times do |i|
temp = @particle_class.new
yield temp, i
@particles << temp
end
@@all_objects.push(self) if flag
end
end
class SampleEmitter
attr_accessor :gravity, :d_alpha, :image, :lifetime
class EmitterGenerator
attr_accessor :b, :interval, :count
def initialize(b, interval)
@b = b
@interval = interval
@count = 0
end
end
def initialize(particle_class)
@factory = ParticleFactory.new(particle_class)
@screen = Sprite.new
@screen.collision = [0, 0, 639, 479]
@generator = []
end
def generate(count)
@factory.generate(count) do |p, i|
p.parent = self
p.lifetime = @lifetime
yield p, i
end
end
def generate_line(count, x1, y1, x2, y2)
diff_x = x2 - x1 + 1
diff_y = y2 - y1 + 1
@factory.generate(count) do |p, i|
r = rand()
p.x = x1 + r * diff_x
p.y = y1 + r * diff_y
p.parent = self
p.lifetime = @lifetime
p.image = @image
yield p, i if block_given?
end
end
def generate_circle(count, x, y, r, angle_min, angle_max)
@factory.generate(count) do |p, i|
angle = angle_min + rand() * (angle_max - angle_min)
p.x = x + Math.cos(angle / 180.0 * Math::PI) * r
p.y = y + Math.sin(angle / 180.0 * Math::PI) * r
p.parent = self
p.lifetime = @lifetime
p.image = @image
yield p, i, angle if block_given?
end
end
def add_generator(interval, &b)
@generator << EmitterGenerator.new(b, interval)
end
def update
@generator.each do |g|
g.count += 1
if g.count >= g.interval
g.count = 0
g.b.call
end
end
@factory.particles = @screen.check(@factory.particles)
end
end
image = Image.new(20,20).circle_fill(10,10,10,[200,150,100])
emitter = SampleEmitter.new(StandardParticle)
emitter.d_alpha = -2
emitter.gravity = 0
emitter.lifetime = 128
emitter.image = image
emitter.add_generator(1) do
emitter.generate_circle(5, 100, 100, 1, 220, 320) do |p, i, angle|
p.dx = Math.cos(angle / 180.0 * Math::PI)*2
p.dy = Math.sin(angle / 180.0 * Math::PI)*2
p.alpha = 100
p.blend = :add
end
end
Window.loop do
emitter.update
ParticleFactory.step
end