반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

코로나 SDK (Corona SDK)에서는 화면 전환을 위해서 transition.to를 사용합니다.
이것만 사용해서도 아주 다이나믹한 효과를 낼 수 있는데요.

Ricardo Rauber Pereira라는 개발자가 아주 보기 좋은 화면 전환 클래스들을 구현해서 이를 공개했습니다.
director.lua라는 파일인데 구글에서 써핑하셔도 쉽게 찾으실 수 있습니다.

이 클래스에는 총 12개의 화면 전환 효과가 있습니다.
("moveFromRight","overFromRight","moveFromLeft","overFromLeft",
"moveFromTop","overFromTop","moveFromBottom",
"overFromBottom","crossfade","fade","flip","downFlip"
)

파일은 아래에 제가 압축해서 올린 샘플파일에 있습니다. 받아보세요.
제가 가지고 있는 건 버전 1.3 이네요.
 - Version: 1.3
 - Made by Ricardo Rauber Pereira @ 2010
 - Blog: http://rauberlabs.blogspot.com/
 - Mail: ricardorauber@gmail.com
이 파일을 보면 블로그와 이메일도 있으니까 참조하시구요.
저 블로그에 가 보니까 지금은 1.4 버전이 나왔네요.
이 개발자는 브라질 사람인가 봐요.

리카르도는 소스코드를 무료로 공개하는 대신 블로그에서 Donation을 받네요.
자신의 노력의 결과물을 나눠서 다른 사람이 쉽게 사용할 수 있도록 공개하는 개발자들에게는 성의 표시를 해줘도 좋겠죠? 여유가 있으면 Donation을 해도 좋고 블로그에 광고가 있으면 광고를 눌러줘도 되고 아니면 메일이나 트위터로 고맙다고 메세지 날려줘도 좋을 거예요.. :) 그리고 리카르도가 만든 앱을 다운받거나 구매하는 것도 ....


이 director.lua를 이용하는 방법은 아래와 같습니다.

http://www.youtube.com/watch?v=RAktnj7nwos

1. main.lua가 있는 폴더에 director.lua를  복사해 넣는다.
2. require 한다 (local director = require("director"))
3. 그룹을 만든다. local mainGroup = display.newGroup()
4. directorView를 그룹에 넣는다. mainGroup:insert(director.directorView)
5. 화면 전환 할 때 changeScene을 이용한다. director:changeScene("scene2","downFlip")
-> 첫번째 파라미터는 다음 화면을 보여줄 파일 이름입니다. 이 경우 scene2.lua가 되겠죠.
-> 두번째 파라미터는 화면 전환 효과 입니다. 아까 봤던 8가지 중에 아무거나 한가지를 넣으시면 됩니다.

그 다음은 전환될 화면 (scene2.lua)에서는 어떻게 해야 하는지 보겠습니다.
1. 모듈 선언을 한다. module(..., package.seeall) -> 이것은 Corona SDK에서 모듈 사용하는 규칙입니다.
2. localGroup이라는 그룹을 만든다. local localGroup = display.newGroup()
3. 함수 new()를 만든다. function new()    return localGroup end
4. 함수 new()는 localGroup을 return한다.
5. 다른 화면으로 전환하려면 마찬가지로 changeScene을 이용한다.
director:changeScene("nextfile","downFlip")

이것만 지켜주시면 됩니다.


우리의 리카르도가 공개한 샘플 입니다. 파일은 아래에 있습니다.


파일을 열어보니까 제가 못 봤던 book이라는 폴더가 있네요.
실행해 보니까 SlideView 관련된 클래스 인가봐요.
화면 전환 뿐만 아니라 Slideview 관련해서도 편리한 기능을 제공하나봅니다.

이건 제가 공부 좀 해서 다음 기회에 소개해 드릴께요.

오늘은 팁으로 제가 이 director.lua 클래스를 사용할 때 화면 전환 효과를 랜덤하게 처리하고 있는데요.

그 소스를 소개해 드릴께요.

일단 randomScreen.lua 파일을 아래처럼 만들어 놓습니다.
module(..., package.seeall)
function init()
    RandomScreen()
end

function RandomScreen() 
    changes = {"moveFromRight","overFromRight","moveFromLeft","overFromLeft",
                "moveFromTop","overFromTop","moveFromBottom",
                "overFromBottom","crossfade","fade","flip","downFlip"}
    selectScreen = math.random(1,12)
    screenChange = changes[selectScreen]
    return screenChange   
       
end


그리고 main.lua에서 이 파일을 require합니다.

local changeScreen = require("randomScreen")

그리고 화면전환 하기 직전에 이 랜덤한 화면전환 기능 값을 받습니다.

randomScreen = changeScreen.RandomScreen();

그리고 director.lua의 cangeScene을 이용할 때 이 값을 넣습니다.

director:changeScene("파일이름", randomScreen);

이렇게 하면 랜덤하게 화면 전환 효과들을 이용할 수 있습니다.
저는 앱을 만들 때 이렇게 처리하면 편하더라구요.

오늘의 팁이였구요.

director.lua에서 파라미터 넘기기나 팝업 기능 사용하기는 직접 소스 보면서 해 보세요.

그렇게 어렵지 않을 겁니다.

그럼...
반응형


반응형
오늘은 Sprite Sheet과 timer와 관련된 팁을 다루겠습니다.

오늘 다룰 소스는 Peach Pellen 이라는 개발자가 자기 친구가 앱을 개발한다는 얘기를듣고 도움이 될까 해서 만든 주사위놀이 샘플 코드입니다. 그리고 그 코드를 공개해서 다른 분들도 도움이 되길 바란다고 하네요.

아래 링크로 가시면 관련 글을 보실 수 있습니다.

http://techority.com/2011/11/22/rolling-the-dice/

저 싸이트로 가시면 샘플 코드를 다운 받으실 수 있구요.
아래 저도 그 코드를 올려 놓을 테니까 여기서 곧바로 다운 받으셔도 됩니다.

실행 화면은 아래와 같습니다.


오른쪽 위에 하얀 사각형을 누르면 주사위가 막 돌다가 멈춥니다.
그러면 터미널에 두 주사위의 합이 출력 됩니다.

그런데 이상한건 제가 집에서 이 소스코드를 실행 했을 때는 두 주사위가 항상 같은 숫자만 나왔거든요.

그래서 다른 숫자가 나오도록 소스를 좀 수정했습니다.
그리고 터미널뿐만 아니라 화면에도 합계가 텍스트로 표시 되도록 했구요.

그런데 회사와서 이 코드를 돌려보니까 두 주사위가 항상 같은 숫자가 나오는게 아니더라구요.

집에 있는 컴퓨터는 윈도우고 회사에 있는건 맥이라서 그런가?

