- 最近心情比较低落,想找些事转移下注意力,于是就产生了这篇文章。讲真,写写东西还真能让自己平静。对象池主要应用于游戏中频繁产生消失的物体,比如王者荣耀里面的小兵、SLG游戏里面的地图格、飞机大战里面的飞机子弹,捕鱼游戏里面的鱼,按照传统做法,用的时候创建,不用的时候移除,那么带来的内存开销是巨大的,可以通过实现创建好保存在内存中来解决此类问题。废话不多上,附上初版(未完成动态扩容及缩容,后续完善)代码:
local M = {}
ObPool = M
function M.new(name, size)
size = size or 1
local pool, cls = M[name] or {_usingNum = 0}, _G[name]
for i = 1, size do
local obj, index = cls.new(), #pool + 1
obj:retain()
obj._index = index
pool[index] = obj
end
M[name] = pool
end
function M.delete(name)
local pool = M[name]
if pool == nil then return end
for _, obj in pairs(pool) do
obj:release()
end
M[name] = nil
end
function M.getOb(name)
local pool = M[name]
if pool == nil then return end
local usingNum = pool._usingNum + 1
pool._usingNum = usingNum
local obj = pool[usingNum]
if obj == nil then
M.new(name)
obj = pool[usingNum]
end
return obj
end
function M.backOb(obj)
local pool = M[obj.__cname]
local usingNum = pool._usingNum
pool._usingNum = usingNum - 1
-- 交换释放的对象和对象池中最后一个元素的位置,并交换索引,因为getOb()都是取的最后一个位置
local tmp, tmpIndex = pool[usingNum], obj._index
pool[usingNum], obj._index = obj, usingNum
pool[tmpIndex], tmp._index = tmp, tmpIndex
end
- 需要放入对象池的对象的类写法,说的有点绕,就是通过这个类创造出来的对象需要放入对象池。
local M = class("TestSprite", function()
return cc.Sprite:create()
end)
function M:ctor()
-- 初始化
end
--[[
此函数非必须:
将对象归还对象池时候,清理遗留下的状态和变量;
以免下次使用时候附带“杂物”;
]]
function M:poolReset()
end
--[[
此函数必须:
从父类移除时候,清理自己并归还对象池
]]
function M:onCleanup()
local f = self.poolReset()
if f then f(self) end
ObPool.backOb(self)
end
function M
- 附加说明,TestSprite在require的时候以及加入lua 全局变量表_G中。如下对cocos2d class略作改变,加了一句if classname then _G[classname] = cls end
,因此可以通过_G["TestSprite"]取得TestSprite类。
function class(classname, super)
local superType = type(super)
local cls
if superType ~= "function" and superType ~= "table" then
superType = nil
super = nil
end
if superType == "function" or (super and super.__ctype == 1) then
-- inherited from native C++ Object
cls = {}
if superType == "table" then
-- copy fields from super
for k,v in pairs(super) do cls[k] = v end
cls.__create = super.__create
cls.super = super
else
cls.__create = super
end
cls.ctor = function() end
cls.__cname = classname
cls.__ctype = 1
function cls.new(...)
local instance = cls.__create(...)
-- copy fields from class to native object
for k,v in pairs(cls) do instance[k] = v end
instance.class = cls
instance:ctor(...)
return instance
end
else
-- inherited from Lua Object
if super then
cls = clone(super)
cls.super = super
else
cls = {ctor = function() end}
end
cls.__cname = classname
cls.__ctype = 2 -- lua
cls.__index = cls
function cls.new(...)
local instance = setmetatable({}, cls)
instance.class = cls
instance:ctor(...)
return instance
end
end
if classname then _G[classname] = cls end
return cls
end
- 使用例子简单说明如下,还未完全测试。写了一晚上困死了先睡觉,代码明后天再测试下,有bug的话会更新。
-- 对象池里面new出100个TestSprite
ObPool.new("TestSprite", 100)
-- delete对象池中所有TestSprite
ObPool.delete("TestSprite")
-- get
local spr = ObPool.getOb("TestSprite")
parent:addChild(spr)
网友评论