Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Last active August 29, 2015 14:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dermotbalson/7de7e17bdd01c32bfd77 to your computer and use it in GitHub Desktop.
Save dermotbalson/7de7e17bdd01c32bfd77 to your computer and use it in GitHub Desktop.
Multiplayer examples
--all code by JakAttak
--# Main
function setup()
local connectionMade = function()
output.clear()
parameter.clear()
print("Connected!")
gameSetup()
end
multihandler = Multiplayer(receiveData, connectionMade)
parameter.action("Host Game", function()
multihandler:hostGame()
end)
parameter.action("Find Game", function()
multihandler:findGame()
end)
parameter.action("Join Game", function()
if other_ip then
multihandler:joinGame(other_ip, other_port)
else
parameter.text("other_ip", "")
parameter.text("other_port", "")
print("Fill in the host's ip and port, then click join game again")
end
end)
end
function gameSetup()
canvas = image(WIDTH, HEIGHT)
parameter.color("pen_col", color(0, 255, 0))
parameter.integer("pen_size", 2, 100, 10)
parameter.action("clear", function()
clear()
multihandler:sendData("clear")
end)
pen_touch = nil
last_point = vec2(0, 0)
end
function clear()
canvas = image(WIDTH, HEIGHT)
end
function receiveData(d)
if d == "clear" then
clear()
else
local tb = loadstring("return " .. d)()
drawPoint(tb.point, tb.last_point, tb.drawing_line, tb.pen_size, tb.pen_col)
end
end
function drawPoint(point, lastPoint, drawingLine, penSize, penCol)
pushStyle()
setContext(canvas) -- Start drawing to screen image
fill(penCol) stroke(penCol) -- Set draw color to color var
strokeWidth(penSize)
if drawingLine then
line(point.x, point.y, lastPoint.x, lastPoint.y) -- draw a line between the two points
else
ellipse(point.x, point.y, penSize) -- Place a dot there
end
setContext()
popStyle()
end
function draw()
background(255, 255, 255, 255)
multihandler:update()
if multihandler.connected then
sprite(canvas, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT) -- Draw the image onto the screen
else
fill(0)
text("Waiting for connection...", WIDTH / 2, HEIGHT / 2)
end
end
function vec2ToStr(vec)
return "vec2" .. tostring(vec)
end
function colToStr(col)
return "color(" .. col.r .. ", " .. col.g .. ", " .. col.b.. ", " .. col.a .. ")"
end
function touched(t)
if multihandler.connected then
local p, lp, d, ps, pc = vec2(t.x, t.y), last_point, drawing_line, pen_size, pen_col
if t.state == BEGAN then
pen_touch = t.id
end
if t.id == pen_touch then
drawPoint(vec2(t.x, t.y), last_point, drawing_line, pen_size, pen_col)
drawing_line = true
last_point = vec2(t.x, t.y)
end
if t.state == ENDED then
drawing_line = false
pen_touch = nil
end
multihandler:sendData("{ point = " .. vec2ToStr(p) .. ", last_point = " .. vec2ToStr(lp) .. ", drawing_line = " .. tostring(d) .. ", pen_size = " .. ps .. ", pen_col = " .. colToStr(pc) .. " }")
end
end
--multiplayer library follows
--# Multiplayer
local socket = require("socket")
Multiplayer = class()
function Multiplayer:init(dcb, ccb)
self.my_ip, self.my_port = self:getLocalIP(), 5400
self.peer_ip, self.peer_port = nil, self.my_port
self.client = socket.udp()
self.client:settimeout(0)
self.connected = false
self.is_host = false
self.searching = false
self.dataCallback = dcb or function() end
self.connectedCallback = ccb or function() end
end
-- Returns this iPad's local ip
function Multiplayer:getLocalIP()
local randomIP = "192.167.188.122"
local randomPort = "3102"
local randomSocket = socket.udp()
randomSocket:setpeername(randomIP,randomPort)
local localIP, somePort = randomSocket:getsockname()
randomSocket:close()
randomSocket = nil
return localIP
end
-- Set the connected status and call the connection callback if needed
function Multiplayer:setConnectedVal(bool)
self.connected = bool
if self.connected then
self.connectedCallback()
end
end
function Multiplayer:setHostVal(bool)
self.is_host = bool
end
-- Prepare to be the host
function Multiplayer:hostGame()
print("Connect to " .. self.my_ip .. ":" .. self.my_port)
self.client:setsockname(self.my_ip, self.my_port)
self:setConnectedVal(false)
self.is_host = true
self.searching = false
end
-- Find a host
function Multiplayer:findGame()
print("Searching for games...")
self.searching = true
local ip_start, ip_end = self.my_ip:match("(%d+.%d+.%d+.)(%d+)")
for i = 1, 255 do
if i ~= tonumber(ip_end) then
tween.delay(0.01 * i, function()
self.client:setsockname(ip_start .. i, self.my_port)
self.client:sendto("connection_confirmation", ip_start .. i, self.my_port)
end)
end
end
end
-- Prepare to join a host
function Multiplayer:joinGame(ip, port)
self.peer_ip, self.peer_port = ip, port
self.client:setsockname(ip, port)
self.is_host = false
self.searching = false
self:sendData("connection_confirmation")
end
-- Send data to the other client
function Multiplayer:sendData(msg_to_send)
if self.peer_ip then
self.client:sendto(msg_to_send, self.peer_ip, self.peer_port)
end
end
-- Check for data received from the other client
function Multiplayer:checkForReceivedData()
local data, msg_or_ip, port_or_nil = self.client:receivefrom()
if data then
-- Store the ip of this new client so you can send data back
self.peer_ip, self.peer_port = msg_or_ip, port_or_nil
if not self.connected and data == "connection_confirmation" then
self:sendData("connection_confirmation")
self:setConnectedVal(true)
end
-- Call callback with received data
if data ~= "connection_confirmation" then
self.dataCallback(data)
end
end
end
function Multiplayer:update()
self:checkForReceivedData()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment