diff options
l--------- | client/common | 1 | ||||
-rw-r--r-- | client/conf.lua | 3 | ||||
-rw-r--r-- | client/main.lua | 122 | ||||
-rw-r--r-- | common/words.lua | 17 | ||||
l--------- | server/common | 1 | ||||
-rw-r--r-- | server/server.lua | 111 |
6 files changed, 255 insertions, 0 deletions
diff --git a/client/common b/client/common new file mode 120000 index 0000000..60d3b0a --- /dev/null +++ b/client/common @@ -0,0 +1 @@ +../common
\ No newline at end of file diff --git a/client/conf.lua b/client/conf.lua new file mode 100644 index 0000000..5c58cb3 --- /dev/null +++ b/client/conf.lua @@ -0,0 +1,3 @@ +function love.conf(t) + t.window.title = "rectangle emulator" +end diff --git a/client/main.lua b/client/main.lua new file mode 100644 index 0000000..4375ed3 --- /dev/null +++ b/client/main.lua @@ -0,0 +1,122 @@ +local enet = require"enet" +local words = require"common.words" + + +local PLAYER_SIZE = 30 + +local local_player = false + +-- { +-- pos={100,100}, +-- color={love.math.colorFromBytes(0xdf,0x73,0xff)}, +-- } + +local host,peer + +local function draw_player(pl,me) + local hplsz = PLAYER_SIZE/2 + love.graphics.setColor(pl.color) + love.graphics.rectangle("fill",pl.pos[1]-hplsz,pl.pos[2]-hplsz,PLAYER_SIZE,PLAYER_SIZE) + love.graphics.setColor(0,0,0) + love.graphics.print(tostring(pl.id),pl.pos[1],pl.pos[2]) + if me then + love.graphics.setColor(1,1,1) + love.graphics.rectangle("line",pl.pos[1]-hplsz,pl.pos[2]-hplsz,PLAYER_SIZE,PLAYER_SIZE) + end +end + +local remote_players = {} + +local function update_local_player(pl,dt) + local SPEED = 300 -- pixels/sec + local function kd(code) + if love.keyboard.isScancodeDown(code) then return 1 else return 0 end + end + local dx = kd"d"-kd"a" + local dy = kd"s"-kd"w" + + if dx == 0 and dy == 0 then + pl.pos_dirty = false + return + end + + if dx ~= 0 and dy ~= 0 then + dx = dx / math.sqrt(2) + dy = dy / math.sqrt(2) + end + + pl.pos[1] = pl.pos[1] + SPEED * dt * dx + pl.pos[2] = pl.pos[2] + SPEED * dt * dy + pl.pos_dirty = true +end + +local function sync_local_player(pl,peer) + -- send updated info about local player to server + if pl.pos_dirty then + peer:send(words.join("ppos",pl.pos[1],pl.pos[2])) + end +end + +function love.update(dt) + if local_player then + update_local_player(local_player,dt) + sync_local_player(local_player,peer) + end + repeat + local ev = host:service() + if ev and ev.type == "receive" then + local w = words.split(ev.data) + local op = w[1] + if op == "join" then + local id,x,y,r,g,b = unpack(w,2) + -- blegh + id=tonumber(id) + x=tonumber(x) + y=tonumber(y) + r=tonumber(r) + g=tonumber(g) + b=tonumber(b) + remote_players[id] = {pos={x,y},color={r,g,b},id=id} + elseif op == "leave" then + local id = tonumber(w[2]) + remote_players[id]=nil + elseif op == "move" then + local id,x,y = unpack(w,2) + id=tonumber(id) + x=tonumber(x) + y=tonumber(y) + assert(remote_players[id],"wheeze") + remote_players[id].pos[1] = x + remote_players[id].pos[2] = y + elseif op == "you" then + local id,x,y,r,g,b = unpack(w,2) + id=tonumber(id) + x=tonumber(x) + y=tonumber(y) + r=tonumber(r) + g=tonumber(g) + b=tonumber(b) + local_player = {pos={x,y},color={r,g,b},id=id} + end + end + until not ev +end + +function love.draw() + if local_player then + draw_player(local_player,true) + end + for _,pl in pairs(remote_players) do + draw_player(pl) + end +end + +function love.load() + host = enet.host_create() + peer = host:connect("localhost:8473") +end + +function love.quit() + peer:disconnect() + host:flush() +end diff --git a/common/words.lua b/common/words.lua new file mode 100644 index 0000000..4d6904e --- /dev/null +++ b/common/words.lua @@ -0,0 +1,17 @@ +local function join(...) + return table.concat({...}," ") +end + +local function split(s) + local o = {} + for w in string.gmatch(s,"(%S+)") do + table.insert(o,w) + end + return o +end + +return { + join=join, + split=split, +} + diff --git a/server/common b/server/common new file mode 120000 index 0000000..60d3b0a --- /dev/null +++ b/server/common @@ -0,0 +1 @@ +../common
\ No newline at end of file diff --git a/server/server.lua b/server/server.lua new file mode 100644 index 0000000..4db0207 --- /dev/null +++ b/server/server.lua @@ -0,0 +1,111 @@ +local enet = require"enet" +local words = require"common.words" +local unpack = unpack or table.unpack + +math.randomseed(os.time()) + +local host = enet.host_create("*:8473") +print(host) + +-- sequential list of all players +local playerlist = {} + +-- this is maybe suboptimal +-- but it is simplest for now +local function player_by_id(id) + for i,pl in ipairs(playerlist) do + if pl.id == id then return pl, i end + end + return nil +end +local function player_by_peer(peer) + for i,pl in ipairs(playerlist) do + if pl.peer == peer then return pl, i end + end + return nil +end + + +local function gen_id() + local x = math.random(100000) + -- if players[x] then error("cough") end + return x +end +local function random_color() + return {math.random(),math.random(),math.random()} +end +local function make_player(peer) + return {pos={100,100},color=random_color(),peer=peer} +end + +-- maybe json could be used for this +-- or something +local function player_info_part(player) + return words.join( + player.id, + player.pos[1], + player.pos[2], + player.color[1], + player.color[2], + player.color[3]) +end +local function player_join_packet(player) + return "join "..player_info_part(player) +end +local function player_you_packet(player) + return "you "..player_info_part(player) +end +local function player_leave_packet(player) + return words.join("leave",player.id) +end +local function player_move_packet(player,x,y) + return words.join("move",player.id,x,y) +end + +while true do + local ev = host:service(100) + if ev then + if ev.type == "connect" then + local player = make_player(ev.peer) + table.insert(playerlist,player) + player.id = #playerlist + print("connect",player.peer,player.id) + player.peer:send(player_you_packet(player)) + + for i,otherplayer in ipairs(playerlist) do + if otherplayer ~= player then + -- tell new player about each other player + player.peer:send(player_join_packet(otherplayer)) + -- tell each other player about new player + otherplayer.peer:send(player_join_packet(player)) + end + end + elseif ev.type == "disconnect" then + local player, idx = player_by_peer(ev.peer) + if not player then error("sneeze "..ev.peer) end + table.remove(playerlist,idx) + for i,otherplayer in ipairs(playerlist) do + otherplayer.peer:send(player_leave_packet(player)) + end + elseif ev.type == "receive" then + local player = player_by_peer(ev.peer) + if not player then error("sneezey "..ev.peer) end + local w = words.split(ev.data) + local op = w[1] + if op == "ppos" then + local _,x,y,a = unpack(w) + player.pos[1] = tonumber(x) + player.pos[2] = tonumber(y) + print(player.id,"-->",player.pos[1],player.pos[2]) + for i,otherplayer in ipairs(playerlist) do + if otherplayer ~= player then + otherplayer.peer:send(player_move_packet(player,x,y)) + end + end + end + + end + -- for k,v in pairs(ev) do io.write(tostring(k),":",tostring(v)," ") end + -- print() + end +end |