Class: MiniGL::Particles

Inherits:
Object
  • Object
show all
Defined in:
lib/minigl/particles.rb

Overview

A particle system.

Defined Under Namespace

Classes: Particle

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ Particles

Create a new particle system. Options:

  • x: x-coordinate of the origin of the particle system. If source is set, it has precedence.

  • y: y-coordinate of the origin of the particle system. If source is set, it has precedence.

  • source: if set, must be an object that responds to x and y. The position of the particle system will be updated to this object’s position on initialization and every time update is called.

  • emission_interval (Integer|Range): interval in frames between each particle emission. It can be a fixed value or a range, in which case the interval will be a random value within that range (a new value before each emission). Default: 10.

  • emission_rate (Integer|Range): how many particles will be emitted at a time. It can be a fixed value or a range, in which case a random number of particles in that range will be emitted each time. Default: 1.

  • duration (Integer): how many frames each particle will live. Default: 30.

  • shape (Symbol|nil): one of :square, :triangle_up, or :triangle_down, to emit basic shapes (if the img option is set, it has precedence). Shape particles don’t support rotation. Either this or img must be set.

  • img (Gosu::Image|nil): image of the particle, has precedence over shape. Either this or shape must be set.

  • scale (Numeric): fixed scale of each particle, ignored if scale_change is set to a valid value. Default: 1.

  • scale_change (Symbol|nil): one of :grow, :shrink, or :alternate, indicates how the scale of the particle will change over time. :grow will cause the scale to change from scale_min to scale_max; :shrink will cause the scale to change from scale_max to scale_min; :alternate will cause the scale to first go from scale_min to scale_max, in scale_inflection * duration frames, and then back to scale_min in the remaining frames. All changes are linear over time.

  • scale_min (Numeric): minimum scale, to be used together with scale_change. Default: 0.

  • scale_max (Numeric): maximum scale, to be used together with scale_change. Default: 1.

  • scale_inflection (Numeric): should be a number between 0 and 1, to be used with scale_change set to :alternate. Default: 0.5.

  • alpha (Numeric): fixed alpha of each particle, ignored if alpha_change is set to a valid value. Default: 255.

  • alpha_change, alpha_min, alpha_max, alpha_inflection: behave the same way as the corresponding properties for scale. Default alpha_max is 255.

  • angle (Numeric|Range|nil): initial rotation angle of each particle in degrees. Can be a fixed value or a range, in which case the initial rotation will be a random value within that range. Default: nil (no rotation).

  • rotation(Numeric|nil): how much each particle will rotate each frame, in degrees. Default: nil (no rotation).

  • speed (Vector|Hash|nil): specifies how the particle will move each frame. It can be a Vector, in which case the particle will move a fixed amount (corresponding to the x and y values of the vector) or a Hash with :x and :y keys, in this case the value can be fixed or a range, for random movement. Default: nil (no movement).

  • color (Integer): color to tint the particles, in the 0xRRGGBB format. Default: 0xffffff (white, no tinting).

  • round_position (Boolean): only draw particles in integer positions. Default: true.



63
64
65
66
67
68
69
70
71
72
# File 'lib/minigl/particles.rb', line 63

def initialize(**options)
  raise "Particles must have either a shape or an image!" if options[:shape].nil? && options[:img].nil?

  @options = DEFAULT_OPTIONS.merge(options)
  @x = @options[:source]&.x || @options[:x] || 0
  @y = @options[:source]&.y || @options[:y] || 0

  @particles = []
  @emitting = false
end

Instance Method Details

#countObject

Returns the current particle count.



97
98
99
# File 'lib/minigl/particles.rb', line 97

def count
  @particles.size
end

#draw(map = nil, z_index = 0) ⇒ Object

Draws the particles. Parameters:

  • map (Map|nil): a map whose camera will be used to determine the position of particles in the screen.

  • z_index (Integer): z-index to draw the particles. Default: 0.



138
139
140
141
142
# File 'lib/minigl/particles.rb', line 138

def draw(map = nil, z_index = 0)
  @particles.each do |particle|
    particle.draw(map, z_index)
  end
end

#emitting?Boolean

Returns a boolean indicating whether this particle system is currently emitting particles.

Returns:

  • (Boolean)


92
93
94
# File 'lib/minigl/particles.rb', line 92

def emitting?
  @emitting
end

#startObject

Starts emitting particles. This returns self, so you can create, start, and assign a particle system to a variable like this: @p_system = Particles.new(...).start



77
78
79
80
81
82
# File 'lib/minigl/particles.rb', line 77

def start
  set_emission_time
  @timer = @emission_time
  @emitting = true
  self
end

#stopObject

Stops emitting new particles. The existing particles will still be kept alive until they hit duration frames.



86
87
88
# File 'lib/minigl/particles.rb', line 86

def stop
  @emitting = false
end

#updateObject

Updates the particle system. This should be called in the update loop of the game.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/minigl/particles.rb', line 103

def update
  @particles.each do |particle|
    particle.update
    @particles.delete(particle) if particle.dead?
  end
  return unless @emitting

  if @options[:source]
    @x = @options[:source].x
    @y = @options[:source].y
  end

  @timer += 1
  if @timer >= @emission_time
    count = @options[:emission_rate].is_a?(Range) ? rand(@options[:emission_rate]) : @options[:emission_rate]
    count.times do
      x = @options[:area] ? @x + rand * @options[:area].x : @x + @options[:spread] * (rand - 0.5)
      y = @options[:area] ? @y + rand * @options[:area].y : @y + @options[:spread] * (rand - 0.5)
      @particles << Particle.new(x:,
                                 y:,
                                 duration: @options[:duration],
                                 shape: @options[:shape],
                                 img: @options[:img],
                                 **@options.slice(*PARTICLE_OPTIONS))
    end
    set_emission_time
    @timer = 0
  end
end