graphics 1.0.0b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - checksums.yaml.gz.sig +0 -0
 - data.tar.gz.sig +0 -0
 - data/.autotest +26 -0
 - data/.gemtest +0 -0
 - data/History.rdoc +12 -0
 - data/Manifest.txt +37 -0
 - data/README.rdoc +71 -0
 - data/Rakefile +26 -0
 - data/examples/boid.rb +653 -0
 - data/examples/bounce.rb +86 -0
 - data/examples/collision.rb +74 -0
 - data/examples/demo.rb +90 -0
 - data/examples/editor.rb +70 -0
 - data/examples/fluid.rb +246 -0
 - data/examples/fluid2.rb +199 -0
 - data/examples/lito.rb +108 -0
 - data/examples/lito2.rb +110 -0
 - data/examples/logo.rb +73 -0
 - data/examples/math.rb +42 -0
 - data/examples/radar.rb +31 -0
 - data/examples/tank.rb +160 -0
 - data/examples/tank2.rb +173 -0
 - data/examples/targeting.rb +46 -0
 - data/examples/vants.rb +69 -0
 - data/examples/walker.rb +116 -0
 - data/examples/zenspider1.rb +93 -0
 - data/examples/zenspider2.rb +123 -0
 - data/examples/zenspider3.rb +104 -0
 - data/examples/zenspider4.rb +90 -0
 - data/examples/zombies.rb +385 -0
 - data/lib/graphics.rb +9 -0
 - data/lib/graphics/body.rb +216 -0
 - data/lib/graphics/extensions.rb +48 -0
 - data/lib/graphics/simulation.rb +377 -0
 - data/lib/graphics/trail.rb +69 -0
 - data/lib/graphics/v.rb +71 -0
 - data/resources/images/body.png +0 -0
 - data/resources/images/turret.png +0 -0
 - data/rubysdl_setup.sh +34 -0
 - data/test/test_graphics.rb +408 -0
 - metadata +191 -0
 - metadata.gz.sig +2 -0
 
    
        data/examples/fluid2.rb
    ADDED
    
    | 
         @@ -0,0 +1,199 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Particle < Graphics::Body
         
     | 
| 
      
 4 
     | 
    
         
            +
              MASS       = 5          # Particle mass
         
     | 
| 
      
 5 
     | 
    
         
            +
              DENSITY    = 1          # Rest density
         
     | 
| 
      
 6 
     | 
    
         
            +
              GRAVITY    = V[0, -0.5] #
         
     | 
| 
      
 7 
     | 
    
         
            +
              H          = 1          # Smoothing cutoff: essentially, particle size
         
     | 
| 
      
 8 
     | 
    
         
            +
              K          = 20         # Temperature constant: higher repels more strongly
         
     | 
| 
      
 9 
     | 
    
         
            +
              ETA        = 1          # Viscosity constant: higher for more viscous
         
     | 
| 
      
 10 
     | 
    
         
            +
              DELTA_TIME = 0.1        #
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              attr_accessor :density, :pressure_force, :viscosity_force, :s
         
     | 
| 
      
 13 
     | 
    
         
            +
              attr_writer :nearby
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def initialize w, x, y, s
         
     | 
| 
      
 16 
     | 
    
         
            +
                super w
         
     | 
| 
      
 17 
     | 
    
         
            +
                self.x = x
         
     | 
| 
      
 18 
     | 
    
         
            +
                self.y = y
         
     | 
| 
      
 19 
     | 
    
         
            +
                self.s = s
         
     | 
| 
      
 20 
     | 
    
         
            +
                self.nearby = nil
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                clear
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def draw
         
     | 
| 
      
 26 
     | 
    
         
            +
                x = self.x * s
         
     | 
| 
      
 27 
     | 
    
         
            +
                y = self.y * s
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                w.circle(x, y, density, :gray)
         
     | 
| 
      
 30 
     | 
    
         
            +
                w.circle(x, y, 5, :white)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                w.angle x, y, a, m * s, :red
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def clear
         
     | 
| 
      
 36 
     | 
    
         
            +
                self.nearby          = nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                self.density         = DENSITY
         
     | 
| 
      
 38 
     | 
    
         
            +
                self.pressure_force  = V::ZERO
         
     | 
| 
      
 39 
     | 
    
         
            +
                self.viscosity_force = V::ZERO
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              def nearby
         
     | 
| 
      
 43 
     | 
    
         
            +
                @nearby ||= begin
         
     | 
| 
      
 44 
     | 
    
         
            +
                              p = self.position
         
     | 
