chichilku3 5.0.0

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 (38) hide show
  1. checksums.yaml +7 -0
  2. data/bin/chichilku3 +3 -0
  3. data/bin/chichilku3-server +3 -0
  4. data/client.json +6 -0
  5. data/lib/client/chichilku3.rb +18 -0
  6. data/lib/client/client.rb +289 -0
  7. data/lib/client/client_cfg.rb +15 -0
  8. data/lib/client/gui.rb +492 -0
  9. data/lib/client/img/background1024x512.png +0 -0
  10. data/lib/client/img/battle1024x576.png +0 -0
  11. data/lib/client/img/connecting1024x512.png +0 -0
  12. data/lib/client/img/grass1024x512.png +0 -0
  13. data/lib/client/img/grey128.png +0 -0
  14. data/lib/client/img/menu1920x1080.png +0 -0
  15. data/lib/client/img/stick128/stick0.png +0 -0
  16. data/lib/client/img/stick128/stick1.png +0 -0
  17. data/lib/client/img/stick128/stick2.png +0 -0
  18. data/lib/client/img/stick128/stick3.png +0 -0
  19. data/lib/client/img/stick128/stick4.png +0 -0
  20. data/lib/client/img/stick128/stick5.png +0 -0
  21. data/lib/client/img/stick128/stick_crouching0.png +0 -0
  22. data/lib/client/img/stick128/stick_crouching1.png +0 -0
  23. data/lib/client/img/stick128/stick_crouching2.png +0 -0
  24. data/lib/client/img/stick128/stick_crouching3.png +0 -0
  25. data/lib/client/img/stick128/stick_crouching4.png +0 -0
  26. data/lib/client/img/stick128/stick_crouching5.png +0 -0
  27. data/lib/client/scoreboard.rb +25 -0
  28. data/lib/client/test.rb +39 -0
  29. data/lib/client/text.rb +86 -0
  30. data/lib/server/chichilku3_server.rb +293 -0
  31. data/lib/server/gamelogic.rb +121 -0
  32. data/lib/server/server_cfg.rb +6 -0
  33. data/lib/share/config.rb +53 -0
  34. data/lib/share/console.rb +18 -0
  35. data/lib/share/network.rb +145 -0
  36. data/lib/share/player.rb +286 -0
  37. data/server.json +4 -0
  38. metadata +81 -0
