rubygoal 0.0.1
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/MIT-LICENSE +24 -0
- data/README.md +62 -0
- data/bin/rubygoal +5 -0
- data/lib/rubygoal/ball.rb +41 -0
- data/lib/rubygoal/coach.rb +11 -0
- data/lib/rubygoal/coach_loader.rb +32 -0
- data/lib/rubygoal/coaches/coach_away.rb +52 -0
- data/lib/rubygoal/coaches/coach_home.rb +28 -0
- data/lib/rubygoal/coaches/template.rb +198 -0
- data/lib/rubygoal/config.rb +64 -0
- data/lib/rubygoal/config_definitions.rb +77 -0
- data/lib/rubygoal/coordinate.rb +25 -0
- data/lib/rubygoal/field.rb +84 -0
- data/lib/rubygoal/field_metrics.rb +85 -0
- data/lib/rubygoal/formation.rb +69 -0
- data/lib/rubygoal/game.rb +179 -0
- data/lib/rubygoal/goal.rb +43 -0
- data/lib/rubygoal/match.rb +52 -0
- data/lib/rubygoal/moveable.rb +55 -0
- data/lib/rubygoal/player.rb +86 -0
- data/lib/rubygoal/players/average.rb +20 -0
- data/lib/rubygoal/players/captain.rb +20 -0
- data/lib/rubygoal/players/fast.rb +20 -0
- data/lib/rubygoal/team.rb +217 -0
- data/lib/rubygoal/version.rb +3 -0
- data/lib/rubygoal.rb +7 -0
- data/media/average_away.png +0 -0
- data/media/average_home.png +0 -0
- data/media/background.png +0 -0
- data/media/ball.png +0 -0
- data/media/captain_away.png +0 -0
- data/media/captain_home.png +0 -0
- data/media/fast_away.png +0 -0
- data/media/fast_home.png +0 -0
- data/media/goal.png +0 -0
- data/test/formation_test.rb +66 -0
- data/test/random.txt +788 -0
- data/test/record.txt +432000 -0
- data/test/test.rb +104 -0
- metadata +116 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'gosu'
|
3
|
+
|
4
|
+
require 'rubygoal/ball'
|
5
|
+
require 'rubygoal/coach_loader'
|
6
|
+
require 'rubygoal/team'
|
7
|
+
require 'rubygoal/field_metrics'
|
8
|
+
require 'rubygoal/match'
|
9
|
+
require 'rubygoal/coaches/coach_home'
|
10
|
+
require 'rubygoal/coaches/coach_away'
|
11
|
+
|
12
|
+
module Rubygoal
|
13
|
+
class Field
|
14
|
+
attr_reader :ball, :team_home, :team_away
|
15
|
+
|
16
|
+
extend Forwardable
|
17
|
+
def_delegators :ball, :goal?
|
18
|
+
|
19
|
+
def initialize(game_window)
|
20
|
+
@game_window = game_window
|
21
|
+
@background_image = Gosu::Image.new(game_window, Config.field.background_image_file, true)
|
22
|
+
|
23
|
+
@ball = Ball.new(game_window, FieldMetrics.center_position)
|
24
|
+
|
25
|
+
coach_home = CoachLoader.get(CoachHome)
|
26
|
+
coach_away = CoachLoader.get(CoachAway)
|
27
|
+
|
28
|
+
puts "Home coach: #{coach_home.class.name}"
|
29
|
+
puts "Away coach: #{coach_away.class.name}"
|
30
|
+
|
31
|
+
@team_home = Team.new(game_window, :home, coach_home)
|
32
|
+
@team_away = Team.new(game_window, :away, coach_away)
|
33
|
+
end
|
34
|
+
|
35
|
+
def reinitialize
|
36
|
+
team_home.players_to_initial_position
|
37
|
+
team_away.players_to_initial_position
|
38
|
+
ball.position = FieldMetrics.center_position
|
39
|
+
end
|
40
|
+
|
41
|
+
def team_names
|
42
|
+
{
|
43
|
+
home: team_home.name,
|
44
|
+
away: team_away.name
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def update
|
49
|
+
team_home.update(game_data(:home))
|
50
|
+
team_away.update(game_data(:away))
|
51
|
+
ball.update
|
52
|
+
end
|
53
|
+
|
54
|
+
def draw
|
55
|
+
background_image.draw(0, 0, 0);
|
56
|
+
ball.draw
|
57
|
+
team_home.draw
|
58
|
+
team_away.draw
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def game_data(side)
|
64
|
+
case side
|
65
|
+
when :home
|
66
|
+
Match.new(
|
67
|
+
game_window.score_home,
|
68
|
+
game_window.score_away,
|
69
|
+
game_window.time,
|
70
|
+
team_away.formation
|
71
|
+
)
|
72
|
+
when :away
|
73
|
+
Match.new(
|
74
|
+
game_window.score_away,
|
75
|
+
game_window.score_home,
|
76
|
+
game_window.time,
|
77
|
+
team_home.formation
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
attr_reader :background_image, :game_window
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rubygoal/config'
|
2
|
+
require 'rubygoal/coordinate'
|
3
|
+
require 'rubygoal/field_metrics'
|
4
|
+
|
5
|
+
module Rubygoal
|
6
|
+
module FieldMetrics
|
7
|
+
class << self
|
8
|
+
def center_position
|
9
|
+
center = Position.new(
|
10
|
+
Config.field.width / 2,
|
11
|
+
Config.field.height / 2
|
12
|
+
)
|
13
|
+
Config.field.offset.add(center)
|
14
|
+
end
|
15
|
+
|
16
|
+
def goal_position(side)
|
17
|
+
position = center_position
|
18
|
+
case side
|
19
|
+
when :home
|
20
|
+
position.x = Config.field.offset.x
|
21
|
+
when :away
|
22
|
+
position.x = Config.field.offset.x + Config.field.width
|
23
|
+
end
|
24
|
+
position
|
25
|
+
end
|
26
|
+
|
27
|
+
def initial_player_positions(side)
|
28
|
+
Config.team.initial_player_positions.map do |pos|
|
29
|
+
case side
|
30
|
+
when :home
|
31
|
+
Position.new(
|
32
|
+
Config.field.offset.x + pos[0],
|
33
|
+
Config.field.offset.y + pos[1]
|
34
|
+
)
|
35
|
+
when :away
|
36
|
+
Position.new(
|
37
|
+
Config.field.offset.x + Config.field.width - pos[0],
|
38
|
+
Config.field.offset.y + Config.field.height - pos[1]
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def goalkeeper_position(side)
|
45
|
+
initial_player_positions(side).first
|
46
|
+
end
|
47
|
+
|
48
|
+
def position_side(position)
|
49
|
+
if position.x < FieldMetrics.center_position.x
|
50
|
+
:home
|
51
|
+
else
|
52
|
+
:away
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def out_of_bounds_width?(position)
|
57
|
+
lower_limit = Config.field.offset.x
|
58
|
+
upper_limit = Config.field.offset.x + Config.field.width
|
59
|
+
!(lower_limit..upper_limit).include?(position.x)
|
60
|
+
end
|
61
|
+
|
62
|
+
def out_of_bounds_height?(position)
|
63
|
+
lower_limit = Config.field.offset.y
|
64
|
+
upper_limit = Config.field.offset.y + Config.field.height
|
65
|
+
!(lower_limit..upper_limit).include?(position.y)
|
66
|
+
end
|
67
|
+
|
68
|
+
def goal?(position)
|
69
|
+
if out_of_bounds_width?(position)
|
70
|
+
lower_limit = center_position.y - Config.field.goal_height / 2
|
71
|
+
upper_limit = center_position.y + Config.field.goal_height / 2
|
72
|
+
|
73
|
+
(lower_limit..upper_limit).include?(position.y)
|
74
|
+
else
|
75
|
+
false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def close_to_goal?(position, side)
|
80
|
+
goal_position = FieldMetrics.goal_position(side)
|
81
|
+
goal_position.distance(position) < Config.field.close_to_goal_distance
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class Formation
|
3
|
+
attr_accessor :lineup
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@lineup = [
|
7
|
+
[:none, :none, :none, :none, :none],
|
8
|
+
[:none, :none, :none, :none, :none],
|
9
|
+
[:none, :none, :none, :none, :none],
|
10
|
+
[:none, :none, :none, :none, :none],
|
11
|
+
[:none, :none, :none, :none, :none],
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
def defenders
|
16
|
+
column(0)
|
17
|
+
end
|
18
|
+
|
19
|
+
def midfielders
|
20
|
+
column(2)
|
21
|
+
end
|
22
|
+
|
23
|
+
def attackers
|
24
|
+
column(4)
|
25
|
+
end
|
26
|
+
|
27
|
+
def column(i)
|
28
|
+
lineup.map { |row| row[i] }
|
29
|
+
end
|
30
|
+
|
31
|
+
def defenders=(f)
|
32
|
+
assign_column(0, f)
|
33
|
+
end
|
34
|
+
|
35
|
+
def midfielders=(f)
|
36
|
+
assign_column(2, f)
|
37
|
+
end
|
38
|
+
|
39
|
+
def attackers=(f)
|
40
|
+
assign_column(4, f)
|
41
|
+
end
|
42
|
+
|
43
|
+
def assign_column(index, column)
|
44
|
+
column.each_with_index do |player, row_index|
|
45
|
+
lineup[row_index][index] = player
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def errors
|
50
|
+
errors = {}
|
51
|
+
|
52
|
+
unified = lineup.flatten
|
53
|
+
captains = unified.count(:captain)
|
54
|
+
fast = unified.count(:fast)
|
55
|
+
average = unified.count(:average)
|
56
|
+
total = captains + fast + average
|
57
|
+
|
58
|
+
errors[:captains] = "La cantidad de capitanes es #{captains}" if captains != 1
|
59
|
+
errors[:fast] = "La cantidad de rapidos es #{fast}" if fast != 3
|
60
|
+
errors[:total] = "La cantidad total de jugadores es #{total}" if total != 10
|
61
|
+
|
62
|
+
errors
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid?
|
66
|
+
errors.empty?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'gosu'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
require 'rubygoal/coordinate'
|
5
|
+
require 'rubygoal/field'
|
6
|
+
require 'rubygoal/field_metrics'
|
7
|
+
require 'rubygoal/goal'
|
8
|
+
|
9
|
+
module Rubygoal
|
10
|
+
class Game < Gosu::Window
|
11
|
+
attr_reader :field, :time, :score_home, :score_away
|
12
|
+
|
13
|
+
extend Forwardable
|
14
|
+
def_delegators :field, :ball, :close_to_goal?
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super(1920, 1080, true)
|
18
|
+
self.caption = "Ruby Goal"
|
19
|
+
|
20
|
+
@field = Field.new(self)
|
21
|
+
@goal = Goal.new(self)
|
22
|
+
|
23
|
+
@state = :playing
|
24
|
+
|
25
|
+
@time = Config.game.time
|
26
|
+
@score_home = 0
|
27
|
+
@score_away = 0
|
28
|
+
|
29
|
+
@font = Gosu::Font.new(
|
30
|
+
self,
|
31
|
+
Gosu.default_font_name,
|
32
|
+
Config.game.default_font_size
|
33
|
+
)
|
34
|
+
|
35
|
+
@home_team_label = create_label_image(name_home)
|
36
|
+
@away_team_label = create_label_image(name_away)
|
37
|
+
end
|
38
|
+
|
39
|
+
def update
|
40
|
+
return if state == :ended
|
41
|
+
|
42
|
+
update_elapsed_time
|
43
|
+
|
44
|
+
if field.goal?
|
45
|
+
update_goal
|
46
|
+
else
|
47
|
+
update_remaining_time
|
48
|
+
field.update
|
49
|
+
end
|
50
|
+
|
51
|
+
end_match! if time <= 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def draw
|
55
|
+
field.draw
|
56
|
+
draw_scoreboard
|
57
|
+
draw_team_labels
|
58
|
+
goal.draw if field.goal?
|
59
|
+
end
|
60
|
+
|
61
|
+
def button_down(id)
|
62
|
+
if id == Gosu::KbEscape
|
63
|
+
close
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
attr_writer :time, :score_home, :score_away
|
70
|
+
attr_accessor :state, :last_time, :elapsed_time
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
attr_reader :font, :goal, :home_team_label, :away_team_label
|
75
|
+
|
76
|
+
def create_label_image(name)
|
77
|
+
name = truncate_label(name, Config.game.max_name_length)
|
78
|
+
Gosu::Image.from_text(
|
79
|
+
self,
|
80
|
+
name,
|
81
|
+
Gosu.default_font_name,
|
82
|
+
Config.game.team_label_font_size,
|
83
|
+
1,
|
84
|
+
Config.game.team_label_width,
|
85
|
+
:center
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
def truncate_label(name, limit)
|
90
|
+
words = name.split
|
91
|
+
|
92
|
+
left = limit
|
93
|
+
truncated = []
|
94
|
+
words.each do |word|
|
95
|
+
break unless left > 0
|
96
|
+
|
97
|
+
truncated << word
|
98
|
+
left -= word.length + 1
|
99
|
+
end
|
100
|
+
|
101
|
+
truncated.join(' ')[0..limit]
|
102
|
+
end
|
103
|
+
|
104
|
+
def update_elapsed_time
|
105
|
+
self.last_time ||= Time.now
|
106
|
+
|
107
|
+
self.elapsed_time = Time.now - last_time
|
108
|
+
self.last_time = Time.now
|
109
|
+
end
|
110
|
+
|
111
|
+
def update_remaining_time
|
112
|
+
self.time -= elapsed_time
|
113
|
+
end
|
114
|
+
|
115
|
+
def update_goal
|
116
|
+
goal.update(elapsed_time)
|
117
|
+
reinitialize_match if goal.celebration_done?
|
118
|
+
end
|
119
|
+
|
120
|
+
def reinitialize_match
|
121
|
+
if FieldMetrics.position_side(ball.position) == :home
|
122
|
+
self.score_away += 1
|
123
|
+
else
|
124
|
+
self.score_home += 1
|
125
|
+
end
|
126
|
+
|
127
|
+
field.reinitialize
|
128
|
+
end
|
129
|
+
|
130
|
+
def draw_scoreboard
|
131
|
+
draw_text(time_text, Config.game.time_label_position, :gray)
|
132
|
+
draw_text(score_home.to_s, Config.game.score_home_label_position, :white)
|
133
|
+
draw_text(score_away.to_s, Config.game.score_away_label_position, :white)
|
134
|
+
end
|
135
|
+
|
136
|
+
def draw_team_labels
|
137
|
+
pos = Config.game.home_team_label_position
|
138
|
+
home_team_label.draw_rot(pos.x, pos.y, 1, -90)
|
139
|
+
pos = Config.game.away_team_label_position
|
140
|
+
away_team_label.draw_rot(pos.x, pos.y, 1, 90)
|
141
|
+
end
|
142
|
+
|
143
|
+
def draw_text(text, position, color, size = 1)
|
144
|
+
font.draw_rel(text, position.x, position.y, 0.5, 0.5, 1, size, size, color_to_hex(color))
|
145
|
+
end
|
146
|
+
|
147
|
+
def time_text
|
148
|
+
minutes = Integer(time) / 60
|
149
|
+
seconds = Integer(time) % 60
|
150
|
+
"%d:%02d" % [minutes, seconds]
|
151
|
+
end
|
152
|
+
|
153
|
+
def color_to_hex(color)
|
154
|
+
case color
|
155
|
+
when :white
|
156
|
+
0xffffffff
|
157
|
+
when :gray
|
158
|
+
0xff6d6e70
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def end_match!
|
163
|
+
self.state = :ended
|
164
|
+
write_score
|
165
|
+
end
|
166
|
+
|
167
|
+
def write_score
|
168
|
+
puts "#{name_home} #{score_home} - #{score_away} #{name_away}"
|
169
|
+
end
|
170
|
+
|
171
|
+
def name_home
|
172
|
+
field.team_names[:home]
|
173
|
+
end
|
174
|
+
|
175
|
+
def name_away
|
176
|
+
field.team_names[:away]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'gosu'
|
2
|
+
|
3
|
+
require 'rubygoal/config'
|
4
|
+
|
5
|
+
module Rubygoal
|
6
|
+
class Goal
|
7
|
+
def initialize(game_window)
|
8
|
+
@goal_image = Gosu::Image.new(game_window, Config.goal.image_file, true)
|
9
|
+
|
10
|
+
@celebration_time = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def celebration_done?
|
14
|
+
!celebrating?
|
15
|
+
end
|
16
|
+
|
17
|
+
def draw
|
18
|
+
position = Config.game.goal_image_position
|
19
|
+
goal_image.draw(position.x, position.y, 1)
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(elapsed_time)
|
23
|
+
start_celebration unless celebrating?
|
24
|
+
self.celebration_time -= elapsed_time
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
attr_accessor :celebration_time
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :goal_image
|
34
|
+
|
35
|
+
def start_celebration
|
36
|
+
self.celebration_time = 3
|
37
|
+
end
|
38
|
+
|
39
|
+
def celebrating?
|
40
|
+
celebration_time > 0
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class Match
|
3
|
+
class Team
|
4
|
+
attr_reader :score, :result, :formation
|
5
|
+
|
6
|
+
def initialize(score, result, other_formation = nil)
|
7
|
+
@score = score
|
8
|
+
@result = result
|
9
|
+
@formation = other_formation
|
10
|
+
end
|
11
|
+
|
12
|
+
def draw?
|
13
|
+
result == :draw
|
14
|
+
end
|
15
|
+
|
16
|
+
def winning?
|
17
|
+
result == :win
|
18
|
+
end
|
19
|
+
|
20
|
+
def losing?
|
21
|
+
result == :lose
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :me, :other, :time
|
26
|
+
|
27
|
+
def initialize(my_score, other_score, time, other_formation)
|
28
|
+
@me = Match::Team.new(
|
29
|
+
my_score,
|
30
|
+
result(my_score, other_score)
|
31
|
+
)
|
32
|
+
@other = Match::Team.new(
|
33
|
+
other_score,
|
34
|
+
result(other_score, my_score),
|
35
|
+
other_formation
|
36
|
+
)
|
37
|
+
@time = time
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def result(my_score, other_score)
|
43
|
+
if my_score > other_score
|
44
|
+
:win
|
45
|
+
elsif my_score < other_score
|
46
|
+
:lose
|
47
|
+
else
|
48
|
+
:draw
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'gosu'
|
2
|
+
|
3
|
+
require 'rubygoal/coordinate'
|
4
|
+
|
5
|
+
module Rubygoal
|
6
|
+
module Moveable
|
7
|
+
MIN_DISTANCE = 10
|
8
|
+
|
9
|
+
attr_accessor :position, :velocity
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@position = Position.new(0, 0)
|
13
|
+
@velocity = Velocity.new(0, 0)
|
14
|
+
@speed = 0
|
15
|
+
@destination = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def moving?
|
19
|
+
velocity.nonzero?
|
20
|
+
end
|
21
|
+
|
22
|
+
def distance(position)
|
23
|
+
Gosu.distance(self.position.x, self.position.y, position.x, position.y)
|
24
|
+
end
|
25
|
+
|
26
|
+
def move_to(destination)
|
27
|
+
self.destination = destination
|
28
|
+
|
29
|
+
angle = Gosu.angle(position.x, position.y, destination.x, destination.y)
|
30
|
+
velocity.x = Gosu.offset_x(angle, speed)
|
31
|
+
velocity.y = Gosu.offset_y(angle, speed)
|
32
|
+
end
|
33
|
+
|
34
|
+
def update
|
35
|
+
return unless moving?
|
36
|
+
|
37
|
+
if destination && distance(destination) < MIN_DISTANCE
|
38
|
+
stop
|
39
|
+
else
|
40
|
+
position.x += velocity.x
|
41
|
+
position.y += velocity.y
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_reader :speed
|
48
|
+
attr_accessor :destination
|
49
|
+
|
50
|
+
def stop
|
51
|
+
self.destination = nil
|
52
|
+
self.velocity = Velocity.new(0, 0)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'gosu'
|
2
|
+
|
3
|
+
require 'rubygoal/coordinate'
|
4
|
+
require 'rubygoal/moveable'
|
5
|
+
|
6
|
+
module Rubygoal
|
7
|
+
class Player
|
8
|
+
include Moveable
|
9
|
+
|
10
|
+
def initialize(game_window, side)
|
11
|
+
super()
|
12
|
+
|
13
|
+
@image = Gosu::Image.new(game_window, image_filename(side), false)
|
14
|
+
@time_to_kick_again = 0
|
15
|
+
@field = game_window.field
|
16
|
+
end
|
17
|
+
|
18
|
+
def can_kick?(ball)
|
19
|
+
!waiting_to_kick_again? && control_ball?(ball)
|
20
|
+
end
|
21
|
+
|
22
|
+
def kick(ball, target)
|
23
|
+
strength = Config.player.kick_strength * Random.rand(error_range)
|
24
|
+
|
25
|
+
direction = Gosu.angle(position.x, position.y, target.x, target.y)
|
26
|
+
direction *= Random.rand(error_range)
|
27
|
+
|
28
|
+
velocity = Velocity.new(
|
29
|
+
Gosu.offset_x(direction, strength),
|
30
|
+
Gosu.offset_y(direction, strength)
|
31
|
+
)
|
32
|
+
ball.velocity = velocity
|
33
|
+
|
34
|
+
reset_waiting_to_kick!
|
35
|
+
end
|
36
|
+
|
37
|
+
def update
|
38
|
+
update_waiting_to_kick!
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def draw
|
43
|
+
if moving?
|
44
|
+
angle = Gosu.angle(position.x, position.y, destination.x, destination.y)
|
45
|
+
angle -= 90
|
46
|
+
else
|
47
|
+
angle = 0.0
|
48
|
+
end
|
49
|
+
|
50
|
+
image.draw_rot(position.x, position.y, 1, angle)
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
attr_accessor :time_to_kick_again
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_reader :field, :image, :error
|
60
|
+
|
61
|
+
def waiting_to_kick_again?
|
62
|
+
time_to_kick_again > 0
|
63
|
+
end
|
64
|
+
|
65
|
+
def reset_waiting_to_kick!
|
66
|
+
self.time_to_kick_again = Config.player.time_to_kick_again
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_waiting_to_kick!
|
70
|
+
# TODO Make it time-based rather than counting ticks
|
71
|
+
self.time_to_kick_again -= 1 if waiting_to_kick_again?
|
72
|
+
end
|
73
|
+
|
74
|
+
def control_ball?(ball)
|
75
|
+
distance(ball.position) < Config.player.distance_control_ball
|
76
|
+
end
|
77
|
+
|
78
|
+
def error_range
|
79
|
+
(1.0 - error) .. (1.0 + error)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
require 'rubygoal/players/average'
|
85
|
+
require 'rubygoal/players/fast'
|
86
|
+
require 'rubygoal/players/captain'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class AveragePlayer < Player
|
3
|
+
def initialize(*args)
|
4
|
+
super
|
5
|
+
@error = 0.10 + Random.rand(0.05)
|
6
|
+
@speed = 3.5
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def image_filename(side)
|
12
|
+
case side
|
13
|
+
when :home
|
14
|
+
Config.player.average_home_image_file
|
15
|
+
when :away
|
16
|
+
Config.player.average_away_image_file
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class CaptainPlayer < Player
|
3
|
+
def initialize(*args)
|
4
|
+
super
|
5
|
+
@error = 0.05
|
6
|
+
@speed = 4.5
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def image_filename(side)
|
12
|
+
case side
|
13
|
+
when :home
|
14
|
+
Config.player.captain_home_image_file
|
15
|
+
when :away
|
16
|
+
Config.player.captain_away_image_file
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class FastPlayer < Player
|
3
|
+
def initialize(*args)
|
4
|
+
super
|
5
|
+
@error = 0.10 + Random.rand(0.05)
|
6
|
+
@speed = 4
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def image_filename(side)
|
12
|
+
case side
|
13
|
+
when :home
|
14
|
+
Config.player.fast_home_image_file
|
15
|
+
when :away
|
16
|
+
Config.player.fast_away_image_file
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|