Class: GUI::TkArena

Inherits:
Object
  • Object
show all
Defined in:
lib/GUI/tk.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(battlefield, xres, yres, speed_multiplier) ⇒ TkArena

Returns a new instance of TkArena.



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/GUI/tk.rb', line 34

def initialize battlefield, xres, yres, speed_multiplier
  @engine = 'tk'
  @battlefield = battlefield
  @xres, @yres = xres, yres
  @speed_multiplier = speed_multiplier
  @text_colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#00ffff', '#ff00ff', '#ffffff', '#777777']
  @path_prefix = "#{gem_path}/medias/#{@engine}"
  @default_skin_prefix = "images/red_"
  @on_game_over_handlers = []
  init_canvas
  init_simulation
end

Instance Attribute Details

#battlefieldObject (readonly)

Returns the value of attribute battlefield.



29
30
31
# File 'lib/GUI/tk.rb', line 29

def battlefield
  @battlefield
end

#boomObject

Returns the value of attribute boom.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def boom
  @boom
end

#bulletsObject

Returns the value of attribute bullets.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def bullets
  @bullets
end

#canvasObject

Returns the value of attribute canvas.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def canvas
  @canvas
end

#colorsObject

Returns the value of attribute colors.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def colors
  @colors
end

#default_skin_prefixObject

Returns the value of attribute default_skin_prefix.



32
33
34
# File 'lib/GUI/tk.rb', line 32

def default_skin_prefix
  @default_skin_prefix
end

#engineObject (readonly)

Returns the value of attribute engine.



28
29
30
# File 'lib/GUI/tk.rb', line 28

def engine
  @engine
end

#explosionsObject

Returns the value of attribute explosions.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def explosions
  @explosions
end

#mine_imgObject

Returns the value of attribute mine_img.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def mine_img
  @mine_img
end

#minesObject

Returns the value of attribute mines.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def mines
  @mines
end

#on_game_over_handlersObject

Returns the value of attribute on_game_over_handlers.



30
31
32
# File 'lib/GUI/tk.rb', line 30

def on_game_over_handlers
  @on_game_over_handlers
end

#path_prefixObject

Returns the value of attribute path_prefix.



32
33
34
# File 'lib/GUI/tk.rb', line 32

def path_prefix
  @path_prefix
end

#robotsObject

Returns the value of attribute robots.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def robots
  @robots
end

#speed_multiplierObject

Returns the value of attribute speed_multiplier.



30
31
32
# File 'lib/GUI/tk.rb', line 30

def speed_multiplier
  @speed_multiplier
end

#toolbox_imgObject

Returns the value of attribute toolbox_img.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def toolbox_img
  @toolbox_img
end

#toolboxesObject

Returns the value of attribute toolboxes.



31
32
33
# File 'lib/GUI/tk.rb', line 31

def toolboxes
  @toolboxes
end

#xresObject (readonly)

Returns the value of attribute xres.



29
30
31
# File 'lib/GUI/tk.rb', line 29

def xres
  @xres
end

#yresObject (readonly)

Returns the value of attribute yres.



29
30
31
# File 'lib/GUI/tk.rb', line 29

def yres
  @yres
end

Instance Method Details

#draw_battlefieldObject



139
140
141
142
143
144
145
# File 'lib/GUI/tk.rb', line 139

def draw_battlefield
  draw_toolboxes
  draw_mines
  draw_robots
  draw_bullets
  draw_explosions
end

#draw_bulletsObject



177
178
179
180
181
182
183
184
185
186
# File 'lib/GUI/tk.rb', line 177

def draw_bullets
  @battlefield.bullets.each do |bullet|
    @bullets[bullet] ||= TkcOval.new(
    @canvas, [-2, -2], [3, 3],
    :fill=>'#'+("%02x" % (128+bullet.energy*14).to_i)*3)
    @bullets[bullet].coords(
    bullet.x / 2 - 2, bullet.y / 2 - 2,
    bullet.x / 2 + 3, bullet.y / 2 + 3)
  end
