chichilku3 14.0.3 → 15.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/bin/chichilku3 +1 -0
  3. data/bin/chichilku3-server +1 -0
  4. data/lib/client/chichilku3.rb +3 -1
  5. data/lib/client/client.rb +112 -59
  6. data/lib/client/client_cfg.rb +2 -1
  7. data/lib/client/gui.rb +219 -197
  8. data/lib/client/img/stick128/arm64/arm0.png +0 -0
  9. data/lib/client/img/stick128/arm64/arm1.png +0 -0
  10. data/lib/client/img/stick128/arm64/arm2.png +0 -0
  11. data/lib/client/img/stick128/arm64/arm3.png +0 -0
  12. data/lib/client/img/stick128/noarms/stick0.png +0 -0
  13. data/lib/client/img/stick128/noarms/stick1.png +0 -0
  14. data/lib/client/img/stick128/noarms/stick2.png +0 -0
  15. data/lib/client/img/stick128/noarms/stick3.png +0 -0
  16. data/lib/client/img/stick128/noarms/stick4.png +0 -0
  17. data/lib/client/img/stick128/noarms/stick5.png +0 -0
  18. data/lib/client/keys.rb +29 -0
  19. data/lib/client/particles.rb +54 -0
  20. data/lib/client/scoreboard.rb +29 -27
  21. data/lib/{client → external/gosu}/text.rb +29 -38
  22. data/lib/external/rubyzip/recursive.rb +58 -0
  23. data/lib/server/chichilku3_server.rb +169 -64
  24. data/lib/server/gamelogic.rb +107 -51
  25. data/lib/server/server_cfg.rb +2 -0
  26. data/lib/share/config.rb +21 -7
  27. data/lib/share/console.rb +22 -5
  28. data/lib/share/game_map.rb +279 -0
  29. data/lib/share/math.rb +14 -0
  30. data/lib/share/network.rb +47 -42
  31. data/lib/share/player.rb +168 -105
  32. data/lib/share/projectile.rb +97 -98
  33. data/lib/share/string.rb +24 -0
  34. data/server.json +3 -2
  35. metadata +49 -23
  36. data/lib/client/img/battle1024x576.png +0 -0
  37. data/lib/client/img/grass1024x512.png +0 -0
  38. data/lib/client/img/stick128/stick_noarms.png +0 -0
  39. data/lib/client/test.rb +0 -39
data/lib/client/gui.rb CHANGED
@@ -1,26 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'gosu'
2
4
  require_relative 'client'
3
- require_relative 'text'
5
+ require_relative '../external/gosu/text'
4
6
  require_relative 'scoreboard'
5
7
  require_relative '../share/console'
6
8
  require_relative '../share/player'
7
-
8
- KEY_A = 4
9
- KEY_C = 6
10
- KEY_D = 7
11
- KEY_H = 11
12
- KEY_J = 13
13
- KEY_K = 14
14
- KEY_L = 15
15
- KEY_M = 16
16
- KEY_Q = 20
17
- KEY_S = 22
18
- KEY_T = 23
19
- KEY_W = 26
20
- KEY_RIGHT = 79
21
- KEY_LEFT = 80
22
- KEY_DOWN = 81
23
- KEY_UP = 82
9
+ require_relative 'keys'
10
+ require_relative 'particles'
24
11
 
25
12
  MENU_MAIN = 0
26
13
  MENU_CONNECT = 1
@@ -28,13 +15,13 @@ MENU_USERNAME = 2
28
15
 
29
16
  MOUSE_RADIUS = 200
30
17
 
31
- $time_point=Time.now
32
- $time_buffer=0
18
+ $time_point = Time.now
19
+ $time_buffer = 0
33
20
 
34
- def get_frame_time
21
+ def frame_time
35
22
  diff = Time.now - $time_point
36
23
  $time_point = Time.now
37
- return diff
24
+ diff
38
25
  end
39
26
 
40
27
  # Main Game getting gui form gosu
@@ -44,34 +31,34 @@ class Gui < Gosu::Window
44
31
  self.caption = 'chichilku3'
45
32
  self.fullscreen = true if cfg.data['fullscreen']
46
33
  # images
47
- @crosshair = Gosu::Image.new(img("crosshair128x128.png"))
48
- @background_image = Gosu::Image.new(img("battle1024x576.png"))
49
- @connecting_image = Gosu::Image.new(img("connecting1024x512.png"))
50
- @menu_image = Gosu::Image.new(img("menu1920x1080.png"))
51
- @arrow_image = Gosu::Image.new(img("arrow64.png"))
34
+ @crosshair = Gosu::Image.new(img('crosshair128x128.png'))
35
+ @background_image = nil
36
+ @connecting_image = Gosu::Image.new(img('connecting1024x512.png'))
37
+ @menu_image = Gosu::Image.new(img('menu1920x1080.png'))
38
+ @arrow_image = Gosu::Image.new(img('arrow64.png'))
52
39
  @stick_arm_images = []
