2011年4月15日 星期五

Corona SDK -- Group使用

Group的使用其實很方便,方便管理一群有相同相關性的物件。
例如:需要同時出現,需要同時移動等等

在Corona SDK中需要用到 display.newGroup()這個API,我們來看看官網是怎麼敘述:
Syntax:
        display.newGroup()
Example:
        local rect = display.newRect(0, 0, 100, 100)
        rect:setFillColor(140, 140, 140)

        local group = display.newGroup()
        group:insert( rect )

因此可以知道,把物件直接"insert"進去Group裡面就好。
那,怎麼把Group刪除呢?
請看以下範例:
-----------------------------------------
        local Group = display.newGroup()
local myRectangle = display.newRoundedRect(Group,40, 190, 240, 100,12)
              myRectangle.strokeWidth = 3
            myRectangle:setFillColor(140, 140, 140)
              myRectangle:setStrokeColor(180, 180, 180)
local tag = display.newText( Group, "Hello, this is an example.", 60, 210,    
                       native.systemFont, 16)
              tag:setTextColor(255, 255, 255)
-----------------------------------------
上面這段範例,主要是建立一個對話框,並在對話框上顯示"Hello, this is an example."


把這兩個物件都加入Group之後,就可以針對tempGroup去做任何動作。
例如:
        移動:
-----------------------------------------
            transition.to( Group, { time=400, x=200, y=245})
-----------------------------------------
        維持一段時間後把對話框取消:
-----------------------------------------
            local function clear_Group()
               for i = tempGroup.numChildren,1,-1 do
    local child = Group[i]
                  child.parent:remove( child )
        child = nil
    end
end
           timer.performWithDelay(500, clear_Group )
-----------------------------------------
因此把Group刪除,可以透過numChildren的方式,把Group底下的子物件叫出,然後刪除。
timer.performWithDelay(500, clear_Group )是計時500ms之後執行clear_Group此function。

================================================
那麼如果要針對Group裡面的成員來做控制,該怎麼去控制他呢?用什麼語法?
其實,把物件insert到Group裡面,並無法透過 .obj的方式去呼叫他,因為他其實還並不是Group裡面的成員(有點弔詭,可以想成,其實被丟進去Group裡面,但是你沒有賦與他一個名稱與設定為Group成員)

因此可以透過以下方式來設定物件為Group內一個成員:
-----------------------------------------
local    Group=display.newGroup()
local    text1=display.newText("Hello, I'm Group 1",50,50,native.systemFontBold,24)
local    text2=display.newText("Hello, I'm Group 2",50,80,native.systemFontBold,24)
           Group:insert(text1)
           Group:insert(text2)
           --把text1、text2設定為Group之成員
           Group.text1=text1
           Group.text2=text2
           --透過以下方式可以去更改Group成員之數值
           Group['text1'].text = "Hello, I'm text1 in Group.text1"
           Group['text1'].size = 40
           Group['text1']:setTextColor(255,2,2)
           Group['text2'].text = "Hello, I'm text2 in Group.text2"


           --也可以直接取用Group成員
           Group.text1.text = "Hello, I'm text1 in Group.text1"
           Group.text2.text = "Hello, I'm text2 in Group.text2"
-----------------------------------------

13 則留言:

  1. Hi,
    目前覺得group除了可以保留物件不被gc掉,還有做大量display object顯示的管理,此外似乎不是很好用?不知道你們在開發的時候怎麼樣利用group?

    我剛剛遇到另一個問題,原本某物件先塞到groupA,取出來後(用remove)塞進另一個groupB,物件的physics屬性會不見,是我的方式不對嗎?

    回覆刪除
  2. Hello:
    1. 你說的沒錯,Group主要是拿來處理display object的。但是他很好用。主要用來分類不同屬性、或者說有不同特性的一群display object,可利於管理。另外,也可以想成是顯示上不同圖層,可以同時顯示與刪除。

    2. 你這程式可以寄給我嗎? 因為如果用Group:remove()掉,原始的屬性是會被刪除的。

    回覆刪除
  3. Hi,
    我又做了一些測試,根據官方文件如果將一個display obj加入不同的group,會自前一個group移除再加入第二個,這點沒錯,physics屬性也有保留。但如果把這兩個動作拆開就有問題了,Corona的一些潛規則其實還蠻惱人的。

    程式如下,用兩個circle做碰撞而已
    local physics = require "physics"
    physics.start()
    physics.setGravity(0,0)

    local groupA, groupB
    groupA = display.newGroup()
    groupB = display.newGroup()

    local ball = display.newCircle(100,100,20)
    ball:setFillColor(255,0,0)
    physics.addBody(ball,{friction=0.5, bounce=0.5, radius=20})

    local stone = display.newCircle(200,200,15)
    stone.myName = "Stone"
    stone:setFillColor(255,255,0)
    physics.addBody(stone,{friction=0.5, bounce=0.5, radius=15})
    groupA:insert(stone)
    local item = groupA:remove(1)
    stone_txt = display.newText(item.myName, 30,50,system.nativeFont, 18)
    groupB:insert(item)

    ball:setLinearVelocity(100,100)
    ball:applyLinearImpulse(0,0, ball.x, ball.y)

    回覆刪除
  4. 你好:
    基本上,當從GroupA中移除物件,其屬性是會被砍掉的。
    在Corona SDK的Group:remove()說明中:
    When an object is removed, the rendering-related resources of the removed object are deleted immediately. What remains of object is simply a plain Lua table with all non-display object properties (the metatable is set to nil and all properties relating to display object are removed).

    因此,當使用remove的時候,只保留了物件的基本table,例如:名字,位置等等,但是,其他顯示的屬性都不存在了。因此,當你從GroupA中搬出來後,要放進GroupB裡頭,為了要保持碰撞的參數,是必須要在設定一次physics的。

    回覆刪除
  5. 原來API那邊有寫 囧~

    謝謝

    回覆刪除
  6. 你好,很感谢你做的教程文章,我目前想实现在3角形,在每个角都表明一个数字,可否给个提示。

    回覆刪除
  7. 詈晟,您好:
    不是很懂你的需求。你是希望完全用畫的還是直接貼圖呢?因為直接貼圖比較簡單。另外,數字是只要寫字上去就好,還是要有其他功能呢?
    如果只是要用畫的,可以考慮直接用display.newLine( )去畫。另外標字的話,可以用display.newText()去標字。

    有問題可以在提出來討論喔~~

    回覆刪除
    回覆
    1. 感谢你的回复,我把思路整理好了再在分享

      刪除
  8. Triominos 这个游戏你玩过吗?我就是想做那个三角图加数字效果。

    回覆刪除
    回覆
    1. 這個遊戲的話呢,我會建議你,準備一個三角形的圖檔,然後,每次建立的時候,依照你的關卡所需擺放的數字,然後再三角形圖檔上放置數字,然後自成一個Group讓使用者使用。這樣那個三角形跟數字就相當於被綁在一起,一起轉動。當然數字你也可以準備圖檔,會比較好看。

      刪除
    2. 準備一個三角形的圖檔,然後,每次建立的時候,依照你的關卡所需擺放的數字,然後再三角形圖檔上放置數字, 网上可否有现成的,还是需要用display.newLine来画?

      刪除
    3. 在三角形圖檔上放置數字, 这个希望能提示下。

      刪除
    4. 不用用到display.newLine,由於是現成三角形圖檔,你只要display.newImage就可以把圖檔貼上。然後在上面再用display.newText放入字。需要的話可以參考corona SDK官網的sample code。

      刪除