dongqiao5573 2013-09-22 02:36
浏览 26
已采纳

弄不清楚去对象组成

I'm currently using go to implement a Game server due to the awesome concurrency primitives. That has all been a breeze to implement and works very reliably. I come mostly from a Java background though and I am having trouble forgetting Java's type hierarchy. I need to have a collection of game objects which all share a similar data structure like position, velocity, etc., but they may all have different behavior within their update methods, or special fields to allow different functionality. Initially I had a struct containing all of the shared data, and each custom type would embed that struct. The trouble is using data structures for organization. I use a quadtree to keep clients notified about nearby object's state. This way I can pass the tree a pointer to the embedded struct of each game object and everything works.

The problem with this is I can't access the containing type once I query the quadtree. So for example,

type GameObject struct {
    Position Point
    Velocity Point
    ID int32
}

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

Now, when If I want to update nearby players about an object's state, I query the quadtree, but there is now way to determine if the GameObject is actually a Client, and there is no way to access it's connection to send packets.

From Java, I'm used to creating a base class and subclassing it for Client, etc. Then I can use instanceof to determine which ones need special treatment and cast them accordingly to access custom functionality. I think I could do something like the following:

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
}

With this method I can use a type assertion to isolate the clients, but this will lead to a lot of duplicate code for implementing other game objects. I assume there is a more idiomatic way to do something like this in go, and I appreciate any help I can get. If this is the go way, maybe someone can help me understand the reasoning behind this design.

  • 写回答

1条回答 默认 最新

  • dozpv84422 2013-09-22 09:16
    关注

    It's hard to answer the question without knowing more about the problem and your constraints, but here's three ideas.

    First, perhaps you can store a composite type in the quad tree rather than just the GameObject pointer.

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

    The "Entity" would be a *Client, and whatever else goes in your quadtree.

    Second, you might consider if you need all of GameObject in the quadtree. Perhaps this would be better?

    type QuadTreeEntry struct {
        Position Point
        Entity interface{}
    }
    

    This has the nice effect of removing an indirection to get at the Position in the QuadTree code, and it's harder to accidentally invalidate your QuadTree, since its not sharing Position data with the original entity.

    Third, if efficiency isn't too important, you could do this:

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

    So everything that goes in the quad tree would be a GameObjectGetter.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题