2015년 11월 6일 금요일

corona sdk 에서 level director 이용 level간 전환과 object class

corona sdk 에서 level director 이용 level간 전환하기


corona sdk에서 story board가 api가 생겨서 변환이 쉽게 되지만 LD에서는 storyboard api 사용 없이도 쉽게 변환 할 수 있습니다.

LD site 예제에서 찾아보았습니다.
V2Demo 예제에서 사용법을 찾아볼 수 있습니다.


function loadScene()
 if (scene > 0) then
  myLevel:removeLevel()
  clickText:removeEventListener("tap",loadScene)
  Runtime:removeEventListener("enterFrame",move)
  Runtime:removeEventListener("touch", drag )
  
  if (toggle) then
   toggle:removeSelf()
   toggle = nil
  end
 end
 
 scene = scene + 1
 
 if (scene > 4) then
  scene = 1
 end
 
 myLevel = LD:loadLevel ('Scene' .. scene)

 --print ('layers ' .. #myLevel.layers)
 clickText = myLevel:getLayerObject("Text","click").view
 clickText:addEventListener( "tap", loadScene )
 initScene()
end

loadScene()

레벨을 로딩할때 LD:loadLevel() 함수를 사용하고 제거시 myLevel:removeLevel() 함수를 사용하면 됩니다.

지난번 animation 작업하던곳에 새로운 level을 만들어서 object가 5번 생성되면 다음 level로 전환되는 예제를 만들어 보도록 하겠습니다.

level01은 기존 그대로 사용하고 level02는 level01을 그대로 복사합니다.

level02



그후에 bird를 삭제하고 y만 남겨두고 위치를 변경합니다.
그리고 itemGet이라는 level을 새로 만듭니다. 복사를 안하고 만들면 asset이 하나도 생기지 않습니다.
level01->level02->itemGet 순으로 level이 변경되도록 제작하겠습니다.

아래는 소스입니다.


physics = require ("physics")
physics.start()

local LD = require("lib.LD_LoaderG2") -- G2 is for Corona Graphic2.0, remove for Graphics1.0
local myLevel ={}

local yobj
local bird

local tPrevious = system.getTimer()
local deltaSum = 0
local level = 0
local count = 0
local tm
local initScene = nil

-------------------------------------------------
--function to position new ball and update scores
-------------------------------------------------
function spawnObject()

 local objProps = 
 {
  name  = "bird_dy", 
  x  = math.random(20,300),
  y  = 0,
  xScale  =  1,
  yScale  =  1,
  assetName = "bird_png_1",
 }
 
 -- set the graphics 
 local bird_d = myLevel:createObject("New Layer", objProps).view
 
 bird_d:setSequence("Sequence0")
 bird_d:play()

 transition.moveTo( bird_d, { x=yobj.x, y=yobj.y, time=8000 } )

end

-------------------------------------
function update(event)
-------------------------------------
 if( level == 1 ) then
  local tDelta = event.time - tPrevious
  tPrevious = event.time
  deltaSum = deltaSum + tDelta;
  
  if (deltaSum > 5000 ) then
   deltaSum = 0
   count = count + 1
   if (count > 5 ) then
    initScene()
    count = 0
    print("initscene",level)
   else
    spawnObject()
   end
  end
 elseif( level == 2 ) then
  local tDelta = event.time - tPrevious
  tPrevious = event.time
  deltaSum = deltaSum + tDelta;
  
  if (deltaSum > 5000 ) then
   deltaSum = 0
   count = count + 1
   if (count > 5 ) then
    level = 10000
    initScene()
    count = 0
    print("initscene",level)
   else
    spawnObject()
   end
  end
 end
end

-- poop collision handler
function onGlobalCollision( event )
 if( level == 1 ) then
  if event.phase == "began" then
   local obj1 = event.object1; 
   local obj2 = event.object2; 
   print (obj1.name)
   print (obj2.name)
   if ( obj1.name == "bird_dy" and obj2.name == "y" ) or 
   ( obj1.name == "y" and obj2.name == "bird_dy" )  then
    if( obj1.name == "y" ) then 
     myLevel:removeLayerObject("New Layer", obj2.name)
     obj2 = nil
    else 
     myLevel:removeLayerObject("New Layer", obj1.name)
     obj1 = nil
    end
   end
  end
 end
end

function initScene(event)
 print("initscene")
 if ( level~=0 ) then
  print("remove")
  myLevel:removeLevel()
  myLevel = nil
 end
 if( level < 10000 ) then
  level = level+1
  myLevel=LD:loadLevel("level0"..level)
 else
  if ( level == 10000 ) then
   myLevel=LD:loadLevel("itemGet")
  end
 end
 print("level",level)

 if ( level == 1 ) then
  bird = myLevel:getLayerObject("New Layer","bird").view
  bird:setSequence("Sequence0")
  bird:play()
  yobj = myLevel:getLayerObject("New Layer","y").view
  yobj:setSequence("Sequence0")
  yobj:play()
 elseif ( level == 2 ) then
  yobj = myLevel:getLayerObject("New Layer","y").view
  yobj:setSequence("Sequence0")
  yobj:play()
 end
end

initScene()

-- add frame handler
Runtime:addEventListener( "enterFrame", update )
Runtime:addEventListener( "collision", onGlobalCollision )


이전 예제에서 잘못구현한 내용이 있는데 동적 object삭제시 아래와 같이 LD api를 이용하여 삭제 하여야 합니다.
myLevel:removeLayerObject("New Layer", obj2.name)
myLevel:removeLayerObject("New Layer", obj1.name)


최종 개선한 코드 입니다.
birdcount 부분을 추가하였습니다. 왜냐하면 이름이 같아버리면 충돌시 삭제할때 어려움이 있었습니다. 충돌시 myLevel:removeLayerObject("New Layer", obj2.name) 함수를 이용하여 object를 제거할때 이름이 같아버려서 오동작을 하는 경우가 있었습니다.
function spawnObject()
birdcount = birdcount + 1
local objProps =
{
name = "bird_dy "..birdcount,



physics = require ("physics")
physics.start()

local LD = require("lib.LD_LoaderG2") -- G2 is for Corona Graphic2.0, remove for Graphics1.0
local myLevel ={}

local yobj
local bird

local tPrevious = system.getTimer()
local deltaSum = 0
local level = 0
local count = 0
local tm
local initScene = nil
local birdcount = 0
-------------------------------------------------
--function to position new ball and update scores
-------------------------------------------------
function spawnObject()
 birdcount = birdcount + 1
 local objProps = 
 {
  name  = "bird_dy "..birdcount, 
  x  = math.random(20,300),
  y  = 0,
  xScale  =  1,
  yScale  =  1,
  assetName = "bird_png_1",
 }
 
 -- set the graphics 
 local bird_d = myLevel:createObject("New Layer", objProps).view
 
 bird_d:setSequence("Sequence0")
 bird_d:play()

 transition.moveTo( bird_d, { x=yobj.x, y=yobj.y, time=math.random(500,10000) } )

end

-------------------------------------
function update(event)
-------------------------------------
 if( level == 1 ) then
  local tDelta = event.time - tPrevious
  tPrevious = event.time
  deltaSum = deltaSum + tDelta;
  
  if (deltaSum > 1000 ) then
   deltaSum = 0
   count = count + 1
   if (count > 50 ) then
    initScene()
    count = 0
    print("initscene",level)
   else
    spawnObject()
   end
  end
 elseif( level == 2 ) then
  local tDelta = event.time - tPrevious
  tPrevious = event.time
  deltaSum = deltaSum + tDelta;
  
  if (deltaSum > 5000 ) then
   deltaSum = 0
   count = count + 1
   if (count > 5 ) then
    level = 10000
    initScene()
    count = 0
    print("initscene",level)
   else
    spawnObject()
   end
  end
 end
end

-- poop collision handler
function onGlobalCollision( event )

 if( level == 1 ) then
  if event.phase == "began" then
   local obj1 = event.object1; 
   local obj2 = event.object2; 

   local sp = string.find(obj1.name," ")
   local obj1_name
   if (sp == nil) then
    obj1_name = obj1.name
   else
    obj1_name = string.sub(obj1.name, 0,string.find(obj1.name," ")-1)
   end
   local sp = string.find(obj2.name," ")
   local obj2_name
   if (sp == nil) then
    obj2_name = obj2.name
   else
    obj2_name = string.sub(obj2.name, 0,string.find(obj2.name," ")-1)
   end
   print (obj1_name, obj1.name)
   print (obj2_name, obj2.name)
   
   if ( obj1_name == "bird_dy" and obj2_name == "y" ) or 
   ( obj1_name == "y" and obj2_name == "bird_dy" )  then
    if( obj1_name == "y" ) then 
     myLevel:removeLayerObject("New Layer", obj2.name)
     obj2 = nil
    else 
     myLevel:removeLayerObject("New Layer", obj1.name)
     obj1 = nil
    end
   end
  end
 end
end

function initScene(event)
 print("initscene")
 if ( level~=0 ) then
  print("remove")
  myLevel:removeLevel()
  myLevel = nil
 end
 if( level < 10000 ) then
  level = level+1
  myLevel=LD:loadLevel("level0"..level)
 else
  if ( level == 10000 ) then
   myLevel=LD:loadLevel("itemGet")
  end
 end
 print("level",level)

 if ( level == 1 ) then
  bird = myLevel:getLayerObject("New Layer","bird").view
  bird:setSequence("Sequence0")
  bird:play()
  yobj = myLevel:getLayerObject("New Layer","y").view
  yobj:setSequence("Sequence0")
  yobj:play()
 elseif ( level == 2 ) then
  yobj = myLevel:getLayerObject("New Layer","y").view
  yobj:setSequence("Sequence0")
  yobj:play()
 end
end

initScene()

-- add frame handler
Runtime:addEventListener( "enterFrame", update )
Runtime:addEventListener( "collision", onGlobalCollision )


충돌 처리가 상당히 복잡해 졌습니다.
그래서 Tool > Options > Project 항목에 Class Types을 이용합니다.

y,brid를 추가하고

object의 Object Class를 변경합니다.
y의 경우 꺼내 놓은 객체를 변경하도록 합니다.

충돌 검사 소스를 변경합니다.


physics = require ("physics")
physics.start()

local LD = require("lib.LD_LoaderG2") -- G2 is for Corona Graphic2.0, remove for Graphics1.0
local myLevel ={}

local yobj
local bird

local tPrevious = system.getTimer()
local deltaSum = 0
local level = 0
local count = 0
local tm
local initScene = nil
local birdcount = 0
-------------------------------------------------
--function to position new ball and update scores
-------------------------------------------------
function spawnObject()
 birdcount = birdcount + 1
 local objProps = 
 {
  name  = "bird_dy "..birdcount, 
  x  = math.random(20,300),
  y  = 0,
  xScale  =  1,
  yScale  =  1,
  assetName = "bird_png_1",
 }
 
 -- set the graphics 
 local bird_d = myLevel:createObject("New Layer", objProps).view
 
 bird_d:setSequence("Sequence0")
 bird_d:play()

 transition.moveTo( bird_d, { x=yobj.x, y=yobj.y, time=math.random(500,10000) } )

end

-------------------------------------
function update(event)
-------------------------------------
 if( level == 1 ) then
  local tDelta = event.time - tPrevious
  tPrevious = event.time
  deltaSum = deltaSum + tDelta;
  
  if (deltaSum > 1000 ) then
   deltaSum = 0
   count = count + 1
   if (count > 50 ) then
    initScene()
    count = 0
    print("initscene",level)
   else
    spawnObject()
   end
  end
 elseif( level == 2 ) then
  local tDelta = event.time - tPrevious
  tPrevious = event.time
  deltaSum = deltaSum + tDelta;
  
  if (deltaSum > 5000 ) then
   deltaSum = 0
   count = count + 1
   if (count > 5 ) then
    level = 10000
    initScene()
    count = 0
    print("initscene",level)
   else
    spawnObject()
   end
  end
 end
end

-- poop collision handler
function onGlobalCollision( event )

--[[
 if( level == 1 ) then
  if event.phase == "began" then
   local obj1 = event.object1; 
   local obj2 = event.object2; 

   local sp = string.find(obj1.name," ")
   local obj1_name
   if (sp == nil) then
    obj1_name = obj1.name
   else
    obj1_name = string.sub(obj1.name, 0,string.find(obj1.name," ")-1)
   end
   local sp = string.find(obj2.name," ")
   local obj2_name
   if (sp == nil) then
    obj2_name = obj2.name
   else
    obj2_name = string.sub(obj2.name, 0,string.find(obj2.name," ")-1)
   end
   print (obj1_name, obj1.name)
   print (obj2_name, obj2.name)
   
   if ( obj1_name == "bird_dy" and obj2_name == "y" ) or 
   ( obj1_name == "y" and obj2_name == "bird_dy" )  then
    if( obj1_name == "y" ) then 
     myLevel:removeLayerObject("New Layer", obj2.name)
     obj2 = nil
    else 
     myLevel:removeLayerObject("New Layer", obj1.name)
     obj1 = nil
    end
   end
  end
 end
]]
 if( level == 1 ) then
  if event.phase == "began" then
   local obj1 = event.object1; 
   local obj2 = event.object2;

   if ( obj1.class == "bird" and obj2.class == "y" ) or 
   ( obj1.class == "y" and obj2.class == "bird" )  then
    if( obj1.class == "y" ) then 
     myLevel:removeLayerObject("New Layer", obj2.name)
     obj2 = nil
    else 
     myLevel:removeLayerObject("New Layer", obj1.name)
     obj1 = nil
    end
   end
  end
 end

end

function initScene(event)
 print("initscene")
 if ( level~=0 ) then
  print("remove")
  myLevel:removeLevel()
  myLevel = nil
 end
 if( level < 10000 ) then
  level = level+1
  myLevel=LD:loadLevel("level0"..level)
 else
  if ( level == 10000 ) then
   myLevel=LD:loadLevel("itemGet")
  end
 end
 print("level",level)

 if ( level == 1 ) then
  bird = myLevel:getLayerObject("New Layer","bird").view
  bird:setSequence("Sequence0")
  bird:play()
  yobj = myLevel:getLayerObject("New Layer","y").view
  yobj:setSequence("Sequence0")
  yobj:play()
 elseif ( level == 2 ) then
  yobj = myLevel:getLayerObject("New Layer","y").view
  yobj:setSequence("Sequence0")
  yobj:play()
 end
end

initScene()

-- add frame handler
Runtime:addEventListener( "enterFrame", update )
Runtime:addEventListener( "collision", onGlobalCollision )


기타 참고 : http://www.retrofitproductions.com/level-director/utility-library/


댓글 없음:

댓글 쓰기