# saucer.rb author Martin Prout
class Saucer
# makes use of mixin to replace java inner class
include Processing::Proxy
R1 = 4.0 # class constants that together
R2 = 3.0 # with PI constants are used
R3 = 6.0 # to define the Saucer shape
A1 = 0.25
A2 = 0.60
A3 = 0.0
MAX_THETA = QUARTER_PI/2
# read accessors
attr_reader :acc, :loc, :vel, :my_scale, :tilt, :wdth, :hght
def initialize xpos, ypos, acc_y, acc_x, width, height
@my_scale = 0.0
@tilt = 0
@loc = PVector.new xpos, ypos
@vel = PVector.new 0, 0
@acc = PVector.new acc_x, acc_y
@focus = PVector.new xpos, ypos
@wdth = width # frame width
@hght = height # frame height
end
def height # copes with tilting saucer
# avoided using ternary statement here
wd = R3 * 2 * Math.sin(tilt) * my_scale
ht = R2 * 2 * Math.sin(tilt) * my_scale
if (ht > wd)
return ht
else
return wd
end
end
def width # copes with tilting saucer
return R3 * 2 * Math.cos(tilt) * my_scale
end
def distance
@focus.dist loc
end
def get_point radius, theta
x = loc.x + (radius * Math.cos(theta + tilt)) *my_scale
y = loc.y + (radius * Math.sin(theta + tilt)) *my_scale
return x, y
end
def set_tilt(theta)
theta = Saucer::MAX_THETA if theta > Saucer::MAX_THETA
theta = -Saucer::MAX_THETA if theta < -Saucer::MAX_THETA
@tilt = theta
end
def set_position x, y
@loc.x = x
@loc.y = y
end
def set_scale(scale)
@my_scale = scale unless scale < 0
end
def render
smooth
curve_tightness(-0.05)
begin_shape
x, y = get_point(Saucer::R1, Saucer::A1)
curve_vertex(x, y)
x, y = get_point(Saucer::R2, TWO_PI - Saucer::A2)
curve_vertex(x, y)
x, y = get_point(Saucer::R2, PI + Saucer::A2)
curve_vertex(x, y)
x, y = get_point(Saucer::R1, PI - Saucer::A1)
curve_vertex(x, y)
x, y = get_point(Saucer::R2, PI + Saucer::A2)
vertex(x, y)
x, y = get_point(Saucer::R3, PI)
vertex(x, y)
vertex(x, y)
x, y = get_point(Saucer::R1, PI - Saucer::A1)
vertex(x, y)
vertex(x, y)
x, y = get_point(Saucer::R1, Saucer::A1)
vertex(x, y)
vertex(x, y)
x, y = get_point(Saucer::R3, Saucer::A3)
vertex(x, y)
vertex(x, y)
end_shape CLOSE
end
def update
@vel.x += acc.x
@vel.y += acc.y
@loc.x += vel.x
@loc.y += vel.y
set_scale distance/30
set_tilt vel.x * 0.04
end
def reset_x
@vel.x = 0
# ternary statement gets the job done, best used for assignment?
acc.x < 0 ? @loc.x = self.width/2 : @loc.x = (self.wdth - self.width/2)
@acc.x *= -1
end
def reset_y
@vel.y = 0
acc.y < 0 ? @loc.y = self.height/2 : @loc.y =(self.hght - self.height/2)
@acc.y *= -1
end
end