I would share the Game Center code for this but I pulled it out of an old project and it is truly heinous, involving tons of weirdly interconnected files, and confusing uncommented programming. At this point I’m just demonstrating that this is doable.
You really wouldn’t. Besides the Game Center code, there’s a lot of stuff specific to the game that I wrote the original code for, and it’s kind of impossible to tell which is which.
In theory all the Game Center stuff is doable just by following Apple’s documentation.
Then the communication loop goes like this:
Player A taps the screen, and the touched function calls an AddOn function with the x and y as parameters.
Inside the AddOn function, the x and y are turned into NSData, and sent to Player B using UDP.
Player B receives the data, decodes it back into x and y values, and stores it in two variables inside the AddOn class instance.
Every draw cycle, Codea calls an AddOn function that retrieves those stored variables.
If the variable aren’t 0, 0, it draws an ellipse around that x, y point.
Unreliable Data Protocol, I think. TCP/IP is what the internet runs on but UDP is what all real-time games use (afaik). Whereas TCP/IP is all about getting a complete message across, UDP is all about getting a fast message across. It’s basically like a data hose the sender points at the receiver, the idea being that the information is going to come so fast that if you miss a few packets here or there it doesn’t matter. I think.
With UDP you have to build into your logic the fact that some messages might not get through.
Game Center lets you use both TCP/IP and UDP to send data.
so you need Game center or some server to pick up the data and send it to the other player (s) , there’s no way to do it peer to peer? can we connect without game center?
@skar you don’t need Game Center but man it sure is nice to have it.
And I think technically Game Center is peer-to-peer out of the box. You can configure it for use with a server, but by default it seems to just operate as an enhancement to direct phone-to-phone communication.
If anyone wants to try multi player but without a lot of code, here’s a simple example. It’s doesn’t do anything except move a circle on the other device.
Load this code on 2 devices connected to the same router. Run this code on each. The device that runs second should connect automatically. The one that runs first needs a restart to connect. That could be fixed easily but I’m keeping the code small.
Move a finger on your device and the circle on the other device will follow. Move a finger on the other device and the circle on your device will follow.
It shouldn’t take very much more code to actually create a simple multiplayer game.
viewer.mode=STANDARD
function setup()
rd=remoteDevice()
mx,my=0,0
fill(255)
end
function draw()
background()
rd:receiveTheirMessage()
ellipse(mx,my,50)
end
function touched(t)
if t.state==BEGAN or t.state==CHANGED then
str=string.format("moveXY%04d%04d",t.x//1,t.y//1)
rd:sendMessage(str)
end
end
remoteDevice=class()
function remoteDevice:init()
self.socket=require("socket")
self.theirIp="0.0.0.0"
self:getMyIp()
self:setMySocket()
self:setTheirSocket()
self:getTheirIp()
end
function remoteDevice:setMySocket()
self.server=self.socket.udp()
self.server:setsockname(self.myIp,5544)
self.server:settimeout(0)
end
function remoteDevice:setTheirSocket()
self.client=self.socket.udp()
self.client:settimeout(0)
end
function remoteDevice:getMyIp()
self.server=self.socket.udp()
self.server:setpeername("1.1.1.1",80)
self.myIp,self.myPort=self.server:getsockname()
self.ip1,self.ip2=string.match(self.myIp,"(%d+.%d+.%d+.)(%d+)")
print("my IP = "..self.ip1..self.ip2)
end
function remoteDevice:getTheirIp()
self.client=self.socket.udp()
self.client:settimeout(0)
-- send a message to everyone on this network except to myself
print("Getting their IP")
for z=1,255 do
if z~=tonumber(self.ip2) then
self.client:setpeername(self.ip1..z,5544)
self.client:send("get their ip")
end
end
end
function remoteDevice:receiveTheirMessage()
local data,msg,port=self.server:receivefrom()
if data~=nil then
if data=="get their ip" then
self.client=self.socket.udp()
self.client:settimeout(0)
self.client:setpeername(msg,5544)
self.client:send("got their ip"..self.myIp)
elseif string.sub(data,1,12)=="got their ip" then
self.theirIp=msg
print("their IP = "..self.theirIp)
viewer.mode=FULLSCREEN
elseif string.sub(data,1,6)=="moveXY" then
mx=string.sub(data,7,10)
my=string.sub(data,11,14)
end
end
end
function remoteDevice:sendMessage(tempStr)
self.client = self.socket.udp()
self.client:setpeername(self.theirIp,5544)
self.client:settimeout(0)
self.client:send(tempStr)
end
in Codea:
function functionCalledFromC()
print("Hello from Function in Lua called from C")
end
in Xcode:
//value returned is put at top of stack
lua_getglobal(LuaStack, "functionCalledFromC");
//verify the top of the stack is a function
bool isFunction = lua_isfunction(LuaStack, -1);
if (isFunction) {
//call the function and check return value
if (lua_pcall(LuaStack, 0, 1, 0) == LUA_OK) {
//if value was LUA_OK, take the function off the stack
lua_pop(LuaStack, lua_gettop(LuaStack));
}
}