| 
      
 45 
     | 
    
         
            +
                              w.particles.find_all { |neighbor|
         
     | 
| 
      
 46 
     | 
    
         
            +
                                (p - neighbor.position).magnitude < H
         
     | 
| 
      
 47 
     | 
    
         
            +
                              }
         
     | 
| 
      
 48 
     | 
    
         
            +
                            end
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              def calculate_density
         
     | 
| 
      
 52 
     | 
    
         
            +
                nearby.each do |neighbor|
         
     | 
| 
      
 53 
     | 
    
         
            +
                  distance = (position - neighbor.position)
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  self.density += MASS * weight(distance, H) # if distance.magnitude < H
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              def calculate_forces
         
     | 
| 
      
 60 
     | 
    
         
            +
                particle = self
         
     | 
| 
      
 61 
     | 
    
         
            +
                nearby.each do |neighbor|
         
     | 
| 
      
 62 
     | 
    
         
            +
                  distance = (particle.position - neighbor.position)
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  # Temporary terms used to caclulate forces
         
     | 
| 
      
 65 
     | 
    
         
            +
                  density_p = particle.density
         
     | 
| 
      
 66 
     | 
    
         
            +
                  density_n = neighbor.density
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  # This *should* never happen, but it's good to check, because
         
     | 
| 
      
 69 
     | 
    
         
            +
                  # we're dividing by density later
         
     | 
| 
      
 70 
     | 
    
         
            +
                  raise "Particle density is, impossibly, 0" unless density_n != 0
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  # Pressure derived from the ideal gas law (constant temp)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  pressure_p = K * (density_p - DENSITY)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  pressure_n = K * (density_n - DENSITY)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  # Navier-Stokes equations for pressure and viscosity
         
     | 
| 
      
 77 
     | 
    
         
            +
                  # (ignoring surface tension)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  particle.pressure_force += gradient_weight_spiky(distance, H) *
         
     | 
| 
      
 79 
     | 
    
         
            +
                    (-1.0 * MASS * (pressure_p + pressure_n) / (2 * density_n))
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  particle.viscosity_force += (neighbor.velocity - particle.velocity) *
         
     | 
| 
      
 82 
     | 
    
         
            +
                    (ETA * MASS * (1/density_n) * laplacian_weight_viscosity(distance, H))
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              def apply_forces
         
     | 
| 
      
 87 
     | 
    
         
            +
                particle = self
         
     | 
| 
      
 88 
     | 
    
         
            +
                total_force = particle.pressure_force + particle.viscosity_force
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                # 'Eulerian' style momentum:
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                # Calculate acceleration from forces
         
     | 
| 
      
 93 
     | 
    
         
            +
                acceleration = (total_force * (1.0 / particle.density * DELTA_TIME)) + GRAVITY
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                # Update position and velocity
         
     | 
| 
      
 96 
     | 
    
         
            +
                particle.velocity += acceleration * DELTA_TIME
         
     | 
| 
      
 97 
     | 
    
         
            +
                particle.position += particle.velocity * DELTA_TIME
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                limit
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              E = 0.01
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
              def limit width = 15
         
     | 
| 
      
 105 
     | 
    
         
            +
                if x >= width - E
         
     | 
| 
      
 106 
     | 
    
         
            +
                  self.x = width - (E + 0.1*rand)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  self.m = 0
         
     | 
| 
      
 108 
     | 
    
         
            +
                elsif x < E
         
     | 
| 
      
 109 
     | 
    
         
            +
                  self.x = E + 0.1*rand
         
     | 
| 
      
 110 
     | 
    
         
            +
                  self.m = 0
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                if y >= width - E
         
     | 
| 
      
 114 
     | 
    
         
            +
                  self.y = width - (E+rand*0.1)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  self.m = 0
         
     | 
| 
      
 116 
     | 
    
         
            +
                elsif y < E
         
     | 
| 
      
 117 
     | 
    
         
            +
                  self.y = E + rand*0.1
         
     | 
| 
      
 118 
     | 
    
         
            +
                  self.m = 0
         
     | 
| 
      
 119 
     | 
    
         
            +
                end
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
              ######################################################################
         
     | 
| 
      
 123 
     | 
    
         
            +
              # Helpers
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
              def weight r, h
         
     | 
| 
      
 126 
     | 
    
         
            +
                len_r = r.magnitude
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                if len_r.xbetween? 0, h
         
     | 
