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/bounce.rb
    ADDED
    
    | 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class Ball < Graphics::Body
         
     | 
| 
      
 6 
     | 
    
         
            +
              COUNT = 50
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              G = V[0, -18 / 60.0]
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              attr_accessor :g
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def initialize w
         
     | 
| 
      
 13 
     | 
    
         
            +
                super
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                self.a = rand 180
         
     | 
| 
      
 16 
     | 
    
         
            +
                self.m = rand 100
         
     | 
| 
      
 17 
     | 
    
         
            +
                self.g = G
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def update
         
     | 
| 
      
 21 
     | 
    
         
            +
                fall
         
     | 
| 
      
 22 
     | 
    
         
            +
                move
         
     | 
| 
      
 23 
     | 
    
         
            +
                bounce
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def fall
         
     | 
| 
      
 27 
     | 
    
         
            +
                self.velocity += g
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def label
         
     | 
| 
      
 31 
     | 
    
         
            +
                l = "%.1f %.1f" % dx_dy
         
     | 
| 
      
 32 
     | 
    
         
            +
                w.text l, x-10, y-40, :white
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def draw
         
     | 
| 
      
 36 
     | 
    
         
            +
                # w.angle x, y, a, 3*m, :red
         
     | 
| 
      
 37 
     | 
    
         
            +
                w.angle x, y, a, 50, :red
         
     | 
| 
      
 38 
     | 
    
         
            +
                w.circle x, y, 5, :white, :filled
         
     | 
| 
      
 39 
     | 
    
         
            +
                # label
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            class BounceSimulation < Graphics::Simulation
         
     | 
| 
      
 44 
     | 
    
         
            +
              attr_accessor :bs
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 47 
     | 
    
         
            +
                super 640, 640, 16, "Bounce"
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                self.bs = populate Ball
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              def update n
         
     | 
| 
      
 53 
     | 
    
         
            +
                bs.each(&:update)
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 57 
     | 
    
         
            +
                clear
         
     | 
| 
      
 58 
     | 
    
         
            +
                bs.each(&:draw)
         
     | 
| 
      
 59 
     | 
    
         
            +
                bs.first.label
         
     | 
| 
      
 60 
     | 
    
         
            +
                fps n
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              def handle_keys
         
     | 
| 
      
 64 
     | 
    
         
            +
                super
         
     | 
| 
      
 65 
     | 
    
         
            +
                randomize if SDL::Key.press? SDL::Key::SPACE
         
     | 
| 
      
 66 
     | 
    
         
            +
                reverse if SDL::Key.press? SDL::Key::R
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              def randomize
         
     | 
| 
      
 70 
     | 
    
         
            +
                bs.each do |b|
         
     | 
| 
      
 71 
     | 
    
         
            +
                  b.m = rand(100)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  b.a = rand(180)
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
              end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              def reverse
         
     | 
| 
      
 77 
     | 
    
         
            +
                return if @guard
         
     | 
| 
      
 78 
     | 
    
         
            +
                @guard = true
         
     | 
| 
      
 79 
     | 
    
         
            +
                bs.each do |b|
         
     | 
| 
      
 80 
     | 
    
         
            +
                  b.g *= -1
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
                @guard = false
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            BounceSimulation.new.run
         
     | 
| 
         @@ -0,0 +1,74 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class Sprite < Graphics::Body
         
     | 
| 
      
 6 
     | 
    
         
            +
              COUNT = 8
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              attr_accessor :image
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              def initialize w
         
     | 
| 
      
 11 
     | 
    
         
            +
                super w
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                self.a = random_angle
         
     | 
| 
      
 14 
     | 
    
         
            +
                self.m = 5
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def update
         
     | 
| 
      
 18 
     | 
    
         
            +
                move
         
     | 
| 
      
 19 
     | 
    
         
            +
                bounce
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              def collide
         
     | 
| 
      
 23 
     | 
    
         
            +
                self.a = (a + 180).degrees
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def draw
         
     | 
| 
      
 27 
     | 
    
         
            +
                w.blit image, x, y, a
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def collide_with? other
         
     | 
| 
      
 31 
     | 
    
         
            +
                w.cmap.collision_check(x, y, w.cmap, other.x, other.y) != nil
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            class Collision < Graphics::Simulation
         
     | 
| 
      
 36 
     | 
    
         
            +
              attr_accessor :sprites, :cmap, :image
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 39 
     | 
    
         
            +
                super 850, 850, 16, "Collision"
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                self.image = SDL::Surface.load "resources/images/body.png"
         
     | 