하여간 아래 코드는 제가 조금 수정한 코드입니다. 다운 받은 파일에 있는 소스랑은 아주 조금 다를거예요.


--Hide the status bar => 스테이터스 바 감추기
display.setStatusBar(display.HiddenStatusBar)

--Require sprite => 스프라이트 require하기. 스프라이트는 director.lua나 movieclip.lua 처럼 별도의 파일로 제공되는게 아니라 corona sdk 에 내장된 클래스 입니다. 따로 파일을 구하실 필요가 없습니다.
require "sprite"

=> 스크린 너비와 높이 구해 놓기
_W = display.contentWidth;
_H = display.contentHeight;

--The background image => 배경화면 표시하고 합계를 표시할 텍스트 선언하고 위치 정해 줌
local bg = display.newImage( "bg.png" )
local total = display.newText("", _W/2, _H-(_H/7), native.systemFontBold, 30)

--Total sum of dice after a roll => 주사위 합계 담을 변수
local diceTotal = 0

--States whether or not the dice may be rolled => 주사위 돌리기 가능한 상태인지 아닌지 콘트롤 할 변수
local canRoll = true

--Sprite Setup => 스프라이트를 셋업 함
local diceSheet = sprite.newSpriteSheet( "dice.png", 64, 64)

주사위로 사용할 이미지는 이 이미지 입니다.
일단 이 이미지를 diceSheet이라는 이름으로 만듭니다. 이 프레임의 크기는 64X64 입니다.

local diceSet = sprite.newSpriteSet( diceSheet, 1, 6 )
sprite.add( diceSet, "dice", 1, 6, 195, 0)
sprite.add( diceSet, "dice2", 1, 6, 210, 0)

위 diceSheet를 diceSet이라는 스프라이트 세트에 담습니다. 시작하는 프레임은 1 이고 총 6개 프레임이 있습니다.
이 diceSet를 add합니다. 신택스는 아래와 같습니다.
sprite.add( spriteSet, sequenceName, startFrame, frameCount, time, [loopParam] )
첫번째는 diceSet를 dice라는 sequenceName으로 add를 하는데 시작 프레임 1이고 전체 프레임 count는 6 입니다. time은 195입니다. 이것은 195ms에 이 diceSet을 한번 돌린다는 겁니다.
두번째 줄은 dice2인데 dice와 모두 같고 이 time이 210 입니다.
두 주사위가 6개 프레임의 돌아가는 시간이 다르니까 각각 다른 프레임이 나오겠네요.
윈도우에서 항상 똑 같은 주사위 이미지가 나온게 제가 착각한 건가 본데요?
혹시 여러분 윈도우에서 한번 돌려보시구 어떻게 나오나 잘 살펴 보세요.
저도 집에 돌아간 다음에 다시 돌려 봐야 겠네요.

--First Die
local dice = sprite.newSprite( diceSet )
dice.x = 120
dice.y = 200
dice:prepare("dice")

첫번째 sprite를 dice라는 변수에 담고 화면의 위치를 정해 줍니다.
스프라이트 쉬트 사용하는 순서가 이렇게 되네요.
sprite.newSpriteSheet => sprite.newSpriteSet => sprite.add => sprite.newSprite => spriteInstance:prepare => spriteInstance:play => spriteInstance:pause
따로 정리해서 외워도 좋겠는데요.

--Second Die
local dice2 = sprite.newSprite( diceSet )
dice2.x = 200
dice2.y = 300
dice2:prepare("dice2")

두번째 스프라이트 dice2를 선언합니다.

--Roll button
local rollBtn = display.newImage("die.png")
rollBtn.x = 280
rollBtn.y = 40

=> 버튼 이미지를 표시합니다.

--End Roll Function
local function endRoll()
    dice:pause()
    showTotal();
end

첫번째 주사위 play를 중지시키고 showTotal함수를 실행합니다.

local function endRoll2()
    dice2:pause()
    showTotal();
end

두번째 주사위 play를 중지시키고 showTotal함수를 실행합니다.

function showTotal()
    diceTotal = dice.currentFrame + dice2.currentFrame
    print(diceTotal) --Print the result in the terminal
    total.text="Total : " .. diceTotal;
    canRoll = true --Allow the dice to be rolled again
end

현재 프레임 = 주사위 눈 입니다. dice와 dice2의 현재 프레임을 구해서 더하면 주사위 두 눈의 합이 됩니다.
이것을 터미널에 print하고 스크린에도 표시합니다.
canRoll은 true로 세팅해서 버튼을 누르면 주사위가 돌아갈 수 있도록 합니다.

--Roll function
local function rollDice()
    if canRoll == true then
        canRoll = false --Prevent dice from being rolled again before the current role is over
        dice:play()
        dice2:play()
        randomTime = math.random(1500, 3500)
        timer.performWithDelay(randomTime, endRoll, 1)
        randomTime2 = math.random(1500, 3500)
        timer.performWithDelay(randomTime2, endRoll2, 1)
    end
end
canRoll을 false로 해서 버튼을 눌러도 주사위가 새로 돌지 않도록 막아 놓습니다.
dice와 dice2를 play시킵니다.
랜덤값 (1.5초 ~ 3.5초)를 구해서 timer를 사용해서 그 시간만큼만 돌고 dice를 멈추게 합니다. 다음줄은 dice2를 멈추게 합니다.

rollBtn:addEventListener("tap", rollDice)

버튼에 이벤트 리스너를 달아서 누르면 rollDice가 실행 되도록 합니다.



이렇게 하면 위 그림처럼 화면에 주사위 눈의 합이 출력 됩니다.

원래 소스가 두 주사위의 눈이 각각 다르게 표시되도록 하는 거였다면 제가 수정한 코드는 괜히 수정한 거네요. 이미 원래 소스에 이런 경우를 생각해서 스프라이트에서 프레임 플레이 시간을 각각 다르게 해 준건데......

어쨌든 남의 소스를 보고 나름대로 고쳐보는게 프로그래밍 배우는데 아주 큰 도움이 됩니다.

여러분들도 이 코드를 이용해서 이것저것 고치거나 기능을 덧붙이거나 하면 빨리 실력이 늘고 이 코드도 진짜로 여러분의 코드가 되고 여러분의 자산이 될 거예요.

그럼 다음 시간에 뵐께요......
반응형

스티브 잡스 추모 앱

2011. 11. 21. 23:02 | Posted by 솔웅


반응형

오늘은 누군가가 올린 스티브 잡스 추모 앱을 가지고 공부 해 보겠습니다.

이 앱의 진행은 처음에 애플 인트로 화면이 나오고 조금 있다가 두번째 화면이 나옵니다.
세번째 화면은 로딩 화면이고 그 다음 화면이 스티브 잡스 분향소 이미지 화면입니다.
이 분향소 화면에는 촛불이 있고 유저가 좌측에 있는 버튼을 누르는 동안엔 이 촛불에 불이 켜지게 됩니다.