| 
      
 129 
     | 
    
         
            +
                  315.0 / (64 * Math::PI * h**9) * (h**2 - len_r**2)**3
         
     | 
| 
      
 130 
     | 
    
         
            +
                else
         
     | 
| 
      
 131 
     | 
    
         
            +
                  0.0
         
     | 
| 
      
 132 
     | 
    
         
            +
                end
         
     | 
| 
      
 133 
     | 
    
         
            +
              end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
              def gradient_weight_spiky r, h
         
     | 
| 
      
 136 
     | 
    
         
            +
                len_r = r.magnitude
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                if len_r.xbetween? 0, h
         
     | 
| 
      
 139 
     | 
    
         
            +
                  r * (45.0 / (Math::PI * h**6 * len_r)) * (h - len_r)**2 * (-1.0)
         
     | 
| 
      
 140 
     | 
    
         
            +
                else
         
     | 
| 
      
 141 
     | 
    
         
            +
                  V::ZERO
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
              end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
              def laplacian_weight_viscosity r, h
         
     | 
| 
      
 146 
     | 
    
         
            +
                len_r = r.magnitude
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                if len_r.xbetween? 0, h
         
     | 
| 
      
 149 
     | 
    
         
            +
                  45.0 / (2 * Math::PI * h**5) * (1 - len_r / h)
         
     | 
| 
      
 150 
     | 
    
         
            +
                else
         
     | 
| 
      
 151 
     | 
    
         
            +
                  0.0
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
              end
         
     | 
| 
      
 154 
     | 
    
         
            +
            end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
            class Float
         
     | 
| 
      
 157 
     | 
    
         
            +
              def xbetween? min, max
         
     | 
| 
      
 158 
     | 
    
         
            +
                min < self && self <= max
         
     | 
| 
      
 159 
     | 
    
         
            +
              end
         
     | 
| 
      
 160 
     | 
    
         
            +
            end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
            class FluidDynamics < Graphics::Simulation
         
     | 
| 
      
 163 
     | 
    
         
            +
              WINSIZE = 500
         
     | 
| 
      
 164 
     | 
    
         
            +
              SCALE = 15
         
     | 
| 
      
 165 
     | 
    
         
            +
              S = WINSIZE / SCALE
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
              attr_accessor :particles, :scale
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 170 
     | 
    
         
            +
                super WINSIZE, WINSIZE, 16, "Smoothed Particle Hydrodynamics"
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                self.particles = []
         
     | 
| 
      
 173 
     | 
    
         
            +
                self.scale = SCALE
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                # Instantiate particles!
         
     | 
| 
      
 176 
     | 
    
         
            +
                (0..10).each do |x|
         
     | 
| 
      
 177 
     | 
    
         
            +
                  (0..10).each do |y|
         
     | 
| 
      
 178 
     | 
    
         
            +
                    jitter = rand * 0.1
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                    particles << Particle.new(self, x + 1 + jitter, y + 5, S)
         
     | 
| 
      
 181 
     | 
    
         
            +
                  end
         
     | 
| 
      
 182 
     | 
    
         
            +
                end
         
     | 
| 
      
 183 
     | 
    
         
            +
              end
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 186 
     | 
    
         
            +
                clear
         
     | 
| 
      
 187 
     | 
    
         
            +
                particles.each(&:draw)
         
     | 
| 
      
 188 
     | 
    
         
            +
                fps n
         
     | 
| 
      
 189 
     | 
    
         
            +
              end
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
              def update n
         
     | 
| 
      
 192 
     | 
    
         
            +
                particles.each(&:clear)
         
     | 
| 
      
 193 
     | 
    
         
            +
                particles.each(&:calculate_density)
         
     | 
| 
      
 194 
     | 
    
         
            +
                particles.each(&:calculate_forces)
         
     | 
| 
      
 195 
     | 
    
         
            +
                particles.each(&:apply_forces)
         
     | 
| 
      
 196 
     | 
    
         
            +
              end
         
     | 
| 
      
 197 
     | 
    
         
            +
            end
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
            FluidDynamics.new.run
         
     | 
    
        data/examples/lito.rb
    ADDED
    
    | 
         @@ -0,0 +1,108 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'matrix'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Matrix
         
     | 
| 
      
 4 
     | 
    
         
            +
              def rotate x, y
         
     | 
| 
      
 5 
     | 
    
         
            +
                # I can't find a neat matrix-math solution for
         
     | 
| 
      
 6 
     | 
    
         
            +
                # this, so let's do it with regular 'ol `map`.
         
     | 