53
- @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm0.png"))
54
- @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm1.png"))
55
- @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm2.png"))
56
- @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm3.png"))
40
+ @stick_arm_images << Gosu::Image.new(img('stick128/arm64/arm0.png'))
41
+ @stick_arm_images << Gosu::Image.new(img('stick128/arm64/arm1.png'))
42
+ @stick_arm_images << Gosu::Image.new(img('stick128/arm64/arm2.png'))
43
+ @stick_arm_images << Gosu::Image.new(img('stick128/arm64/arm3.png'))
57
44
  @stick_crouching = []
58
- @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching0.png"))
59
- @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching1.png"))
60
- @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching2.png"))
61
- @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching3.png"))
62
- @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching4.png"))
63
- @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching5.png"))
45
+ @stick_crouching << Gosu::Image.new(img('stick128/stick_crouching0.png'))
46
+ @stick_crouching << Gosu::Image.new(img('stick128/stick_crouching1.png'))
47
+ @stick_crouching << Gosu::Image.new(img('stick128/stick_crouching2.png'))
48
+ @stick_crouching << Gosu::Image.new(img('stick128/stick_crouching3.png'))
49
+ @stick_crouching << Gosu::Image.new(img('stick128/stick_crouching4.png'))
50
+ @stick_crouching << Gosu::Image.new(img('stick128/stick_crouching5.png'))
64
51
  @stick_images = []
65
- @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
66
- @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
67
- @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
68
- @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
69
- @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
52
+ @stick_images << Gosu::Image.new(img('stick128/noarms/stick0.png'))
53
+ @stick_images << Gosu::Image.new(img('stick128/noarms/stick1.png'))
54
+ @stick_images << Gosu::Image.new(img('stick128/noarms/stick2.png'))
55
+ @stick_images << Gosu::Image.new(img('stick128/noarms/stick3.png'))
56
+ @stick_images << Gosu::Image.new(img('stick128/noarms/stick4.png'))
70
57
  @bow_images = []
71
- @bow_images << Gosu::Image.new(img("bow64/bow0.png"))
72
- @bow_images << Gosu::Image.new(img("bow64/bow1.png"))
73
- @bow_images << Gosu::Image.new(img("bow64/bow2.png"))
74
- @bow_images << Gosu::Image.new(img("bow64/bow3.png"))
58
+ @bow_images << Gosu::Image.new(img('bow64/bow0.png'))
59
+ @bow_images << Gosu::Image.new(img('bow64/bow1.png'))
60
+ @bow_images << Gosu::Image.new(img('bow64/bow2.png'))
61
+ @bow_images << Gosu::Image.new(img('bow64/bow3.png'))
75
62
  # TODO: add arms back in if no bow is in use
76
63
  # @stick_images << Gosu::Image.new(img("stick128/stick0.png"))
77
64
  # @stick_images << Gosu::Image.new(img("stick128/stick1.png"))
@@ -85,49 +72,61 @@ class Gui < Gosu::Window
85
72
  @cfg = cfg
86
73
  @tick = 0
87
74
  @console = Console.new
88
- @net_client = Client.new(@console, @cfg)
75
+ @net_client = Client.new(@console, @cfg, self)
76
+ @particles = Particles.new(@console)
89
77
  @net_err = nil
90
78
  @state = @net_client.state
91
79
  @menu_page = MENU_MAIN
92
80
  @font = Gosu::Font.new(20)
93
81
  @is_debug = false
82
+ @is_dbg_grid = false
94
83
  @is_chat = false
95
84
  @is_scoreboard = false
96
- @chat_msg = "" # what we type
97
- @server_chat_msg = "" # what we get from server
85
+ @chat_msg = '' # what we type
86
+ @server_chat_msg = '' # what we get from server
98
87
  @chat_show_time = 4
99
88
  @server_chat_recv = Time.now - @chat_show_time
100
89
  @last_key = nil
101
90
  @events = {
102
- :blood => []
91
+ blood: []
103
92
  }
104
93
  @menu_items = []
105
94
  @selected_menu_item = 0
106
95
  @menu_textfield = TextField.new(self, 60, 200)
107
- @demo_ticks = [0,0]
96
+ @demo_ticks = [0, 0]
97
+ @download_progress = [0, 0]
108
98
  # @chat_inp_stream = nil #TextInput.new
109
99
  # @chat_inp_stream.text # didnt get it working <--- nobo xd
110
-
100
+
111
101
  @last_pressed_button = {}
112
102
 
113
- # depreciated ._.
114
- # @con_msg = Gosu::Image.from_text(self, "connecting to #{@cfg.data['ip']}:#{@cfg.data['port']}...", Gosu.default_font_name, 45)
115
- init_menu()
103
+ init_menu
116
104
 
117
- if ARGV.length > 0
118
- port = ARGV.length > 1 ? ARGV[1].to_i : 9900
119
- connect(ARGV[0], port)
120
- end
105
+ return if ARGV.empty?
106
+
107
+ port = ARGV.length > 1 ? ARGV[1].to_i : 9900
108
+ connect(ARGV[0], port)
109
+ end
110
+
111
+ def needs_cursor?
112
+ @state != STATE_INGAME
121
113
  end
122
114
 
123
115
  def img(path)