data/lib/client/gui.rb ADDED
@@ -0,0 +1,492 @@
1
+ require 'gosu'
2
+ require_relative 'client'
3
+ require_relative 'text'
4
+ require_relative 'scoreboard'
5
+ require_relative '../share/console'
6
+ 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
24
+
25
+ MENU_MAIN = 0
26
+ MENU_CONNECT = 1
27
+ MENU_USERNAME = 2
28
+
29
+ $time_point=Time.now
30
+ $time_buffer=0
31
+
32
+ def get_frame_time
33
+ diff = Time.now - $time_point
34
+ $time_point = Time.now
35
+ return diff
36
+ end
37
+
38
+ # Main Game getting gui form gosu
39
+ class Gui < Gosu::Window
40
+ def initialize(cfg)
41
+ super WINDOW_SIZE_X, WINDOW_SIZE_Y
42
+ self.caption = 'chichilku3'
43
+ self.fullscreen = true if cfg.data['fullscreen']
44
+ # images
45
+ @background_image = Gosu::Image.new("lib/client/img/battle1024x576.png")
46
+ @connecting_image = Gosu::Image.new("lib/client/img/connecting1024x512.png")
47
+ @menu_image = Gosu::Image.new("lib/client/img/menu1920x1080.png")
48
+ @stick = Gosu::Image.new("lib/client/img/stick128/stick0.png")
49
+ @stick_crouching = []
50
+ @stick_crouching << Gosu::Image.new("lib/client/img/stick128/stick_crouching0.png")
51
+ @stick_crouching << Gosu::Image.new("lib/client/img/stick128/stick_crouching1.png")
52
+ @stick_crouching << Gosu::Image.new("lib/client/img/stick128/stick_crouching2.png")
53
+ @stick_crouching << Gosu::Image.new("lib/client/img/stick128/stick_crouching3.png")
54
+ @stick_crouching << Gosu::Image.new("lib/client/img/stick128/stick_crouching4.png")
55
+ @stick_crouching << Gosu::Image.new("lib/client/img/stick128/stick_crouching5.png")
56
+ @stick_images = []
57
+ @stick_images << Gosu::Image.new("lib/client/img/stick128/stick0.png")
58
+ @stick_images << Gosu::Image.new("lib/client/img/stick128/stick1.png")
59
+ @stick_images << Gosu::Image.new("lib/client/img/stick128/stick2.png")
60
+ @stick_images << Gosu::Image.new("lib/client/img/stick128/stick3.png")
61
+ @stick_images << Gosu::Image.new("lib/client/img/stick128/stick4.png")
62
+ @stick_images << Gosu::Image.new("lib/client/img/stick128/stick5.png")
63
+ @x = 0
64
+ @y = 0
65
+ @players = []
66
+ @cfg = cfg
67
+ @tick = 0
68
+ @console = Console.new
69
+ @net_client = Client.new(@console, @cfg)
70
+ @net_err = nil
71
+ @state = @net_client.state
72
+ @menu_page = MENU_MAIN
73
+ @font = Gosu::Font.new(20)
74
+ @is_debug = false
75
+ @is_chat = false
76
+ @is_scoreboard = false
77
+ @chat_msg = "" # what we type
78
+ @server_chat_msg = "" # what we get from server
79
+ @chat_show_time = 4
80
+ @server_chat_recv = Time.now - @chat_show_time
81
+ @last_key = nil
82
+ @events = {
83
+ :blood => []
84
+ }
85
+ @menu_items = []
86
+ @selected_menu_item = 0
87
+ @menu_textfield = TextField.new(self, 60, 200)
88
+ # @chat_inp_stream = nil #TextInput.new
89
+ # @chat_inp_stream.text # didnt get it working <--- nobo xd
90
+
91
+ @last_pressed_button = {}
92
+
93
+ # depreciated ._.
94
+ # @con_msg = Gosu::Image.from_text(self, "connecting to #{@cfg.data['ip']}:#{@cfg.data['port']}...", Gosu.default_font_name, 45)
95
+ init_menu()
96
+ end
97
+
98
+ def button_press?(button)
99
+ last_btn = @last_pressed_button[button]
100
+ @last_pressed_button[button] = button_down?(button)
101
+ return false if last_btn == true
102
+ button_down?(button)
103
+ end
104
+
105
+ # def update_pos(server_data)
106
+ # server_data = server_data.split('')
107
+ # @x = server_data[0].to_i * 20
108
+ # @y = server_data[1].to_i * 20
109
+ # end
110
+
111
+ def chat_tick
112
+ if button_down?(Gosu::KB_ESCAPE)
113
+ @is_chat = false
114
+ elsif button_down?(Gosu::KB_RETURN)
115
+ @is_chat = false
116
+ return @chat_msg
117
+ else
118
+ if !button_down?(@last_key)
119
+ @last_key = nil # refresh blocker
120
+ end
121
+ if button_down?(Gosu::KB_BACKSPACE)
122
+ # press shift to fast delete
123
+ if button_down?(Gosu::KB_LEFT_SHIFT) || @last_key != Gosu::KB_BACKSPACE
124
+ @chat_msg = @chat_msg[0..-2]
125
+ @last_key = Gosu::KB_BACKSPACE
126
+ end
127
+ end
128
+ for key in 4..30 do # alphabet lowercase
129
+ if button_down?(key)
130
+ if @last_key != key
131
+ @chat_msg += button_id_to_char(key)
132
+ @last_key = key
133
+ end
134
+ end
135
+ end
136
+ end
137
+ nil
138
+ end
139
+
140
+ def main_tick
141
+ if @state == STATE_MENU
142
+ if @menu_page == MENU_CONNECT
143
+ enter_ip_tick
144
+ elsif @menu_page == MENU_USERNAME
145
+ enter_name_tick
146
+ else
147
+ menu_tick
148
+ end
149
+ elsif @state == STATE_ERROR
150
+ if button_down?(Gosu::KB_ESCAPE)
151
+ @state = STATE_MENU
152
+ @net_client.disconnect
153
+ end
154
+ else
155
+ game_tick
156
+ end
157
+ end
158
+
159
+ def enter_name_tick
160
+ if button_down?(Gosu::KB_ESCAPE)
161
+ @state = STATE_MENU
162
+ @menu_page = MENU_MAIN
163
+ elsif button_down?(Gosu::KB_RETURN)
164
+ if @last_key != Gosu::KB_RETURN
165
+ @cfg.data['username'] = @menu_textfield.text[0...NAME_LEN]
166
+ @state = STATE_MENU
167
+ @menu_page = MENU_MAIN
168
+ end
169
+ else
170
+ @last_key = nil
171
+ end
172
+ end
173
+
174
+ def enter_ip_tick
175
+ if button_down?(Gosu::KB_ESCAPE)
176
+ ip = @menu_textfield.text.split(":")
177
+ @cfg.data['ip'] = ip[0]
178
+ @cfg.data['port'] = ip[1] if ip.length > 1
179
+ @state = STATE_MENU
180
+ @menu_page = MENU_MAIN
181
+ elsif button_press?(Gosu::KB_RETURN)
182
+ if @last_key != Gosu::KB_RETURN
183
+ ip = @menu_textfield.text.split(":")
184
+ @cfg.data['ip'] = ip[0]
185
+ @cfg.data['port'] = ip[1] if ip.length > 1
186
+ connect
187
+ end
188
+ else
189
+ @last_key = nil
190
+ end
191
+ end
192
+
193
+ def menu_tick
194
+ if button_down?(KEY_Q)
195
+ puts "quitting the game."
196
+ @cfg.save
197
+ exit
198
+ elsif button_down?(KEY_C)
199
+ connect_menu
200
+ return
201
+ end
202
+ if button_press?(KEY_DOWN) or button_press?(KEY_S) or button_press?(KEY_J) or button_press?(Gosu::MS_WHEEL_DOWN)
203
+ @selected_menu_item += 1 if @selected_menu_item < @menu_items.length - 1
204
+ elsif button_press?(KEY_UP) or button_press?(KEY_W) or button_press?(KEY_K) or button_press?(Gosu::MS_WHEEL_UP)
205
+ @selected_menu_item -= 1 if @selected_menu_item > 0
206
+ elsif button_press?(Gosu::KB_RETURN)
207
+ @menu_items[@selected_menu_item][1].call
208
+ end
209
+ end
210
+
211
+ def game_tick
212
+ if button_down?(Gosu::KB_ESCAPE)
213
+ if @state == STATE_CONNECTING
214
+ @state = STATE_MENU
215
+ @net_client.disconnect
216
+ elsif @state == STATE_INGAME
217
+ @state = STATE_MENU
218
+ @net_client.disconnect
219
+ return
220
+ end
221
+ end
222
+ net_request = '0000'.split('')
223
+ protocol = 2
224
+
225
+ if @is_chat
226
+ msg = chat_tick
227
+ if !msg.nil?
228
+ # @console.dbg "rawmsg: #{msg}"
229
+ msg = msg.ljust(4, '0')
230
+ net_request = msg[0..3].split('')
231
+ # @console.dbg "prepedmsg: #{net_request}"
232
+ protocol = 4
233
+ end
234
+ else
235
+ net_request[0] = '0' # space for more
236
+ if button_down?(KEY_S)
237
+ net_request[0] = '1'
238
+ end
239
+ if button_down?(KEY_A)
240
+ net_request[1] = '1'
241
+ end
242
+ if button_down?(KEY_D)
243
+ net_request[2] = '1'
244
+ end
245
+ if button_down?(Gosu::KB_SPACE)
246
+ net_request[3] = '1'
247
+ end
248
+ if button_press?(KEY_M)
249
+ @is_debug = !@is_debug
250
+ end
251
+ if button_down?(KEY_T)
252
+ @last_key = KEY_T
253
+ @is_chat = true
254
+ @chat_msg = ""
255
+ end
256
+ @is_scoreboard = button_down?(Gosu::KB_TAB)
257
+ end
258
+
259
+ # Networking
260
+ begin
261
+ net_data = @net_client.tick(net_request, protocol, @tick)
262
+ rescue Errno::ECONNRESET, Errno::EPIPE
263
+ net_data = [@players, @flags, [0, NET_ERR_DISCONNECT, "connection to server lost"]]
264
+ @net_client.disconnect
265
+ end
266
+ return if net_data.nil?
267
+
268
+ @flags = net_data[1]
269
+ @state = @flags[:state]
270
+ msg = net_data[2]
271
+ if msg
272
+ type = msg[0]
273
+ if type == 0
274
+ @net_err = msg[1..-1]
275
+ @state = STATE_ERROR
276
+ elsif type == 1
277
+ @server_chat_msg = msg[1]
278
+ @server_chat_recv = Time.now
279
+ end
280
+ end
281
+ return if @flags[:skip]
282
+
283
+ @players = net_data[0]
284
+ end
285
+
286
+ def update
287
+ $time_buffer += get_frame_time
288
+ if ($time_buffer > MAX_TICK_SPEED)
289
+ @tick += 1
290
+ main_tick
291
+ $time_buffer = 0
292
+ end
293
+ end
294
+
295
+ def draw_main_menu
296
+ @menu_image.draw(0, 0, 0, UI_SCALE, UI_SCALE)
297
+ offset = 0
298
+ size = 2
299
+ @menu_items.each_with_index do |menu_item, index|
300
+ offset += 20 * size
301
+ if index == @selected_menu_item
302
+ @font.draw_text("> #{menu_item[0]} <", 20, 20 + offset, 0, size, size, Gosu::Color::GREEN)
303
+ else
304
+ @font.draw_text(" #{menu_item[0]} ", 20, 20 + offset, 0, size, size)
305
+ end
306
+ end
307
+ end
308
+
309
+ def event_blood(x, y)
310
+ @events[:blood] << [
311
+ x,
312
+ y,
313
+ 0,
314
+ [
315
+ [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
316
+ [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
317
+ [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
318
+ [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)],
319
+ [x, y, rand(12) - 6, rand(12) - 24, rand(3..12), rand(3..12)]
320
+ ]
321
+ ]
322
+ end
323
+
324
+ def draw_events
325
+ bloods = []
326
+ @events[:blood].each do |blood|
327
+ x = blood[0]
328
+ y = blood[1]
329
+ tick = blood[2]
330
+ splashes = blood[3]
331
+ new_splashes = []
332
+ splashes.each do |splash|
333
+ sx = splash[0]
334
+ sy = splash[1]
335
+ dx = splash[2]
336
+ dy = splash[3]
337
+ sw = splash[4]
338
+ sh = splash[5]
339
+ sx += dx
340
+ sy += dy
341
+ dy += 1 # gravity
342
+ draw_rect(sx, sy, sw, sh, 0xAAFF0000)
343
+ new_splashes << [sx, sy, dx, dy, sw, sh]
344
+ end
345
+ unless tick > 200
346
+ bloods << [x, y, tick + 1, new_splashes]
347
+ end
348
+ end
349
+ @events[:blood] = bloods
350
+ end
351
+
352
+ def draw
353
+ # draw_quad(0, 0, 0xffff8888, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0xffffffff, 0, 0, 0xffffffff, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0xffffffff, 0)
354
+ if @state == STATE_MENU
355
+ if @menu_page == MENU_CONNECT
356
+ @connecting_image.draw(0, 0, 0)
357
+ @font.draw_text("Enter server ip", 20, 20, 0, 5, 5)
358
+ @menu_textfield.draw(0)
359
+ elsif @menu_page == MENU_USERNAME
360
+ @connecting_image.draw(0, 0, 0)
361
+ @font.draw_text("Choose a username", 20, 20, 0, 5, 5)
362
+ @menu_textfield.draw(0)
363
+ else
364
+ draw_main_menu()
365
+ end
366
+ elsif @state == STATE_CONNECTING
367
+ @connecting_image.draw(0, 0, 0)
368
+ @font.draw_text("connecting to #{@cfg.data['ip']}:#{@cfg.data['port']}...", 20, 20, 0, 2, 5)
369
+ # @con_msg.draw(100,200,0)
370
+ elsif @state == STATE_INGAME
371
+ @background_image.draw(0, 0, 0)
372
+ @players.each do |player|
373
+ event_blood(player.x, player.y) if player.state[:bleeding]
374
+ player.draw_tick
375
+ @console.dbg "drawing player id=#{player.id} pos=#{player.x}/#{player.y}"
376
+ # draw_rect(player.x, player.y, TILE_SIZE, TILE_SIZE, Gosu::Color::WHITE)
377
+ # @stick.draw(player.x, player.y, 0)
378
+ if player.state[:crouching]
379
+ @stick_crouching[player.img_index].draw(player.x, player.y, 0, 0.5, 0.5)
380
+ else
381
+ @stick_images[player.img_index].draw(player.x, player.y, 0, 0.5, 0.5)
382
+ end
383
+ if @is_debug # print id
384
+ draw_rect(player.x - 2, player.y - 60, 32, 20, 0xAA000000)
385
+ @font.draw_text("#{player.id}:#{player.score}", player.x, player.y - 60, 0, 1, 1)
386
+ # @font.draw_text("#{player.id}:#{player.img_index}", player.x, player.y - TILE_SIZE * 2, 0, 1, 1)
387
+ if player.state[:crouching]
388
+ draw_rect(player.x, player.y, TILE_SIZE, TILE_SIZE/2, 0xAA00EE00)
389
+ else
390
+ draw_rect(player.x, player.y, TILE_SIZE/2, TILE_SIZE, 0xAA00EE00)
391
+ end
392
+ else
393
+ end
394
+ @font.draw_text(player.name, player.x - (TILE_SIZE/6), player.y - TILE_SIZE / 2, 0, 1, 1, 0xff_000000)
395
+ end
396
+
397
+ # chat input
398
+ if @is_chat
399
+ @font.draw_text("> #{@chat_msg}", 10, WINDOW_SIZE_Y - 30, 0, 1, 1)
400
+ end
401
+
402
+ # chat output
403
+ if @server_chat_recv + @chat_show_time > Time.now
404
+ @font.draw_text(@server_chat_msg, 10, WINDOW_SIZE_Y - 60, 0, 1, 1)
405
+ end
406
+
407
+ if @is_debug
408
+ player = Player.get_player_by_id(@players, @flags[:id])
409
+ unless player.nil?
410
+ draw_rect(5, 10, 295, 75, 0xAA000000)
411
+ @font.draw_text("Press m to deactivate debug mode", 10, 10, 0, 1, 1)
412
+ @font.draw_text("x: #{player.x} y: #{player.y}", 10, 30, 0, 1, 1)
413
+ @font.draw_text("gamestate: #{@flags[:gamestate]}", 10, 60, 0 , 1, 1)
414
+ # thats useless because collide/delta speed is not sent over the network
415
+ # @font.draw_text("dx: #{player.dx} dy: #{player.dy}", 10, 50, 0, 1, 1)
416
+ # @font.draw_text(player.collide_string, 10, 70, 0, 1, 1)
417
+ end
418
+ end
419
+
420
+ draw_events()
421
+
422
+ if @is_scoreboard
423
+ draw_scoreboard(WINDOW_SIZE_X, WINDOW_SIZE_Y, @players, @font)
424
+ end
425
+ elsif @state == STATE_ERROR
426
+ net_err_code = @net_err[0]
427
+ net_err_msg = @net_err[1]
428
+ @connecting_image.draw(0, 0, 0)
429
+ if net_err_code == NET_ERR_SERVER_OUTDATED || net_err_code == NET_ERR_CLIENT_OUTDATED
430
+ server_version = net_err_msg[0..4]
431
+ net_err_msg = net_err_msg[5..-1]
432
+ @font.draw_text("Server version: #{server_version} Your version: #{GAME_VERSION}", 50, 150, 0, 2, 2)
433
+ end
434
+ @font.draw_text("#{NET_ERR[net_err_code]}", 50, 30, 0, 5, 5)
435
+ @font.draw_text("#{net_err_msg}", 50, 200, 0, 2, 2)
436
+ else
437
+ @connecting_image.draw(0, 0, 0)
438
+ @font.draw_text('UNKOWN CLIENT STATE!!!', 20, 20, 0, 2, 10)
439
+ end
440
+ end
441
+
442
+ private
443
+
444
+ def connect()
445
+ begin
446
+ @net_client.connect(@cfg.data['ip'], @cfg.data['port'])
447
+ @state = STATE_CONNECTING;
448
+ @menu_page = MENU_MAIN
449
+ rescue Errno::ECONNREFUSED
450
+ @state = STATE_ERROR
451
+ @menu_page = MENU_MAIN
452
+ @net_err = [NET_ERR_DISCONNECT, "connection refused"]
453
+ @net_client.disconnect
454
+ end
455
+ end
456
+
457
+ def connect_menu()
458
+ @last_key = Gosu::KB_RETURN
459
+ self.text_input = @menu_textfield
460
+ @menu_textfield.text = "#{@cfg.data['ip']}:#{@cfg.data['port']}"
461
+ @state = STATE_MENU
462
+ @menu_page = MENU_CONNECT
463
+ end
464
+
465
+ def username_page()
466
+ @last_key = Gosu::KB_RETURN
467
+ self.text_input = @menu_textfield
468
+ @menu_textfield.text = "#{@cfg.data['username']}"
469
+ @state = STATE_MENU
470
+ @menu_page = MENU_USERNAME
471
+ end
472
+
473
+ def toggle_fullscreen()
474
+ if @cfg.data['fullscreen']
475
+ @cfg.data['fullscreen'] = self.fullscreen = false
476
+ else
477
+ @cfg.data['fullscreen'] = self.fullscreen = true
478
+ end
479
+ end
480
+
481
+ def init_menu()
482
+ @menu_items = []
483
+ add_menu_item("[c]onnect", Proc.new { connect_menu() })
484
+ add_menu_item("username", Proc.new { username_page() })
485
+ add_menu_item("fullscreen", Proc.new { toggle_fullscreen() })
486
+ add_menu_item("[q]uit", Proc.new { exit() })
487
+ end
488
+
489
+ def add_menu_item(name, callback)
490
+ @menu_items.push([name, callback])
491
+ end
492
+ end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+
2
+ def draw_scoreboard(win_size_x, win_size_y, players, font)
3
+ # TODO: do not compute those every frame
4
+ padX = win_size_x / 3
5
+ sizeX = win_size_x / 3
6
+ padY = win_size_y / 6
7
+ sizeY = win_size_y / 3
8
+ slot_height = sizeY / MAX_CLIENTS
9
+ text_scale = slot_height / 15
10
+ # background
11
+ draw_rect(padX, padY, sizeX, sizeY+3, 0xaa000000)
12
+ # left border
13
+ draw_rect(padX, padY, 3, sizeY+3, 0xaa000000)
14
+ # right border
15
+ draw_rect(padX + sizeX - 3, padY, 3, sizeY+3, 0xaa000000)
16
+ (0..MAX_CLIENTS).each do |i|
17
+ # row borders
18
+ draw_rect(padX + 3, padY + (i * slot_height), sizeX - 6, 3, 0xaa000000)
19
+ end
20
+ players.each_with_index do | player, i |
21
+ score_offset = text_scale * 10 * player.score.to_s.length
22
+ font.draw_text(player.name, padX + 5, padY + (i * slot_height), 0, text_scale, text_scale)
23
+ font.draw_text(player.score, padX + sizeX - score_offset, padY + (i * slot_height), 0, text_scale, text_scale)
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../share/player'
2
+
3
+ def server_package_to_player_strs(slots, data)
4
+ players = []
5
+ slots.times do |index|
6
+ players[index] = data[index * 8..index * 8 + 7]
7
+ end
8
+ players
9
+ end
10
+
11
+ def player_strs_to_objects(player_strs)
12
+ players = []
13
+ player_strs.each do |player_str|
14
+ id = player_str[0..1].to_i
15
+ x = player_str[2..4].to_i
16
+ y = player_str[5..7].to_i
17
+ # puts "id: #{id} x: #{x} y: #{y}"
18
+ players << Player.new(id, x, y) unless id.zero?
19
+ end
20
+ players
21
+ end
22
+
23
+ def server_package_to_player_array(data)
24
+ # /(?<count>\d{2})(?<player>(?<id>\d{2})(?<x>\d{3})(?<y>\d{3}))/
25
+ slots = data[0..1].to_i # save slots
26
+ data = data[2..-1] # cut slots off
27
+ players = server_package_to_player_strs(slots, data)
28
+ # puts players
29
+ player_strs_to_objects(players)
30
+ end
31
+
32
+ # 3 players
33
+ pl3 = '03011001010220020203300303'
34
+ p server_package_to_player_array(pl3)
35
+ p server_package_to_player_array(pl3).count
36
+ # 2 players (first has id 00 -> offline)
37
+ pl2 = '03001001010220020203300303'
38
+ p server_package_to_player_array(pl2)
39
+ p server_package_to_player_array(pl2).count
@@ -0,0 +1,86 @@
1
+ # https://github.com/gosu/gosu-examples/blob/master/examples/text_input.rb
2
+ require "gosu"
3
+
4
+ class TextField < Gosu::TextInput
5
+ FONT = Gosu::Font.new(60)
6
+ WIDTH = 800
7
+ LENGTH_LIMIT = 20
8
+ PADDING = 5
9
+
10
+ INACTIVE_COLOR = 0xcc_666666
11
+ ACTIVE_COLOR = 0xcc_555555
12
+ SELECTION_COLOR = 0xcc_444444
13
+ CARET_COLOR = 0xff_ffffff
14
+
15
+ attr_reader :x, :y
16
+
17
+ def initialize(window, x, y)
18
+ # It's important to call the inherited constructor.
19
+ super()
20
+
21
+ @window, @x, @y = window, x, y
22
+
23
+ # Start with a self-explanatory text in each field.
24
+ self.text = "Click to edit"
25
+ end
26
+
27
+ # In this example, we use the filter method to prevent the user from entering a text that exceeds
28
+ # the length limit. However, you can also use this to blacklist certain characters, etc.
29
+ def filter new_text
30
+ allowed_length = [LENGTH_LIMIT - text.length, 0].max
31
+ new_text[0, allowed_length]
32
+ end
33
+
34
+ def draw(z)
35
+ # Change the background colour if this is the currently selected text field.
36
+ if @window.text_input == self
37
+ color = ACTIVE_COLOR
38
+ else
39
+ color = INACTIVE_COLOR
40
+ end
41
+ # ChillerDragon's epic shadow to at least have edited the stolen sample a lil bit
42
+ Gosu.draw_rect (x - PADDING) + 5, (y - PADDING) + 5, WIDTH + 2 * PADDING, height + 2 * PADDING, INACTIVE_COLOR, z
43
+ Gosu.draw_rect x - PADDING, y - PADDING, WIDTH + 2 * PADDING, height + 2 * PADDING, color, z
44
+ Gosu.draw_rect x - PADDING, y - PADDING, WIDTH + 2 * PADDING, height + 2 * PADDING, color, z
45
+
46
+ # Calculate the position of the caret and the selection start.
47
+ pos_x = x + FONT.text_width(self.text[0...self.caret_pos])
48
+ sel_x = x + FONT.text_width(self.text[0...self.selection_start])
49
+ sel_w = pos_x - sel_x
50
+
51
+ # Draw the selection background, if any. (If not, sel_x and pos_x will be
52
+ # the same value, making this a no-op call.)
53
+ Gosu.draw_rect sel_x, y, sel_w, height, SELECTION_COLOR, z
54
+
55
+ # Draw the caret if this is the currently selected field.
56
+ if @window.text_input == self
57
+ Gosu.draw_line pos_x, y, CARET_COLOR, pos_x, y + height, CARET_COLOR, z
58
+ end
59
+
60
+ # Finally, draw the text itself!
61
+ FONT.draw_text self.text, x, y, z
62
+ end
63
+
64
+ def height
65
+ FONT.height
66
+ end
67
+
68
+ # Hit-test for selecting a text field with the mouse.
69
+ def under_mouse?
70
+ @window.mouse_x > x - PADDING and @window.mouse_x < x + WIDTH + PADDING and
71
+ @window.mouse_y > y - PADDING and @window.mouse_y < y + height + PADDING
72
+ end
73
+
74
+ # Tries to move the caret to the position specifies by mouse_x
75
+ def move_caret_to_mouse
76
+ # Test character by character
77
+ 1.upto(self.text.length) do |i|
78
+ if @window.mouse_x < x + FONT.text_width(text[0...i])
79
+ self.caret_pos = self.selection_start = i - 1;
80
+ return
81
+ end
82
+ end
83
+ # Default case: user must have clicked the right edge
84
+ self.caret_pos = self.selection_start = self.text.length
85
+ end
86
+ end