猿问

无法弄清楚 go 对象组合

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


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


type GameObject struct {

    Position Point

    Velocity Point

    ID int32

}


type Client struct {

    GameObject

    conn net.Conn

    // other fields

}

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


从 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

}

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


aluckdog
浏览 181回答 1
1回答

桃花长相依

如果不了解更多关于问题和您的限制,很难回答这个问题,但这里有三个想法。首先,也许您可以在四叉树中存储复合类型而不仅仅是游戏对象指针。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。
随时随地看视频慕课网APP

相关分类

Go
我要回答