dsrawat이라는 분이 만들어서 배포한 것인데요...
소스도 같이 공개 했습니다.

이제 부터는 여러 공개된 샘플 코드를 가지고 공부할 생각입니다.
그 첫번째 대상이 스티브 잡스 추모 앱이 됐습니다.

전체 리소스는 아래 파일을 다운 받으시면 됩니다.





main.lua 파일 소스 먼저 보시면....

 --file main.lua

--To Hide the status bar
display.setStatusBar( display.HiddenStatusBar )
--==> 아이폰의 status bar를 없애줍니다.


-- For Importing director.lua class
local director = require("director")
local movieclip = require("movieclip")
uiButton = require("buttonLib")

--==> 화면전환을 위한 클래스 director.lua와 애니메이션 효과를 위한 movieclip.lua 그리고 버튼을 사용하기 위해서 buttonLib.lua 클래스 파일을 require 합니다.

-- For Creating a main group
local mainGroup = display.newGroup()

--==> 객체들을 그룹화 하기 위해 newGroup을 만듭니다. 특히 director 클래스를 사용할 때는 이렇게 그룹화를 해서 display객체들을 관리해야 좋은 화면 전환 효과를 낼 수 있습니다.

-- Start of Main function
local function main()

--==> main() 함수입니다.

     -- Adding the Group from director.lua class
    mainGroup:insert(director.directorView)

--==> 아까 만든 그룹에 director.directorView를 담습니다.
   
local function flash1()
    local myLogo = display.newImage("menubackground/splash.png")
     myLogo.x = 240
    myLogo.y = 160
    myLogo.alpha = 0
    transition.to( myLogo, {time=500, delay=500, alpha=1})
    transition.to( myLogo, {time=500, delay=3500, alpha=0})
end
    timer.performWithDelay(0, flash1)

--==> flash1() 함수입니다. 여기에서는 첫번째 화면 이미지인 splash.png를 표시해 줍니다. 위치를 설정해주고 transition.to로 서서히 이미지가 나타나는 효과를 줍니다.

타이머를 달아서 delay는 0으로 줘서 곧바로 실행하게 하고 이때 flash1함수를 콜해 줍니다.

local function flash2()
    local myLogo1 = display.newImage("menubackground/apple.png")
     myLogo1.x = 240
    myLogo1.y = 160
    myLogo1.alpha=0
    myLogo1.alpha = 0
    transition.to( myLogo1, {time=500, delay=500, alpha=1})
    transition.to( myLogo1, {time=500, delay=3500, alpha=0})
 end
    timer.performWithDelay(3500, flash2)

--==> flash2() 함수입니다. 첫번째 이미지가 서서히 사라지고 난 후 두번째 이미지인 apple.png를 서서히 나타나게 합니다. 그리고 서서히 사라지게 합니다.



    local changeScene = function()
        director:changeScene("loadmainmenu", "fade")
    end

--==> 이 함수는 director클래스의 fade효과를 주면서 loadmainmenu.lua 클래스를 실행 하도록(화면전환) 하는 함수입니다.

    timer.performWithDelay(8000, changeScene)
    --To Change scene withoutany effects
    return true

--==> main()함수의 마지막 부분입니다. 8초 후에 changeScene 함수를 실행 합니다.
end



-- For Running Main Function
main() --==> main함수를 실행합니다.

이 메인 함수가 실행되면 각각의 timer가 실행 될 겁니다. 첫번째는 곧바로 실행되는 첫번째 타이머가 flash1 함수를 실행할 것이고 두번째 타이머는 3.5초 후에 flash2함수를 실행 할 겁니다.

그리고 세번째는 8초후에 실행되는 타이머로 changeScene 함수를 콜해서 다음 화면으로 넘어가도록 할 겁니다.

loadmainmenu.lua 파일 입니다.


module(..., package.seeall)

--==> 처음에 모듈 선언을 함으로서 외부파일에서 불려질 수 있는 모듈임을 알립니다.

-- Main function - MUST return a display.newGroup()
function new() --==> director 클래스에서 사용되는 모듈은 new()함수 내에 위치해야 됩니다. 그리고 display.newGroup()을 return 해야 합니다.
    local localGroup = display.newGroup() --==> 그룹을 만듭니다.
   
    local theTimer
    local loadingImage

--==> theTimer와 loadingImage 변수를 선언만 해 둡니다.
   
    local showLoadingScreen = function()
        loadingImage = display.newImageRect( "menubackground/loading.png", 480, 320 )
        loadingImage.x = 240; loadingImage.y = 160
       
        local goToLevel = function()
            loadingImage:removeSelf()
            director:changeScene( "mainmenupage" )
        end
       
        theTimer = timer.performWithDelay( 1000, goToLevel, 1 )
   
    end

--==> showLoadingScreen 함수입니다. loading.png 이미지 파일을 보여줍니다.

이 함수 안에는 goToLevel이라는 로컬 함수가 있습니다.

이 로컬 함수에서는 loadingImage를 없애고(removeSelf()) director클래스의 changeScene 함수를 이용해서 mainmenupage.lua 클래스에 있는 것을 표현해 줍니다.

theTimer변수에 타이머를 답니다. 1초 후에 goToLevel 함수를 호출하고 이는 1회만 실행 합니다.

 
    showLoadingScreen()

--==> showLoadingScreen()함수를 호출해서 실행 하도록 만듭니다.
   
    unloadMe = function()
        if theTimer then timer.cancel( theTimer );
       
         end
       
        if loadingImage then
            loadingImage:removeSelf()
            loadingImage = nil
        end
    end

--==> unloadMe함수는 theTimer가 있으면 이를 cancel하고 loadingImage가 있으면 이를 없애고 메모리도 풀어 줍니다.
   
    -- MUST return a display.newGroup()
    return localGroup --==> localGroup을 return 합니다. director.lua로 화면전환을 할 때 반드시 해 줘야 합니다.
end

--==> 이렇게 하면 로딩 화면이 1초 정도 떠 있다고 mainmenupage.lua에 있는 내용들이 실행 되겠죠?



 --==> mainmenupage.lua 파일입니다.

module(..., package.seeall) --==> 모듈선언입니다.

local menuGroup=display.newGroup() --==> 그룹을 만듭니다.

 local ui = require("ui") --==> ui.lua 클래스를 이용하기 위해 require합니다.
  local movieclip = require "movieclip" --==> movieclip.lua를 이용하기 위해 require합니다.
  local candle --==> candle변수를 선언합니다.

function new() --==> director.lua를 사용하려면 new()함수를 사용합니다.

local menuGroup=display.newGroup() --==> 위에서 선언했는데 중복되서 선언했네요. 제 생각엔 위에 선언한 것을 지워도 될 거 같습니다.
 -- Background