| 
      
 42 
     | 
    
         
            +
                self.cmap = image.make_collision_map
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                self.sprites = populate Sprite do |s|
         
     | 
| 
      
 45 
     | 
    
         
            +
                  s.image = image
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              def inspect
         
     | 
| 
      
 50 
     | 
    
         
            +
                "<Screen ...>"
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              def detect_collisions(sprites)
         
     | 
| 
      
 54 
     | 
    
         
            +
                collisions = []
         
     | 
| 
      
 55 
     | 
    
         
            +
                sprites.combination(2).each do |a, b|
         
     | 
| 
      
 56 
     | 
    
         
            +
                  collisions << a << b if a.collide_with? b
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
                collisions.uniq
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              def update n
         
     | 
| 
      
 62 
     | 
    
         
            +
                sprites.each(&:update)
         
     | 
| 
      
 63 
     | 
    
         
            +
                detect_collisions(sprites).each(&:collide)
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 67 
     | 
    
         
            +
                clear
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                sprites.each(&:draw)
         
     | 
| 
      
 70 
     | 
    
         
            +
                fps n
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            Collision.new.run
         
     | 
    
        data/examples/demo.rb
    ADDED
    
    | 
         @@ -0,0 +1,90 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class Ball < Graphics::Body
         
     | 
| 
      
 7 
     | 
    
         
            +
              def initialize w
         
     | 
| 
      
 8 
     | 
    
         
            +
                super
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                self.x = 50
         
     | 
| 
      
 11 
     | 
    
         
            +
                self.y = 50
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                self.a = 60
         
     | 
| 
      
 14 
     | 
    
         
            +
                self.m = 3
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def update
         
     | 
| 
      
 18 
     | 
    
         
            +
                move
         
     | 
| 
      
 19 
     | 
    
         
            +
                wrap
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 23 
     | 
    
         
            +
                a = n % 360
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                w.angle  x, y, a, 50,     :green
         
     | 
| 
      
 26 
     | 
    
         
            +
                w.circle x, y, 5, :white, :filled
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            class Demo < Graphics::Simulation
         
     | 
| 
      
 31 
     | 
    
         
            +
              attr_accessor :ball, :img
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 34 
     | 
    
         
            +
                super 800, 800, 16, "Boid"
         
     | 
| 
      
 35 
     | 
    
         
            +
                self.ball = Ball.new self
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                r = color[:red]
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                self.img = sprite 10, 10 do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  circle 5, 5, 5, :white, :filled
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              def update n
         
     | 
| 
      
 45 
     | 
    
         
            +
                ball.update
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 49 
     | 
    
         
            +
                clear
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                line 100, 50, 125, 75, :white
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                hline 100, :white
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                vline 100, :white
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                angle 125, 50, 45, 10, :white
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                fast_rect 150, 50, 10, 10, :white
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                point 175, 50, :green
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                rect 200, 50, 10, 10, :white
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                circle 225, 50, 10, :white
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                ellipse 250, 50, 10, 10, :white
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                bezier 275, 50, 275, 100, 285, 0, 300, 50, :white
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                rect 300, 25, 50, 50, :white
         
     | 
| 
      
 72 
     | 
    
         
            +
                blit img, 325, 50, 0
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                text "blah", 350, 50, :white
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                x, y, * = mouse
         
     | 
| 
      
 77 
     | 
    
         
            +
                rect x, y, 150, 50, :white
         
     | 
| 
      
 78 
     | 
    
         
            +
                text "#{x}/#{y}", x, y, :white
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                debug "debug"
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                ball.draw n
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                fps n
         
     | 
| 
      
 85 
     | 
    
         
            +
              end
         
     | 
| 
      
 86 
     | 
    
         
            +
            end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
            if $0 == __FILE__
         
     | 
| 
      
 89 
     | 
    
         
            +
              Demo.new.run
         
     | 
| 
      
 90 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/editor.rb
    ADDED
    
    | 
         @@ -0,0 +1,70 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class Editor < Graphics::Simulation
         
     | 
| 
      
 7 
     | 
    
         
            +
              attr_accessor :overlay, :s, :lines
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              alias :overlay? :overlay
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 12 
     | 
    
         
            +
                super 850, 850, 16, self.class.name
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                self.overlay = true
         
     | 
| 
      
 15 
     | 
    
         
            +
                self.s = ""
         
     | 
