You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.1 KiB
142 lines
3.1 KiB
#
|
|
# Copyright (c) 2001 by Jim Menard <jimm@io.com>
|
|
#
|
|
# Released under the same license as Ruby. See
|
|
# http://www.ruby-lang.org/en/LICENSE.txt.
|
|
#
|
|
|
|
require 'BoidView'
|
|
require 'Flock'
|
|
require 'Point'
|
|
require 'Params'
|
|
|
|
class Boid < Thing
|
|
|
|
attr_accessor :maxSpeed, :maxSpeedSquared, :perchingTurnsLeft,
|
|
:wingFlapPos, :almostGroundLevel, :flock
|
|
|
|
def initialize(pos = nil)
|
|
super(pos, nil)
|
|
init
|
|
end
|
|
|
|
def init
|
|
@maxSpeed = $PARAMS['boid_max_speed']
|
|
@maxSpeedSquared = @maxSpeed * @maxSpeed
|
|
@flock = nil # set by flock when flock adds to self
|
|
@wingFlapPos = rand(7)
|
|
@perchingTurnsLeft = 0
|
|
@almostGroundLevel = 5.0
|
|
|
|
@view = BoidView.new(self)
|
|
end
|
|
|
|
def move
|
|
# Flap wings. Only flap occasionally if not perching.
|
|
if (@perchingTurnsLeft == 0 ||
|
|
rand(100) < $PARAMS['boid_perch_wing_flap_percent'])
|
|
@wingFlapPos = (@wingFlapPos + 1) & 7
|
|
end
|
|
|
|
if @perchingTurnsLeft > 0
|
|
# Only take off when wing flap position == 2.
|
|
if --@perchingTurnsLeft == 0 && @wingFlapPos != 2
|
|
@perchingTurnsLeft = (8 + 2 - @wingFlapPos) & 7
|
|
return
|
|
end
|
|
end
|
|
|
|
moveTowardsFlockCenter()
|
|
avoidOthers()
|
|
matchOthersVelocities()
|
|
boundPosition()
|
|
limitSpeed()
|
|
|
|
super() # Add velocity vector to position.
|
|
|
|
# Boids at ground level perch for a while.
|
|
if @position.y < @almostGroundLevel
|
|
@position.y = @almostGroundLevel
|
|
@vector.x = @vector.y = @vector.z = 0
|
|
@perchingTurnsLeft =
|
|
rand($PARAMS['boid_max_perching_turns'])
|
|
end
|
|
end
|
|
|
|
def moveTowardsFlockCenter()
|
|
flockCenter = @flock.centerExcluding(self)
|
|
flockCenter.subtractPoint(@position)
|
|
# Move 1% of the way towards the center
|
|
flockCenter.divideBy(100.0)
|
|
|
|
@vector.addPoint(flockCenter)
|
|
end
|
|
|
|
def avoidOthers()
|
|
c = Point.new()
|
|
@flock.members.each { | b |
|
|
if b != self
|
|
otherPos = b.position
|
|
if @position.squareOfDistanceTo(otherPos) <
|
|
$PARAMS['boid_square_of_personal_space_dist']
|
|
c.addPoint(@position)
|
|
c.subtractPoint(otherPos)
|
|
end
|
|
end
|
|
}
|
|
@vector.addPoint(c)
|
|
end
|
|
|
|
def matchOthersVelocities()
|
|
vel = Point.new()
|
|
flock.members.each { | b |
|
|
if b != self
|
|
vel.addPoint(b.vector)
|
|
end
|
|
}
|
|
vel.divideBy(flock.members.length - 1)
|
|
vel.subtractPoint(@vector)
|
|
vel.divideBy(8)
|
|
|
|
@vector.addPoint(vel)
|
|
end
|
|
|
|
def boundPosition()
|
|
v = Point.new
|
|
|
|
halfWidth = $PARAMS['world_width'] / 2
|
|
halfHeight = $PARAMS['world_height'] / 2
|
|
halfDepth = $PARAMS['world_depth'] / 2
|
|
|
|
if position.x < -halfWidth
|
|
v.x = $PARAMS['boid_bounds_limit_pull']
|
|
elsif position.x > halfWidth
|
|
v.x = -$PARAMS['boid_bounds_limit_pull']
|
|
end
|
|
|
|
if position.y < -halfHeight + almostGroundLevel +
|
|
$PARAMS['boid_bounds_limit_above_ground_level']
|
|
v.y = $PARAMS['boid_bounds_limit_pull']
|
|
elsif position.y > halfHeight
|
|
v.y = -$PARAMS['boid_bounds_limit_pull']
|
|
end
|
|
|
|
if position.z < -halfDepth
|
|
v.z = $PARAMS['boid_bounds_limit_pull']
|
|
elsif position.z > halfDepth
|
|
v.z = -$PARAMS['boid_bounds_limit_pull']
|
|
end
|
|
|
|
@vector.addPoint(v)
|
|
end
|
|
|
|
def limitSpeed()
|
|
speedSquared = Point::ORIGIN.squareOfDistanceTo(@vector)
|
|
if speedSquared > @maxSpeedSquared
|
|
f = Math.sqrt(speedSquared) * @maxSpeed
|
|
@vector.divideBy(f)
|
|
end
|
|
end
|
|
end
|
|
|