local background = display.newImage("menubackground/jobs.png")
menuGroup:insert(background)
local localGroup = display.newGroup()
--==> jobs.png 이미지를 display하고 이를 menuGroup에 넣습니다.
 그리고 localGroup을 만듭니다.

candle = movieclip.newAnim{ "candle/candle0.png","candle/candle.png", "candle/candle1.png","candle/candle2.png","candle/candle3.png"}
candle.x=220
candle.y=220
candle.xScale=.4
candle.yScale=.4
candle:stopAtFrame(1)
--==> 촛불 애니메이션 효과를 줍니다. candle 변수에 newAnim을 이용해서 5개의 촛불 이미지를 담습니다. 그리고 위치와 크기를 설정하고 1번 프레임에 stop시켜 놓습니다.
      
    --- ********************************************************* ---
    ---                            BUTTONS                              ---   
    --- ********************************************************* ---
        -->> Set Up "fire" Button with required variables

    --Custom function to execute on began press state
    local function fireBeganFunction()
        print("fire Began State Executed")
        candle:play()
       
    end
--==> candle애니메이션을 play() 시키는 함수입니다.

    --Custom function to execute on released press state
    local function fireReleasedFunction()
        print("fire Released State Executed")
        candle:stopAtFrame(1)
        new()
    end
--==> candle 애니메이션을 1번 프레임에 stop시키는 함수입니다.

    fireBTN = movieclip.newAnim({"fire.png", "fire1.png"}) -- The sequence of images : Should contain a default and pressed state image
    fireBTN.x = 40          
    fireBTN.y = 260
         fireBTN.xScale=.5
        fireBTN.yScale=.5       
--==> fireBTN 변수에 두개의 이미지를 담습니다. (newAnim을 이용해서요...)            
     fireBTN.beganFunction = fireBeganFunction       -- The pointer to the custom function to execute on button began state (If any) Optional
    fireBTN.releasedFunction = fireReleasedFunction -- The pointer to the custom function to execute on button began state (If any) Optional
    fireBTN.removeListenerOnTouch = true            -- If true the library will automatically remove the event listener for you when it is done.
   menuGroup:insert(fireBTN)
--==> menuGroup에 fireBTN을 insert합니다.

    fireBTN:addEventListener("touch", uiButton.handleEvent)
fireBTN에 리스너를 달아서 터치를 하면 위에 선언했던 fireBeganFunction과 fireReleasedFunction을 실행하도록 합니다.

     ------------------------------------------------------

clean = function()
 fireBTN:removeEventListener("touch", uiButton.handleEvent)
 menuGroup:removeSelf()
end
--==> fireBTN의 리스너를 없애고 메뉴그룹에서도 없애는 함수입니다.

     -- MUST return a display.newGroup()
    return localGroup
end
   
========= o ======= o ======== o ======== o =========

다른 사람이 작성한 코드를 보니까 나 같으면 이렇게 했겠다라는 부분도 있고 내가 모르던 방법을 사용해서 새로 배울 수 있는 부분도 있고 그러네요.

시간이 되면 똑같은 앱을 제 방식대로 한번 만들어 보고 싶네요.
만약 이런 앱을 만드는 의뢰를 받았다면 나는 어떻게 만들지 그리고 이 사람이 만든 코드랑 어떻게 다른지 또 어떤점이 더 낫고 어떤 점은 내가 배울 점인지 좀 더 확실하게 알 수 있도록......

첫번째 샘플 코드 분석은 이렇게 마치겠습니다.

질문이나 의견 있으면 언제든지 기탄없이 댓글로 남겨 주세요...

그럼...

 

반응형

ui 버튼이용 하기 ui.newButton

2011. 11. 18. 23:52 | Posted by 솔웅


반응형

오늘은 ui.lua 클래스 파일을 이용해서 이미지 버튼을 만들겠습니다.

아래 파일을 먼저 받으세요.

이 파일을 열어서 분석해 보시면 newButton과 newLable을 이용할 수 있도록 만든 부분을 보실 수 있으실 거예요.




버튼을 만들면 이렇게 나옵니다.

소스를 볼까요?

display.setStatusBar (display.HiddenStatusBar)

require "ui"

local background = display.newImage ("background.png")

peachbutton = ui.newButton{
default = "peach.png",
over = "peach2.png",
x = 80,
y = 200,
}

local textFieldButtonPress = function( event )
    print("Button Pressed")
end

txtFieldButton = ui.newButton{
        default = "peach.png",
        over = "peach2.png",
        onPress = textFieldButtonPress,
        text = "textField",
        x = 240,
        y = 200,
        size = 16,
        emboss = true
}

local titleLabel = ui.newLabel{
        bounds = { 15, 5, 290, 55 },
        text = "Native Display Objects",
        font = native.systemFontBold,
        textColor = { 240, 240, 90, 255 },
        size = 24,
        align = "center"
}

저 위에 이미지에 newLabel을 하나 추가했어요.

사용법은 간단합니다.
우선 ui.lua를 main.lua 파일이 있는 폴더에 같이 넣구요.
require "ui"를 합니다.

코드를 보시면 우선 백그라운드 이미지를 깔았고
첫번째 이미지 버튼을 만들었습니다.
이 버튼의 평상시 상태는 default로 설정된 peach.png 이미지가 나옵니다.
그리고 이 버튼을 누르면 peach2.png 이미지로 바뀌게 됩니다.

그리고 textFieldButtonPress 라는 함수를 만들었는데 이건 두번째 버튼을 클릭하면 호출되는 함수 입니다.

두번째 이미지 버튼은 첫번째 이미지 버튼에 없는게 몇개 있습니다.
우선 onPress = 는 눌렀을 때 함수를 호출합니다.
그리고 text = 버튼 위에 텍스트를 넣을 수 있구요.
size는 텍스트 사이즈 입니다.

이 두번째 이미지를 누르면 textFieldButtonPress 함수가 실행 됩니다.

그리고 마지막 번엔 newLabel 을 넣었습니다.
처음에 bounds ={} 를  이해하려면 ui.lua의 181번째 줄을 보시면 됩니다.

        local bounds = params.bounds
        local left = bounds[1]
        local top = bounds[2]
        local width = bounds[3]
        local height = bounds[4]

이렇게 돼 있는데요. 4개의 인수들이 있고 각각 왼쪽 위 너비 높이를 나타냅니다.

이렇게 ui.lua를 이용해서 이미지 버튼과 이미지 레이블을 사용하는 법을 알아봤습니다.

전체 소스 파일은 위에서 받으 실 수 있습니다.

코로나에서는 이렇게 ui.lua를 사용하지 않고 Widget API에서 버튼 기능을 제공합니다.
하지만 이것은 Corona build 2011.646 이후 버전에서만 가능합니다.

