Add simple gui client to examples

This commit is contained in:
ChillerDragon 2022-11-19 12:39:58 +01:00
parent ad7ef13926
commit dc72204140
4 changed files with 97 additions and 7 deletions

73
examples/08_gui_snapshot.rb Executable file
View file

@ -0,0 +1,73 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'gosu'
require_relative '../lib/teeworlds_client'
class Entitiy
attr_reader :x, :y
def initialize(attr = {})
@x = attr[:x]
@y = attr[:y]
end
end
class Tee < Entitiy
attr_reader :w, :h
def initialize(attr = {})
@w = 32
@h = 32
super
end
end
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 500
class Gui < Gosu::Window
def initialize
super WINDOW_WIDTH, WINDOW_HEIGHT
self.caption = 'ruby teeworlds client'
@client = TeeworldsClient.new
@client.connect('localhost', 8303, detach: true)
@tees = {}
end
def update
@client.on_snapshot do |_, snap|
snap.items.each do |item|
next unless item.instance_of?(NetObj::Character)
player = item.to_h
@tees[player[:id]] = Tee.new(player)
end
end
end
def center_around_tee(tee)
wc = WINDOW_WIDTH / 2
hc = WINDOW_HEIGHT / 2
x = -tee.x + wc
y = -tee.y + hc
Entitiy.new(x:, y:)
end
def draw
return if @tees.empty?
offset = center_around_tee(@tees.first.last)
@tees.each do |_id, tee|
draw_rect(
tee.x + offset.x,
tee.y + offset.y,
tee.w,
tee.h,
Gosu::Color.argb(0xff_00ff00)
)
end
end
end
Gui.new.show

View file

@ -155,11 +155,15 @@ class GameClient
def on_snapshot(chunk)
u = SnapshotUnpacker.new
game_tick = u.snap_single(chunk)
return if game_tick.nil?
snapshot = u.snap_single(chunk)
return if snapshot.game_tick.nil?
context = Context.new(nil, chunk:)
return if call_hook(:snapshot, context, snapshot).nil?
# ack every snapshot no matter how broken
@ack_game_tick = game_tick
@ack_game_tick = snapshot.game_tick
return unless (@pred_game_tick - @ack_game_tick).abs > 10
@pred_game_tick = @ack_game_tick + 1

View file

@ -63,6 +63,7 @@ class SnapItemBase
def to_h
hash = {}
hash[:id] = @id
@field_names.each_with_index do |name, index|
hash[name] = @fields[index]
end

View file

@ -20,6 +20,14 @@ require_relative 'events/death'
require_relative 'events/hammer_hit'
require_relative '../packer'
class Snapshot
attr_accessor :game_tick, :items
def initialize(items)
@items = items
end
end
class SnapshotUnpacker
def snap_single(chunk)
u = Unpacker.new(chunk.data)
@ -104,6 +112,7 @@ class SnapshotUnpacker
invalid = false
item_type = u.get_int
id_parsed = u.parsed.last
snap_items = []
while item_type
obj = nil
if NetObj::PlayerInput.match_type?(item_type)
@ -146,6 +155,7 @@ class SnapshotUnpacker
puts "no match #{item_type}"
end
if obj
snap_items.push(obj)
notes += obj.notes
notes.push([
:green,
@ -166,12 +176,14 @@ class SnapshotUnpacker
id_parsed = u.parsed.last
end
hexdump_lines(data.pack('C*'), 1, notes, legend: :inline).each do |hex|
puts " #{hex}"
end
# hexdump_lines(data.pack('C*'), 1, notes, legend: :inline).each do |hex|
# puts " #{hex}"
# end
exit 1 if invalid
game_tick
snapshot = Snapshot.new(snap_items)
snapshot.game_tick = game_tick
snapshot
end
end