如何使用Game Center sendDataToAllPlayers

时间:2016-02-12 23:34:33

标签: ios swift sprite-kit nsdata gamekit

我有一个游戏可以将一个玩家的数据发送给所有玩家。我无法弄清楚如何发送UIBezierPath对象。我将UIBezierPath对象存档到NSData中。

以下是我用来发送和接收数据的数据结构:

struct DataStruct {
    var action: Action = Action.Nil
    var point: CGPoint = CGPoint(x: 0.0, y: 0.0)
    var path: NSData = NSData()
    var speed: CGFloat = 0.0
}

在Struct中没有NSData,一切正常。有了它,我能够发送数据,但无法接收和getBytes()。我无法弄清楚如何编码和解码它。这是有道理的,因为DataStruct的sizeof()不是所发送数据的正确大小。但我无法找到这样的例子。非常感谢任何示例或帮助。我在发送和接收数据方面经验有限。

这是我存档和发送它的功能:

func sendData(action: Action, point: CGPoint, path: UIBezierPath, speed: CGFloat, mode: GKMatchSendDataMode) {
    // update player position, velocity and angle
    let pathData = NSKeyedArchiver.archivedDataWithRootObject(path)
    var dataStruct = DataStruct(action: action, point: point, path: pathData, speed: speed)
    let data: NSData = NSData(bytes: &dataStruct, length: sizeof(DataStruct))
    do {
        try GameCenterMatch.sendDataToAllPlayers(data, withDataMode: mode)
        print("data sent: \(dataStruct)")
    } catch {
        print("data sent error")
    }
}

以下是我接收它的功能的一部分:

    func match(match: GKMatch, didReceiveData data: NSData, fromRemotePlayer player: GKPlayer) {
    if GameCenterMatch == match {
        var dataStruct = DataStruct()
        data.getBytes(&dataStruct, length: sizeof(DataStruct))
        print("data received: \(player.displayName), data: \(dataStruct)")

2 个答案:

答案 0 :(得分:2)

我还没有这样做,但有一点突出的是当一些内容(路径)只是指向另一个字节数组的指针时,你发送一个字节数组。你会遇到与String相同的问题,因为sizeOf DataStruct是常量,并且不包括引用内容的内容,如NSData,String,object等,只包括它们的指针。

您应归档DataStruct,并在另一端发送和取消归档。

答案 1 :(得分:0)

感谢Michael的建议,我创建了一个编码和解码的类,它的工作原理!希望这将有助于其他人。

class DataClass: NSObject, NSCoding {
var action: ActionType
var point: CGPoint
var path: UIBezierPath
var speed: CGFloat

override init() {
    self.action = ActionType.Nil
    self.point = CGPoint(x: 0.0, y: 0.0)
    self.path = UIBezierPath()
    self.speed = 0.0

    super.init()
}
init(action: ActionType, point: CGPoint, path: UIBezierPath, speed: CGFloat) {
    self.action = action
    self.point = point
    self.path = path
    self.speed = speed

    super.init()
}

// MARK: NSCoding
required convenience init?(coder decoder: NSCoder) {
    let action = ActionType(rawValue: decoder.decodeIntegerForKey("action")) ?? .Nil
    let point = decoder.decodeCGPointForKey("point")
    let path = decoder.decodeObjectForKey("path") as! UIBezierPath
    let speed = CGFloat(decoder.decodeFloatForKey("speed"))

    self.init(
        action: action,
        point: point,
        path: path,
        speed: speed
    )
}

func encodeWithCoder(coder: NSCoder) {
    coder.encodeInteger(action.rawValue, forKey: "action")
    coder.encodeCGPoint(self.point, forKey: "point")
    coder.encodeObject(self.path, forKey: "path")
    coder.encodeFloat(Float(self.speed), forKey: "speed")
}

}