| 
      
 7 
     | 
    
         
            +
                Matrix[ *self.to_a.rotate(y).map {|row| row.rotate x} ]
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              # Pad or shrink a matrix
         
     | 
| 
      
 11 
     | 
    
         
            +
              def take x, y
         
     | 
| 
      
 12 
     | 
    
         
            +
                Matrix.build(y, x){|i, j| if self[i, j].nil? then 0 else self[i, j] end }
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              # Bitwise operations on boolean matrices
         
     | 
| 
      
 16 
     | 
    
         
            +
              def & other
         
     | 
| 
      
 17 
     | 
    
         
            +
                Matrix.Raise ErrDimensionMismatch unless
         
     | 
| 
      
 18 
     | 
    
         
            +
                  self.row_count == other.row_count and
         
     | 
| 
      
 19 
     | 
    
         
            +
                  self.column_count == other.column_count
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                Matrix.build(self.row_count){|i, j| self[i, j] & other[i, j] }
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              def | other
         
     | 
| 
      
 25 
     | 
    
         
            +
                Matrix.Raise ErrDimensionMismatch unless
         
     | 
| 
      
 26 
     | 
    
         
            +
                  self.row_count == other.row_count and
         
     | 
| 
      
 27 
     | 
    
         
            +
                  self.column_count == other.column_count
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                Matrix.build(self.row_count){|i, j| self[i, j] | other[i, j] }
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
            end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            def sum l
         
     | 
| 
      
 34 
     | 
    
         
            +
              l.reduce :+
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            def twos grid
         
     | 
| 
      
 38 
     | 
    
         
            +
              grid.map{|i| if i == 2 then 1 else 0 end}
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            def threes grid
         
     | 
| 
      
 42 
     | 
    
         
            +
              grid.map{|i| if i == 3 then 1 else 0 end}
         
     | 
| 
      
 43 
     | 
    
         
            +
            end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            AROUND = [-1, 0, 1].product([-1, 0, 1])
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            def neighbors grid
         
     | 
| 
      
 48 
     | 
    
         
            +
              sum(AROUND.map{|x, y| grid.rotate x, y } ) - grid
         
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            def life grid
         
     | 
| 
      
 52 
     | 
    
         
            +
              ((twos neighbors grid) & grid) | (threes neighbors grid)
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            size, width, count = 10, 64, 256
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            require "sdl"
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            SDL.init SDL::INIT_VIDEO
         
     | 
| 
      
 60 
     | 
    
         
            +
            SDL::WM::set_caption "Conway's Game of Life", "Conway's Game of Life"
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            screen = SDL::Screen.open 640, 640, 16, SDL::HWSURFACE|SDL::DOUBLEBUF
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            black = screen.format.map_rgb   0,   0,   0
         
     | 
| 
      
 65 
     | 
    
         
            +
            white = screen.format.map_rgb 255, 255, 255
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            w, h = screen.w, screen.h
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            matrix = Matrix[[1, 1, 1],
         
     | 
| 
      
 70 
     | 
    
         
            +
                            [0, 0, 1],
         
     | 
| 
      
 71 
     | 
    
         
            +
                            [1, 1, 1]].take(width, width).rotate(-(width/2), -(width/2))
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            paused = false
         
     | 
| 
      
 74 
     | 
    
         
            +
            step = false
         
     | 
| 
      
 75 
     | 
    
         
            +
            (1..(1.0/0)).each do |n|
         
     | 
| 
      
 76 
     | 
    
         
            +
              puts n if n % 100 == 0
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              screen.fill_rect 0, 0, w, h, black
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              matrix.to_a.each_with_index do |row, y|
         
     | 
| 
      
 81 
     | 
    
         
            +
                row.each_with_index do |c, x|
         
     | 
| 
      
 82 
     | 
    
         
            +
                  if c == 1 then
         
     | 
| 
      
 83 
     | 
    
         
            +
                    screen.fill_rect x*size, y*size, size-1, size-1, white
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              screen.flip
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
              while event = SDL::Event.poll
         
     | 
| 
      
 91 
     | 
    
         
            +
                case event
         
     | 
| 
      
 92 
     | 
    
         
            +
                when SDL::Event::KeyDown then
         
     | 
| 
      
 93 
     | 
    
         
            +
                  c = event.sym.chr
         
     | 
| 
      
 94 
     | 
    
         
            +
                  exit if c == "q" or c == "Q" or c == "\e"
         
     | 
| 
      
 95 
     | 
    
         
            +
                  step = true if c == " "
         
     | 
