# 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