| 
      
 16 
     | 
    
         
            +
                self.lines = []
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              def handle_event e, n
         
     | 
| 
      
 20 
     | 
    
         
            +
                case e
         
     | 
| 
      
 21 
     | 
    
         
            +
                when SDL::Event::KeyDown then
         
     | 
| 
      
 22 
     | 
    
         
            +
                  if e.mod & (SDL::Key::MOD_LCTRL | SDL::Key::MOD_RCTRL) != 0 then
         
     | 
| 
      
 23 
     | 
    
         
            +
                    case e.sym.chr
         
     | 
| 
      
 24 
     | 
    
         
            +
                    when "t" then
         
     | 
| 
      
 25 
     | 
    
         
            +
                      self.overlay = ! self.overlay
         
     | 
| 
      
 26 
     | 
    
         
            +
                    end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  else
         
     | 
| 
      
 28 
     | 
    
         
            +
                    c = e.sym.chr rescue ""
         
     | 
| 
      
 29 
     | 
    
         
            +
                    c.upcase! if e.mod & (SDL::Key::MOD_LSHIFT | SDL::Key::MOD_RSHIFT) != 0
         
     | 
| 
      
 30 
     | 
    
         
            +
                    case c
         
     | 
| 
      
 31 
     | 
    
         
            +
                    when "\r" then
         
     | 
| 
      
 32 
     | 
    
         
            +
                      c = "\n"
         
     | 
| 
      
 33 
     | 
    
         
            +
                      lines << s.dup
         
     | 
| 
      
 34 
     | 
    
         
            +
                      s.clear
         
     | 
| 
      
 35 
     | 
    
         
            +
                      return
         
     | 
| 
      
 36 
     | 
    
         
            +
                    when "\b" then
         
     | 
| 
      
 37 
     | 
    
         
            +
                      self.s = s[0..-2]
         
     | 
| 
      
 38 
     | 
    
         
            +
                      return
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
                    s << c
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                else
         
     | 
| 
      
 43 
     | 
    
         
            +
                  super
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
              def draw n
         
     | 
| 
      
 48 
     | 
    
         
            +
                clear
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                draw_scene
         
     | 
| 
      
 51 
     | 
    
         
            +
                draw_overlay
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              def draw_scene
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def draw_overlay
         
     | 
| 
      
 58 
     | 
    
         
            +
                if overlay? then
         
     | 
| 
      
 59 
     | 
    
         
            +
                  lines.each_with_index do |l, i|
         
     | 
| 
      
 60 
     | 
    
         
            +
                    text l, 10, ((lines.size-i)*font.height), :gray
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  text "> #{s}_", 10, 0, :white
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            if $0 == __FILE__
         
     | 
| 
      
 69 
     | 
    
         
            +
              Editor.new.run
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/fluid.rb
    ADDED
    
    | 
         @@ -0,0 +1,246 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "graphics"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class Float
         
     | 
| 
      
 4 
     | 
    
         
            +
              ##
         
     | 
| 
      
 5 
     | 
    
         
            +
              # A floating-point friendly `between?` function that excludes
         
     | 
| 
      
 6 
     | 
    
         
            +
              # the lower bound.
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Equivalent to `min < x <= max`
         
     | 
| 
      
 8 
     | 
    
         
            +
              ##
         
     | 
| 
      
 9 
     | 
    
         
            +
              def xbetween? min, max
         
     | 
| 
      
 10 
     | 
    
         
            +
                min < self && self <= max
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            class Particle
         
     | 
| 
      
 15 
     | 
    
         
            +
              attr_accessor :density, :position, :velocity,
         
     | 
| 
      
 16 
     | 
    
         
            +
                            :pressure_force, :viscosity_force
         
     | 
| 
      
 17 
     | 
    
         
            +
              def initialize pos
         
     | 
| 
      
 18 
     | 
    
         
            +
                # Scalars
         
     | 
| 
      
 19 
     | 
    
         
            +
                @density = 0
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                # Forces
         
     | 
| 
      
 22 
     | 
    
         
            +
                @position        = pos
         
     | 
| 
      
 23 
     | 
    
         
            +
                @velocity        = V::ZERO
         
     | 
| 
      
 24 
     | 
    
         
            +
                @pressure_force  = V::ZERO
         
     | 
| 
      
 25 
     | 
    
         
            +
                @viscosity_force = V::ZERO
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            class SPH
         
     | 
| 
      
 30 
     | 
    
         
            +
              ##
         
     | 
| 
      
 31 
     | 
    
         
            +
              # Constants
         
     | 