| 
      
 96 
     | 
    
         
            +
                  puts n
         
     | 
| 
      
 97 
     | 
    
         
            +
                  paused = ! paused
         
     | 
| 
      
 98 
     | 
    
         
            +
                when SDL::Event::Quit then
         
     | 
| 
      
 99 
     | 
    
         
            +
                  exit
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              matrix = life matrix unless paused
         
     | 
| 
      
 104 
     | 
    
         
            +
              if step then
         
     | 
| 
      
 105 
     | 
    
         
            +
                paused = true
         
     | 
| 
      
 106 
     | 
    
         
            +
                step = false
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/lito2.rb
    ADDED
    
    | 
         @@ -0,0 +1,110 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "matrix"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class Matrix
         
     | 
| 
      
 5 
     | 
    
         
            +
              def rotate x, y
         
     | 
| 
      
 6 
     | 
    
         
            +
                # I can't find a neat matrix-math solution for
         
     | 
| 
      
 7 
     | 
    
         
            +
                # this, so let's do it with regular 'ol `map`.
         
     | 
| 
      
 8 
     | 
    
         
            +
                Matrix[ *self.to_a.rotate(y).map {|row| row.rotate x} ]
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              # Pad or shrink a matrix
         
     | 
| 
      
 12 
     | 
    
         
            +
              def take x, y
         
     | 
| 
      
 13 
     | 
    
         
            +
                Matrix.build(y, x){|i, j| if self[i, j].nil? then 0 else self[i, j] end }
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              # Bitwise operations on boolean matrices
         
     | 
| 
      
 17 
     | 
    
         
            +
              def & other
         
     | 
| 
      
 18 
     | 
    
         
            +
                Matrix.Raise ErrDimensionMismatch unless
         
     | 
| 
      
 19 
     | 
    
         
            +
                  self.row_count == other.row_count and
         
     | 
| 
      
 20 
     | 
    
         
            +
                  self.column_count == other.column_count
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                Matrix.build(self.row_count){|i, j| self[i, j] & other[i, j] }
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              def | other
         
     | 
| 
      
 26 
     | 
    
         
            +
                Matrix.Raise ErrDimensionMismatch unless
         
     | 
| 
      
 27 
     | 
    
         
            +
                  self.row_count == other.row_count and
         
     | 
| 
      
 28 
     | 
    
         
            +
                  self.column_count == other.column_count
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                Matrix.build(self.row_count){|i, j| self[i, j] | other[i, j] }
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            class LitoGol
         
     | 
| 
      
 35 
     | 
    
         
            +
              AROUND = [-1, 0, 1].product([-1, 0, 1])
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
              attr_accessor :matrix
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              def initialize width
         
     | 
| 
      
 40 
     | 
    
         
            +
                count = ((width*width) * 0.15).to_i
         
     | 
| 
      
 41 
     | 
    
         
            +
                dimensions = width.times.to_a
         
     | 
| 
      
 42 
     | 
    
         
            +
                data = dimensions.product(dimensions).sample(count).sort
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                self.matrix = Matrix.build(width, width) do |r, c|
         
     | 
| 
      
 45 
     | 
    
         
            +
                  data.include?([r, c]) ? 1 : 0
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              def sum l
         
     | 
| 
      
 50 
     | 
    
         
            +
                l.reduce :+
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              def twos grid
         
     | 
| 
      
 54 
     | 
    
         
            +
                grid.map{|i| if i == 2 then 1 else 0 end}
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def threes grid
         
     | 
| 
      
 58 
     | 
    
         
            +
                grid.map{|i| if i == 3 then 1 else 0 end}
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              def neighbors grid
         
     | 
| 
      
 62 
     | 
    
         
            +
                sum(AROUND.map{|x, y| grid.rotate x, y } ) - grid
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              def life grid
         
     | 
| 
      
 66 
     | 
    
         
            +
                ((twos neighbors grid) & grid) | (threes neighbors grid)
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              def update
         
     | 
| 
      
 70 
     | 
    
         
            +
                self.matrix = life matrix
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              def each
         
     | 
| 
      
 74 
     | 
    
         
            +
                matrix.to_a.each_with_index do |row, y|
         
     | 
| 
      
 75 
     | 
    
         
            +
                  row.each_with_index do |c, x|
         
     | 
| 
      
 76 
     | 
    
         
            +
                    yield c, x, y
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            class LitoGolSimulation < Graphics::Simulation
         
     | 
