游戏模块思路设计

 

 

============================排行榜===========================

 

 

实时排行榜就直接游戏里内存实时排序:

用于排名的分数区间不大,也就是 0 分到 5000 分。而参与排名的人数众多,数以百万计。对百万用户做插入排序,每个插入即使是 O(N) 的也不可接受。可事实是大量玩家的分数相同,都是并列排名的。所以我们只需要做 5000 个桶,每个桶里仅记录这个分数有多少个人就可以了。
当玩家分数变迁,把原来的桶减一,新的桶加一。这个操作就是 O(1) 的。
而排行榜的查询仅需要把当前分数靠前的桶累加,就能获知查询者的名次。对于上百万玩家,看到哪些人和你并列的人的名字是没有意义的。这个查询虽然是 O(n) 复杂度,但 n 只有区区 5000 ,还可以做 cache 以应对查询频率远高于更新频率的情况。
真正需要精确知道人名的是榜单的前 200 个人,而对前 200 个人做插入排序也很快,所以并不会造成性能问题。
我们在系统的单点做排行榜的维持,完全没有外部数据库操作,它只是一小段操作普通内存结构的 c 代码。而这个单点远远成为不了整个系统的热点。
我们在系统临时退出时,把已经排好的榜单落地,下次启动的时候恢复。但也不必完全信任落地的数据,可以用离线脚本检索整个数据库重新生成一份正确的榜单。所以数据库中的榜单只是被 cache 起来而已,系统运行期间是不需要写入数据库的,也不用担心数据丢失。

非实时排行榜可以依赖于数据库的order by排序,虽然会造成数据库io操作,但是影响不大。

 

=======================事件分发=========================

NewEvent 产生事件,创建协程分发(在RegEvent注册过的事件中通过事件名字找到对应的信息,然后执行对应模块的OnEvent函数),多个地方都注册了同一个事件的话,则所有监视该事件的模块都会收到

--Condition:事件条件,满足条件时事件才分发
--Args:附加参数
function clsCoreObj:RegEvent(Obj, Name, Condition, Args)
    if not Name then return end
    local List
    --print("注册事件", Obj, Name, Condition)
    --table.print(Condition)
    if self.__EventLock == Name then
        self.__EventLockAdd = self.__EventLockAdd or {}
        List = self.__EventLockAdd
    else
        if not self.__Event then
            self.__Event = {[Name] = {}}
        elseif not self.__Event[Name] then
            self.__Event[Name] = {}
        end
        List = self.__Event[Name]
    end
    if not List then return end
    for _, v in ipairs(List) do
        if v and v.Obj == Obj and 
            EventConditionCmp(v.Condition, Condition)
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值