end

#draw_explosionsObject



195
196
197
198
199
200
# File 'lib/GUI/tk.rb', line 195

def draw_explosions
  @battlefield.explosions.each do |explosion|
    @explosions[explosion] ||= TkcImage.new(@canvas, explosion.x / 2, explosion.y / 2)
    @explosions[explosion].image(boom[explosion.t])
  end
end

#draw_frameObject



99
100
101
102
# File 'lib/GUI/tk.rb', line 99

def draw_frame
  simulate(@speed_multiplier)
  draw_battlefield
end

#draw_minesObject



188
189
190
191
192
193
# File 'lib/GUI/tk.rb', line 188

def draw_mines
  @battlefield.mines.each do |mine|
    @mines[mine] ||= TkcImage.new(@canvas, mine.x / 2, mine.y / 2)
    @mines[mine].image(mine_img)
  end
end

#draw_robotsObject



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/GUI/tk.rb', line 147

def draw_robots
  @battlefield.robots.each_with_index do |ai, i|
    next if ai.dead
    @robots[ai] ||= GUI::TkRobot.new(
    TkcImage.new(@canvas, 0, 0),
    TkcImage.new(@canvas, 0, 0),
    TkcImage.new(@canvas, 0, 0),
    TkcText.new(@canvas,
    :fill => @text_colors[ai.team],
    :anchor => 's', :justify => 'center', :coords => [ai.x / 2, ai.y / 2 - ai.size / 2]),
    TkcText.new(@canvas,
    :fill => @text_colors[ai.team],
    :anchor => 'n', :justify => 'center', :coords => [ai.x / 2, ai.y / 2 + ai.size / 2]),
    TkcText.new(@canvas,
    :fill => @text_colors[ai.team],
    :anchor => 'nw', :coords => [10, 15 * i + 10], :font => TkFont.new("courier 9")))
    @robots[ai].body.configure( :image => @colors[ai.team].body[(ai.heading+5) / 10],
    :coords => [ai.x / 2, ai.y / 2])
    @robots[ai].gun.configure(  :image => @colors[ai.team].gun[(ai.gun_heading+5) / 10],
    :coords => [ai.x / 2, ai.y / 2])
    @robots[ai].radar.configure(:image => @colors[ai.team].radar[(ai.radar_heading+5) / 10],
    :coords => [ai.x / 2, ai.y / 2])
    @robots[ai].speech.configure(:text => "#{ai.speech}",
    :coords => [ai.x / 2, ai.y / 2 - ai.size / 2])
    @robots[ai].info.configure(:text => "#{ai.name}\n#{'|' * (ai.energy / 5)}",
    :coords => [ai.x / 2, ai.y / 2 + ai.size / 2])
    @robots[ai].status.configure(:text => "#{ai.name.ljust(20)} #{'%.1f' % ai.energy}")
  end
end

#draw_toolboxesObject



202
203
204
205
206
207
# File 'lib/GUI/tk.rb', line 202

def draw_toolboxes
  @battlefield.toolboxes.each do |toolbox|
    @toolboxes[toolbox] ||= TkcImage.new(@canvas, toolbox.x / 2, toolbox.y / 2)
    @toolboxes[toolbox].image(toolbox_img)
  end
end

#init_canvasObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/GUI/tk.rb', line 64