미리 한번 살펴 보면 신택스는 아래와 같습니다.
widget.newButton( [options] )
샘플예제를 보면요.
local widget = require "widget"
 
    local onButtonEvent = function (event )
        if event.phase == "release" then
            print( "You pressed and released a button!" )
        end
    end
 
    local myButton = widget.newButton{
        id = "btn001",
        left = 100,
        top = 200,
        label = "Widget Button",
        width = 150, height = 28,
        cornerRadius = 8,
        onEvent = onButtonEvent
    }
 
    -- Insert button into a group:
    someGroup:insert( myButton.view )
 
    -- Change the button's label text:
    myButton:setLabel( "My Button" )
 
    -- Remove the button
    display.remove( myButton )

widget을 rerquire 하구요. (이 widget은 ui.lua처럼 별도의 파일이 아니라 corona SDK 가 자체적으로 제공하는 겁니다. 물론 646 이후 버전에서요. 그러니까 별도의 파일을 구해서 폴더에 넣을 필요가 없습니다.)

widget.newButton{} 으로 구현합니다.
안에 내용은 id,left,top,lable,width 뭐 이런것들이 있구요.
아주 다양한 파라미터들이 있습니다.
이건 나중에 이 기능을 제가 사용할 수 있을 때 자세히 살펴 보겠습니다.

onEvent = 에 클릭했을 때 실행될 함수를 넣습니다.

아직 안정성이 검증되지 않은 코로나 SDK 버전에 있는 내용입니다.
지금은 Build 2011.591 버전이 공식적으로 배포되고 있습니다.

나중에 646 버전이 공식 인증된 공개 버전이 되고 제가 그 버전을 사용하게 되면 좀 더 자세히 정리해 볼까 합니다.

그럼 즐거운 주말 되세요.
반응형


반응형

오늘은 timer.performWithDelay를 이용해서 시간을 표시하는 소스를 보겠습니다.
일단 1초 단위로 화면을 갱신해 보일 겁니다.

이 소스를 조금 더 손 보시면 스탑와치도 가능 할 거예요.


소스를 볼까요?

display.setStatusBar(display.HiddenStatusBar)

_W = display.contentWidth;
_H = display.contentHeight;

local bg = display.newRect( 0, 0, 320, 480 )

local secsText = 00
local minsText = 0

local timeText = display.newText(minsText.. ":0" ..secsText, _W/2-60, _H/2-60, "Helvetica", 60)
timeText:setTextColor(43,100,154)

local function updateTime (event)
secsText = secsText + 1

if secsText < 10 then
secsText = "0" ..secsText
elseif secsText > 59 then
secsText = 00
minsText = minsText+1
end
timeText.text = minsText .. ":" ..secsText
end
timer.performWithDelay(1000, updateTime, 0)

처음 세 줄은 설명을 건너 뛰겠습니다.

bg 변수에 스크린 크기만한 사각형을 만듭니다.
(칼라가 지정 안 됐으니 디폴트 색인 흰색이 그려질 겁니다.)
그리고 초를 담을 변수와 분을 담을 변수를 만듭니다.

그리고 시간을 표시할 text를 만들고 칼라를 지정합니다.

그 다음에 updateTime 함수가 있습니다
파라미터로 event를 받는 걸로 봐서 어떤 이벤트 리스너에서 호출 할 겁니다.

일단 함수 내용을 볼까요?

위에 초를 담을 변수 secsText에 1을 더합니다.
그러니까 이 함수를 호출할 때마다 1씩 더해 지겠네요.

다음에 secsText가 10 이하이면 sectText 앞에 0을 붙입니다.
즉 secsText가 1 이면 여기서 01로 변환이 됩니다.
그리고 secsText가 59보다 크면 값을 00으로 바꾸고
minsText에 1을 더합니다.

그리고 timeText.text에 minsText:secsText 값을 할당합니다.

여기까지가 함수 updateTime의 내용입니다.

마지막 줄은 이 함수를 1초 단위로 부르는 timer 입니다.

이 소스는 9분 59초까지 1초 단위로 계속 올라가겠네요.
10분이 되면 다시 0:00이 되겠구요.

이 코드를 조금 변환하면 밀리세컨드부터 시간단위까지 나오게 할 수 있겠죠?
버튼을 만들어서 이 버튼을 누르면 updateTime을 불러오는 timer를 멈추게 하고

뭐 이런 기능들을 넣으면 stopWatch 앱이 될 겁니다.

직접 해 보시면 많이 도움이 되실 거예요.

그럼...
반응형


반응형

오늘은 버튼을 누르면 다음 화면이 나오는 기능을 알아보겠습니다.

기본적으로 이 기능은 API 내에 있는 Animation - transitions 를 사용합니다.
(저는 실제 앱 개발에서는 director.lua 클래스를 사용하고 있지만 이 클래스도 기본적으로 transitions 기능으로 구성 돼 있습니다.  director.lua 클래스 사용법도 조만간 정리할 예정입니다.)

transitions에는 아래와 같은 네가지 메소드가 있습니다.
transition.to() : handle = transition.to( target, params )
예) transition.to( square, { time=1500, alpha=0, x=(w-50), y=(h-50), onComplete=listener1 } )

transition.from() : handle = transition.from( target, params )
예) transition.from( square, { time=1500, x=(w-50), y=(h-50), onComplete=listener } )

transition.dissolve() : transition.dissolve( src, dst, duration, delayDuration )

transition.cancel() : transition.cancel(tween)
예) local trans1 = transition.to(currentTarget, { time=400, y=upperLimit, transition=easing.outQuad}) 
transition.cancel(trans1)




위 그림은 화면을 클릭하면 다음 화면으로 바뀌는 앱입니다.
압축파일은 아래에 있습니다.


소스코드를 분석해 보겠습니다.

-- Views Handler App
-- Developed by Carlos Yanez
-- Hide Status Bar
display.setStatusBar(display.HiddenStatusBar)
-- Add Default View
defaultView = display.newImage('defaultView.png')
-- Swap View Function
lastView = {}
local function swapViews(current, new, from)
    lastView = current
    if(from == 'down') then
        transition.from(new, {y = new.height * 2, onComplete = removeLastView})
    elseif(from == 'up') then
        transition.from(new, {y = -new.height, onComplete = removeLastView})
    elseif(from == 'left') then
        transition.from(new, {x = -new.width * 2, onComplete = removeLastView})
    elseif(from == 'right') then
        transition.from(new, {x = new.width * 2, onComplete = removeLastView})
    end
end

-- Remove Last View
removeLastView = {}
function removeLastView()
    lastView:removeSelf()
end