| 
      
 32 
     | 
    
         
            +
              #
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              MASS          = 5  # Particle mass
         
     | 
| 
      
 35 
     | 
    
         
            +
              DENSITY       = 1  # Rest density
         
     | 
| 
      
 36 
     | 
    
         
            +
              GRAVITY       = V[0, -0.5]
         
     | 
| 
      
 37 
     | 
    
         
            +
              H             = 1  # Smoothing cutoff- essentially, particle size
         
     | 
| 
      
 38 
     | 
    
         
            +
              K             = 20 # Temperature constant- higher means particle repel more strongly
         
     | 
| 
      
 39 
     | 
    
         
            +
              ETA           = 1  # Viscosity constant- higher for more viscous
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              attr_reader :particles
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 44 
     | 
    
         
            +
                # Instantiate particles!
         
     | 
| 
      
 45 
     | 
    
         
            +
                @particles = []
         
     | 
| 
      
 46 
     | 
    
         
            +
                (0..10).each do |x|
         
     | 
| 
      
 47 
     | 
    
         
            +
                  (0..10).each do |y|
         
     | 
| 
      
 48 
     | 
    
         
            +
                    jitter = rand * 0.1
         
     | 
| 
      
 49 
     | 
    
         
            +
                    particles << Particle.new(V[x+1+jitter, y+5])
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              ##
         
     | 
| 
      
 55 
     | 
    
         
            +
              # A weighting function (kernel) for the contribution of each neighbor
         
     | 
| 
      
 56 
     | 
    
         
            +
              # to a particle's density. Forms a nice smooth gradient from the center
         
     | 
| 
      
 57 
     | 
    
         
            +
              # of a particle to H, where it's 0
         
     | 
| 
      
 58 
     | 
    
         
            +
              #
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              def weight r, h
         
     | 
| 
      
 61 
     | 
    
         
            +
                len_r = r.magnitude
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                if len_r.xbetween? 0, h
         
     | 
| 
      
 64 
     | 
    
         
            +
                  315.0 / (64 * Math::PI * h**9) * (h**2 - len_r**2)**3
         
     | 
| 
      
 65 
     | 
    
         
            +
                else
         
     | 
| 
      
 66 
     | 
    
         
            +
                  0.0
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              ##
         
     | 
| 
      
 71 
     | 
    
         
            +
              # Gradient ( that is, V(dx, dy) ) of a weighting function for
         
     | 
| 
      
 72 
     | 
    
         
            +
              # a particle's pressure. This weight function is spiky (not flat or
         
     | 
| 
      
 73 
     | 
    
         
            +
              # smooth at x=0) so particles close together repel strongly.
         
     | 
| 
      
 74 
     | 
    
         
            +
              #
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              def gradient_weight_spiky r, h
         
     | 
| 
      
 77 
     | 
    
         
            +
                len_r = r.magnitude
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                if len_r.xbetween? 0, h
         
     | 
| 
      
 80 
     | 
    
         
            +
                  r * (45.0 / (Math::PI * h**6 * len_r)) * (h - len_r)**2 * (-1.0)
         
     | 
| 
      
 81 
     | 
    
         
            +
                else
         
     | 
| 
      
 82 
     | 
    
         
            +
                  V::ZERO
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              ##
         
     | 
| 
      
 87 
     | 
    
         
            +
              # The laplacian of a weighting function that tends towards infinity when
         
     | 
| 
      
 88 
     | 
    
         
            +
              # approching 0 (slows down particles moving faster than their neighbors)
         
     | 
| 
      
 89 
     | 
    
         
            +
              #
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              def laplacian_weight_viscosity r, h
         
     | 
| 
      
 92 
     | 
    
         
            +
                len_r = r.magnitude
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                if len_r.xbetween? 0, h
         
     | 
| 
      
 95 
     | 
    
         
            +
                  45.0 / (2 * Math::PI * h**5) * (1 - len_r / h)
         
     | 
| 
      
 96 
     | 
    
         
            +
                else
         
     | 
| 
      
 97 
     | 
    
         
            +
                  0.0
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
              def clear
         
     | 
| 
      
 102 
     | 
    
         
            +
                # Clear everything
         
     | 
| 
      
 103 
     | 
    
         
            +
                particles.each do |particle|
         
     | 
| 
      
 104 
     | 
    
         
            +
                  particle.density = DENSITY
         
     | 
| 
      
 105 
     | 
    
         
            +
                  particle.pressure_force = V::ZERO
         
     | 
