纹理加载/管理

本指南讨论 TextureResource 对象,它提供了一个句柄来手动管理和访问有关纹理的信息。

注意

本指南中概述的方法旨在更细粒度地控制在非常特定情况下管理纹理。对于一般的应用程序开发,这些方法不是必需的,但我们为更高级的目的提供它们。

概述

TextureResource 对象使您可以控制纹理在内存中的生命周期,同时还提供对文件名和目录的抽象。这些对象的主要目的是预加载纹理到内存中,以便使用它们创建显示对象几乎是即时的。

本质上,当您使用 graphics.newTexture() 创建 TextureResource 对象时,会在内存中保留对纹理的引用 — 这类似于显示对象如果使用纹理所持有的引用。关键区别在于,作为 TextureResource 对象加载的纹理将在没有显示对象使用该纹理时被处置/释放,而作为 TextureResource 对象加载的纹理将保留在内存中,直到您通过 object:releaseSelf()graphics.releaseTextures() 显式释放它。

创建和使用

创建

使用 graphics.newTexture() 方法可以轻松创建 TextureResource 对象。唯一的参数是一个包含 TextureResource 对象所需参数的表。例如

local texture = graphics.newTexture( { type="image", filename="background.png" } )
local texture = graphics.newTexture( { type="canvas", width=128, height=128 } )

此代码将在变量句柄 `texture` 下创建纹理资源对象。创建后,您可以将底层纹理与与 TextureResource 本身关联的各种属性和方法一起使用。

使用/访问

TextureResource 对象中,filenamebaseDir 属性允许您创建图像、图像页、自定义填充/描边以及其他接受文件名和目录常量的对象。例如

-- TextureResource-based image
local background = display.newImageRect(
    texture.filename,  -- "filename" property required
    texture.baseDir,   -- "baseDir" property required
    display.contentWidth,
    display.contentHeight
)

-- TextureResource-based fill
local circle = display.newCircle( 200, 100, 50 )
circle.fill = {
    type = "image",
    filename = texture.filename,  -- "filename" property required
    baseDir = texture.baseDir     -- "baseDir" property required
}

请注意,这些与纹理相关的属性不应在非纹理相关方法中用于引用相同的文件或目录常量 — 例如,如果您将 `"background.png"` 指定为纹理的 `filename`,请勿尝试在 system.pathForFile() 中使用 `texture.filename` 作为对同一文件的引用。本质上,这些属性指的是内部内存,而不是文件系统。

生命周期管理

为了防止内存泄漏,如果不再需要 TextureResource 对象,则务必处置/释放它们。这可以在单个基础上或更广泛的范围内完成

texture:releaseSelf()
graphics.releaseTextures( { type="image" } )
graphics.releaseTextures( { type="canvas" } )

请注意,如果任何显示对象当前正在使用已释放的纹理,它们将不会被破坏 — 相反,它们将在底层持有该纹理,并且如果/当它们被移除时,该纹理将被自动处置。

纹理类型

调用 graphics.newTexture() 实际上会根据指定的 `type` 参数生成不同类型的对象。所有类型都包含 TextureResource 的共享属性/方法,以及根据类型而定的其他属性/方法

示例

预加载图像
-- This simplified example pre-loads textures into memory

-- These files are high-resolution images which may affect performance if loaded normally
local filenames = {
    "splat1.png",
    "splat2.png",
    "splat3.png",
    "splat4.png",
    "splat5.png"
}

-- Pre-load textures to memory
local textures = {}
for i = 1,#filenames do
    textures[i] = graphics.newTexture(
        {
            type = "image",
            filename = filenames[i],
            baseDir = system.ResourceDirectory
        })
    textures[i]:preload()
end

-- Sometime later, display the images
-- Because the images were pre-loaded, no performance impact will occur
local objects = {}
for i = 1,#textures do
    local texture = textures[i]
    objects[i] = display.newImageRect( texture.filename, texture.baseDir, 100, 100 )
end

-- If the textures are no longer needed, release them to prevent memory leaks
for i = 1,#textures do
    textures[i]:releaseSelf()
end
textures = {}
渲染到画布资源
local tex = graphics.newTexture( { type="canvas", width=128, height=128 } )

-- Create display object with texture as contents
local rect = display.newImageRect(
    tex.filename,  -- "filename" property required
    tex.baseDir,   -- "baseDir" property required
    display.contentWidth,
    display.contentHeight
)
rect.x = display.contentCenterX
rect.y = display.contentCenterY

-- Create a circle and draw/render it to the texture
local circ = display.newCircle( 0, 0, 64 )
circ:setFillColor( { type="gradient", color1={0,0.2,1}, color2={0.8,0.8,0.8}, direction="down" } )
tex:draw( circ )

-- Schedule texture objects to be rendered to texture before next frame
tex:invalidate()
高级管理

高级示例,可在 GitHub 上找到,它从 Web 下载图像,并能够预加载并在运行时释放纹理以优化性能。