124
- File.join(File.dirname(__FILE__), "../../lib/client/img/", path)
116
+ File.join(File.dirname(__FILE__), '../../lib/client/img/', path)
117
+ end
118
+
119
+ def load_background_image(map_path)
120
+ bg_path = File.join(map_path, 'background.png')
121
+ @console.log "loading background image '#{bg_path}' ..."
122
+ @background_image = Gosu::Image.new(bg_path)
125
123
  end
126
124
 
127
125
  def button_press?(button)
128
126
  last_btn = @last_pressed_button[button]
129
127
  @last_pressed_button[button] = button_down?(button)
130
128
  return false if last_btn == true
129
+
131
130
  button_down?(button)
132
131
  end
133
132
 
@@ -144,22 +143,19 @@ class Gui < Gosu::Window
144
143
  @is_chat = false
145
144
  return @chat_msg
146
145
  else
147
- if !button_down?(@last_key)
146
+ unless button_down?(@last_key)
148
147
  @last_key = nil # refresh blocker
149
148
  end
150
- if button_down?(Gosu::KB_BACKSPACE)
151
- # press shift to fast delete
152
- if button_down?(Gosu::KB_LEFT_SHIFT) || @last_key != Gosu::KB_BACKSPACE
153
- @chat_msg = @chat_msg[0..-2]
154
- @last_key = Gosu::KB_BACKSPACE
155
- end
149
+ if button_down?(Gosu::KB_BACKSPACE) && (button_down?(Gosu::KB_LEFT_SHIFT) || @last_key != Gosu::KB_BACKSPACE)
150
+ @chat_msg = @chat_msg[0..-2]
151
+ @last_key = Gosu::KB_BACKSPACE
156
152
  end
157
- for key in 4..30 do # alphabet lowercase
158
- if button_down?(key)
159
- if @last_key != key
160
- @chat_msg += button_id_to_char(key)
161
- @last_key = key
162
- end
153
+ (4..30).each do |key| # alphabet lowercase
154
+ next unless button_down?(key)
155
+
156
+ if @last_key != key
157
+ @chat_msg += button_id_to_char(key)
158
+ @last_key = key
163
159
  end
164
160
  end
165
161
  end
@@ -167,15 +163,17 @@ class Gui < Gosu::Window
167
163
  end
168
164
 
169
165
  def main_tick
170
- if @state == STATE_MENU
171
- if @menu_page == MENU_CONNECT
166
+ case @state
167
+ when STATE_MENU
168
+ case @menu_page
169
+ when MENU_CONNECT
172
170
  enter_ip_tick
173
- elsif @menu_page == MENU_USERNAME
171
+ when MENU_USERNAME
174
172
  enter_name_tick
175
173
  else
176
174
  menu_tick
177
175
  end
178
- elsif @state == STATE_ERROR
176
+ when STATE_ERROR
179
177
  if button_down?(Gosu::KB_ESCAPE)
180
178
  @state = STATE_MENU
181
179
  @net_client.disconnect
@@ -202,14 +200,14 @@ class Gui < Gosu::Window
202
200
 
203
201
  def enter_ip_tick
204
202
  if button_down?(Gosu::KB_ESCAPE)
205
- ip = @menu_textfield.text.split(":")
203
+ ip = @menu_textfield.text.split(':')
206
204
  @cfg.data['ip'] = ip[0]
207
205
  @cfg.data['port'] = ip[1] if ip.length > 1
208
206
  @state = STATE_MENU
209
207
  @menu_page = MENU_MAIN
210
208
  elsif button_press?(Gosu::KB_RETURN)
211
209
  if @last_key != Gosu::KB_RETURN
212
- ip = @menu_textfield.text.split(":")
210
+ ip = @menu_textfield.text.split(':')
213
211
  @cfg.data['ip'] = ip[0]
214
212
  @cfg.data['port'] = ip[1] if ip.length > 1
215
213
  connect(@cfg.data['ip'], @cfg.data['port'])
@@ -221,17 +219,17 @@ class Gui < Gosu::Window
221
219
 
222
220
  def menu_tick
223
221
  if button_down?(KEY_Q)
224
- puts "quitting the game."
222
+ puts 'quitting the game.'
225
223
  @cfg.save
226
224
  exit
227
225
  elsif button_down?(KEY_C)
228
226
  connect_menu
229
227
  return
230
228
  end
231
- if button_press?(KEY_DOWN) or button_press?(KEY_S) or button_press?(KEY_J) or button_press?(Gosu::MS_WHEEL_DOWN)
229
+ if button_press?(KEY_DOWN) || button_press?(KEY_S) || button_press?(KEY_J) || button_press?(Gosu::MS_WHEEL_DOWN)
232
230
  @selected_menu_item += 1 if @selected_menu_item < @menu_items.length - 1
233
- elsif button_press?(KEY_UP) or button_press?(KEY_W) or button_press?(KEY_K) or button_press?(Gosu::MS_WHEEL_UP)
234
- @selected_menu_item -= 1 if @selected_menu_item > 0
231
+ elsif button_press?(KEY_UP) || button_press?(KEY_W) || button_press?(KEY_K) || button_press?(Gosu::MS_WHEEL_UP)
232
+ @selected_menu_item -= 1 if @selected_menu_item.positive?
235
233
  elsif button_press?(Gosu::KB_RETURN)
