class TankPhysics

Attributes

collides_with[RW]
in_collision[RW]
speed[RW]

Public Class Methods

new(game_object, object_pool) click to toggle source
Calls superclass method Component::new
# File lib/entities/components/tank_physics.rb, line 4
def initialize(game_object, object_pool)
  super(game_object)
  @object_pool = object_pool
  @map = object_pool.map
  @speed = 0.0
end

Public Instance Methods

box() click to toggle source

Tank box looks like H. Vertices: 1 2 5 6

 3   4

10   9

12 11 8 7

# File lib/entities/components/tank_physics.rb, line 69
def box
  w = box_width / 2 - 1
  h = box_height / 2 - 1
  tw = 8 # track width
  fd = 8 # front depth
  rd = 6 # rear depth
  Utils.rotate(object.direction, x, y,
               x + w,      y + h,      #1
               x + w - tw, y + h,      #2
               x + w - tw, y + h - fd, #3

               x - w + tw, y + h - fd, #4
               x - w + tw, y + h,      #5
               x - w,      y + h,      #6

               x - w,      y - h,      #7
               x - w + tw, y - h,      #8
               x - w + tw, y - h + rd, #9

               x + w - tw, y - h + rd, #10
               x + w - tw, y - h,      #11
               x + w,      y - h,      #12
              )
end
box_height() click to toggle source
# File lib/entities/components/tank_physics.rb, line 55
def box_height
  @box_height ||= object.graphics.height
end
box_width() click to toggle source
# File lib/entities/components/tank_physics.rb, line 59
def box_width
  @box_width ||= object.graphics.width
end
can_move_to?(x, y) click to toggle source
# File lib/entities/components/tank_physics.rb, line 11
def can_move_to?(x, y)
  old_x, old_y = object.x, object.y
  object.move(x, y)
  return false unless @map.can_move_to?(x, y)
  @object_pool.nearby(object, 100).each do |obj|
    next if obj.class == Bullet && obj.source == object
    if collides_with_poly?(obj.box)
      if obj.is_a? Powerup
        obj.on_collision(object)
      else
        @collides_with = obj
        # Allow to get unstuck
        old_distance = Utils.distance_between(
          obj.x, obj.y, old_x, old_y)
        new_distance = Utils.distance_between(
          obj.x, obj.y, x, y)
        return false if new_distance < old_distance
      end
    else
      @collides_with = nil
    end
  end
  true
ensure
  object.move(old_x, old_y)
end
change_direction(new_direction) click to toggle source
# File lib/entities/components/tank_physics.rb, line 38
def change_direction(new_direction)
  change = (new_direction - object.direction + 360) % 360
  change = 360 - change if change > 180
  if change > 90
    @speed = 0
  elsif change > 45
    @speed *= 0.33
  elsif change > 0
    @speed *= 0.66
  end
  object.direction = new_direction % 360
end
moving?() click to toggle source
# File lib/entities/components/tank_physics.rb, line 51
def moving?
  @speed > 0
end
update() click to toggle source
# File lib/entities/components/tank_physics.rb, line 94
def update
  if object.throttle_down && !object.health.dead?
    accelerate
  else
    decelerate
  end
  if @speed > 0
    new_x, new_y = x, y
    speed = apply_movement_penalty(@speed)
    shift = Utils.adjust_speed(speed) * object.speed_modifier
    case @object.direction.to_i
    when 0
      new_y -= shift
    when 45
      new_x += shift
      new_y -= shift
    when 90
      new_x += shift
    when 135
      new_x += shift
      new_y += shift
    when 180
      new_y += shift
    when 225
      new_y += shift
      new_x -= shift
    when 270
      new_x -= shift
    when 315
      new_x -= shift
      new_y -= shift
    end
    if can_move_to?(new_x, new_y)
      object.move(new_x, new_y)
      @in_collision = false
    else
      object.on_collision(@collides_with)
      @speed = 0.0
      @in_collision = true
    end
  end
end

Private Instance Methods

accelerate() click to toggle source
# File lib/entities/components/tank_physics.rb, line 143
def accelerate
  @speed += 0.08 if @speed < 5
end
apply_movement_penalty(speed) click to toggle source
# File lib/entities/components/tank_physics.rb, line 139
def apply_movement_penalty(speed)
  speed * (1.0 - @map.movement_penalty(x, y))
end
collides_with_point?(x, y) click to toggle source
# File lib/entities/components/tank_physics.rb, line 176
def collides_with_point?(x, y)
  Utils.point_in_poly(x, y, box)
end
collides_with_poly?(poly) click to toggle source
# File lib/entities/components/tank_physics.rb, line 160
def collides_with_poly?(poly)
  if poly
    if poly.size == 2
      px, py = poly
      return Utils.point_in_poly(px, py, *box)
    end
    poly.each_slice(2) do |x, y|
      return true if Utils.point_in_poly(x, y, *box)
    end
    box.each_slice(2) do |x, y|
      return true if Utils.point_in_poly(x, y, *poly)
    end
  end
  false
end
damp_speed() click to toggle source
# File lib/entities/components/tank_physics.rb, line 156
def damp_speed
  @speed = 0 if @speed < 0.01
end
decelerate() click to toggle source
# File lib/entities/components/tank_physics.rb, line 147
def decelerate
  if @speed > 0
    @speed = [@speed - 0.5, 0].max
  elsif @speed < 0
    @speed = [@speed + 0.5, 0].min
  end
  damp_speed
end