0

由于很棒的并发原语,我目前正在使用 go 来实现游戏服务器。这一切都很容易实施并且工作非常可靠。虽然我主要来自 Java 背景,但我很难忘记 Java 的类型层次结构。我需要一个游戏对象的集合,它们都共享类似的数据结构,如位置、速度等,但它们在更新方法中可能都有不同的行为,或者允许不同功能的特殊字段。最初我有一个包含所有共享数据的结构,每个自定义类型都会嵌入该结构。问题在于使用数据结构进行组织。我使用四叉树让客户了解附近对象的状态。这样,我可以将树传递给每个游戏对象的嵌入式结构的指针,并且一切正常。

这样做的问题是,一旦我查询四叉树,我就无法访问包含类型。例如,

type GameObject struct {
    Position Point
    Velocity Point
    ID int32
}

type Client struct {
    GameObject
    conn net.Conn
    // other fields
}

现在,如果我想更新附近玩家关于对象状态的信息,我会查询四叉树,但现在有办法确定 GameObject 是否实际上是客户端,并且无法访问它的连接以发送数据包。

从 Java 开始,我习惯于创建一个基类并将其子类化为 Client 等。然后我可以使用instanceof它来确定哪些需要特殊处理并相应地转换它们以访问自定义功能。我想我可以做以下事情:

type GameObject interface {
    Position() Point
    Velocity() Point
    ID() int32
}

type Client struct {
    pos Point
    vel Point
    id int32
    conn net.Conn
    // other fields
}

func (c *Client) Position() Point {
    return c.pos
}

func (c *Client) Velocity() Point {
    return c.vel
}

func (c *Client) ID() int32 {
    return c.id
}

使用这种方法,我可以使用类型断言来隔离客户端,但这会导致大量重复代码来实现其他游戏对象。我认为有一种更惯用的方式来做这样的事情,我很感激我能得到的任何帮助。如果这是可行的方法,也许有人可以帮助我理解这种设计背后的原因。

4

1 回答 1

0

如果不了解更多有关问题和您的限制,很难回答这个问题,但这里有三个想法。

首先,也许您可​​以在四叉树中存储复合类型,而不仅仅是 GameObject 指针。

type QuadTreeEntry struct {
   GameOb *GameObject
   Entity interface{}
}

“实体”将是一个 *Client,以及您的四叉树中的任何其他内容。

其次,您可能会考虑是否需要四叉树中的所有 GameObject。也许这会更好?

type QuadTreeEntry struct {
    Position Point
    Entity interface{}
}

这具有消除间接以获取 QuadTree 代码中的位置的良好效果,并且更难意外地使您的 QuadTree 无效,因为它不与原始实体共享位置数据。

第三,如果效率不是太重要,你可以这样做:

type GameObjectGetter interface {
    GetGameObject() *GameObject
}

func (c *Client) GetGameObject() *GameObject {
    return &c.GameObject
}

因此,四叉树中的所有内容都是 GameObjectGetter。

于 2013-09-22T09:16:02.363 回答