| 
      
 83 
     | 
    
         
            +
              attr_accessor :gol
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
              SIZE, WIDTH = 10, 64
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 88 
     | 
    
         
            +
                super 640, 640, 16, "Conway's Game of Life"
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                self.gol = LitoGol.new WIDTH
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 94 
     | 
    
         
            +
                clear
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                gol.each do |c, x, y|
         
     | 
| 
      
 97 
     | 
    
         
            +
                  if c == 1 then
         
     | 
| 
      
 98 
     | 
    
         
            +
                    ellipse x*SIZE, y*SIZE, (SIZE-1)/2, (SIZE-1)/2, :white
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                fps n
         
     | 
| 
      
 103 
     | 
    
         
            +
              end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
              def update n
         
     | 
| 
      
 106 
     | 
    
         
            +
                self.gol.update
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
            end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
            LitoGolSimulation.new.run
         
     | 
    
        data/examples/logo.rb
    ADDED
    
    | 
         @@ -0,0 +1,73 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 5 
     | 
    
         
            +
            $: << "."
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "examples/editor"
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            class Turtle < Graphics::Body
         
     | 
| 
      
 9 
     | 
    
         
            +
              attr_accessor :src, :pen
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def initialize w, src
         
     | 
| 
      
 12 
     | 
    
         
            +
                super w
         
     | 
| 
      
 13 
     | 
    
         
            +
                self.x = w.w/2
         
     | 
| 
      
 14 
     | 
    
         
            +
                self.y = w.h/2
         
     | 
| 
      
 15 
     | 
    
         
            +
                self.a = 90
         
     | 
| 
      
 16 
     | 
    
         
            +
                self.src = src
         
     | 
| 
      
 17 
     | 
    
         
            +
                self.pen = true
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def draw
         
     | 
| 
      
 21 
     | 
    
         
            +
                self.x = w.w/2
         
     | 
| 
      
 22 
     | 
    
         
            +
                self.y = w.h/2
         
     | 
| 
      
 23 
     | 
    
         
            +
                self.a = 90
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                src.each do |line|
         
     | 
| 
      
 26 
     | 
    
         
            +
                  case line
         
     | 
| 
      
 27 
     | 
    
         
            +
                  when "pd" then
         
     | 
| 
      
 28 
     | 
    
         
            +
                    self.pen = true
         
     | 
| 
      
 29 
     | 
    
         
            +
                  when "pu" then
         
     | 
| 
      
 30 
     | 
    
         
            +
                    self.pen = false
         
     | 
| 
      
 31 
     | 
    
         
            +
                  when /rt (\d+)/ then
         
     | 
| 
      
 32 
     | 
    
         
            +
                    self.a -= $1.to_i
         
     | 
| 
      
 33 
     | 
    
         
            +
                  when /lt (\d+)/ then
         
     | 
| 
      
 34 
     | 
    
         
            +
                    self.a += $1.to_i
         
     | 
| 
      
 35 
     | 
    
         
            +
                  when /f (\d+)/ then
         
     | 
| 
      
 36 
     | 
    
         
            +
                    dist = $1.to_i
         
     | 
| 
      
 37 
     | 
    
         
            +
                    if pen then
         
     | 
| 
      
 38 
     | 
    
         
            +
                      w.angle x, y, a, dist, :white
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    move_by a, dist
         
     | 
| 
      
 41 
     | 
    
         
            +
                  else
         
     | 
| 
      
 42 
     | 
    
         
            +
                    src.delete line
         
     | 
| 
      
 43 
     | 
    
         
            +
                    warn "ERROR: #{line}"
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
                draw_turtle
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              def draw_turtle
         
     | 
| 
      
 50 
     | 
    
         
            +
                p1 = w.project(x, y, a, 15)
         
     | 
| 
      
 51 
     | 
    
         
            +
                p2 = w.project(x, y, a+90, 5)
         
     | 
| 
      
 52 
     | 
    
         
            +
                p3 = w.project(x, y, a-90, 5)
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                polygon p1, p2, p3, :green
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            class Logo < Editor
         
     | 
| 
      
 59 
     | 
    
         
            +
              attr_accessor :turtle
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 62 
     | 
    
         
            +
                super
         
     | 
| 
      
 63 
     | 
    
         
            +
                self.turtle = Turtle.new self, lines
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              def draw_scene
         
     | 
| 
      
 67 
     | 
    
         
            +
                turtle.draw
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            if $0 == __FILE__
         
     | 
| 
      
 72 
     | 
    
         
            +
              Logo.new.run
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     |