标签:
Composer是corona官方提供的场景创建和管理系统,我大CoronaSDK果然威武!
1 场景者,何也
corona中的每个场景是以一个lua文件的形式出现,多个.lua文件分散在你的项目中组成众多场景。你编写这些lua文件的时候必须遵循一些规则,以便Composer可以正确理解你的场景代码。
场景代码文件中须得包含两样东西,以使得场景可以被正确地初始化:
具体的例子呆会可以看后面的场景模版。
因为场景都是Lua模块,所以加载的方式首先是require()来加载到内存中,并且只能加载一次。有一件事非常重要,就是放在四个场景监听函数之外的代码,在每次场景显示和隐藏时,并不会被重复执行。
场景对象的创建,主要是通过调用compose.newScene()。这个对象保存着Composer必须访问的重要的场景数据,对于开发者来说,最重要的方面,就是场景的视图(self.view)--这是一个display group对象,场景中所有可视的内容都被添加于其中。例如像image、vector对象这些display object都必须加入这个视图(view),连同交互对象如widgets也都如此。这是关于Composer最重要的概念。
一个场景的self.view这个组对象,位于显示层级的底部。如果你创建一个display object而不加入场景的view组,他们将会处于Composer舞台的前面。
2 生命周期
Composer生命周期起于main.lua。然而main.lua自己并不是一个Composer场景--这只不过是一个初始化代码,然后它会通过composer.gotoscene()来启动第一个场景。在这次调用中,需要指定被加载的场景(也是文件)的名字,去掉.lua扩展名:
local composer = require( "composer" ) -- Code to initialize your app -- Assumes that "scene1.lua" exists and is configured as a Composer scene composer.gotoScene( "scene1" )
一旦加载,场景的生命周期就开始了,它也将遵循下面基本规则:
3 场景事件
四个不同的生命周期函数,来处理Composer产生的事件。
scene:create()
当一个场景刚被加载时,还没有一个关联的self.view产生,Composer将会分发一个事件给本地函数scene:create()。如果self.view已经存在,则create事件就会跳过。因为,默认情况下,Composer试图把self.view保持在内存里,假设你在某个时候还会返回这个场景。这样,scene:create()函数将不会在每次场景被显示时都被执行。
local composer = require( "composer" ) local scene = composer.newScene() function scene:create( event ) local sceneGroup = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. end scene:addEventListener( "create", scene ) return scene
这个scene:create函数对于下面这些事来说是一个恰好的时机:
不过这并不包括native对象,比如文本输入框--这些应该在scene:show()函数里创建。
重要提示:
如果display object应该成为场景的一部分并被Composer所管理--例如当场景被删除时就清除--这些对象就必须被插入到场景的self.view里。注意下面self.view被简单赋给本地变量sceneGroup引用。
local composer = require( "composer" ) local scene = composer.newScene() function scene:create( event ) local sceneGroup = self.view local background = display.newRect( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) background:setFillColor( 1, 0, 0.2 ) sceneGroup:insert( background ) end scene:addEventListener( "create", scene ) return scene
一旦创建完成,场景的视图便被隐藏。根据你的scene transition设置,它将处于当前存在的场景之下或甚至屏幕之外。因为这个场景还不可见的,你这时不应该开始任何timer或激活任何物理对象。同样如果你会用到场景特定的音效,你可以将它加载到内存里,而不是现在就播放它。
scene:show()
这个函数将会在场景每次被显示时被激活两次:一次是在场景正要显示出来之前,另一次在场景完全显示到屏幕上之后。
local composer = require( "composer" ) local scene = composer.newScene() function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Called when the scene is still off screen (but is about to come on screen). elseif ( phase == "did" ) then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc. end end scene:addEventListener( "show", scene ) return scene
正如你所看到,这个传给scene:show()的参数event,包含了一个phase字段--它可以取两个值:“will”或"did"。
scene:hide()
这个函数在每次场景被隐藏时被激活两次:一次在场景正要离开屏幕时,另一次在场景已经完全离开屏幕后。
local composer = require( "composer" ) local scene = composer.newScene() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( event.phase == "will" ) then -- Called when the scene is on screen (but is about to go off screen). -- Insert code here to "pause" the scene. -- Example: stop timers, stop animation, stop audio, etc. elseif ( phase == "did" ) then -- Called immediately after scene goes off screen. end end scene:addEventListener( "hide", scene ) return scene
类似于show,传给scene:hide()的参数event,也有一个phase字段,分别可以取值:"will"或"did":
will:发生在当场景正要离开屏幕的时候。这是暂停或停止物理系统‘取消timer和transition、停止场景音乐的好机会。
did:这个阶段不需要太多的动作,尽管你可以在这里删除场景self.view或者甚至删除场景。
scene:destrory()
这个函数就是Composer用来清除场景中的display object(任何你插入self.view组的对象)。scene:destroy()在场景被清除前被调用。在这里,你可以undo你在scene:create()里所做的事---没有被关联到场景display object上的东西。例如,dispose()场景音乐等。
function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene‘s view ("sceneGroup"). -- Insert code here to clean up the scene. end
因为Composer出于性能考虑,视图保持场景在内存中,这个函数指挥在下面这些情况被调用:
如果你在scene:create()函数里加载音乐文件到内存里,scene:destroy()就是dispose这个音乐的好时机。同理,如果你在scene:create()里建立了数据库连接,那么在这里你可以关闭这个连接。
4 场景模版
下面这个模版就是你创建新场景文件时可以使用的。注意模版中包含的监听事件函数是场景中所有可能的事件,但是你可以只加入你想要处理的。
local composer = require( "composer" ) local scene = composer.newScene() -- ----------------------------------------------------------------------------------------------------------------- -- All code outside of the listener functions will only be executed ONCE unless "composer.removeScene()" is called. -- ----------------------------------------------------------------------------------------------------------------- -- local forward references should go here -- ------------------------------------------------------------------------------- -- "scene:create()" function scene:create( event ) local sceneGroup = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. end -- "scene:show()" function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Called when the scene is still off screen (but is about to come on screen). elseif ( phase == "did" ) then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc. end end -- "scene:hide()" function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Called when the scene is on screen (but is about to go off screen). -- Insert code here to "pause" the scene. -- Example: stop timers, stop animation, stop audio, etc. elseif ( phase == "did" ) then -- Called immediately after scene goes off screen. end end -- "scene:destroy()" function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene‘s view ("sceneGroup"). -- Insert code here to clean up the scene. -- Example: remove display objects, save state, etc. end -- ------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ------------------------------------------------------------------------------- return scene
5 跳转场景
一旦你创建了场景文件,你需要一个方法去访问他们。在Composer中,就是通过composer.gotoScene(sceneName)来完成。这个sceneName参数,对应着lua文件的名字,只是不带.lua扩展名而已。例如,如果你有一个名为menu.lua的场景文件,你访问这个场景的方式就是:
composer.gotoScene( "menu" )
另外,有一些参数,你也可以传给composer.gotoScene()来控制转场动画,或传递数据给这个场景。你可以做如下事:
local options = { effect = "fade", time = 500, params = { someKey = "someValue", someOtherKey = 10 } } composer.gotoScene( "menu", options )
而在场景中,读取这个参数params则如下:
function scene:create( event ) local sceneGroup = self.view local params = event.params print( params.someKey ) print( params.someOtherKey ) end
重要提示:
因为Composer默认把当前场景视图保存在内存里,所以scene:create()函数只有在场景第一次被创建时被调用。这样,如果你传一个table作为参数给scene:create(),它也只能在第一次被创建时有效。
6 转场特效
"fade"
"crossFade"
"zoomOutIn"
"zoomOutInFade"
"zoomInOut"
"zoomInOutFade"
"flip"
"flipFadeOutIn"
"zoomOutInRotate"
"zoomOutInFadeRotate"
"zoomInOutRotate"
"zoomInOutFadeRotate"
"fromRight"
— over current scene"fromLeft"
— over current scene"fromTop"
— over current scene"fromBottom"
— over current scene"slideLeft"
— pushes current scene off"slideRight"
— pushes current scene off"slideDown"
— pushes current scene off"slideUp"
— pushes current scene off
7 场景管理
Composer的一个重要特性就是,大部分时候它会自动管理display object,当然前提是你把它们插入到场景的view组里:
function scene:create( event ) local sceneGroup = self.view local menuBack = display.newRect( display.contentCenterX, display.contentCenterY, 280, 360 ) sceneGroup:insert( menuBack ) end
一旦这个场景被回收或删除,Composer将会恰当地清理menuBack对象,连同其他被插入view组的对象。被应用到这些对象上的touch、tap、collision一类监听器也将会删除。
重要提示:
正如删除Composer管理之外的display object一样,你还应该在结束一个场景时对下面这些东西负责:
8 自动回收场景
默认情况下,当改变场景时,composer保持当前场景在内存中。假如你频繁切换场景的话,这样的确可以提升性能。如果你希望当前场景改变到一个新的场景时就回收当前场景,你可以设置composer.recycleOnSceneChange属性为true:
composer.recycleOnSceneChange = true
恢复到默认行为,让view可以在切换时被保存,则可以设置属性为false:
composer.recycleOnSceneChange = false
很重要的一点是,这两种情况都不会把场景从lua内存中卸载。为了显式从内存中删除场景,就需要使用composer.removeScene()。
9 删除场景
如果你彻底用完了一个场景,并再也不打算访问它了,你可以通过下面的API删除之:
composer.removeScene( sceneName [, shouldRecycle])
例如,如果你想删除menu.lua中的view组以及场景对象,那么调用:
composer.removeScene( "menu" )
也可以传入一个参数,把shouldRecycle设置为true。这样将会从显示层次中删除场景的view,而它仍然会保存在lua内存中:
composer.removeScene( "menu", true )
10 重新加载场景
重新加载场景需要一些不同的方式。许多人想在scene:create()函数里创建和定位所有的场景显示对象。然而如果你重新加载场景,这个函数不会再次被调用,因为场景的view已经存在了。已经移动过的对象(比如游戏中的橘色)在你重新加载的时候依然保持原位,监听函数之外定义的变量也将保持他们当前的值。例如,如果你在监听函数之外设置一个分数变量,他在你重新加载场景的时候不会重置到那个初值。
甚至如果你销毁了场景的view,那些变量也还是不会重置。就算scence:create()可以重新执行,但是监听函数以外的代码也无法重新执行。
重新加载场景最好的办法,就是使用一个中间场景。在游戏中,这是经常被用来做一个“过场动画”,也可能显示玩家表现的一个评价,再或者一个菜单选项例如“重玩”和“退出”等等。使用一个中间过度场景,你可以手动删除你想要重新加载的场景,导致你再次加载它的时候有一个新的开始。然而你仍然需要在scene:show()函数的will阶段重新设置变量和重新放置对象。
如果你想跳过过度场景方法,你可以通过调用自己的方法来重新加载一个场景:
local currScene = composer.getSceneName( "current" ) composer.gotoScene( currScene )
CoronaSDK场景管理库:Composer library (上)
标签:
原文地址:http://www.cnblogs.com/leezj/p/4234767.html