| 
      
 106 
     | 
    
         
            +
                  particle.viscosity_force = V::ZERO
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              def calculate_density
         
     | 
| 
      
 111 
     | 
    
         
            +
                # Calculate fluid density around each particle
         
     | 
| 
      
 112 
     | 
    
         
            +
                particles.each do |particle|
         
     | 
| 
      
 113 
     | 
    
         
            +
                  particles.each do |neighbor|
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                    # If particles are close together, density increases
         
     | 
| 
      
 116 
     | 
    
         
            +
                    distance = particle.position - neighbor.position
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                    if distance.magnitude < H  # Particles are close enough to matter
         
     | 
| 
      
 119 
     | 
    
         
            +
                      particle.density += MASS * weight(distance, H)
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
                  # p particle.density if particle.density > 2*H
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              def calculate_forces
         
     | 
| 
      
 127 
     | 
    
         
            +
                # Calculate forces on each particle based on density
         
     | 
| 
      
 128 
     | 
    
         
            +
                particles.each do |particle|
         
     | 
| 
      
 129 
     | 
    
         
            +
                  particles.each do |neighbor|
         
     | 
| 
      
 130 
     | 
    
         
            +
                    distance = particle.position - neighbor.position
         
     | 
| 
      
 131 
     | 
    
         
            +
                    if  distance.magnitude <= H then
         
     | 
| 
      
 132 
     | 
    
         
            +
                      # Temporary terms used to caclulate forces
         
     | 
| 
      
 133 
     | 
    
         
            +
                      density_p = particle.density
         
     | 
| 
      
 134 
     | 
    
         
            +
                      density_n = neighbor.density
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                      # This *should* never happen, but it's good to check,
         
     | 
| 
      
 137 
     | 
    
         
            +
                      # because we're dividing by density later
         
     | 
| 
      
 138 
     | 
    
         
            +
                      raise "Particle density is, impossibly, 0" unless density_n != 0
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                      # Pressure derived from the ideal gas law (constant temp)
         
     | 
| 
      
 141 
     | 
    
         
            +
                      pressure_p = K * (density_p - DENSITY)
         
     | 
| 
      
 142 
     | 
    
         
            +
                      pressure_n = K * (density_n - DENSITY)
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                      # Navier-Stokes equations for pressure and viscosity
         
     | 
| 
      
 145 
     | 
    
         
            +
                      # (ignoring surface tension)
         
     | 
| 
      
 146 
     | 
    
         
            +
                      particle.pressure_force += gradient_weight_spiky(distance, H) *
         
     | 
| 
      
 147 
     | 
    
         
            +
                        (-1.0 * MASS * (pressure_p + pressure_n) / (2 * density_n))
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                      particle.viscosity_force +=
         
     | 
| 
      
 150 
     | 
    
         
            +
                        (neighbor.velocity - particle.velocity) *
         
     | 
| 
      
 151 
     | 
    
         
            +
                        (ETA * MASS * (1/density_n) * laplacian_weight_viscosity(distance, H))
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
                  end
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
              def apply_forces delta_time
         
     | 
| 
      
 158 
     | 
    
         
            +
                # Apply forces to particles- make them move!
         
     | 
| 
      
 159 
     | 
    
         
            +
                particles.each do |particle|
         
     | 
| 
      
 160 
     | 
    
         
            +
                  total_force = particle.pressure_force + particle.viscosity_force
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                  # 'Eulerian' style momentum:
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                  # Calculate acceleration from forces
         
     | 
| 
      
 165 
     | 
    
         
            +
                  acceleration = (total_force * (1.0 / particle.density * delta_time)) + GRAVITY
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                  # Update position and velocity
         
     | 
| 
      
 168 
     | 
    
         
            +
                  particle.velocity += acceleration * delta_time
         
     | 
| 
      
 169 
     | 
    
         
            +
                  particle.position += particle.velocity * delta_time
         
     | 
| 
      
 170 
     | 
    
         
            +
                end
         
     | 
| 
      
 171 
     | 
    
         
            +
              end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
              def step delta_time
         
     | 
| 
      
 174 
     | 
    
         
            +
                clear
         
     | 
| 
      
 175 
     | 
    
         
            +
                calculate_density
         
     | 
| 
      
 176 
     | 
    
         
            +
                calculate_forces
         
     | 
| 
      
 177 
     | 
    
         
            +
                apply_forces delta_time
         
     | 
