class Graphics::Body

A body in the simulation.

All bodies know their position, their angle, goal angle (optional), and momentum.

Constants

D2R

degrees to radians

NORMAL

The normals for the cardinal directions.

R2D

radians to degrees

Attributes

a[RW]

Body’s angle, in degrees.

ga[RW]

Body’s goal angle, in degrees.

m[RW]

Body’s magnitude.

w[RW]

Body’s window.

x[RW]

Body’s x coordinate.

y[RW]

Body’s y coordinate.

Public Class Methods

new(w) click to toggle source

Create a new body in windowing system w with a random x/y and everything else zero’d out.

# File lib/graphics/body.rb, line 63
def initialize w
  self.w = w

  self.x, self.y = rand(w.w), rand(w.h)
  self.a = 0.0
  self.ga = 0.0
  self.m = 0.0
end

Public Instance Methods

angle_to(body) click to toggle source

Return the angle to another body in degrees.

# File lib/graphics/body.rb, line 133
def angle_to body
  dx = body.x - self.x
  dy = body.y - self.y

  (R2D * Math.atan2(dy, dx)).degrees
end
bounce(friction = 0.2) click to toggle source

Like clip, keep the body in bounds of the window, but set the angle to the angle of reflection. Also slows momentum by friction%.

# File lib/graphics/body.rb, line 235
def bounce friction = 0.2
  if wall = clip then
    self.a = (2 * NORMAL[wall] - 180 - a).degrees
    self.m *= (1.0 - friction) if friction and friction > 0
    true
  end
end
clip() click to toggle source

Keep the body in bounds of the window. If it went out of bounds, set its position to be on that bound and return the cardinal direction of the wall it hit.

See also: NORMALS

# File lib/graphics/body.rb, line 183
def clip
  max_h, max_w = w.h, w.w

  if x < 0 then
    self.x = x.abs
    return :west
  elsif x > max_w then
    self.x = 2 * max_w - x
    return :east
  end

  if y < 0 then
    self.y = y.abs
    return :south
  elsif y > max_h then
    self.y = 2 * max_h - y
    return :north
  end

  nil
end
clip_off_wall() click to toggle source

clip and then set the goal angle to the normal plus or minus a random 45 degrees.

# File lib/graphics/body.rb, line 224
def clip_off_wall
  if wall = clip then
    normal = NORMAL[wall]
    self.ga = (normal + random_turn(90)).degrees unless (normal - ga).abs < 45
  end
end
distance_to_squared(p) click to toggle source

Return the distance to another body, squared.

# File lib/graphics/body.rb, line 143
def distance_to_squared p
  dx = p.x - x
  dy = p.y - y
  dx * dx + dy * dy
end
move() click to toggle source

Move the body via its current angle and momentum.

# File lib/graphics/body.rb, line 163
def move
  move_by a, m
end
move_by(a, m) click to toggle source

Move the body by a specified angle and momentum.

# File lib/graphics/body.rb, line 170
def move_by a, m
  rad = a * D2R
  self.x += Math.cos(rad) * m
  self.y += Math.sin(rad) * m
end
position() click to toggle source

Convert the body to a vector representing its position.

DO NOT modify this vector expecting it to modify the body. It is a copy.

# File lib/graphics/body.rb, line 111
def position
  V[x, y]
end
position=(o) click to toggle source

Set the body’s position from a velocity vector.

# File lib/graphics/body.rb, line 118
def position= o
  self.x = o.x
  self.y = o.y
end
random_angle() click to toggle source

Return a random angle 0…360.

# File lib/graphics/body.rb, line 208
def random_angle
  360 * rand
end
random_turn(deg) click to toggle source

Randomly turn the body inside an arc of deg degrees from where it is currently facing.

# File lib/graphics/body.rb, line 216
def random_turn deg
  rand(deg) - (deg/2)
end
turn(dir) click to toggle source

Turn the body dir degrees.

# File lib/graphics/body.rb, line 156
def turn dir
  self.a = (a + dir).degrees if dir
end
update() click to toggle source

Update the body. Does nothing by default. Override this method to add behavior to the body.

# File lib/graphics/body.rb, line 76
def update
  # do nothing
end
velocity() click to toggle source

Convert the body to a vector representing its velocity.

DO NOT modify this vector expecting it to modify the body. It is a copy.

# File lib/graphics/body.rb, line 91
def velocity
  x, y = dx_dy
  V[x, y]
end
velocity=(o) click to toggle source

Set the body’s magnitude and angle from a velocity vector.

# File lib/graphics/body.rb, line 99
def velocity= o
  dx, dy = o.x, o.y
  self.m = Math.sqrt(dx*dx + dy*dy)
  self.a = Math.atan2(dy, dx) * R2D
end
wrap() click to toggle source

Wrap the body if it hits an edge.

# File lib/graphics/body.rb, line 246
def wrap
  max_h, max_w = w.h, w.w

  self.x = max_w if x < 0
  self.y = max_h if y < 0

  self.x = 0 if x > max_w
  self.y = 0 if y > max_h
end