-- Change View Event Function
local modes = {'up', 'down', 'left', 'right'}
local changeView = {}
local changed = false
function changeView:tap(e)
    if(changed == false) then
        secondView = display.newGroup()
        bg = display.newImage('secondViewBg.png')
        button = display.newImage('button.png', 40, 223)

        secondView.insert(secondView, bg)
        secondView.insert(secondView, button)
        secondView:addEventListener('tap', changeView)
       
        swapViews(defaultView, secondView, modes[math.random(1, 4)])
        changed = true
    else
        defaultView = display.newImage('defaultView.png')
        defaultView:addEventListener('tap', changeView)
       
        swapViews(secondView, defaultView, modes[math.random(1, 4)])
        changed = false
    end
end

-- Listener
defaultView:addEventListener('tap', changeView)
 
처음에 statusBar 없애고 defaultView.png를 display합니다.
그리고 lastView 테이블을 선언합니다.

다음엔 swapViews함수가 있습니다. 이 함수는 current,new,from 이렇게 세 인자값을 받습니다.
함수 안에서 하는 일은 아래와 같습니다.
1. 아까 선언했던 lastView 테이블에 current를 넣습니다.
2. from이 down,up,left,right인지 체크가호 그에 따라 new의 좌표를 바꿔줍니다.
    transition이 끝나면 removeLastView 함수를 실행합니다.

다음은 removeLastView 테이블을 선언합니다.
removeLastView함수가 있고 이 함수는 lastView:removeSelf() 를 수행합니다.

다음 단계를 보면요
modes 테이블에 up,down,left,right를 넣습니다.
changeView 테이블을 선언하고 changed를 false로 선언합니다.

다음엔 changeView함수가 있습니다. tap 이벤트 리스너에서 호출될 함수입니다.
이 함수에서 하는 일은 다음과 같습니다.
1. changed가 false이면 secondView 라는 새 그룹을 만들고 secondViewBG.png를 display합니다.
2. button.png를 적당한 위치에 display합니다.
3. secondView그룹에 bg와 button을 insert합니다.
4. secondView그룹에 tab이벤트 리스너를 달고 탭이 이뤄지면 changeView를 호출합니다.
5. swapViews를 호출합니다. 인자로는 defaultView,secondView,modes 중 랜덤하게 선택된 값을 넘겨 줍니다.
6. changed=true로 바꿉니다.
7. changed가 false가 아니면 defaultView에 defaultView.png를 넣습니다.
8. tap 이벤트 리스너를 달고 탭이 일어나면 changeView를 호출합니다.
9. swapViews 함수를 호출하고 4개 인자를 전달합니다.
10. changed를 false로 선언합니다.

그리고 맨 마지막 줄엔 defaultView에 탭 이벤트 리스너를 달고 탭 이벤트가 일어나면 changeView 함수를 호출합니다.

이렇게 하면 버튼을 누를 때마다 화면이 전환되는 효과를 줄 수 있습니다.
화면전환도 위,아래,좌,우 측으로 화면이 이동하면서 바뀝니다.

보시면 아시겠지만 실제로는 다른 화면이 두개 있는 것이 아니라 객체들의 위치를 바꾸면서 화면 전환 효과를 주는 겁니다.

안드로이드의 Activity개념과는 다릅니다.

이 transition기능을 이용해서 다양한 화면 이동 효과를 내 보세요.
반응형


반응형
앱을 사용하다 일정 시간 동안 사용하지 않으면 핸드폰 화면이 black이 됩니다.

오랫동안 사용하지 않아도 화면이 계속 켜져 있는 상태로 둘 수 있는 방법이 있습니다.
system.setIdleTimer( enabled )

디폴트는 true입니다.
system.setIdleTimer( true )

true일 경우 이 idle timer가 작동을 하고 오랫동안 사용이 없으면 스크린이 흐려졌다가 sleep상태로 바뀝니다.

system.setIdleTimer( false )
위와 같이 false로 하면 오랫동안 사용하지 않아도 해당 앱이 계속 켜져있게 됩니다.
(맥이나 윈도우 시뮬레이터에서는 작동하지 않습니다.)

아마 앱을 tilt로 동작시키고 touch는 일어날 필요가 없는 앱이라면 이 기능이 반드시 필요할 수도 있겟네요.

많이 필요한 기능은 아니지만 알아두면 쓸모가 있겠죠?
반응형


반응형
요즘 만드는 앱에 다양한 애니메이션 효과를 사용하고 있습니다.
스피드 콘트롤 할 일이 많아서 찾아봤는데요.

mivieclip은 frame base라 근본적으로 frame 속도를 바꾸지 않는한 speed control 이 힘듭니다. (Sprites는 time base랍니다.)

http://blog.anscamobile.com/2010/06/improved-movieclip-library/ 에 있는 speed control 관련 내용을 볼께요.

하찮은 내용일 수도 있겠지만 코로나로 앱을 개발하면서 꼭 알아두어야 할, 그러지 않으면 반드시 한번은 에너지 낭비를 해야 될 그런 내용이더라구요.
한번쯤 정리해 두는것도 좋을 것 같습니다.

Richard HakinJune 8th, 2010 at 2:59 pm

We desperately need a speed control as the animation just play crazy

앱을 쌈박하게 만들기 위해서는 애니메이션 스피드 조절 기능이 완전 필요합니다.

PaulAugust 3rd, 2010 at 4:41 am

What is the best way to control the speed of the animation?

Would it be a case of using a timer and calling something like

myAnim:nextFrame()

애니메이션의 스피드 조절하는 가장 좋은 방법이 뭐지요?

myAnim:nextFrame() 함수를 타이머를 이용해서 부르는 것이 방법이 될까요?

EvanAugust 3rd, 2010 at 11:21 am

@Paul – your suggestion would probably work well in some cases, although if you had more than a few clips onscreen, you’d want to test it on target devices to see the performance. I don’t think timers are necessarily that expensive, but they might add up if you had a lot of functions constantly polling the system time.

The movieclip library is primarily designed for a Flash-like model, in which there’s a global framerate for everything. For greater timing control, or for complex animation cases, we’d recommend using Game Edition and the sprite-sheet feature.

In addition to using texture memory much more efficiently (one big image rather than lots of little ones), that feature includes an animated-sprite API that lets you set different animation speeds for different sprites, or even for different sequences within the same sprite. Also, it’s a time-based API rather than frame-based, so the total animation time will remain the same even on slower devices that need to drop frames — the engine automatically handles all this under the hood.

@Paul - 당신의 방법이 잘 적용되는 케이스도 있을 거예요. 아마 무비크립이 적거나 특정한 디바이스에서만 테스트를 원한다면 더 그럴거예요. 하지만 내 생각엔 타이머는 앱을 좀 헤비하게 만들것 같네요.