| 
      
 178 
     | 
    
         
            +
              end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
              ##
         
     | 
| 
      
 181 
     | 
    
         
            +
              # The walls nudge particles back in-bounds, plus a little jitter
         
     | 
| 
      
 182 
     | 
    
         
            +
              # so nothing gets stuck
         
     | 
| 
      
 183 
     | 
    
         
            +
              #
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
              def make_particles_stay_in_bounds scale
         
     | 
| 
      
 186 
     | 
    
         
            +
                # TODO: Better boundary conditions (THESE ARE A LAME WORKAROUND)
         
     | 
| 
      
 187 
     | 
    
         
            +
                particles.each do |particle|
         
     | 
| 
      
 188 
     | 
    
         
            +
                  if particle.position.x >= scale - 0.01
         
     | 
| 
      
 189 
     | 
    
         
            +
                    particle.position.x = scale - (0.01 + 0.1*rand)
         
     | 
| 
      
 190 
     | 
    
         
            +
                    particle.velocity.x = 0
         
     | 
| 
      
 191 
     | 
    
         
            +
                  elsif particle.position.x < 0.01
         
     | 
| 
      
 192 
     | 
    
         
            +
                    particle.position.x = 0.01 + 0.1*rand
         
     | 
| 
      
 193 
     | 
    
         
            +
                    particle.velocity.x = 0
         
     | 
| 
      
 194 
     | 
    
         
            +
                  end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                  if particle.position.y >= scale - 0.01
         
     | 
| 
      
 197 
     | 
    
         
            +
                    particle.position.y = scale - (0.01+rand*0.1)
         
     | 
| 
      
 198 
     | 
    
         
            +
                    particle.velocity.y = 0
         
     | 
| 
      
 199 
     | 
    
         
            +
                  elsif particle.position.y < 0.01
         
     | 
| 
      
 200 
     | 
    
         
            +
                    particle.position.y = 0.01 + rand*0.1
         
     | 
| 
      
 201 
     | 
    
         
            +
                    particle.velocity.y = 0
         
     | 
| 
      
 202 
     | 
    
         
            +
                  end
         
     | 
| 
      
 203 
     | 
    
         
            +
                end
         
     | 
| 
      
 204 
     | 
    
         
            +
              end
         
     | 
| 
      
 205 
     | 
    
         
            +
            end
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
            class SimulationWindow < Graphics::Simulation
         
     | 
| 
      
 208 
     | 
    
         
            +
              WINSIZE = 500
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
              attr_reader :simulation, :s
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
              DELTA_TIME = 0.1
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 215 
     | 
    
         
            +
                super WINSIZE, WINSIZE, 16, "Smoothed Particle Hydrodynamics"
         
     | 
| 
      
 216 
     | 
    
         
            +
                @simulation = SPH.new
         
     | 
| 
      
 217 
     | 
    
         
            +
                @scale = 15
         
     | 
| 
      
 218 
     | 
    
         
            +
                @s = WINSIZE.div @scale
         
     | 
| 
      
 219 
     | 
    
         
            +
              end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
              def update time
         
     | 
| 
      
 222 
     | 
    
         
            +
                simulation.step DELTA_TIME
         
     | 
| 
      
 223 
     | 
    
         
            +
                simulation.make_particles_stay_in_bounds @scale
         
     | 
| 
      
 224 
     | 
    
         
            +
              end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
              def draw time
         
     | 
| 
      
 227 
     | 
    
         
            +
                clear
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                simulation.particles.each do |particle|
         
     | 
| 
      
 230 
     | 
    
         
            +
                  pos = particle.position * s
         
     | 
| 
      
 231 
     | 
    
         
            +
                  vel = particle.velocity * s
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
                  # Particles
         
     | 
| 
      
 234 
     | 
    
         
            +
                  circle(pos.x, pos.y, 5, :white)
         
     | 
| 
      
 235 
     | 
    
         
            +
                  circle(pos.x, pos.y, particle.density, :gray)
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
                  # Velocity vectors
         
     | 
| 
      
 238 
     | 
    
         
            +
                  p2 = pos + vel
         
     | 
| 
      
 239 
     | 
    
         
            +
                  line(pos.x, pos.y, p2.x, p2.y, :red)
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
                  fps time
         
     | 
| 
      
 242 
     | 
    
         
            +
                end
         
     | 
| 
      
 243 
     | 
    
         
            +
              end
         
     | 
| 
      
 244 
     | 
    
         
            +
            end
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
            SimulationWindow.new.run
         
     |