def init_canvas
  @canvas = TkCanvas.new(:height=>yres, :width=>xres, :scrollregion=>[0, 0, xres, yres], :background => '#000000').pack
  @colors = []
  [[0,1,1],[1,0,1],[1,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[1,1,1]][0...@battlefield.robots.length].zip(@battlefield.robots) do |color, robot|
    bodies, guns, radars = [], [], []
    image_path = robot.skin_prefix || @default_skin_prefix
    image_path = "#{@path_prefix}/#{image_path}"
    reader = robot.skin_prefix ? lambda{|fn| TkPhotoImage.new(:file => fn) } : lambda{|fn| read_gif(fn, *color)}
    36.times do |i|
      bodies << reader["#{image_path}body#{(i*10).to_s.rjust(3, '0')}.gif"]
      guns << reader["#{image_path}turret#{(i*10).to_s.rjust(3, '0')}.gif"]
      radars << reader["#{image_path}radar#{(i*10).to_s.rjust(3, '0')}.gif"]
    end
    @colors << GUI::TkRobot.new(bodies << bodies[0], guns << guns[0], radars << radars[0])
  end

  @boom = (0..14).map do |i|
    TkPhotoImage.new(:file => "#{path_prefix}/images/explosion#{i.to_s.rjust(2, '0')}.gif")
  end
  @toolbox_img = TkPhotoImage.new(:file => "#{path_prefix}/images/toolbox.gif")
  @mine_img = TkPhotoImage.new(:file => "#{path_prefix}/images/mine.gif")
end

#init_simulationObject



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/GUI/tk.rb', line 87

def init_simulation
@robots, @bullets, @explosions, @toolboxes, @mines = {}, {}, {}, {}, {}
TkTimer.new(20, -1, Proc.new{
  begin
    draw_frame
  rescue => err
    puts err.class, err, err.backtrace
    raise
  end
  }).start
end

#on_game_over(&block) ⇒ Object



47
48
49
# File 'lib/GUI/tk.rb', line 47

def on_game_over(&block)
  @on_game_over_handlers << block
end

#read_gif(name, c1, c2, c3) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/GUI/tk.rb', line 51

def read_gif name, c1, c2, c3
  data = nil
  open(name, 'rb') do |f|
    data = f.read()
    ncolors = 2**(1 + data[10][0] + data[10][1] * 2 + data[10][2] * 4)
    ncolors.times do |j|
      data[13 + j * 3 + 0], data[13 + j * 3 + 1], data[13 + j * 3 + 2] =
      data[13 + j * 3 + c1], data[13 + j * 3 + c2], data[13 + j * 3 + c3]
    end
  end
  TkPhotoImage.new(:data => Base64.encode64(data))
end

#runObject



209
210
211
# File 'lib/GUI/tk.rb', line 209

def run
  Tk.mainloop
end

#simulate(ticks = 1) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/GUI/tk.rb', line 104

def simulate(ticks=1)
  @explosions.reject!{|e,tko| @canvas.delete(tko) if e.dead; e.dead }
  @bullets.reject!{|b,tko| @canvas.delete(tko) if b.dead; b.dead }
  @toolboxes.reject!{|t,tko| @canvas.delete(tko) if t.dead; t.dead }
  @mines.reject!{|m,tko| @canvas.delete(tko) if m.dead; m.dead }
  @robots.reject! do |ai,tko|
    if ai.dead
      tko.status.configure(:text => I18n.t('gui.ai_name_dead', :ai_name => ai.name.ljust(20)))
      tko.each{|part| @canvas.delete(part) if part != tko.status}
      true
    end
  end
  ticks.times do
    if @battlefield.game_over
      @on_game_over_handlers.each{|h| h.call(@battlefield) }
      unless @game_over
        winner = @robots.keys.first
        whohaswon = if winner.nil?
          I18n.t('gui.draw')
        elsif @battlefield.teams.all?{|k,t|t.size<2}
          I18n.t('gui.no_team_won', :winner_name => winner.name)
        else
          I18n.t('gui.team_won', :winner_team => winner.team)
        end
        text_color = winner ? winner.team : 7
        @game_over = TkcText.new(canvas,
        :fill => @text_colors[text_color],
        :anchor => 'c', :coords => [400,400], :font=>'courier 36', :justify => 'center',
        :text => I18n.t('gui.game_over').concat("\n#{whohaswon}"))
      end
    end
    @battlefield.tick
  end
end