무비클립은 플래쉬를 모델로 디자인 된 겁니다. 기본적으로 전체 frame rate가 있고 이것이 모든 무비클립에 동일하게 적용됩니다. 좀 더 타이밍 콘트롤을 하고 싶거나 복잡한 애니메이션을 원한다면 Game Edition과 Sprite sheet를 사용하기를 권장합니다.

더군다나 sprite API는 메모리도 효율적으로 운용할 수 있어요. 그리고 각 애니메이션 마다 다른 스피드를 줄 수도 있구요. 스프라이트 애니메이션은 time base 입니다. movieclip은 프레임 베이스이구요. 그래서 사양이 낮은 기계에서도 각 애니메이션별 스피드 차이는 동일하게 나타날 겁니다.

TomAugust 16th, 2011 at 8:27 am

@Chan, You should use the Sprite library instead of the Movieclip library because it gives you better control over the animations. You do have a onComplete listener with Sprites.

@Chan, 무비클립 라이브러리 보다는 스프라이트 라이브러리를 이용해야 애니메이션의 속도 컨트롤이 더 수월합니다. 그리고 스프라이트에는 onComplete리스너도 있습니다.

=======  o ===== o ===== o ====== o ====== o ====== o ======

자 이렇게 애니메이션 기능의 스피드 조절을 위해서는 MovieClip보다는 스프라이트를 사용하라는 것이 코로나SDK의 기본 입장입니다.

그런데 Michael Hartlef 라는 개발자가 movieclip.lua를 수정해서 animation speed를 control 할 수 있는 방법을 개발해서 공유하고 있습니다.

 http://developer.anscamobile.com/code/modified-moviecliplua

위 싸이트에 가면 그 소스 코드가 있습니다.

따로 lua파일을 올리니까 이걸 다운 받으셔도 됩니다.

이 파일의 91번째 줄 에 있는 animSpeed =1.0 의 값을 바꾸시면 애니메이션의 속도를 조절 할 수 있습니다.

이것도 movieClip이기 때문에 framebase이고 이 스피드는 모든 애니메이션에 동일하게 적용됩니다.

애니메이션마다 각각 다른 스피드 컨트롤을 해야 된다면 여전히 movieClip보다는 Sprite를 사용하는 것이 좋습니다.

하지만 Michael Hartlef 이 발견한 방법도 아주 유용하네요.
저도 지금 개발하고 있는 앱에 Michael Hartlef이 개발한 방법을 사용하려고 합니다.

위 소스파일 중에 -- added by M.Hartlef June 12th, 2010 이렇게 주석이 달린 부분이 Hartlef가 추가한 부분입니다.

필요하신분은 이 코드 사용하면서 무료로 자기 노력의 결과물을 공유한 Hartlef에게 감사하는 마음을 가지셔야겠죠?

In everything, Give thanks.

그럼
반응형


반응형

오늘 다룰 예제는 작은 원을 드래그해서 큰 원에 닿으면 작은 원의 색을 바뀌게 하는 기능 입니다.

기본적으로 Physics와 Collision 이벤트 리스너를 이용합니다.
그리고 addBody에서 isSensor 기능을 이용하게 됩니다.


이 isSensor 기능이 오늘 보실 새로운 기능입니다. 그리고 두번째 예제에서 preCollision 이벤트도 덤으로 보시겠습니다.


결과 화면을 먼저 보시고 소스코드를 보겠습니다.



display.setStatusBar(display.HiddenStatusBar)

require ( "physics" )
physics.start()
physics.setGravity( 0, 0 )
local hero = display.newCircle( 40, 40, 30 )
hero.name = "hero"
physics.addBody(hero, "dynamic")

local function moveHero (event)
hero.x = event.x
hero.y = event.y
end
hero:addEventListener("touch", moveHero)

local colorSensor = display.newCircle( 160, 240, 80 )
physics.addBody(colorSensor, {isSensor = true})
colorSensor.alpha = 0.2

colorSensor:addEventListener("collision", colorSensor)
function colorSensor:collision (event)
if event.other.name == "hero" and event.phase == "began" then
red = math.random(0,255)
green = math.random(0,255)
blue = math.random(0,255)
hero:setFillColor(red, green, blue)
end
end

소스를 보시면 우선 status바를 없애고 physics를 require하고 중력을 0으로 합니다.
나중에 원 두개 다 dynamic으로 addBody를 할 거니까 중력을 0으로 하지 않으면 밑으로 떨어지겠죠?

그리고 hero라는 이름으로 작은 원을 만들고 name을 정해주고 dynamic으로 addBody를 해 줍니다.

이 작은 원에 touch 리스너 이벤트를 달아서 touch 한 지점에 위치하게 됩니다.
그러면 손가락으로 잡고 끌면 따라 오겠네요.

다음엔 큰 원을 만들고 addBody에서 isSensor = true로 선언합니다.

이 큰 원에 collision이벤트를 줍니다.
이 이벤트에서 불러오는 함수는 (colorSensor) event.other.name이 hero이고 이벤트가 시작 됐을 때 hero.setFillColor로 작은 원의 색을 바꿔 줍니다.

간단하죠?

여기서 isSensor를 false 로 하면 어떻게 될까요?
그러면 둘 다 dynamic으로 addBody를 했기 때문에 둘이 부딪히면 큰 원이 밀려 날 겁니다.

isSensor를 true로 한다는 얘기는 physics 객체가 와서 부딪혀도 밀려나지않고 제자리에서 센서의 역할만 한다는 의미입니다.

한가지만 더 볼까요?

이번 예제는 노란 사각형이 위에서 떨어지는데 첫번째 흰 줄은 그냥 통과하고 두번째 흰 줄에서 걸리는 프로그램 입니다.

local physics = require("physics")
physics.start()
display.setStatusBar( display.HiddenStatusBar )
 
local platform1 = display.newRect( 20, 200, 280, 15 )
platform1.myName = "platform1"
physics.addBody(platform1, "static")
 
local platform2 = display.newRect( 20, 320, 280, 15 )
platform2.myName = "platform2"
physics.addBody(platform2, "static")
 
local box = display.newRect( 20, 20, 50, 50 )
box:setFillColor(255,255,0,255)
box.myName = "box"
physics.addBody(box)
 
local function onLocalPreCollision( self, event )
        -- Let box pass through platform 1
        local platform = event.other
        if platform.myName == "platform1" then
                platform.isSensor = true
        end
end
 
box.preCollision = onLocalPreCollision
box:addEventListener( "preCollision", box )

첫번째 세줄은 그냥 넘어가겠습니다.
다음은 두개의 긴 사각형을 만들고 모두 static으로 선언합니다.
그리고 각각 myName에 이름을 할당합니다.

그리고 노란 정사각형을 만들로 addBody를 합니다. 디폴트로 dynamic이 선언됩니다.

