local socket = require "socket"--由于是love内建,这里仅仅需要require这个接口即可。它提供了底层的网络接口功能。
local address, port = "localhost", 12345 --定义地址和端口
local entity = tostring(math.random(99999)) --我们要同步的对象,这里仅仅用一个随机数来代替,只不过强调的是唯一性。
local updaterate = 0.1 -- 同步速率,同步率越高,来往的流量越高,越精密
local world = {} -- 一个沙盒
local t = 0 --同步计时器
function love.load()
udp = socket.udp() --首先建立一个udp接口,关于udp和http之间的区别,自行百度。
udp:settimeout(0) --如果设置延迟的话,系统将阻塞,知道延迟结束,但是会卡住游戏,我们不想这样。
udp:setpeername(address, port) --设置连接服务器的地址和端口,注意,udp并不是真实连接,我们并不管发送消息之后是否能够抵达服务器。
--下面,我们开始制造一条信息,并发送了。这里的格式是:对象,行为,x,y。说到这个,有的内容跟存档差不多。
local dg = string.format("%s %s %d %d", entity, 'at', 320, 240) --制造一条消息。
udp:send(dg) -- 发送!
end
function love.update(deltatime)
t = t + deltatime --计时器叠加
-- 我们使用这个计时器来控制网络更新速度,实际上,对于大多数游戏来讲,每秒10次的频率已经足够了,即使是网络游戏,而对于那些对延迟比较高的游戏,也不会要求更新频率高于30次每秒。
if t > updaterate then
local x, y = 0, 0
if love.keyboard.isDown('up') then y=y-(20*t) end
if love.keyboard.isDown('down') then y=y+(20*t) end
if love.keyboard.isDown('left') then x=x-(20*t) end
if love.keyboard.isDown('right') then x=x+(20*t) end
--上面代码实现了一个简单移动。注意为什么是t而不是dt?因为我们使用了差速更新,需要用积累的数值。
--接下来我们把位移的消息告诉给服务器
local dg = string.format("%s %s %f %f", entity, 'move', x, y)
udp:send(dg)
-- 然后我们发送一个同步命令。
local dg = string.format("%s %s $", entity, 'update')
udp:send(dg)
t=t-updaterate --重置计时器
end
repeat
--这里使用重复,是因为我们至少需要得到一个消息,所以要不停的监听。
data, msg = udp:receive()
if data then --这判断是否有消息进入,如果有就在msg中了。
--就像存档一样,我们需要对匹配模式比较了解才能方便的解析命令。
local ent, cmd, parms = data:match("^(%S*) (%S*) (.*)")
if cmd == 'at' then --如果命令是定位,那么解析出 x,y
local x, y = parms:match("^(%-?[%d.e]*) (%-?[%d.e]*)$")
assert(x and y) -- 这里只是看一眼数据是否合格而已。
x, y = tonumber(x), tonumber(y) -- 我们string解析出来的当然是字符串,而位置是数值。
world[ent] = {x=x, y=y} --我们沙盒中有了一个对象,名字是随机数,包含x,y两个属性。
else
--如果发现了不能识别的命令,最好还是查阅log,因为肯定有错误。
print("unrecognised command:", cmd)
end
--如果消息为否,说明有错误,而错误信息在msg中,因为我们设置了延迟为0,所以,得到的错误基本都是timeout,我们希望得到除了timeout外的其他错误。
elseif msg ~= 'timeout' then
error("Network error: "..tostring(msg))
end
until not data
end
function love.draw()
for k, v in pairs(world) do
love.graphics.print(k, v.x, v.y) --世界沙盒了,你画圆也可以。
end
end