ruby_arena 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +31 -0
- data/LICENSE.txt +22 -0
- data/README.md +118 -0
- data/Rakefile +5 -0
- data/bin/ruby_arena +7 -0
- data/lib/ruby_arena/ai.rb +68 -0
- data/lib/ruby_arena/arena.rb +75 -0
- data/lib/ruby_arena/bullet.rb +53 -0
- data/lib/ruby_arena/bullet_renderer.rb +53 -0
- data/lib/ruby_arena/class_loader.rb +20 -0
- data/lib/ruby_arena/command_parser.rb +41 -0
- data/lib/ruby_arena/game.rb +74 -0
- data/lib/ruby_arena/gui.rb +62 -0
- data/lib/ruby_arena/level.rb +42 -0
- data/lib/ruby_arena/level0.rb +6 -0
- data/lib/ruby_arena/level1.rb +9 -0
- data/lib/ruby_arena/movable.rb +18 -0
- data/lib/ruby_arena/option_parser.rb +29 -0
- data/lib/ruby_arena/robot.rb +196 -0
- data/lib/ruby_arena/robot_renderer.rb +180 -0
- data/lib/ruby_arena/value_sanitizer.rb +11 -0
- data/lib/ruby_arena/version.rb +3 -0
- data/lib/ruby_arena.rb +23 -0
- data/ruby_arena.gemspec +25 -0
- data/screenshot.png +0 -0
- data/spec/ai_spec.rb +11 -0
- data/spec/ai_test.rb +11 -0
- data/spec/arena_spec.rb +79 -0
- data/spec/bullet_renderer_spec.rb +4 -0
- data/spec/bullet_spec.rb +36 -0
- data/spec/class_loader_spec.rb +14 -0
- data/spec/command_parser_spec.rb +72 -0
- data/spec/fake_gui.rb +28 -0
- data/spec/game_spec.rb +4 -0
- data/spec/gui_spec.rb +50 -0
- data/spec/level_spec.rb +29 -0
- data/spec/movable_tests.rb +48 -0
- data/spec/option_parser_spec.rb +49 -0
- data/spec/robot_renderer_spec.rb +4 -0
- data/spec/robot_spec.rb +294 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/value_sanitizer_spec.rb +21 -0
- metadata +163 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module RubyArena
|
2
|
+
module Movable
|
3
|
+
def move
|
4
|
+
@x += offset_x(heading, speed)
|
5
|
+
@y += offset_y(heading, speed)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def offset_x(heading, speed)
|
11
|
+
Gosu.offset_x(heading, speed)
|
12
|
+
end
|
13
|
+
|
14
|
+
def offset_y(heading, speed)
|
15
|
+
Gosu.offset_y(heading, speed)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class OptionParser
|
2
|
+
def self.parse(args)
|
3
|
+
options = {}
|
4
|
+
|
5
|
+
opt_parser = OptionParser.new do |opts|
|
6
|
+
opts.banner = %{Usage: ruby_arena -l <level> [ai_file]
|
7
|
+
Usage: ruby_arena <ai_file1> [ai_file2] ... [ai_fileN]
|
8
|
+
}
|
9
|
+
|
10
|
+
opts.on("-l", "--level level_number", Integer, "Specify level") do |l|
|
11
|
+
options[:level] = l
|
12
|
+
end
|
13
|
+
|
14
|
+
if args.empty?
|
15
|
+
puts opts
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
20
|
+
puts opts
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
opt_parser.parse!(args)
|
26
|
+
|
27
|
+
options
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module RubyArena
|
2
|
+
class Robot
|
3
|
+
include Movable
|
4
|
+
|
5
|
+
SIZE = 40
|
6
|
+
MAX_SPEED = 8
|
7
|
+
MAX_TURN_ANGLE = 10
|
8
|
+
MAX_TURN_GUN_ANGLE = 30
|
9
|
+
MAX_TURN_RADAR_ANGLE = 60
|
10
|
+
RADAR_RANGE = 1000
|
11
|
+
DEFAULT_RADAR_VIEW_ANGLE = 10
|
12
|
+
|
13
|
+
attr_reader :ai, :tank, :command_parser, :arena
|
14
|
+
attr_reader :x, :y, :speed, :heading, :gun_heading, :radar_heading, :robot
|
15
|
+
attr_reader :energy, :gun_heat
|
16
|
+
attr_accessor :radar_view_angle
|
17
|
+
|
18
|
+
def initialize(args)
|
19
|
+
@command_parser = CommandParser.new
|
20
|
+
@ai = args.fetch(:ai).new(robot: self, command_parser: command_parser)
|
21
|
+
@arena = args.fetch(:arena)
|
22
|
+
@x = args[:x] || rand(arena.width - 2*size)
|
23
|
+
@y = args[:y] || rand(arena.height - 2*size)
|
24
|
+
@speed = args[:speed] || 0
|
25
|
+
@heading = args[:heading] || 0
|
26
|
+
@gun_heading = args[:gun_heading] || heading
|
27
|
+
@radar_heading = args[:radar_heading] || gun_heading
|
28
|
+
@energy = args[:energy] || 100
|
29
|
+
@scanned_robots = []
|
30
|
+
@gun_heat = args[:gun_heat] || 0
|
31
|
+
@radar_view_angle = args[:radar_view_angle] || DEFAULT_RADAR_VIEW_ANGLE
|
32
|
+
end
|
33
|
+
|
34
|
+
def tick
|
35
|
+
ai.tick(tick_events)
|
36
|
+
@gun_heat -= 0.1 if @gun_heat > 0
|
37
|
+
end
|
38
|
+
|
39
|
+
def update
|
40
|
+
execute_actions(actions)
|
41
|
+
reset_actions
|
42
|
+
move
|
43
|
+
fix_position
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute_actions(actions)
|
47
|
+
fire if actions[:fire]
|
48
|
+
turn(actions[:turn]) if actions[:turn]
|
49
|
+
turn_gun(actions[:turn_gun]) if actions[:turn_gun]
|
50
|
+
turn_radar(actions[:turn_radar]) if actions[:turn_radar]
|
51
|
+
accelerate if actions[:accelerate]
|
52
|
+
decelerate if actions[:decelerate]
|
53
|
+
self.radar_view_angle = actions[:radar_view_angle] if actions[:radar_view_angle]
|
54
|
+
end
|
55
|
+
|
56
|
+
def actions
|
57
|
+
command_parser.actions
|
58
|
+
end
|
59
|
+
|
60
|
+
def reset_actions
|
61
|
+
command_parser.reset_actions
|
62
|
+
end
|
63
|
+
|
64
|
+
def accelerate
|
65
|
+
@speed += 1 if speed < MAX_SPEED
|
66
|
+
end
|
67
|
+
|
68
|
+
def decelerate
|
69
|
+
@speed -= 1 if speed > -MAX_SPEED
|
70
|
+
end
|
71
|
+
|
72
|
+
def turn(angle)
|
73
|
+
angle = sanitize_maximum_value(angle, MAX_TURN_ANGLE)
|
74
|
+
self.heading = heading + angle
|
75
|
+
self.gun_heading = gun_heading + angle
|
76
|
+
self.radar_heading = radar_heading + angle
|
77
|
+
end
|
78
|
+
|
79
|
+
def turn_gun(angle)
|
80
|
+
angle = sanitize_maximum_value(angle, MAX_TURN_GUN_ANGLE)
|
81
|
+
self.gun_heading = gun_heading + angle
|
82
|
+
self.radar_heading = radar_heading + angle
|
83
|
+
end
|
84
|
+
|
85
|
+
def turn_radar(angle)
|
86
|
+
angle = sanitize_maximum_value(angle, MAX_TURN_RADAR_ANGLE)
|
87
|
+
self.radar_heading = radar_heading + angle
|
88
|
+
end
|
89
|
+
|
90
|
+
def fire
|
91
|
+
unless gun_heat > 0
|
92
|
+
bullet = new_bullet
|
93
|
+
arena.add_bullet(bullet)
|
94
|
+
3.times { bullet.update }
|
95
|
+
@gun_heat += 3
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def hit(bullet)
|
100
|
+
@energy -= bullet.energy
|
101
|
+
end
|
102
|
+
|
103
|
+
def dead?
|
104
|
+
energy < 0
|
105
|
+
end
|
106
|
+
|
107
|
+
def scan
|
108
|
+
other_robots.map do |robot|
|
109
|
+
if robot_in_radar_view?(robot)
|
110
|
+
Gosu.distance(x, y, robot.x, robot.y)
|
111
|
+
end
|
112
|
+
end.compact
|
113
|
+
end
|
114
|
+
|
115
|
+
def size
|
116
|
+
SIZE
|
117
|
+
end
|
118
|
+
|
119
|
+
def radar_range
|
120
|
+
RADAR_RANGE
|
121
|
+
end
|
122
|
+
|
123
|
+
def time
|
124
|
+
arena.time
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
def heading=(angle)
|
130
|
+
@heading = normalize_angle(angle)
|
131
|
+
end
|
132
|
+
|
133
|
+
def gun_heading=(angle)
|
134
|
+
@gun_heading = normalize_angle(angle)
|
135
|
+
end
|
136
|
+
|
137
|
+
def radar_heading=(angle)
|
138
|
+
@radar_heading = normalize_angle(angle)
|
139
|
+
end
|
140
|
+
|
141
|
+
def normalize_angle(angle)
|
142
|
+
angle % 360
|
143
|
+
end
|
144
|
+
|
145
|
+
def tick_events
|
146
|
+
{ scanned_robots: scan }
|
147
|
+
end
|
148
|
+
|
149
|
+
def new_bullet
|
150
|
+
Bullet.new(x: x, y: y, heading: gun_heading, arena: arena, origin: self)
|
151
|
+
end
|
152
|
+
|
153
|
+
def robot_in_radar_view?(robot)
|
154
|
+
angle_diff(radar_heading, enemy_angle(robot)).abs <= radar_view_angle/2
|
155
|
+
end
|
156
|
+
|
157
|
+
def enemy_angle(robot)
|
158
|
+
Gosu.angle(x, y, robot.x, robot.y)
|
159
|
+
end
|
160
|
+
|
161
|
+
def angle_diff(angle1, angle2)
|
162
|
+
Gosu.angle_diff(angle1, angle2)
|
163
|
+
end
|
164
|
+
|
165
|
+
def other_robots
|
166
|
+
arena.robots.find_all { |robot| robot != self }
|
167
|
+
end
|
168
|
+
|
169
|
+
def fix_position
|
170
|
+
@x = min_x if x < min_x
|
171
|
+
@x = max_x if x > max_x
|
172
|
+
@y = min_y if y < min_y
|
173
|
+
@y = max_y if y > max_y
|
174
|
+
end
|
175
|
+
|
176
|
+
def min_x
|
177
|
+
size/2
|
178
|
+
end
|
179
|
+
|
180
|
+
def max_x
|
181
|
+
arena.width - min_x
|
182
|
+
end
|
183
|
+
|
184
|
+
def min_y
|
185
|
+
size/2
|
186
|
+
end
|
187
|
+
|
188
|
+
def max_y
|
189
|
+
arena.height - min_y
|
190
|
+
end
|
191
|
+
|
192
|
+
def sanitize_maximum_value(number, maximum_change)
|
193
|
+
ValueSanitizer.sanitize(number, maximum_change)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
module RubyArena
|
2
|
+
class RobotRenderer
|
3
|
+
attr_reader :robot, :window
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@robot = args.fetch(:robot)
|
7
|
+
@window = args.fetch(:window)
|
8
|
+
end
|
9
|
+
|
10
|
+
def draw
|
11
|
+
draw_tank_body
|
12
|
+
draw_gun
|
13
|
+
draw_radar
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def draw_tank_body
|
19
|
+
window.rotate(heading, x, y) do
|
20
|
+
window.draw_quad(
|
21
|
+
x1, y1, color,
|
22
|
+
x2, y1, color,
|
23
|
+
x2, y2, color,
|
24
|
+
x1, y2, color
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def x
|
30
|
+
robot.x
|
31
|
+
end
|
32
|
+
|
33
|
+
def y
|
34
|
+
robot.y
|
35
|
+
end
|
36
|
+
|
37
|
+
def x1
|
38
|
+
x - size/2
|
39
|
+
end
|
40
|
+
|
41
|
+
def x2
|
42
|
+
x + size/2
|
43
|
+
end
|
44
|
+
|
45
|
+
def y1
|
46
|
+
y - size/2
|
47
|
+
end
|
48
|
+
|
49
|
+
def y2
|
50
|
+
y + size/2
|
51
|
+
end
|
52
|
+
|
53
|
+
def size
|
54
|
+
robot.size
|
55
|
+
end
|
56
|
+
|
57
|
+
def heading
|
58
|
+
robot.heading
|
59
|
+
end
|
60
|
+
|
61
|
+
def color
|
62
|
+
Gosu::Color::WHITE
|
63
|
+
end
|
64
|
+
|
65
|
+
def draw_radar
|
66
|
+
color = Gosu::Color.new(40, 0, 255, 0)
|
67
|
+
|
68
|
+
window.draw_triangle(
|
69
|
+
x, y, color,
|
70
|
+
radar_x1, radar_y1, color,
|
71
|
+
radar_x2, radar_y2, color
|
72
|
+
)
|
73
|
+
|
74
|
+
window.rotate(radar_heading, x, y) do
|
75
|
+
window.draw_triangle(
|
76
|
+
radar_base_x1, y, color,
|
77
|
+
radar_base_x2, y, color,
|
78
|
+
x, radar_base_y3, color
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def radar_x1
|
84
|
+
x + Gosu.offset_x(radar_heading - radar_view_angle / 2, radar_range)
|
85
|
+
end
|
86
|
+
|
87
|
+
def radar_x2
|
88
|
+
x + Gosu.offset_x(radar_heading + radar_view_angle / 2, radar_range)
|
89
|
+
end
|
90
|
+
|
91
|
+
def radar_y1
|
92
|
+
y + Gosu.offset_y(radar_heading - radar_view_angle / 2, radar_range)
|
93
|
+
end
|
94
|
+
|
95
|
+
def radar_y2
|
96
|
+
y + Gosu.offset_y(radar_heading + radar_view_angle / 2, radar_range)
|
97
|
+
end
|
98
|
+
|
99
|
+
def radar_base_x1
|
100
|
+
x + 4
|
101
|
+
end
|
102
|
+
|
103
|
+
def radar_base_x2
|
104
|
+
x - 4
|
105
|
+
end
|
106
|
+
|
107
|
+
def radar_base_y3
|
108
|
+
y + 6
|
109
|
+
end
|
110
|
+
|
111
|
+
def radar_heading
|
112
|
+
robot.radar_heading
|
113
|
+
end
|
114
|
+
|
115
|
+
def radar_view_angle
|
116
|
+
robot.radar_view_angle
|
117
|
+
end
|
118
|
+
|
119
|
+
def radar_range
|
120
|
+
robot.radar_range
|
121
|
+
end
|
122
|
+
|
123
|
+
def draw_gun
|
124
|
+
window.rotate(gun_heading, x, y) do
|
125
|
+
window.draw_quad(
|
126
|
+
gun_x1, gun_y1, gun_color,
|
127
|
+
gun_x2, gun_y1, gun_color,
|
128
|
+
gun_x2, gun_y2, gun_color,
|
129
|
+
gun_x1, gun_y2, gun_color
|
130
|
+
)
|
131
|
+
window.draw_quad(
|
132
|
+
gun_base_x1, gun_base_y1, gun_color,
|
133
|
+
gun_base_x2, gun_base_y1, gun_color,
|
134
|
+
gun_base_x2, gun_base_y2, gun_color,
|
135
|
+
gun_base_x1, gun_base_y2, gun_color
|
136
|
+
)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def gun_x1
|
141
|
+
x - 2
|
142
|
+
end
|
143
|
+
|
144
|
+
def gun_x2
|
145
|
+
x + 2
|
146
|
+
end
|
147
|
+
|
148
|
+
def gun_y1
|
149
|
+
y - size/1.5
|
150
|
+
end
|
151
|
+
|
152
|
+
def gun_y2
|
153
|
+
y
|
154
|
+
end
|
155
|
+
|
156
|
+
def gun_base_x1
|
157
|
+
x - size/4
|
158
|
+
end
|
159
|
+
|
160
|
+
def gun_base_x2
|
161
|
+
x + size/4
|
162
|
+
end
|
163
|
+
|
164
|
+
def gun_base_y1
|
165
|
+
y - size/4
|
166
|
+
end
|
167
|
+
|
168
|
+
def gun_base_y2
|
169
|
+
y + size/4
|
170
|
+
end
|
171
|
+
|
172
|
+
def gun_heading
|
173
|
+
robot.gun_heading
|
174
|
+
end
|
175
|
+
|
176
|
+
def gun_color
|
177
|
+
Gosu::Color::GRAY
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
data/lib/ruby_arena.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'gosu'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
require 'ruby_arena/ai'
|
5
|
+
require 'ruby_arena/arena'
|
6
|
+
require 'ruby_arena/bullet_renderer'
|
7
|
+
require 'ruby_arena/class_loader'
|
8
|
+
require 'ruby_arena/command_parser'
|
9
|
+
require 'ruby_arena/gui'
|
10
|
+
require 'ruby_arena/value_sanitizer'
|
11
|
+
require 'ruby_arena/movable'
|
12
|
+
require 'ruby_arena/robot'
|
13
|
+
require 'ruby_arena/level0'
|
14
|
+
require 'ruby_arena/level1'
|
15
|
+
require 'ruby_arena/level'
|
16
|
+
require 'ruby_arena/game'
|
17
|
+
require 'ruby_arena/bullet'
|
18
|
+
require 'ruby_arena/option_parser'
|
19
|
+
require 'ruby_arena/robot_renderer'
|
20
|
+
require "ruby_arena/version"
|
21
|
+
|
22
|
+
module RubyArena
|
23
|
+
end
|
data/ruby_arena.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'ruby_arena/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "ruby_arena"
|
7
|
+
spec.version = RubyArena::VERSION
|
8
|
+
spec.authors = ["Patrik Bóna"]
|
9
|
+
spec.email = ["hello@mrhead.sk"]
|
10
|
+
spec.summary = %q{Ruby Arena for fights between robots with own AI.}
|
11
|
+
spec.description = %q{Ruby Arena for fights between robots with own AI.}
|
12
|
+
spec.homepage = "https://github.com/mrhead/ruby_arena"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_runtime_dependency "gosu"
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
23
|
+
spec.add_development_dependency "rake"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.0.0.beta1"
|
25
|
+
end
|
data/screenshot.png
ADDED
Binary file
|
data/spec/ai_spec.rb
ADDED
data/spec/ai_test.rb
ADDED
data/spec/arena_spec.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RubyArena:: Arena do
|
4
|
+
describe '#add_robot' do
|
5
|
+
it 'adds new robot' do
|
6
|
+
arena.add_robot(:robot)
|
7
|
+
|
8
|
+
expect(arena.robots).to eq [:robot]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#add_bullet' do
|
13
|
+
it 'adds new robot' do
|
14
|
+
arena.add_bullet(:bullet)
|
15
|
+
|
16
|
+
expect(arena.bullets).to eq [:bullet]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#update' do
|
21
|
+
it 'calls #tick on all robots and then #update on all robots' do
|
22
|
+
arena.add_robot(robot)
|
23
|
+
|
24
|
+
expect(robot).to receive(:tick)
|
25
|
+
expect(robot).to receive(:update)
|
26
|
+
|
27
|
+
arena.update
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'removes robot if it is dead' do
|
31
|
+
robot = robot(dead?: true)
|
32
|
+
|
33
|
+
arena.add_robot(robot)
|
34
|
+
arena.update
|
35
|
+
|
36
|
+
expect(arena.robots).to eq []
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'removes bullet if it is dead' do
|
40
|
+
bullet = robot(dead?: true)
|
41
|
+
|
42
|
+
arena.add_bullet(bullet)
|
43
|
+
arena.update
|
44
|
+
|
45
|
+
expect(arena.bullets).to eq []
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'increases time by 1' do
|
49
|
+
arena.update
|
50
|
+
|
51
|
+
expect(arena.time).to be 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#game_over?' do
|
56
|
+
it 'returns false with empty arena' do
|
57
|
+
expect(arena.game_over?).to be false
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns true if number of alive robots drops to 1 and less' do
|
61
|
+
robot1 = double('robot1', dead?: false, tick: nil, update: nil)
|
62
|
+
robot2 = double('robot2', dead?: true, tick: nil, update: nil)
|
63
|
+
|
64
|
+
arena.add_robot(robot1)
|
65
|
+
arena.add_robot(robot2)
|
66
|
+
arena.update
|
67
|
+
|
68
|
+
expect(arena.game_over?). to be true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def arena
|
73
|
+
@_arena ||= RubyArena::Arena.new
|
74
|
+
end
|
75
|
+
|
76
|
+
def robot(args = {})
|
77
|
+
@_robot ||= double('robot', tick: nil, dead?: args[:dead?], update: nil)
|
78
|
+
end
|
79
|
+
end
|
data/spec/bullet_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RubyArena:: Bullet do
|
4
|
+
it_behaves_like 'movable'
|
5
|
+
|
6
|
+
describe '#intersect?' do
|
7
|
+
it 'returns true if given object intersects bullet' do
|
8
|
+
robot = double('robot', x: 10, y: 10, size: 30)
|
9
|
+
bullet = bullet(x: 0, y: 0)
|
10
|
+
|
11
|
+
expect(bullet.intersect?(robot)).to be true
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns false if given object doesnt intersect bullet' do
|
15
|
+
robot = double('robot', x: 100, y: 10, size: 30)
|
16
|
+
bullet = bullet(x: 0, y: 0)
|
17
|
+
|
18
|
+
expect(bullet.intersect?(robot)).to be false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def object(args = {})
|
23
|
+
bullet(args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def bullet(args = {})
|
27
|
+
defaults = {
|
28
|
+
x: 0,
|
29
|
+
y: 0,
|
30
|
+
heading: 0,
|
31
|
+
arena: nil,
|
32
|
+
origin: nil
|
33
|
+
}
|
34
|
+
@_bullet ||= RubyArena::Bullet.new(defaults.merge(args))
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RubyArena:: ClassLoader do
|
4
|
+
describe '#class_from_file' do
|
5
|
+
it 'returns class loaded from a file' do
|
6
|
+
file = File.dirname(__FILE__) + '/ai_test.rb'
|
7
|
+
class_loader = RubyArena::ClassLoader.new(file)
|
8
|
+
|
9
|
+
klass = class_loader.get_class
|
10
|
+
|
11
|
+
expect(klass).to be AiTest
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|