Class: AiGun

Inherits:
Object
  • Object
show all
Defined in:
lib/entities/components/ai/gun.rb

Constant Summary collapse

DECISION_DELAY =
300

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object, vision) ⇒ AiGun

Returns a new instance of AiGun.



5
6
7
8
9
10
11
12
# File 'lib/entities/components/ai/gun.rb', line 5

def initialize(object, vision)
  @object = object
  @vision = vision
  @desired_gun_angle = rand(0..360)
  @retarget_speed = rand(1..5)
  @accuracy = rand(0..10)
  @aggressiveness = rand(1..5)
end

Instance Attribute Details

#desired_gun_angleObject (readonly)

Returns the value of attribute desired_gun_angle.



3
4
5
# File 'lib/entities/components/ai/gun.rb', line 3

def desired_gun_angle
  @desired_gun_angle
end

#targetObject (readonly)

Returns the value of attribute target.



3
4
5
# File 'lib/entities/components/ai/gun.rb', line 3

def target
  @target
end

Instance Method Details

#adjust_angleObject



14
15
16
17
# File 'lib/entities/components/ai/gun.rb', line 14

def adjust_angle
  adjust_desired_angle
  adjust_gun_angle
end

#adjust_desired_angleObject



77
78
79
80
81
82
83
84
# File 'lib/entities/components/ai/gun.rb', line 77

def adjust_desired_angle
  @desired_gun_angle = if @target
     Utils.angle_between(
      @object.x, @object.y, @target.x, @target.y)
  else
    @object.direction
  end
end

#adjust_gun_angleObject



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/entities/components/ai/gun.rb', line 91

def adjust_gun_angle
  actual = @object.gun_angle
  desired = @desired_gun_angle
  if actual > desired
    if actual - desired > 180 # 0 -> 360 fix
      @object.gun_angle = (actual + @retarget_speed) % 360
      if @object.gun_angle < desired
        @object.gun_angle = desired # damp
      end
    else
      @object.gun_angle = [actual - @retarget_speed, desired].max
    end
  elsif actual < desired
    if desired - actual > 180 # 360 -> 0 fix
      @object.gun_angle = (360 + actual - @retarget_speed) % 360
      if @object.gun_angle > desired
        @object.gun_angle = desired # damp
      end
    else
      @object.gun_angle = [actual + @retarget_speed, desired].min
    end
  end
end

#can_make_new_decision?Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
75
# File 'lib/entities/components/ai/gun.rb', line 69

def can_make_new_decision?
  now = Gosu.milliseconds
  if now - (@last_decision ||= 0) > DECISION_DELAY
    @last_decision = now
    true
  end
end

#change_target(new_target) ⇒ Object



86
87
88
89
# File 'lib/entities/components/ai/gun.rb', line 86

def change_target(new_target)
  @target = new_target
  adjust_desired_angle
end

#distance_to_targetObject



59
60
61
62
# File 'lib/entities/components/ai/gun.rb', line 59

def distance_to_target
  Utils.distance_between(
    @object.x, @object.y, @target.x, @target.y)
end

#draw(viewport) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/entities/components/ai/gun.rb', line 45

def draw(viewport)
  if $debug
    color = Gosu::Color::BLUE
    x, y = @object.x, @object.y
    t_x, t_y = Utils.point_at_distance(x, y, @desired_gun_angle,
                                       BulletPhysics::MAX_DIST)
    $window.draw_line(x, y, color, t_x, t_y, color, 1001)
    color = Gosu::Color::RED
    t_x, t_y = Utils.point_at_distance(x, y, @object.gun_angle,
                                       BulletPhysics::MAX_DIST)
    $window.draw_line(x, y, color, t_x, t_y, color, 1000)
  end
end

#should_shoot?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/entities/components/ai/gun.rb', line 65

def should_shoot?
  rand * @aggressiveness > 0.3
end

#updateObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/entities/components/ai/gun.rb', line 19

def update
  if @vision.in_sight.any?
    if @vision.closest_tank != @target
      change_target(@vision.closest_tank)
    end
  else
    @target = nil
  end

  if @target
    if (0..30 - rand(0..@accuracy)).include?(
      (@desired_gun_angle - @object.gun_angle).abs.round)
      distance = distance_to_target
      if distance - 50 <= BulletPhysics::MAX_DIST
        target_x, target_y = Utils.point_at_distance(
          @object.x, @object.y, @object.gun_angle,
          distance + 10 - rand(0..@accuracy))
        if can_make_new_decision? && @object.can_shoot? &&
            should_shoot?
          @object.shoot(target_x, target_y)
        end
      end
    end
  end
end