有时,应用程序的设计要求“图像切换”,即开发者在给定位置显示一个图像,然后在一段时间或某个操作后,将该图像切换为另一个图像。 这是一个理论上的例子。
local myImage = display.newImageRect( "image1.png", 64, 64 ) -- After some time or upon some event myImage:swapImage( "image2.png" )
然而,Solar2D 并非如此工作,因为 :swapImage()
不是
local myImage = display.newImageRect( "image1.png", 64, 64 ) -- After some time or upon some event display.remove( myImage ) myImage = display.newImageRect( "image2.png", 64, 64 )
在这个理论场景中,通过使用 display.remove() 调用销毁 image1.png
,您可能不打算很快再次使用它。 这种方法的优点是它最大限度地减少了纹理内存,因为一次只加载两个图像中的一个。 但是,如果您想恢复原始图像,您将陷入这种图像加载和卸载的循环中。 这本身就是一个低效的过程,会影响性能。 因此,如果您需要更频繁地交换图像,则应探索其他技术。 让我们看看几个选项。
如果您有两个图像,您可以简单地加载它们,将它们添加到显示组中,并将图像作为组的参数引用。 在此示例中,我们加载两个图像,redBall
和 blueBall
。 然后我们将它们放置在相同的位置,使一个可见而另一个不可见。
-- Create a basic display group local imageGroup = display.newGroup() -- Create a red ball inside the group local redBall = display.newImageRect( imageGroup, "red-ball.png", 128, 128 ) redBall.x = display.contentCenterX redBall.y = display.contentCenterY -- Create a blue ball inside the same group local blueBall = display.newImageRect( imageGroup, "blue-ball.png", 128, 128 ) blueBall.x = display.contentCenterX blueBall.y = display.contentCenterY -- Make the blue ball invisible blueBall.isVisible = false
现在让我们关注交换代码。
for i = 1,imageGroup.numChildren do if ( imageGroup[i].isVisible == false ) then imageGroup[i].isVisible = true else imageGroup[i].isVisible = false end end
很简单,这段代码循环遍历 imageGroup
的子级,它们显然是 redBall
和 blueBall
。 如果子级不可见,则将其切换回可见,
您还可以利用图形“填充”方法来交换图像。
local image1 = { type="image", filename="red-ball.png" } local image2 = { type="image", filename="blue-ball.png" } local ball = display.newRect( display.contentCenterX, display.contentCenterY, 128, 128 ) ball.fill = image1 ball.isShowing = "image1"
此方法消除了对显示组的需求 — 我们只需创建一个基本显示对象(在本例中是一个与图像大小相同的矩形),并用red-ball.png
image1
画笔填充它。 我们还为球声明了一个附加属性 isShowing
,用于交换代码,如下所示。
if ( ball.isShowing == "image1" ) then ball.fill = image2 ball.isShowing = "image2" else ball.fill = image1 ball.isShowing = "image1" end
有时您需要交换两个以上的图像。 在这种情况下,我们可以回到显示组模型,将所有图像加载到一个数组中,并通过它们的索引号访问它们。 在这里,我们遍历 imageCache
表来创建显示对象,并将它们存储在 balls
表中,并使每个对象都不可见。 然后,我们再次使第一个可见。
local imageGroup = display.newGroup() local imageCache = { "red-ball.png", "blue-ball.png", "green-ball.png", "yellow-ball.png", "purple-ball.png" } local balls = {} for i = 1,#imageCache do balls[i] = display.newImageRect( imageGroup, imageCache[i], 128, 128 ) balls[i].x = display.contentCenterX balls[i].y = display.contentCenterY balls[i].isVisible = false end imageGroup.isShowing = 1 balls[imageGroup.isShowing].isVisible = true
现在,要管理交换,我们可以执行以下代码,将局部变量 showingImage
设置为我们要显示的图像的索引。 在这种情况下,值 4
将显示yellow-ball.png
imageCache
数组的第 4 个位置声明。
local showingImage = 4 for i = 1,imageGroup.numChildren do if ( i == showingImage ) then imageGroup[i].isVisible = true else imageGroup[i].isVisible = false end end
虽然上述方法都完全有效,但使用单个图像文件并不是内存和加载时间的最佳利用方式。 此外,在项目目录中创建/存储大量单个文件可能会变得混乱。 这就是我们鼓励使用 图像表单 的原因,在图像表单中,您可以加载包含所有单个图像的单个图像表单/图集,然后从中显示特定帧。 图像表单需要更多的初始设置,但好处是值得的。
将上述代码转换为图像表单可能如下所示。
local imageGroup = display.newGroup() local sheetOptions = { width = 128, height = 128, numFrames = 5, sheetContentWidth = 640, sheetContentHeight = 128 } local ballSheet = graphics.newImageSheet( "ballSheet.png", sheetOptions ) local balls = {} for i = 1,sheetOptions.numFrames do balls[i] = display.newImageRect( imageGroup, ballSheet, i, 128, 128 ) balls[i].x = display.contentCenterX balls[i].y = display.contentCenterY balls[i].isVisible = false end imageGroup.isShowing = 2 balls[imageGroup.isShowing].isVisible = true
从代码的角度来看,这与上面的数组方法没有太大区别,除了使用图像表单带来的效率提升之外 — 但是图像表单是通往精灵的门户,这是一种交换图像的绝佳方式!
Solar2D 包含一个全面的 精灵 引擎。 虽然术语“精灵”似乎仅表示游戏中动画对象,但您应该将其简单地视为可用于多种目的的有序图像序列,包括交换图像。
让我们看一个
local sheetOptions = { width = 128, height = 128, numFrames = 5, sheetContentWidth = 640, sheetContentHeight = 128 } local ballSheet = graphics.newImageSheet( "ballSheet.png", sheetOptions ) local ball = display.newSprite( ballSheet, { name="balls", start=1, count=sheetOptions.numFrames } ) ball:setFrame( 2 ) ball.x = display.contentCenterX ball.y = display.contentCenterY
与使用图形填充的版本一样,我们不再需要显示组 (imageGroup
),因为精灵根据定义是
如您所见,"交换图像" 概念有多种方法和途径,最适合的方法取决于您的需求和设计细节。 从单个图像到填充再到精灵,Solar2D 都能满足您的需求!