我该如何以这种方式管理类,以便根据需要创建该类的任意数量的对象,同时不造成数据泄露?
我已经在一个项目上工作了一段时间,最近在尝试为我正在开发的游戏5加载一个“谱面”时,遇到了一个问题:游戏会无响应,吞吃全部内存(RAM),直到崩溃。我现在猜测这是代码中的数据泄漏。我知道问题会出现在这三个脚本中的一个(或多个),因为它们是唯一在管理我的音符的脚本。
总体而言,我的目标是在屏幕上同时生成固定数量的音符,能够在同一时间更新它们,并且如果它们移出屏幕就能够删除它们。
我承认我的命名风格有些不一致,不过就这个项目的性质而言,这不应该造成太大问题。
https://github.com/StrategicVirus/RhythmGameMayhem-Love2d
game.lua
require("load_level")
game={}
scale=0.0520833333
current_max = 30
chart_time_start = love.timer.getTime()
function game.load()
local r, g, b = love.math.colorFromBytes(0x00, 0x00, 0x00)
love.graphics.setBackgroundColor(r, g, b)
if love.filesystem.getInfo("RGM") == nil then
love.filesystem.createDirectory("RGM")
end
note_image = love.graphics.newImage("img/Note_1.png")
--next line is used for testing purposes on chart loading, commented out for screen tests.
load_chart("173612 xi - FREEDOM DiVE","xi - FREEDOM DiVE (razlteh) [4K Another]", 7)
--load_chart("Testing_script", "Multiple_notes_test", 0)
end
function game.update(dt)
notesClass:update()
end
function game.draw()
love.graphics.setColor(1,1,1)
love.graphics.rectangle("line", 700, 0, 500, 1280) -- 700 to 1200
love.graphics.rectangle("line", 720, 20, 100, 1240) -- 720 to 820
love.graphics.rectangle("line", 840, 20, 100, 1240) -- 840 to 940
love.graphics.rectangle("line", 960, 20, 100, 1240) -- 960 to 1060
love.graphics.rectangle("line", 1080, 20, 100, 1240) -- 1080 to 1180
notesClass:draw()
end
function game.keypressed(key)
if (key == "d") then
print("delete column 1")
current_max = current_max+ 1
elseif (key == "f") then
print("delete column 2")
current_max = current_max+ 1
elseif (key == "j") then
print("delete column 3")
current_max = current_max+ 1
elseif (key == "k") then
print("delete column 4")
current_max = current_max+ 1
end
end
load_level.lua
notesClass = require ("notesClass")
note_table={id=0, x=0, hitTime=0, speed=0, column=0}
-- used to create tokens from each of the lines. Will be used in several instances through load_level and new_note
function tokeniser(s, split)
split = split or '%s'
local t={}
local i=1
for str in string.gmatch(s, '([^'..split..']+)') do
t[i] = str
i=i+1
end
return t
end
function find_info(r)
--r = tonumber(r)
if r == 1 then
return ("MIN")
elseif r == 7 then
return ("SONG")
elseif r==0 then
return("TEST")
end
end
function load_chart(BMP_ID, DIF_NAME, REQ_INFO)
NAME=DIF_NAME ..".osu"
ID=BMP_ID.."/"
local HitObjects, TimingPoints, Difficulty, Editor, General, speed, iterator = false, false, false, false, false, 1, 1
REQUIRED = find_info(REQ_INFO)
for line in love.filesystem.lines(ID..NAME) do
if (line == "[HitObjects]" or HitObjects) and REQUIRED ~= "MIN" or REQUIRED == "TEST" then
TimingPoints=false
Metadata = false
if HitObjects then
local cL=tokeniser(line, ",")
for i=1, 5, 1 do
cL[i] = tonumber(cL[i])
end
cL[6] = nil
local new_note = notesClass:new(iterator, cL[1], cL[3], speed)
table.insert(note_table, new_note)
iterator = iterator+1
end
HitObjects = true
else if (line == "[Metadata]" or Metadata) and REQUIRED ~= "SONG" then
General = false
if Metadata then
local cL=tokeniser(line, ":")
if cL[1] == "Title" then
t = cL[2]
elseif cL[1] == "Version" then
v = cL[2]
end
if t ~= nil and v ~= nil then
local song_data = {title=t, version=v}
return song_data
end
end
Metadata = true
else if (line == "[General]" or General) and REQUIRED ~= "MIN" then
if General then
local cL = tokeniser(line, ":")
if cL[1] == "AudioFilename" then
c = string.sub(cL[2], 2)
source = love.audio.newSource(ID..c, "stream")
source:play()
end
end
end
end
end
end
end
notesClass.lua
notesClass={id=0, x=0, hitTime=0, speed=0, column=0}
notesClassMT = {__index = notesClass}
local function getColumn(c)
if c == 64 then
return 1
elseif c == 192 then
return 2
elseif c == 320 then
return 3
elseif c == 448 then
return 4
else
-- print("this is not a 4K map. Error")
end
end
function notesClass:new(id, x, hitTime, speed)
local note=setmetatable({id=0, x=0, hitTime=0, speed=0, column=0}, notesClassMT)
x=tonumber(x)
note.id=id or 0
note.x=x or 0
note.hitTime=tonumber(hitTime) or 0
note.speed=tonumber(speed) or 0
note.image = love.graphics.newImage("img/Note_1.png")
note.off_screen = true
note.updated = false
return note
end
function notesClass:load()
end
function notesClass:update(dt)
if notesClass.id <= current_max then
notesClass.hitTime = notesClass.hitTime +( 1 * 5 )
if notesClass.hitTime > 1080 then
notesClass.off_screen = true
end
if notesClass.updated == false then
update_time = love.timer.getTime() - chart_time_start
notesClass.hitTime = notesClass.hitTime + update_time
notesClass.updated = true
notesClass.off_screen = false
end
end
print(notesClass.hitTime)
end
function notesClass:draw()
if notesClass.off_screen == false then
love.graphics.draw(notesClass.image, notesClass.x, notesClass.hitTime, 0, scale, scale)
end
end
return notesClass
解决方案
因为每次你创建一个新的音符时,也会创建一个新的 Image 对象:
function notesClass:new(id, x, hitTime, speed)
...
note.image = love.graphics.newImage("img/Note_1.png")
...
end
但你似乎知道图片应该在load函数中加载:
function game.load()
...
note_image = love.graphics.newImage("img/Note_1.png")
...
end
你需要做的是重用这个对象,因为你已经将 notesClass 自身设置为每个音符对象的元表,你可以直接这样做:
function game.load()
...
notesClass.image = love.graphics.newImage("img/Note_1.png")
...
end
function notesClass:new(id, x, hitTime, speed)
...
--note.image = love.graphics.newImage("img/Note_1.png")
...
end
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。