236
234
  @menu_items[@selected_menu_item][1].call
237
235
  end
@@ -239,72 +237,62 @@ class Gui < Gosu::Window
239
237
 
240
238
  def game_tick
241
239
  if button_down?(Gosu::KB_ESCAPE)
242
- if @state == STATE_CONNECTING
240
+ case @state
241
+ when STATE_CONNECTING
243
242
  @state = STATE_MENU
244
243
  @net_client.disconnect
245
- elsif @state == STATE_INGAME
244
+ when STATE_INGAME
246
245
  @state = STATE_MENU
247
246
  @net_client.disconnect
248
247
  return
249
- elsif @state == STATE_REC_PLAYBACK
248
+ when STATE_REC_PLAYBACK
250
249
  @state = STATE_MENU
251
250
  return
252
251
  end
253
252
  end
254
253
  net_request = '0000'.split('')
255
- net_request << "!!!!"
254
+ net_request << '!!!!'
256
255
  protocol = 2
257
256
 
258
257
  if @is_chat
259
258
  msg = chat_tick
260
- if !msg.nil?
259
+ unless msg.nil?
261
260
  # @console.dbg "rawmsg: #{msg}"
262
- msg = msg.ljust(8, '0')
261
+ msg = msg.ljust(8, ' ')
263
262
  net_request = msg[0..CMD_LEN].split('')
264
263
  # @console.dbg "prepedmsg: #{net_request}"
265
264
  protocol = 4
266
265
  end
267
266
  else
268
267
  net_request[0] = '0' # space for more
269
- if button_down?(KEY_S)
270
- net_request[0] = '1'
271
- end
272
- if button_down?(KEY_A)
273
- net_request[1] = 'l'
274
- end
275
- if button_down?(KEY_D)
276
- net_request[1] = 'r'
277
- end
278
- if button_down?(Gosu::KB_SPACE)
279
- net_request[2] = '1'
280
- end
281
- if button_press?(KEY_M)
282
- @is_debug = !@is_debug
283
- end
268
+ net_request[0] = '1' if button_down?(KEY_S)
269
+ net_request[1] = 'l' if button_down?(KEY_A)
270
+ net_request[1] = 'r' if button_down?(KEY_D)
271
+ net_request[2] = '1' if button_down?(Gosu::KB_SPACE)
272
+ @is_debug = !@is_debug if button_press?(KEY_M)
273
+ @is_dbg_grid = !@is_dbg_grid if button_press?(KEY_G) && @is_debug
284
274
  if button_down?(KEY_T)
285
275
  @last_key = KEY_T
286
276
  @is_chat = true
287
- @chat_msg = ""
288
- end
289
- if button_down?(Gosu::MsLeft)
290
- net_request[3] = '1'
277
+ @chat_msg = ''
291
278
  end
279
+ net_request[3] = '1' if button_down?(Gosu::MsLeft)
292
280
  # TODO: check for active window
293
281
  # do not leak mouse movement in other applications than chichilku3
294
- net_request[4] = net_pack_bigint(self.mouse_x.to_i.clamp(0, 8834), 2)
295
- net_request[5] = net_pack_bigint(self.mouse_y.to_i.clamp(0, 8834), 2)
282
+ net_request[4] = net_pack_bigint(mouse_x.to_i.clamp(0, 8834), 2)
283
+ net_request[5] = net_pack_bigint(mouse_y.to_i.clamp(0, 8834), 2)
296
284
  @is_scoreboard = button_down?(Gosu::KB_TAB)
297
285
  end
298
286
 
299
287
  if @state == STATE_REC_PLAYBACK
300
- net_data = @net_client.recording_playback_tick()
288
+ net_data = @net_client.recording_playback_tick
301
289
  @demo_ticks = net_data[3] unless net_data.nil?
302
290
  else
303
291
  # Networking
304
292
  begin
305
293
  net_data = @net_client.tick(net_request, protocol, @tick)
306
294
  rescue Errno::ECONNRESET, Errno::EPIPE
307
- net_data = [@players, @flags, [0, NET_ERR_DISCONNECT, "connection to server lost"]]
295
+ net_data = [@players, @flags, [0, NET_ERR_DISCONNECT, 'connection to server lost']]
308
296
  @net_client.disconnect
309
297
  end
310
298
  end
@@ -315,26 +303,28 @@ class Gui < Gosu::Window
315
303
  msg = net_data[2]
316
304
  if msg
317
305
  type = msg[0]
318
- if type == 0
306
+ case type
307
+ when 0
319
308
  @net_err = msg[1..-1]
320
309
  @state = STATE_ERROR
321
- elsif type == 1
310
+ when 1
322
311
  @server_chat_msg = msg[1]
323
312
  @server_chat_recv = Time.now
324
313
  end
325
314
  end
315
+ @download_progress = net_data[3] if @state == STATE_DOWNLOADING && !net_data[3].nil?
326
316
  return if @flags[:skip]
327
317
 
328
318
  @players = net_data[0]
329
319
  end
330
320
 
331
321
  def update
