rubygoal 0.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +0,0 @@
1
- module Rubygoal
2
- class Coach
3
- def name
4
- raise NotImplementedError
5
- end
6
-
7
- def formation(match)
8
- raise NotImplementedError
9
- end
10
- end
11
- end
@@ -1,32 +0,0 @@
1
- module Rubygoal
2
- module CoachLoader
3
- class << self
4
- def get(default)
5
- file = ARGV.shift
6
-
7
- if file && File.exists?(file)
8
- load file
9
-
10
- class_name = camelize(File.basename(file, ".rb"))
11
- Rubygoal.const_get(class_name).new
12
- else
13
- if file
14
- puts "File `#{file}` doesn't exist. Using #{default.name}."
15
- end
16
-
17
- default.new
18
- end
19
- end
20
-
21
- private
22
-
23
- def camelize(term)
24
- string = term.to_s
25
- string = string.sub(/^[a-z\d]*/) { $&.capitalize }
26
- string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
27
- string.gsub!('/', '::')
28
- string
29
- end
30
- end
31
- end
32
- end
@@ -1,52 +0,0 @@
1
- require 'rubygoal/coach'
2
- require 'rubygoal/formation'
3
-
4
- module Rubygoal
5
- class CoachAway < Coach
6
- def name
7
- "Danubio"
8
- end
9
-
10
- def formation(match)
11
- formation = Formation.new
12
-
13
- if match.me.winning?
14
- formation.lineup = [
15
- [:average, :none, :average, :none, :none],
16
- [:fast, :none, :none, :average, :none],
17
- [:none, :none, :captain, :none, :fast],
18
- [:fast, :none, :none, :none, :average],
19
- [:average, :none, :average, :none, :none],
20
- ]
21
- elsif match.me.draw?
22
- formation.lineup = [
23
- [:average, :none, :average, :none, :none],
24
- [:fast, :none, :none, :none, :fast],
25
- [:none, :fast, :none, :captain, :none],
26
- [:average, :none, :none, :none, :average],
27
- [:average, :none, :average, :none, :none],
28
- ]
29
- elsif match.me.losing?
30
- if match.time < 30
31
- formation.lineup = [
32
- [:none, :none, :average, :none, :none],
33
- [:average, :none, :none, :none, :average],
34
- [:average, :fast, :none, :captain, :none],
35
- [:average, :none, :fast, :none, :fast],
36
- [:none, :none, :average, :none, :none],
37
- ]
38
- else
39
- formation.lineup = [
40
- [:none, :none, :average, :none, :none],
41
- [:average, :none, :none, :none, :average],
42
- [:fast, :average, :none, :fast, :none],
43
- [:average, :none, :captain, :none, :fast],
44
- [:none, :none, :average, :none, :none],
45
- ]
46
- end
47
- end
48
-
49
- formation
50
- end
51
- end
52
- end
@@ -1,28 +0,0 @@
1
- require 'rubygoal/coach'
2
- require 'rubygoal/formation'
3
-
4
- module Rubygoal
5
- class CoachHome < Coach
6
- def name
7
- "Wanderers"
8
- end
9
-
10
- def formation(match)
11
- formation = Formation.new
12
-
13
- if match.me.winning?
14
- formation.defenders = [:average, :average, :average, :captain, :average]
15
- formation.midfielders = [:average, :none, :fast, :none, :average]
16
- formation.attackers = [:none, :fast, :none, :fast, :none]
17
- elsif match.time < 20
18
- formation.defenders = [:none, :fast, :average, :average, :none]
19
- formation.midfielders = [:average, :average, :captain, :none, :average]
20
- formation.attackers = [:fast, :none, :none, :fast, :average]
21
- else
22
- formation.lineup = match.other.formation.lineup
23
- end
24
-
25
- formation
26
- end
27
- end
28
- end
@@ -1,198 +0,0 @@
1
- # RubyGoal - Fútbol para Rubistas
2
- #
3
- # Este documento contiene varias implementaciones mínimas de un entrenador de RubyGoal.#
4
- #
5
- # Esta clase debe implementar, como mínimo, los métodos `name` y `formation(match)`
6
- # Esta clase debe ser implementada dentro del módulo Rubygoal
7
-
8
- module Rubygoal
9
- class MyCoach < Coach
10
- # Indica el nombre del equipo
11
- # Debe retornar un string
12
- def name
13
- "My team name"
14
- end
15
-
16
- # Este método debe devolver una instancia de Formation indicando como
17
- # se tienen que parar los jugadores en la cancha
18
- #
19
- # Este método es invocado constantemente (varias veces por segundo)
20
- # proporcionando información de como va el partido utilizando el
21
- # parámetro match
22
- def formation(match)
23
- formation = Formation.new
24
-
25
- # La clase Formation tiene varios helpers para ayudar a definir la
26
- # formación del equipo
27
- #
28
- # La cancha se divide en una matriz de 5 por 5
29
- #
30
- # ------------------------------
31
- # | N N N N N |
32
- # | |
33
- # | N N N N N |
34
- # A | | A
35
- # R | N N N N N | R
36
- # C | | C
37
- # O | N N N N N | O
38
- # | |
39
- # | N N N N N |
40
- # ------------------------------
41
- #
42
- # Esto es un ejemplo que posiciona jugadores en columnas de la matriz
43
- #
44
- # Los tipos de jugadores válidos son :average, :fast, :captain
45
- # Se usa :none para las posiciones que no se usen en la línea
46
- #
47
- # Restricciones:
48
- # Exactamente un :captain
49
- # Exactamente tres :fast
50
- # Exactamente seis :average
51
- #
52
- # :captain -> Este jugador es el más rápido y preciso del equipo
53
- # :fast -> Estos jugadores son más rápidos que los demás (aunque más lentos que
54
- # el capitán del equipo)
55
- # :average -> Estos jugadores completan el equipo
56
- #
57
- # El arquero no hay que especificarlo, ya viene incluido por defecto
58
- formation.defenders = [:none, :average, :average, :average, :none]
59
- formation.midfielders = [:average, :fast, :captain, :none, :average]
60
- formation.attackers = [:none, :fast, :none, :fast, :average]
61
-
62
- # Esto produce la siguiente alineación
63
- #
64
- # ------------------------------
65
- # | N N A N N |
66
- # | |
67
- # | A N F N F |
68
- # A | | A
69
- # R | A N C N N | R
70
- # C | | C
71
- # O | A N N N F | O
72
- # | |
73
- # | N N A N A |
74
- # ------------------------------
75
-
76
- formation
77
- end
78
- end
79
-
80
- # Lo siguiente es otra implementación posible de una instancia de Coach
81
-
82
- class AnotherCoach < Coach
83
- def name
84
- "Maeso FC"
85
- end
86
-
87
- # El método formation debe devolver una instancia de Formation
88
- # El siguiten ejemplo muestra como controlar la posición de los jugadores
89
- # de una forma más fina, usando el método `lineup`
90
- #
91
- def formation(match)
92
- formation = Formation.new
93
-
94
- # Por defecto el valor de formation.lineup es
95
- #
96
- # [
97
- # [:none, :none, :none, :none, :none],
98
- # [:none, :none, :none, :none, :none],
99
- # [:none, :none, :none, :none, :none],
100
- # [:none, :none, :none, :none, :none],
101
- # [:none, :none, :none, :none, :none],
102
- # ]
103
- #
104
- # Este valor DEBE sobreescribirse con una formación que incluya las
105
- # cantidades correctas de :average, :fast y :captain
106
- #
107
- # Para este tipo de estrategias es importante siempre considerar que el arco
108
- # que atacas es el de la derecha.
109
- #
110
- # En el siguiente ejemplo, la formación 4322 puede interpretarse
111
- # de la siguiente manera
112
- # | |
113
- # defensa | medio campo | delantera
114
- # [ | |
115
- # [ :average, | :none, :average, :none, | :none ],
116
- # [ :fast, | :none, :none, :average, | :none ],
117
- # [ :none, | :none, :captain, :none, | :fast ],
118
- # [ :fast, | :none, :none, :average, | :average ],
119
- # [ :average, | :none, :average, :none, | :none ],
120
- # ] | |
121
- # | |
122
- #
123
- # Usando `lineup`, la línea mas defensiva son los primeros elementos de
124
- # cada uno de los arrays (:average, :fast, :none, :fast, :average)
125
- #
126
- # La segunda línea (entre la defensa y los mediocampistas) no tiene jugadores
127
- # (son todos :none)
128
- #
129
- # La tercer línea, la que corresponde a los mediocampistas, son el tercer
130
- # elemento de cada array (:average, :none, :captain, :none, :average)
131
- #
132
- # La cuarta línea está ubicada entre los mediocampistas y delanteros
133
- # (:none, :average, :none, :average, :none)
134
- #
135
- # Los últimos elementos de los arrays corresponden a la línea de
136
- # delanteros (:none, :none, :fast, :average, :none)
137
- formation.lineup = [
138
- [:average, :none, :average, :none, :none],
139
- [:fast, :none, :none, :average, :none],
140
- [:none, :none, :captain, :none, :fast],
141
- [:fast, :none, :none, :average, :average],
142
- [:average, :none, :average, :none, :none],
143
- ]
144
-
145
- formation
146
- end
147
- end
148
-
149
- # Otra implementación posible de una instancia de Coach
150
-
151
- # Gran parte de la gracia de este juego está en hacer cambios en la formación
152
- # a medida que va transcurriendo el partido
153
- #
154
- # La instancia de `match` que recibe el método `formation` contiene información
155
- # sobre el partido y el rival de turno
156
- #
157
- # Veamos un ejemplo
158
-
159
- class MyCoach < Coach
160
- def name
161
- "Villa Pancha"
162
- end
163
-
164
- def formation(match)
165
- formation = Formation.new
166
-
167
- # El método `me` trae información sobre mi equipo en el partido
168
- #
169
- # me.winning? indica si estoy ganando
170
- # me.losing? y me.draw? son análogos al anterior :)
171
- # me.score me indica la cantidad exacta de goles que marcó mi equipo
172
- if match.me.winning?
173
- formation.defenders = [:average, :average, :average, :captain, :average]
174
- formation.midfielders = [:average, :none, :fast, :none, :average]
175
- formation.attackers = [:none, :fast, :none, :fast, :none]
176
- #
177
- # El método `time` indica cuanto tiempo (segundos) le queda al partido.
178
- # Devuelve un número entre 120 y 0 (120 cuando comienza el partido)
179
- elsif match.time < 10
180
- formation.defenders = [:none, :average, :average, :average, :none]
181
- formation.midfielders = [:average, :average, :captain, :none, :average]
182
- formation.attackers = [:fast, :fast, :none, :fast, :average]
183
- else
184
- #
185
- # El método `other` devuelve información básica del rival. Tiene los mismos
186
- # métodos que `me`.
187
- #
188
- # En particular, se puede acceder a la formación definida por el equipo
189
- # contrario. En la siguiente linea, a modo de ejemplo, se estableció
190
- # una táctica `espejo` con respecto al rival (posiciono mis jugadores en forma
191
- # simétrica)
192
- formation.lineup = match.other.formation.lineup
193
- end
194
-
195
- formation
196
- end
197
- end
198
- end
@@ -1,64 +0,0 @@
1
- require 'rubygoal/config_definitions'
2
- require 'rubygoal/coordinate'
3
-
4
- module Rubygoal
5
- module Config
6
- field.width = 1392
7
- field.height = 934
8
- field.offset = Position.new(262, 114)
9
- field.goal_height = 275
10
- field.close_to_goal_distance = 275
11
- field.background_image_file = File.dirname(__FILE__) + '/../../media/background.png'
12
-
13
- team.initial_player_positions = [
14
- [50, 466],
15
- [236, 106],
16
- [236, 286],
17
- [236, 646],
18
- [236, 826],
19
- [436, 106],
20
- [436, 286],
21
- [436, 646],
22
- [436, 826],
23
- [616, 436],
24
- [616, 496]
25
- ]
26
- team.average_players_count = 7
27
- team.fast_players_count = 3
28
- team.captain_players_count = 1
29
-
30
-
31
- ball.width = 20
32
- ball.height = 20
33
- ball.image_file = File.dirname(__FILE__) + '/../../media/ball.png'
34
-
35
-
36
- player.time_to_kick_again = 60
37
- player.distance_control_ball = 30
38
- player.kick_strength = 20
39
-
40
-
41
- player.captain_home_image_file = File.dirname(__FILE__) + '/../../media/captain_home.png'
42
- player.captain_away_image_file = File.dirname(__FILE__) + '/../../media/captain_away.png'
43
- player.fast_home_image_file = File.dirname(__FILE__) + '/../../media/fast_home.png'
44
- player.fast_away_image_file = File.dirname(__FILE__) + '/../../media/fast_away.png'
45
- player.average_home_image_file = File.dirname(__FILE__) + '/../../media/average_home.png'
46
- player.average_away_image_file = File.dirname(__FILE__) + '/../../media/average_away.png'
47
-
48
-
49
- goal.image_file = File.dirname(__FILE__) + '/../../media/goal.png'
50
-
51
-
52
- game.time = 120
53
- game.goal_image_position = Position.new(596, 466)
54
- game.time_label_position = Position.new(870, 68)
55
- game.score_home_label_position = Position.new(1150, 68)
56
- game.score_away_label_position = Position.new(1220, 68)
57
- game.max_name_length = 20
58
- game.default_font_size = 48
59
- game.team_label_font_size = 64
60
- game.team_label_width = 669
61
- game.home_team_label_position = Position.new(105, 580)
62
- game.away_team_label_position = Position.new(1815, 580)
63
- end
64
- end
@@ -1,77 +0,0 @@
1
- module Rubygoal
2
- module Config
3
- class Field < Struct.new(:width,
4
- :height,
5
- :offset,
6
- :goal_height,
7
- :close_to_goal_distance,
8
- :background_image_file)
9
- end
10
-
11
- class Team < Struct.new(:initial_player_positions,
12
- :average_players_count,
13
- :fast_players_count,
14
- :captain_players_count)
15
- end
16
-
17
- class Ball < Struct.new(:width,
18
- :height,
19
- :image_file)
20
- end
21
-
22
- class Player < Struct.new(:time_to_kick_again,
23
- :distance_control_ball,
24
- :kick_strength,
25
- :average_home_image_file,
26
- :average_away_image_file,
27
- :fast_home_image_file,
28
- :fast_away_image_file,
29
- :captain_home_image_file,
30
- :captain_away_image_file)
31
- end
32
-
33
- class Goal < Struct.new(:image_file,
34
- :sound_file)
35
- end
36
-
37
- class Game < Struct.new(:time,
38
- :goal_image_position,
39
- :time_label_position,
40
- :score_home_label_position,
41
- :score_away_label_position,
42
- :max_name_length,
43
- :default_font_size,
44
- :team_label_font_size,
45
- :team_label_width,
46
- :home_team_label_position,
47
- :away_team_label_position,
48
- :background_sound_file)
49
- end
50
-
51
- class << self
52
- def field
53
- @field ||= Field.new
54
- end
55
-
56
- def team
57
- @team ||= Team.new
58
- end
59
-
60
- def ball
61
- @ball ||= Ball.new
62
- end
63
-
64
- def player
65
- @player ||= Player.new
66
- end
67
-
68
- def goal
69
- @goal ||= Goal.new
70
- end
71
-
72
- def game
73
- @game ||= Game.new
74
- end
75
- end
76
- end
77
- end
@@ -1,25 +0,0 @@
1
- require 'gosu'
2
-
3
- module Rubygoal
4
- class Coordinate < Struct.new(:x, :y)
5
- def distance(coordinate)
6
- Gosu.distance(x, y, coordinate.x, coordinate.y)
7
- end
8
-
9
- def add(coordinate)
10
- Coordinate.new(x + coordinate.x, y + coordinate.y)
11
- end
12
-
13
- def to_s
14
- "(#{x}, #{y})"
15
- end
16
- end
17
-
18
- class Position < Coordinate; end
19
-
20
- class Velocity < Coordinate
21
- def nonzero?
22
- x != 0 && y != 0
23
- end
24
- end
25
- end
@@ -1,84 +0,0 @@
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
@@ -1,85 +0,0 @@
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