From 501ec02e894865836f2960b0bbc16b3448e3707f Mon Sep 17 00:00:00 2001 From: realtradam Date: Mon, 9 Aug 2021 09:15:38 -0400 Subject: ruboids! --- assets/Background.png | Bin 0 -> 210943 bytes assets/Guppy Large Normal.png | Bin 0 -> 11952 bytes assets/Guppy Small Normal.png | Bin 0 -> 5716 bytes assets/Jellyfish3.png | Bin 0 -> 7246 bytes assets/Predator 1.png | Bin 0 -> 12221 bytes lib/00-define.rb | 2 +- lib/01-render.rb | 20 +++----- lib/02-apply_boid_calculations.rb | 48 +++++++++++++++---- lib/03-cohesion.rb | 34 ------------- lib/04-seperation.rb | 16 ------- lib/rules/alignment.rb | 20 ++++++++ lib/rules/bounds.rb | 15 ++++++ lib/rules/cohesion.rb | 21 ++++++++ lib/rules/limit.rb | 13 +++++ lib/rules/seperation.rb | 14 ++++++ lib/rules/target.rb | 6 +++ run.rb | 98 +++++++++++++++++++++++--------------- 17 files changed, 196 insertions(+), 111 deletions(-) create mode 100644 assets/Background.png create mode 100644 assets/Guppy Large Normal.png create mode 100644 assets/Guppy Small Normal.png create mode 100644 assets/Jellyfish3.png create mode 100644 assets/Predator 1.png delete mode 100644 lib/03-cohesion.rb delete mode 100644 lib/04-seperation.rb create mode 100644 lib/rules/alignment.rb create mode 100644 lib/rules/bounds.rb create mode 100644 lib/rules/cohesion.rb create mode 100644 lib/rules/limit.rb create mode 100644 lib/rules/seperation.rb create mode 100644 lib/rules/target.rb diff --git a/assets/Background.png b/assets/Background.png new file mode 100644 index 0000000..a865ecd Binary files /dev/null and b/assets/Background.png differ diff --git a/assets/Guppy Large Normal.png b/assets/Guppy Large Normal.png new file mode 100644 index 0000000..5c4224a Binary files /dev/null and b/assets/Guppy Large Normal.png differ diff --git a/assets/Guppy Small Normal.png b/assets/Guppy Small Normal.png new file mode 100644 index 0000000..02fd562 Binary files /dev/null and b/assets/Guppy Small Normal.png differ diff --git a/assets/Jellyfish3.png b/assets/Jellyfish3.png new file mode 100644 index 0000000..9a4658c Binary files /dev/null and b/assets/Jellyfish3.png differ diff --git a/assets/Predator 1.png b/assets/Predator 1.png new file mode 100644 index 0000000..90e4794 Binary files /dev/null and b/assets/Predator 1.png differ diff --git a/lib/00-define.rb b/lib/00-define.rb index b0606a2..0075b7f 100644 --- a/lib/00-define.rb +++ b/lib/00-define.rb @@ -1,5 +1,5 @@ FF::Stg.add FF::Scn.new('Default') -FF::Stg.add FF::Scn.new('BoidCalculations') +FF::Scn.new('BoidCalculations') FelFlame::Components.new('Boids', # holds the object to render diff --git a/lib/01-render.rb b/lib/01-render.rb index e3a1271..a4542e9 100644 --- a/lib/01-render.rb +++ b/lib/01-render.rb @@ -1,21 +1,13 @@ -#FF::Scn::Default.add(FelFlame::Systems.new('Render', priority: 99) do -# Camera._redraw -#end) FF::Scn::Default.add(FelFlame::Systems.new('Render', priority: 99) do FelFlame::Components::Boids.each do |boid| renderable = boid.entities[0].components[FF::Cmp::BoidVisuals][0] - renderable.vect.x2 = renderable.vect.x1 = renderable.obj.x = boid.x + renderable.obj.radius - renderable.vect.y2 = renderable.vect.y1 = renderable.obj.y = boid.y + renderable.obj.radius - renderable.vect.x1 += renderable.obj.radius - renderable.vect.y1 += renderable.obj.radius + renderable.vect.x1 = renderable.obj.x = boid.x + renderable.obj.width + renderable.vect.y1 = renderable.obj.y = boid.y + renderable.obj.height + renderable.vect.x2 = renderable.vect.x1 += renderable.obj.width / 2.0 + renderable.vect.y2 = renderable.vect.y1 += renderable.obj.height / 2.0 - renderable.vect.x2 += (boid.vx * 3) + (renderable.obj.radius * 2) - renderable.vect.y2 += (boid.vy * 3) + (renderable.obj.radius * 2) - #Circle.draw(x: boid.x, - # y: boid.y, - # color: [0.86,0.57,0.96,1], - # radius: 7, - # sectors: 10) + renderable.vect.x2 += (boid.vx * 10.0) + renderable.vect.y2 += (boid.vy * 10.0) end Camera._redraw end) diff --git a/lib/02-apply_boid_calculations.rb b/lib/02-apply_boid_calculations.rb index 250a394..8b84ab5 100644 --- a/lib/02-apply_boid_calculations.rb +++ b/lib/02-apply_boid_calculations.rb @@ -1,15 +1,47 @@ -FF::Scn::BoidCalculations.add(FF::Sys.new('ApplyBoidCalculations', priority: 51) do +FF::Scn::BoidCalculations.add(FF::Sys.new('ApplyBoidCalculations', priority: 75) do + @center ||= Camera::Circle.new(color: [0.25,0.0,0.5,0.5], + radius: 10, + sectors: 10, + z: -49) + @center_vel ||= Camera::Line.new(color: [0.25,0.0,0.5,0.5], + width: 12, + z: -50) + unless $config.debug + @center.remove + @center_vel.remove + end + + group_velocity = [0.0,0.0] + center_mass = [0.0,0.0] + boids_count = FF::Cmp::Boids.each.to_a.count + FF::Cmp::Boids.each do |boid| boid.vx += boid.cx boid.vy += boid.cy + FF::Sys::Limit.call boid.x += boid.vx boid.y += boid.vy - #boid.obj.x = boid.obj.x - #boid.vect.x1 = boid.obj.x + 7 - #boid.vect.y1 = boid.obj.y + 7 - #boid.vect.x2 = boid.obj.x + (boid.vx * 3) + 7 - #boid.vect.y2 = boid.obj.y + (boid.vy * 3) + 7 - boid.cx = 0 - boid.cy = 0 + + boid.cx = 0.0 + boid.cy = 0.0 + + + center_mass[0] += boid.x + center_mass[1] += boid.y + group_velocity[0] += boid.vx + group_velocity[1] += boid.vy + end + + @center_vel.x1 = @center.x = (center_mass[0] / boids_count) + @center_vel.y1 = @center.y = (center_mass[1] / boids_count) + + @center_vel.x1 += @center.radius + @center_vel.y1 += @center.radius + + if $follow + Camera.x = @center_vel.x1 = @center.x + @center.radius + Camera.y = @center_vel.y1 = @center.y + @center.radius end + @center_vel.x2 = @center_vel.x1 + ((group_velocity[0] / boids_count) * 10.0) + @center_vel.y2 = @center_vel.y1 + ((group_velocity[1] / boids_count) * 10.0) end) diff --git a/lib/03-cohesion.rb b/lib/03-cohesion.rb deleted file mode 100644 index 49ede9c..0000000 --- a/lib/03-cohesion.rb +++ /dev/null @@ -1,34 +0,0 @@ -FF::Scn::BoidCalculations.add(FF::Sys.new('Cohesion', priority: 50) do - @center ||= Camera::Circle.new(color: [1,0.3,0.4,1], - radius: 15, - sectors: 10) - - center_mass = [0,0] - boids_count = FF::Cmp::Boids.each.to_a.count - - FF::Cmp::Boids.each do |boid| - center_mass[0] += boid.x - center_mass[1] += boid.y - end - - - center_mass[0] #/= boids_count - center_mass[1] #/= boids_count - - @center.x = (center_mass[0] / boids_count) - @center.y = (center_mass[1] / boids_count) - - #Camera.x = center_mass[0] / boids_count - #Camera.y = center_mass[1] / boids_count - - FF::Cmp::Boids.each do |boid_update| - move_boid = center_mass.dup - move_boid[0] -= boid_update.x - move_boid[1] -= boid_update.y - move_boid[0] /= boids_count - 1 - move_boid[1] /= boids_count - 1 - - boid_update.cx += (move_boid[0] - boid_update.x) / 1000.0 - boid_update.cy += (move_boid[1] - boid_update.y) / 1000.0 - end -end) diff --git a/lib/04-seperation.rb b/lib/04-seperation.rb deleted file mode 100644 index dad82f6..0000000 --- a/lib/04-seperation.rb +++ /dev/null @@ -1,16 +0,0 @@ -FF::Scn::BoidCalculations.add(FF::Sys.new('Seperation', priority: 50) do - FF::Cmp::Boids.each do |boid_update| - newvec = [0,0] - FF::Cmp::Boids.each do |boid_check| - next if boid_check == boid_update - if Math.sqrt(((-boid_check.x + boid_update.x)**2) + ((-boid_check.y + boid_update.y)**2)).abs < 200 - puts 'repelling' - newvec[0] -= boid_check.x - boid_update.x - newvec[1] -= boid_check.y - boid_update.y - end - end - boid_update.cx += newvec[0] / 100.0 - boid_update.cy += newvec[1] / 100.0 - end - puts 'end of frame' -end) diff --git a/lib/rules/alignment.rb b/lib/rules/alignment.rb new file mode 100644 index 0000000..b30683c --- /dev/null +++ b/lib/rules/alignment.rb @@ -0,0 +1,20 @@ +FF::Sys.new('Alignment', priority: 50) do + group_velocity = [0.0,0.0] + boids_count = FF::Cmp::Boids.each.to_a.count + + FF::Cmp::Boids.each do |boid| + group_velocity[0] += boid.vx + group_velocity[1] += boid.vy + end + + FF::Cmp::Boids.each do |boid_update| + move_boid = group_velocity.dup + move_boid[0] -= boid_update.vx + move_boid[1] -= boid_update.vy + move_boid[0] /= boids_count - 1.0 + move_boid[1] /= boids_count - 1.0 + + boid_update.cx += (move_boid[0] - boid_update.vx) / $alignment + boid_update.cy += (move_boid[1] - boid_update.vy) / $alignment + end +end diff --git a/lib/rules/bounds.rb b/lib/rules/bounds.rb new file mode 100644 index 0000000..5045d60 --- /dev/null +++ b/lib/rules/bounds.rb @@ -0,0 +1,15 @@ +FF::Sys.new('Bounds', priority: 50) do + FF::Cmp::Boids.each do |boid| + if boid.x > $config.xmax + boid.cx -= $config.bounds_strength + elsif boid.x < $config.xmin + boid.cx += $config.bounds_strength + end + + if boid.y > $config.ymax + boid.cy -= $config.bounds_strength + elsif boid.y < $config.ymin + boid.cy += $config.bounds_strength + end + end +end diff --git a/lib/rules/cohesion.rb b/lib/rules/cohesion.rb new file mode 100644 index 0000000..efbd71d --- /dev/null +++ b/lib/rules/cohesion.rb @@ -0,0 +1,21 @@ +FF::Sys.new('Cohesion', priority: 50) do + + center_mass = [0.0,0.0] + boids_count = FF::Cmp::Boids.each.to_a.count + + FF::Cmp::Boids.each do |boid| + center_mass[0] += boid.x + center_mass[1] += boid.y + end + + FF::Cmp::Boids.each do |boid_update| + move_boid = center_mass.dup + move_boid[0] -= boid_update.x + move_boid[1] -= boid_update.y + move_boid[0] /= boids_count - 1.0 + move_boid[1] /= boids_count - 1.0 + + boid_update.cx += (move_boid[0] - boid_update.x) / $cohesion + boid_update.cy += (move_boid[1] - boid_update.y) / $cohesion + end +end diff --git a/lib/rules/limit.rb b/lib/rules/limit.rb new file mode 100644 index 0000000..c454de4 --- /dev/null +++ b/lib/rules/limit.rb @@ -0,0 +1,13 @@ +# This special function is already called by apply_boid_calculations.rb +# do not add or call this function elsewhere +FF::Sys.new('Limit') do + unless $limit < 0 + FF::Cmp::Boids.each do |boid| + absolute_velocity = Math.sqrt((boid.vx**2) + (boid.vy**2)) + if absolute_velocity > $limit + boid.vx = (boid.vx / absolute_velocity) * $limit + boid.vy = (boid.vy / absolute_velocity) * $limit + end + end + end +end diff --git a/lib/rules/seperation.rb b/lib/rules/seperation.rb new file mode 100644 index 0000000..31039f3 --- /dev/null +++ b/lib/rules/seperation.rb @@ -0,0 +1,14 @@ +FF::Sys.new('Seperation', priority: 50) do + FF::Cmp::Boids.each do |boid_update| + newvec = [0.0,0.0] + FF::Cmp::Boids.each do |boid_check| + next if boid_check == boid_update + if Math.sqrt(((-boid_check.x + boid_update.x)**2) + ((-boid_check.y + boid_update.y)**2)).abs < $seperation_distance + newvec[0] -= boid_check.x - boid_update.x + newvec[1] -= boid_check.y - boid_update.y + end + end + boid_update.cx += newvec[0] / $seperation + boid_update.cy += newvec[1] / $seperation + end +end diff --git a/lib/rules/target.rb b/lib/rules/target.rb new file mode 100644 index 0000000..ffee93a --- /dev/null +++ b/lib/rules/target.rb @@ -0,0 +1,6 @@ +FF::Sys.new('Target', priority: 50) do + FF::Cmp::Boids.each do |boid| + boid.cx += ($x_target - boid.x) / $target_strength + boid.cy += ($y_target - boid.y) / $target_strength + end +end diff --git a/run.rb b/run.rb index bfce180..e21f723 100644 --- a/run.rb +++ b/run.rb @@ -1,65 +1,88 @@ require 'ruby2d' require 'ruby2d/camera' require 'felflame' +# If Camera should follow center mass +$follow = false +# Values that can tune strength of certain rules +# Lower is stronger +$cohesion = 3000.0 +$seperation = 75.0 +$seperation_distance = 125.0 +$alignment = 1000.0 +$target_strength = 2500.0 + +# The velocity limit of a boid +# Set to negative to remove limit +$limit = 12.0 + +# These are changed later by mouse position +$x_target = 0.0 +$y_target = 0.0 + +FF::Cmp.new('SingletonConfig', + debug: false, + bounds_strength: 2.0, + xmax: 480.0, xmin: -580.0, + ymax: 250.0, ymin: -340.0) +$config = FF::Cmp::SingletonConfig.new + +# Used by the Camera Library +set(title: "Ruboids", width: 1164, height: 764, resizable: true) Dir[File.join(__dir__, 'lib/**', '*.rb')].sort.each { |file| require file } -#FF::Scn::BoidCalculations.remove FF::Sys::Cohesion -FF::Stg.remove FF::Scn::BoidCalculations +# Comment out to remove a rule +FF::Scn::BoidCalculations.add FF::Sys::Cohesion +FF::Scn::BoidCalculations.add FF::Sys::Alignment +FF::Scn::BoidCalculations.add FF::Sys::Seperation +FF::Scn::BoidCalculations.add FF::Sys::Target +FF::Scn::BoidCalculations.add FF::Sys::Bounds + +FF::Stg.add FF::Scn::BoidCalculations class GameWindow < Ruby2D::Window def initialize super - #Camera.x = 10 - #Camera.y = 10 - randspot = ((-720 / 2)..(720/2)).to_a - @ent = FF::Ent.new( - FF::Cmp::Boids.new(x: randspot.sample, y:randspot.sample), - FF::Cmp::BoidVisuals.new( - obj: Camera::Circle.new( - color: [0.86,1.0,0.96,1], - radius: 7, - sectors: 10 - ), - vect: Camera::Line.new( - width: 7, - color: 'red', - z: -1 - ) - ) - ) - 5.times do + Camera::Image.new('assets/Background.png', x: -get(:width)+57, y: -get(:height)+97, z: -99) + randspot = ((-get(:height) / 2)..(get(:height)/2)).to_a + 6.times do FF::Ent.new( - FF::Cmp::Boids.new(x: randspot.sample, y:randspot.sample), + FF::Cmp::Boids.new(x: randspot.sample.to_f, y: randspot.sample.to_f), FF::Cmp::BoidVisuals.new( - obj: Camera::Circle.new( - color: [0.86,0.57,0.96,1], - radius: 7, - sectors: 10 + obj: Camera::Image.new( + 'assets/Guppy Large Normal.png', + width: 45, height: 46 + #obj: Camera::Circle.new( + # color: [0.86,0.57,0.96,1], + # radius: 7, + # sectors: 10 ), vect: Camera::Line.new( width: 7, - color: 'red', + color: [1.0,0,0,0.5], z: -1 ) ) ) end + unless $config.debug + FF::Cmp::BoidVisuals.each do |boid| + boid.vect.remove + end + end end def update + $x_target = Camera.coordinate_to_worldspace(get(:mouse_x), get(:mouse_y))[0] + $y_target = Camera.coordinate_to_worldspace(get(:mouse_y), get(:mouse_y))[1] FF::Stage.call - Camera.y += 5 if key_held('s') - Camera.y -= 5 if key_held('w') - Camera.x += 5 if key_held('d') - Camera.x -= 5 if key_held('a') + Camera.y += 1 if key_held('s') + Camera.y -= 1 if key_held('w') + Camera.x += 1 if key_held('d') + Camera.x -= 1 if key_held('a') Camera.zoom *= 1.1 if key_held('z') Camera.zoom /= 1.1 if key_held('x') if key_held('space') - FF::Scn::BoidCalculations.call #if key_held('space') - puts "X: #{@ent.components[FF::Cmp::Boids].first.x}" - puts "Y: #{@ent.components[FF::Cmp::Boids].first.y}" - puts "VX:#{@ent.components[FF::Cmp::Boids].first.vx}" - puts "VY:#{@ent.components[FF::Cmp::Boids].first.vy}" + FF::Scn::BoidCalculations.call end end @@ -69,6 +92,5 @@ end gamewindow = GameWindow.new -set(title: "Ruboids", width: 1280, height: 720, resizable: true) -gamewindow.set(title: "Ruboids", width: 1280, height: 720, resizable: true) +gamewindow.set(title: get(:title), width: get(:width), height: get(:height), resizable: get(:resizable)) gamewindow.show -- cgit v1.2.3