332
- $time_buffer += get_frame_time
333
- if ($time_buffer > MAX_TICK_SPEED)
334
- @tick += 1
335
- main_tick
336
- $time_buffer = 0
337
- end
322
+ $time_buffer += frame_time
323
+ return unless $time_buffer > MAX_TICK_SPEED
324
+
325
+ @tick += 1
326
+ main_tick
327
+ $time_buffer = 0
338
328
  end
339
329
 
340
330
  def draw_main_menu
@@ -352,17 +342,15 @@ class Gui < Gosu::Window
352
342
  end
353
343
 
354
344
  def event_blood(x, y)
345
+ splashes = []
346
+ 20.times do
347
+ splashes << [x, y, rand(-3..2), rand(-10..-5), rand(1..6), rand(1..6)]
348
+ end
355
349
  @events[:blood] << [
356
350
  x,
357
351
  y,
358
352
  0,
359
- [
360
- [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
361
- [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
362
- [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
363
- [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
364
- [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)]
365
- ]
353
+ splashes
366
354
  ]
367
355
  end
368
356
 
@@ -387,41 +375,62 @@ class Gui < Gosu::Window
387
375
  draw_rect(sx, sy, sw, sh, 0xAAFF0000)
388
376
  new_splashes << [sx, sy, dx, dy, sw, sh]
389
377
  end
390
- unless tick > 200
391
- bloods << [x, y, tick + 1, new_splashes]
392
- end
378
+ bloods << [x, y, tick + 1, new_splashes] unless tick > 200
393
379
  end
394
380
  @events[:blood] = bloods
395
381
  end
396
382
 
397
- def draw_debug(x, y, s=1)
383
+ def draw_debug(x, y, s = 1)
398
384
  return unless @is_debug
399
385
 
400
- draw_rect(x, y, 4*s, 4*s, 0xFFFF0000, 1)
401
- draw_rect(x+1*s, y+1*s, 2*s, 2*s, 0xFF00FF00, 1)
386
+ draw_rect(x, y, 4 * s, 4 * s, 0xFFFF0000, 1)
387
+ draw_rect(x + 1 * s, y + 1 * s, 2 * s, 2 * s, 0xFF00FF00, 1)
388
+ end
389
+
390
+ def draw_debug_gametiles
391
+ return unless @net_client.game_map&.ready
392
+
393
+ (0..(MAP_HEIGHT - 1)).each do |gy|
394
+ (0..(MAP_WIDTH - 1)).each do |gx|
395
+ if @net_client.game_map.collision?(gx, gy)
396
+ draw_rect(gx * TILE_SIZE, gy * TILE_SIZE, TILE_SIZE, TILE_SIZE, 0xAA00EE00)
397
+ elsif @net_client.game_map.death?(gx, gy)
398
+ draw_rect(gx * TILE_SIZE, gy * TILE_SIZE, TILE_SIZE, TILE_SIZE, 0xAAEE0000)
399
+ end
400
+ end
401
+ end
402
402
  end
403
403
 
404
404
  def draw
405
- # draw_quad(0, 0, 0xffff8888, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0xffffffff, 0, 0, 0xffffffff, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0xffffffff, 0)
406
- if @state == STATE_MENU
407
- if @menu_page == MENU_CONNECT
405
+ case @state
406
+ when STATE_MENU
407
+ case @menu_page
408
+ when MENU_CONNECT
408
409
  @connecting_image.draw(0, 0, 0)
409
- @font.draw_text("Enter server ip", 20, 20, 0, 5, 5)
410
+ @font.draw_text('Enter server ip', 20, 20, 0, 5, 5)
410
411
  @menu_textfield.draw(0)
411
- elsif @menu_page == MENU_USERNAME
412
+ when MENU_USERNAME
412
413
  @connecting_image.draw(0, 0, 0)
413
- @font.draw_text("Choose a username", 20, 20, 0, 5, 5)
414
+ @font.draw_text('Choose a username', 20, 20, 0, 5, 5)
414
415
  @menu_textfield.draw(0)
415
416
  else
416
- draw_main_menu()
417
+ draw_main_menu
417
418
  end
418
- elsif @state == STATE_CONNECTING
419
+ when STATE_CONNECTING
419
420
  @connecting_image.draw(0, 0, 0)
420
421
  @font.draw_text("connecting to #{@cfg.data['ip']}:#{@cfg.data['port']}...", 20, 20, 0, 3, 3)
421
- # @con_msg.draw(100,200,0)
422
- elsif @state == STATE_INGAME || @state == STATE_REC_PLAYBACK
423
- @background_image.draw(0, 0, 0)
424
- @crosshair.draw(self.mouse_x-16, self.mouse_y-16, 0, 0.25, 0.25)
422
+ when STATE_DOWNLOADING
423
+ @connecting_image.draw(0, 0, 0)
424
+ @font.draw_text("downloading map #{@download_progress[0]} / #{@download_progress[1]} ...", 20, 20, 0, 3, 3)
425
+ when STATE_INGAME, STATE_REC_PLAYBACK
426
+ # TODO: remove this dirty nil check
427
+ # this is used for demo recordings
428
+ # there seems to be some sort of race coniditon when repaying and already rendering
429
+ # before the map packet was parsed
430
+ # just render black background for a few ticks
431
+ # but what should be done is adding a loading state for demos
432
+ @background_image&.draw(0, 0, 0)
433
+ @crosshair.draw(mouse_x - 16, mouse_y - 16, 0, 0.25, 0.25)
425
434
  # useless mouse trap
426
435
  # since its buggo and your character moves maybe keep it free
427
436
  # mouse players should go fullscreen
@@ -430,27 +439,27 @@ class Gui < Gosu::Window
430
439
  # self.mouse_y = (WINDOW_SIZE_Y / 2) + MOUSE_RADIUS - 1 if self.mouse_y > (WINDOW_SIZE_Y / 2) + MOUSE_RADIUS
431
440
  # self.mouse_y = (WINDOW_SIZE_Y / 2) - MOUSE_RADIUS + 1 if self.mouse_y < (WINDOW_SIZE_Y / 2) - MOUSE_RADIUS
432
441
  @players.each do |player|
433
- event_blood(player.x, player.y) if player.state[:bleeding]
442
+ event_blood(player.x + (player.w / 2), player.y + (player.h / 2)) if player.state[:bleeding]
434
443
  player.draw_tick
435
444
  @console.dbg "drawing player id=#{player.id} pos=#{player.x}/#{player.y}"
436
445
  # draw_rect(player.x, player.y, TILE_SIZE, TILE_SIZE, Gosu::Color::WHITE)
437
- if player.state[:crouching]
446
+ if player.crouching?
438
447
  @stick_crouching[player.img_index].draw(player.x, player.y, 0, 0.5, 0.5)
439
448
  else
440
449
  @stick_images[player.img_index].draw(player.x, player.y, 0, 0.5, 0.5)
441
- x = player.aimX - player.x
442
- y = player.aimY - player.y
450
+ x = player.aim_x - player.x
451
+ y = player.aim_y - player.y
443
452
  rot = Math.atan2(x, y) * 180 / Math::PI * -1 + 90 * -1
444
453
  rot2 = Math.atan2(x, y) * 180 / Math::PI * -1 + 270 * -1
445
- stick_center_x = player.x + TILE_SIZE/4
446
- stick_center_y = player.y + TILE_SIZE/2
454
+ stick_center_x = player.x + TILE_SIZE / 4
455
+ stick_center_y = player.y + TILE_SIZE / 2
447
456
  d = -8
448
457
  d += player.state[:fire] * 3
449
458
  arr_x = stick_center_x + (d * Math.cos((rot2 + 180) / 180 * Math::PI))
450
459
  arr_y = stick_center_y + (d * Math.sin((rot2 + 180) / 180 * Math::PI))
451
460
  @bow_images[player.state[:fire]].draw_rot(stick_center_x, stick_center_y, 0, rot, 0.5, 0.5, 0.5, 0.5)
452
461
  @stick_arm_images[player.state[:fire]].draw_rot(stick_center_x, stick_center_y, 0, rot, 0.5, 0.5, 0.5, 0.5)
453
- if player.projectile.x == 0 and player.projectile.y == 0
462
+ if player.projectile.x.zero? && player.projectile.y.zero?
454
463
  @arrow_image.draw_rot(arr_x, arr_y, 0, rot2, 0.5, 0.5, 0.5, 0.5)
455
464
  end
456
465
  if @is_debug
@@ -458,39 +467,44 @@ class Gui < Gosu::Window
458
467
  draw_debug(stick_center_x, stick_center_y, 1)
459
468
  draw_line(arr_x, arr_y, 0xFFFF0000, stick_center_x, stick_center_y, 0xFF000000)
460
469
  @font.draw_text("rot=#{rot.to_i} rot2=#{rot2.to_i}", player.x - 60, player.y - 100, 0, 1, 1, 0xFF000000)
461
- @font.draw_text("d=#{d} (#{stick_center_x}/#{stick_center_y}) -> (#{arr_x.to_i}/#{arr_y.to_i})", player.x - 80, player.y - 80, 0, 1, 1, 0xFF000000)
470
+ @font.draw_text("d=#{d} (#{stick_center_x}/#{stick_center_y}) -> (#{arr_x.to_i}/#{arr_y.to_i})",
471
+ player.x - 80, player.y - 80, 0, 1, 1, 0xFF000000)
462
472
  end
463
473
  end
464
- unless player.projectile.x == 0 or player.projectile.y == 0
474
+ unless player.projectile.x.zero? || player.projectile.y.zero?
465
475
  rot = player.projectile.r.to_i * 45
466
476
  @arrow_image.draw_rot(player.projectile.x, player.projectile.y, 0, rot, 0.5, 0.5, 0.5, 0.5)
467
477
  end
468
478
  if @is_debug # print id
469
479
  # aim
470
- draw_rect(player.aimX - 2, player.aimY - 16, 4, 32, 0xCC33FF33)
471
- draw_rect(player.aimX - 16, player.aimY - 2, 32, 4, 0xCC33FF33)
472
- draw_rect(player.aimX, player.aimY - 15, 1, 30, 0xAA000000)
473
- draw_rect(player.aimX - 15, player.aimY, 30, 1, 0xAA000000)
480
+ draw_rect(player.aim_x - 2, player.aim_y - 16, 4, 32, 0xCC33FF33)
481
+ draw_rect(player.aim_x - 16, player.aim_y - 2, 32, 4, 0xCC33FF33)
482
+ draw_rect(player.aim_x, player.aim_y - 15, 1, 30, 0xAA000000)
483
+ draw_rect(player.aim_x - 15, player.aim_y, 30, 1, 0xAA000000)
474
484
  # text background
475
485
  draw_rect(player.x - 2, player.y - 60, 32, 20, 0xAA000000)
476
486
  @font.draw_text("#{player.id}:#{player.score}", player.x, player.y - 60, 0, 1, 1)
477
487
  # @font.draw_text("#{player.id}:#{player.img_index}", player.x, player.y - TILE_SIZE * 2, 0, 1, 1)
478
- if player.state[:crouching]
479
- draw_rect(player.x, player.y, TILE_SIZE, TILE_SIZE/2, 0xAA00EE00)
488
+ if player.crouching?
489
+ draw_rect(player.x, player.y, PLAYER_SIZE, PLAYER_SIZE / 2, 0xAA00EE00)
480
490
  else
481
- draw_rect(player.x, player.y, TILE_SIZE/2, TILE_SIZE, 0xAA00EE00)
491
+ draw_rect(player.x, player.y, PLAYER_SIZE / 2, PLAYER_SIZE, 0xAA00EE00)
482
492
  end
483
- unless player.projectile.x == 0 or player.projectile.y == 0
493
+ unless player.projectile.x.zero? || player.projectile.y.zero?
484
494
  draw_rect(player.projectile.x, player.projectile.y, player.projectile.w, player.projectile.h, 0xAA00EE00)
485
495
  end
486
496
  end
487
- @font.draw_text(player.name, player.x - (TILE_SIZE/6), player.y - TILE_SIZE / 2, 0, 1, 1, 0xff_000000)
497
+ next unless @net_client.game_map&.ready
498
+
499
+ unless @net_client.game_map.grass?(player.x / TILE_SIZE, player.y / TILE_SIZE)
500
+ @font.draw_text(player.name, player.x - (TILE_SIZE / 6), player.y - TILE_SIZE / 2, 0, 1, 1, 0xff_000000)
501
+ end
488
502
  end
489
503
 
504
+ @particles.draw(@net_client.game_map, @players) if @net_client.game_map&.ready
505
+
490
506
  # chat input
491
- if @is_chat
492
- @font.draw_text("> #{@chat_msg}", 10, WINDOW_SIZE_Y - 30, 0, 1, 1)
493
- end
507
+ @font.draw_text("> #{@chat_msg}", 10, WINDOW_SIZE_Y - 30, 0, 1, 1) if @is_chat
494
508
 
495
509
  # chat output
496
510
  if @server_chat_recv + @chat_show_time > Time.now
@@ -501,36 +515,44 @@ class Gui < Gosu::Window
501
515
  player = Player.get_player_by_id(@players, @flags[:id])
502
516
  unless player.nil?
503
517
  draw_rect(5, 10, 290, 85, 0xAA000000)
504
- @font.draw_text("Press m to deactivate debug mode", 10, 10, 0, 1, 1)
518
+ @font.draw_text('Press m to deactivate debug mode', 10, 10, 0, 1, 1)
505
519
  @font.draw_text("x: #{player.x} y: #{player.y}", 10, 30, 0, 1, 1)
506
- @font.draw_text("aimX: #{player.aimX} aimY: #{player.aimY}", 10, 45, 0, 1, 1)
507
- @font.draw_text("gamestate: #{@flags[:gamestate]}", 10, 60, 0 , 1, 1)
508
- @font.draw_text("server version: #{@net_client.server_version}", 10, 75, 0 , 1, 1)
520
+ @font.draw_text("aim_x: #{player.aim_x} aim_y: #{player.aim_y}", 10, 45, 0, 1, 1)
521
+ @font.draw_text("gamestate: #{@flags[:gamestate]}", 10, 60, 0, 1, 1)
522
+ @font.draw_text("server version: #{@net_client.server_version}", 10, 75, 0, 1, 1)
509
523
  # thats useless because collide/delta speed is not sent over the network
510
524
  # @font.draw_text("dx: #{player.dx} dy: #{player.dy}", 10, 50, 0, 1, 1)
511
525
  # @font.draw_text(player.collide_string, 10, 70, 0, 1, 1)
512
526
  end
527
+
528
+ if @is_dbg_grid
529
+ (1..MAP_WIDTH).each do |gx|
530
+ draw_rect(gx * TILE_SIZE, 0, 1, WINDOW_SIZE_Y, 0xAA00EE00)
531
+ end
532
+ (1..MAP_HEIGHT).each do |gy|
533
+ draw_rect(0, gy * TILE_SIZE, WINDOW_SIZE_X, 1, 0xAA00EE00)
534
+ end
535
+ draw_debug_gametiles
536
+ end
513
537
  end
514
538
 
515
- draw_events()
539
+ draw_events
516
540
 
517
- if @is_scoreboard
518
- draw_scoreboard(WINDOW_SIZE_X, WINDOW_SIZE_Y, @players, @font, @is_debug)
519
- end
520
- if @state == STATE_REC_PLAYBACK && !(@demo_ticks.nil?)
541
+ draw_scoreboard(WINDOW_SIZE_X, WINDOW_SIZE_Y, @players, @font, @is_debug) if @is_scoreboard
542
+ if @state == STATE_REC_PLAYBACK && !@demo_ticks.nil?
521
543
  @font.draw_text("#{@demo_ticks[0]}/#{@demo_ticks[1]}", 10, WINDOW_SIZE_Y - 20, 0)
522
544
  end
523
- elsif @state == STATE_ERROR
545
+ when STATE_ERROR
524
546
  net_err_code = @net_err[0]
525
547
  net_err_msg = @net_err[1]
526
548
  @connecting_image.draw(0, 0, 0)
527
- if net_err_code == NET_ERR_SERVER_OUTDATED || net_err_code == NET_ERR_CLIENT_OUTDATED
549
+ if [NET_ERR_SERVER_OUTDATED, NET_ERR_CLIENT_OUTDATED].include?(net_err_code)
528
550
  server_version = net_err_msg[0..4]
529
551
  net_err_msg = net_err_msg[5..-1]
530
552
  @font.draw_text("Server version: #{server_version} Your version: #{GAME_VERSION}", 50, 150, 0, 2, 2)
531
553
  end
532
- @font.draw_text("#{NET_ERR[net_err_code]}", 50, 30, 0, 5, 5)
533
- @font.draw_text("#{net_err_msg}", 50, 200, 0, 2, 2)
554
+ @font.draw_text((NET_ERR[net_err_code]).to_s, 50, 30, 0, 5, 5)
555
+ @font.draw_text(net_err_msg.to_s, 50, 200, 0, 2, 2)
534
556
  else
535
557
  @connecting_image.draw(0, 0, 0)
536
558
  @font.draw_text('UNKOWN CLIENT STATE!!!', 20, 20, 0, 2, 10)
@@ -543,17 +565,17 @@ class Gui < Gosu::Window
543
565
  @console.log "connecting to server '#{ip}:#{port}' ..."
544
566
  begin
545
567
  @net_client.connect(ip, port)
546
- @state = STATE_CONNECTING;
568
+ @state = STATE_CONNECTING
547
569
  @menu_page = MENU_MAIN
548
570
  rescue Errno::ECONNREFUSED
549
571
  @state = STATE_ERROR
550
572
  @menu_page = MENU_MAIN
551
- @net_err = [NET_ERR_DISCONNECT, "connection refused"]
573
+ @net_err = [NET_ERR_DISCONNECT, 'connection refused']
552
574
  @net_client.disconnect
553
575
  end
554
576
  end
555
577
 
556
- def connect_menu()
578
+ def connect_menu
557
579
  @last_key = Gosu::KB_RETURN
558
580
  self.text_input = @menu_textfield
559
581
  @menu_textfield.text = "#{@cfg.data['ip']}:#{@cfg.data['port']}"
@@ -561,34 +583,34 @@ class Gui < Gosu::Window
561
583
  @menu_page = MENU_CONNECT
562
584
  end
563
585
 
564
- def username_page()
586
+ def username_page
565
587
  @last_key = Gosu::KB_RETURN
566
588
  self.text_input = @menu_textfield
567
- @menu_textfield.text = "#{@cfg.data['username']}"
589
+ @menu_textfield.text = @cfg.data['username'].to_s
568
590
  @state = STATE_MENU
569
591
  @menu_page = MENU_USERNAME
570
592
  end
571
593
 
572
- def toggle_fullscreen()
573
- if @cfg.data['fullscreen']
574
- @cfg.data['fullscreen'] = self.fullscreen = false
575
- else
576
- @cfg.data['fullscreen'] = self.fullscreen = true
577
- end
594
+ def toggle_fullscreen
595
+ @cfg.data['fullscreen'] = self.fullscreen = if @cfg.data['fullscreen']
596
+ false
597
+ else
598
+ true
599
+ end
578
600
  end
579
601
 
580
- def play_recording()
602
+ def play_recording
581
603
  @net_client.load_recording('autorec.txt')
582
604
  @state = STATE_REC_PLAYBACK
583
605
  end
584
606
 
585
- def init_menu()
607
+ def init_menu
586
608
  @menu_items = []
587
- add_menu_item("[c]onnect", Proc.new { connect_menu() })
588
- add_menu_item("username", Proc.new { username_page() })
589
- add_menu_item("fullscreen", Proc.new { toggle_fullscreen() })
590
- add_menu_item("recording", Proc.new { play_recording() })
591
- add_menu_item("[q]uit", Proc.new { exit() })
609
+ add_menu_item('[c]onnect', proc { connect_menu })
610
+ add_menu_item('username', proc { username_page })
611
+ add_menu_item('fullscreen', proc { toggle_fullscreen })
612
+ add_menu_item('recording', proc { play_recording })
613
+ add_menu_item('[q]uit', proc { exit })
592
614
  end
593
615
 
594
616
  def add_menu_item(name, callback)