여기에 노란 정사각형에 preCollision 이벤트를 달로 이 preCollision은 onLocalPreCollision 함수를 콜 합니다.

preCollision은 충돌하기 직전에 호출 되는 이벤트 입니다.
그러니까 onLocalPreCollision은 충돌되기 직전에 이것이 platform1 이면 isSensor를 true로 바꿔서 그냥 통과 시켜 버리게 됩니다.

오늘 배운 기능도 꽤 유용한 기능이네요.

잘 알아두면 게임 만들 때 아주 요긴하게 쓰일 것 같습니다.

그럼 다음 시간에 또 뵐께요.

반응형


반응형
간단하지만 유용한 팁들

1. 애니메이션 일시 정지 시키고 다시 시작 시키기

local logo = display.newImage( "endinggreen.png", 100, 140 )
logo.isPaused = true;
function logo:enterFrame(event)
        -- do something like make the logo bounce around the edges of the screen
        logo:rotate(-5)
end
 
Runtime:addEventListener( "enterFrame", logo );
 
function logo:tap( event )
        if (logo.isPaused) then -- initially nil which is false anyways
                Runtime:removeEventListener( "enterFrame", self )
                logo.isPaused=false;
        else
                Runtime:addEventListener( "enterFrame", self )
                logo.isPaused = true;
        end
        return true -- we handled the event so don't propagate
end
 
logo:addEventListener( "tap", logo )

위 코드는 앱을 실행하면 이미지가 회전하도록 만들었습니다.
1. 이미지 logo를 만들고 isPaused=true를 해 준 상태에서 Runtime 이벤트 리스너로 logo:enterFrame 함수를 실행시키비다.
2. logo:enterFrame 함수에서는 이미지를 rotate 시켜 줍니다.

그 다음은 이미지를 한번 tap하면 회전이 정지하고 다시 tap하면 회전하도록 합니다.
1. logo 이미지에 이벤트 리스너 tap을 달고 logo 함수를 호출함
2. logo:tap 함수에서는 isPaused 가 true이면 회전을 멈추고 isPaused를 false로 만들고
   만약 isPaused가 false이면 Runtime enterFrame 리스너를 다시 시작합니다.

이 소스 코드는 http://developer.anscamobile.com/content/application-programming-guide-common-design-tasks 에 있습니다.
그런데 이 코드로는 내가 기대한 대로 안 되서 약간 수정했으니 참고하세요.

2. Managing Screen

인트로 화면 - 메인 화면 - 게임 화면 등 각 스크린 별 이동이 있어야 할 때 Group object를 사용하면 좋습니다.
각 화면별로 그룹을 만들어서 다음 화면으로 넘어갈 때 transitions를 사용하면 화면 이동의 효과가 있습니다.
저의 경우는 이런 화면 이동을 쉽게 하도록 도와주는 director.lua를 require해서 사용하고 있습니다.
저는 단지 director.lua의 함수를 불러와 사용하기 때문에 transition 기능은 따로 코딩하지 않습니다.
director.lua 사용법은 나중에 따로 다루도록 하겠습니다.

3. 앱 시작 종료 시 데이터 저장하기

local path = system.pathForFile( "data.txt", system.DocumentsDirectory )
 
-- io.open opens a file at path. returns nil if no file found
local file = io.open( path, "r" )
if file then
   -- read all contents of file into a string
   local contents = file:read( "*a" )
   print( "Contents of " .. path .. "\n" .. contents )
   io.close( file )
else
   -- create file b/c it doesn't exist yet
   file = io.open( path, "w" )
   local numbers = {1,2,3,4,5,6,7,8,9}
   file:write( "Feed me data!\n", numbers[1], numbers[2], "\n" )
   for _,v in ipairs( numbers ) do file:write( v, " " ) end
   file:write( "\nNo more data\n" )
   io.close( file )
end



위 코드는 게임 등을 만들 때 점수나 기타 저장 할 사항들을 저장하는 방법을 보여줍니다.
적당한 시점에 데이터들을 파일로 저장하고 다음 앱을 실행 할 때 불러와서 이어서 할 수 있도록 할 수 있습니다.
Corona DOC 에 소개 돼 있는 테크닉이긴 한데 그리 특별한 테크닉은 아니네요.
데이터가 많을 경우는 SQLite를 사용해도 되겠죠?

위 코드를 활용해서 Runtime system 이벤트 리스너로 앱 시작할 때 혹은 앱이 종료할 때 데이터를 저장할 수 있습니다.

local function shouldResume()
        -- return true or false depending on whether we need to resume
end
 
local function onSystemEvent( event )
        if event.type == "applicationExit" then
                -- save stuff to disk
        elseif event.type == "applicationStart" then
                if shouldResume() then
                        -- load stuff off disk
                else
                        -- start app up normally
                end
        end
end
 
Runtime:addEventListener( "system", onSystemEvent );


system 이벤트에서 event.type 이 applicationExit일 때나 applicationStart 일 때 어떠한 행위를 하도록 핸들링 하시면 됩니다.


========= o ========= o ========= o ========= o =========

이상으로 총 36강에 걸쳐 Ansca Mobile의 Corona SDK 웹 사이트에 있는 매뉴얼인 Corona DOC 를 다뤘습니다.
원본은 http://developer.anscamobile.com/resources/docs 에 있습니다.

이제 기본 교과서를 뗀 셈입니다.
다음엔 참고서를 가지고 좀 더 실용적인 응용방법을 터득해야겠죠?

지금 제가 개발 하면서 얻은 TIP은 따로 카테고리를 만들어서 소개해 드리고 있습니다.
그리고 개발을 편리하게 해 주는 3rd Party 제품들 소개 및 사용법 알아보는 코너도 괜찮을 것 같구요.
이것 외에 Corona SDK 에서 제공하는 기본 샘플 예제 분석 이나 다른 공개된 예제 분석 카테고리를 별도로 만들까 합니다.
남들이 짜 놓은 코드를 분석하는 것도 많은 도움이 됩니다.


혹시 여러분 중에서도 분석을 원하시는 다른 샘플 코드가 있으면 보내주세요.
같이 분석해 보죠.

제 이메일은 solkit2011@yahoo.com 입니다.

그리고 코드 분석 외에 다른 카테고리를 만들어서 공부하면 좋겠다는 의견도 있으면 댓글에 달아 주세요.
그러면 제 공부하고 또 그 경험을 다른 많은 분들과 공유하는데 많은 도움이 될 것 같습니다.

아무쪼록 제 글이 여러분들에게 조금이나마 도움이 되기를 바랍니다.

다음에 다른 카테고리에서 만나뵙겠습니다.

감사합니다.

P.S. 이 Corona DOC 카테고리에 있는 강좌 중에도 질문이 있으시면 댓글에 달아주세요.
성실히 답변해 드릴꼐요...

반응형