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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

얼마전 KOW님 질문에 대한 corona sdk 의 답변이었죠?


코로나로 개발하면서 안드로이드의 메뉴 버튼 클릭했을 때 이것을 콘트롤 할 수 있느냐는 거요.

대답은 event.keyName API를 보라는 거였는데요.


그 document를 아래 번역합니다.

예제 소스도 하나 만들었습니다.


event.keyName

Description:

"key" 리스너를 사용해서 눌려진 navigation key 의 이름을 스트링으로 얻습니다. key의 state (up,down)에 대한 사항은 event.phase를 보세요.

Note : home 하고 text 키들 (A-Z,0-9,punctuation)을 capture 될 수 없습니다.

** 안드로이드 디바이스에만 해당 됩니다.***


Syntax: keyName = event.keyName


Example:

-- Key listener
local function onKeyEvent( event )
        local phase = event.phase
        local keyName = event.keyName
        eventTxt.text = "("..phase.." , " .. keyName ..")"
 
        -- we handled the event, so return true.
        -- for default behavior, return false.
        return true
end
 
-- Add the key callback
Runtime:addEventListener( "key", onKeyEvent );


Note : keyEvent 리스너에서 false를 사용하면 해당 키의 디폴트 액션이 실행 됩니다.


Parameters: 없음


Returns: string


눌려진 navigation key의 이름이 return 됩니다 : "back", "search", "menu", "volumeUp", "volumeDown".

The D-Pad/Trackball key strings 는 "up", "down", "left", "right", "center" 가 return 됩니다

Note: home 키는 캡쳐 될 수 없습니다.


안드로이드 디바이스에서만 가능하고 코로나 SDK Build 2011.559 이상에서만 작동 합니다.

   

이상입니다.





위 소스를 조금 변경해서 아래 샘플 코드를 만들어 봤습니다.


-- Key listener
    _W = display.contentWidth;
    _H = display.contentHeight;
local txtPhase, txtKeyName, haveFun

txtPhase = display.newText( "Phase ", _W/2, _H/5, native.systemFont, 32 )
txtKeyName = display.newText( "KeyName : ", _W/2, _H/3, native.systemFont, 32 )
haveFun = display.newText( "Move", _W/8, _H/2, native.systemFont, 32 )

local function onKeyEvent( event )
        local phase = event.phase
        local keyName = event.keyName

        txtPhase.text = phase;
        txtKeyName.text = keyName;

        haveFun.x = haveFun.x + 50;
        if(haveFun.x > _W) then haveFun.x = 0 end
         -- we handled the event, so return true.
        -- for default behavior, return false.
        return true
end
 
-- Add the key callback
Runtime:addEventListener( "key", onKeyEvent );


main.lua에 이 소스를 붙여 넣고 실행하시면 화면에 phase와 keyName이 뜰겁니다.

제 디바이스에서 menu , back, search, volumeUp, volumeDown 등이 뜨는 거 확인 했어요.

마지막에 haveFun은 그냥 키가 눌려질 때 글자가 움직이도록 해 봤어요. 심심해서....


KOW님 덕분에 저도 몰랐던 사실을 알게 됬네요.


감사합니다.


반응형

Corona SDK로부터 받은 답변

2012. 4. 18. 07:35 | Posted by 솔웅


반응형

안녕하세요?

제가 이 블로그에서 받은 Corona SDK 와 관련된 질문 댓글 중 제 수준에서 답할 수 없는 것을 두건 Corona SDK에 문의 했었습니다.

오늘 아침 (4.17)에 보냈는데 오후에 답변이 왔네요.

feedback이 정말 좋네요. 고맙게도...


지금부터는 여러분들이 올리는 질문 (코로나 SDK에 대해) 에 더 성실히 답하고 모르는 건 이렇게 Corona SDK에 질문을 할 테니까 질문 많이 많이 올려 주세요.


오늘은 Kow님이 올리신 질문과 이상봉님께서 보내신 질문을 문의했었습니다.


오늘 온 답변 메일은 아래와 같습니다.





Changsoo,


Here are some answers to your questions from one of our team members:
아래 우리 팀원 중 한명이 당신이 보낸 질문에 대한 답변을 해 왔습니다.


1. 2012.03.28  KOW 
    Can I control 'MENU' Button on Android device with Corona SDK?  


You can override the Menu key by using Corona key listener as documented here...
Corona key 리스너를 사용해서 Menu를 오버라이드 할 수 있습니다. 문서는 아래에 있습니다.

 
2. 2012.03.26  Lee,Sangbong
    Regarding Image Sheets. If I use MASK on an object, screen becomes black except the object on Galaxy 2 LTE. There is no problem on other device. 



This sounds like the masking issue that was introduced in build 759 where textures are disappearing on devices with low-end graphics hardware.  It typically happens on devices with whose OpenGL max texture units are 2, the absolute minimum the OpenGL spec allows. We will work on this soon.

이 건은 빌드 759에서 나왔던 이슈 같습니다. low-end graphics 하드웨어에서 디바이스에서 texture가 사라지는 문제였는데요. 이 이슈는 특히  OpenGL max texture units 가 2인 디바이스에서 일어났습니다. 이 건에 대해서는 곧 해결하도록 하겠습니다.

You should be able to work-around this issue by reverting to build #758.

아마 빌드 758로 되돌아 가시면 이 현상은 일어나지 않을 겁니다.

이 상입니다.

이상봉님이 질문하신 내용은 빌드 759 이상에서 나오는 문제 같습니다. 오히려 그 이전 버전인 빌드 758로 돌아가면 그 문제가 없을 거라네요.

그리고 지금 그 버그를 수정중에 있다니까 조만간 그 정된 버전의 Corona SDK를  다운 받아 사용하실 수 있게 될 것 같습니다.

다른 분들도 질문이나 건의 또는 건설적인 의견이 있으면 댓글 달아 주세요.

Corona SDK 측에서 이렇게 확실히 신속하게 응답을 해 주니까 저도 여러분에게 좋은 답변을 드릴 수 있을 것 같습니다.

1번 KOW님의 질문에 대한 답변에서 보라고 했던 document는 제가 곧바로 번역해서 올리겠습니다.
혹시 테스트까지 하면 샘플을 올릴 수도 있겠죠?
아님 여러분 중에서 테스트 해 보신 후 성공하시면 샘플을 보내 주세요.

서로 공유하면서 필요한 자료를 share 하면 많은 도움이 될 것 같습니다.

감사합니다.



추천~~꾸욱~~


반응형


반응형

안녕하세요?


Corona SDK 명예 대사가 된 이후로 제대로 역할을 못하는 것 같네요.

여러분들의 많은 질문에도 답변 못하는 경우가 많구요.


일단 할 수 있는 것 부터 해야겠습니다.


여러분들이 Corona SDK 에 대해서 댓글로 질문 한 것 중 제가 답하기 어려운 것은 Corona SDK에 질문을 토스 하겠습니다.


그리고 답변을 받으면 이 블로그에 그 답변 내용을 올릴께요.


질문 이외에 코로나 SDK와 관련된 어떤 의견이나 제안사항도 마찬가자로 전달하겠습니다.


일단 이번에는 3월달에 올라온 질문 2가지를 Corona SDK CEO 인 Walter 하고 명예대사 담당자인 David 한테 보냈습니다.


아래 그 보낸 메일 내용입니다.


혹시 제가 빠뜨리거나 오래전에 올린 댓글 중에 제가 미처 답변 제대로 못 드린것도 있을 수 있습니다. 그 분들께는 죄송합니다. 제가 너무 일을 미루다가 발생한 일입니다.


지금부터는 정기적으로 질문 사항 정리해서 전달할 계획이니 질문사항이나 의견 있으시면 언제든지 댓글에 달아 주세요.





Dear Walter and David

I am Changsoo Park one of the Ambassador of Corona SDK.
I have blog http://coronasdk.tistory.com and I post Tutorial, DOC, Corona SDK News etc. on that blog in Korean.
Many people visit my blog and ask questions or suggest their opinion for Corona SDK.
I'd like to send you the questions and suggestions once a month and When I get back reply then I will let them know.

I am sending 2 questions at this time. 

Please check it out and reply soon .

1. 2012.03.28  KOW 
    Can I control 'MENU' Button on Android device with Corona SDK?  
2. 2012.03.26  Lee,Sangbong
    Regarding Image Sheets. If I use MASK on an object, screen becomes black except the object on Galaxy 2 LTE. There is no problem on other device. 

Best Regards

Changsoo (Douglas) Park


반응형


반응형

오늘은 Corona SDK 를 만든 회사인 Ansca의 CEO 강연을 하나 소개해 드리겠습니다.
얼마전 Carlos 공동 창업자가 2선으로 물러나면서 단독 CEO 가 된 Walter Luh 가 스탠포드 대학에서 한 강연입니다.

Corona SDK는 Lua 라는 Script Language를 사용하고 있는데요. 이 Lua 는 요즘 게임에 많이 사용되는 언어입니다.
앵그리버드도 이 Lua로 만든 겁니다.

이 Lua Language를 만든 사람이 Roberto Ierusalimschy 인데요. 스탠포드에서 교수로 있나 봅니다.
이 Roberto가 자신의 수업에 Walter를 초청해서 대신 수업을 진행한 화면입니다.

이 동영상을 보시면 Corona SDK에 대한 이해를 도울 수 있을 겁니다. 스탠포드 대학 학생들이 수업하는 분위기도 느낄 수 있구요.
한번 스탠포드 대학 수업에 같이 참여해 보시죠.





반응형


반응형

코로나에서 이번에 업데이트된 Daily build 2012.782, Daily build 2012.783 에서 몇가지 API를 변경 했습니다.

아래 그 변경된 내용을 소개해 드리겠습니다.



Storyboard, Network Changes, and More!


최근의 Daily Builds 를 눈여겨 보시지 않으신 분들께 안내 말씀 드리겠습니다. 몇가지 API 가 바꿘것들에 대해 소개합니다. 실제로 바뀐 내용들은 많이 있지만 이 글에서 다룰 수 있는 내용만 다루겠습니다. 유료 고객이시면 Daily Builds summary 를 보시면 변경된 사항을 자세히 보실 수 있을 겁니다.

Network API Changes

build 2012.782 에서는  network.request()network.download() 에 새로운 HTTP 메소드 지원을 하도록 기능을 확장했습니다.  (PUT,DELETE,HEAD - 기존의 POST와 GET은 여전히 사용가능 합니다. -)

이 기능 확장으로 코로나의 네트워킹 기능이 REST API에 좀 더 어울릴 수 있도록 함으로서 웹상의 여러 개발 API들을 더 많이 활용해서 코로나 앱을 개발 할 수 있도록 했습니다.


media.show() + Android = Better

buils 2012.783 에서 media.show() API가 코로나 internal camera 기능말고도 안드로이드 디바이스의 디폴트 카메라 앱을 사용할 수 있도록 확장됐습니다. 이를 위해서는 "WRITE_EXTERNAL_STORAGE" 퍼미션이 필요합니다. 물론 그 디바이스에는 Enternal storage 가 있어야 겠죠.

안드로이드의 디바이스 카메라를 사용해서 안드로이드 앱을 개발하려고 하시는 분들에게는 아주 좋은 뉴스가 되겠죠? 

Storyboard API Changes

Storyboard API에 몇가지 변경된 사항들이 있습니다. 큰 것은 아니지만 아주 유용한 추가 기능도 있구요.

“willEnterScene” and “didExitScene”

스토리보드 이벤트 이름이 바뀌었습니다. enterBegan 이 willEnterScene으로 바뀌었고 exitEnded 가 didExitScene으로 바뀌었습니다.  이전의 이름은 해당 기능에 대해 딱 맞는 이름이 아니었습니다. 그리고 다른 이벤트와도 이름이 너무 비슷했구요.  Storyboard Scene Events Explained  document 에도 이 바뀐 내용이 적용되었습니다.


New Storyboard Functions


스토리보드에 두개의 새로운 function이 추기 됐습니다. storyboard.loadScene(), storyboard.reloadScene(), 과 storyboard.getCurrentSceneName()      

두 함수인데요. 자세한 설명은 위 함수를 클릭하시면 보실 수 있습니다.


storyboard.loadScene()은 어떤 scene으로 화면전환을 하지 않은 채 그 scene을 load 해야 할 경우 사용할 수 있습니다. (전체 scene을 로드할 수도 있고 특정 모듈을 로드할 수도 있습니다. 설명서를 보시면 그 방법을 자세히 아실 수 있습니다.)  이 기능은 아주 heavy한 scene을 로드할 경우 미리 로드함으로서 화면전환을 자연스럽게 하고자 할 때 사용 하시면 유용하실 겁니다.

Storyboard 변경사항은 build 2012.782 버전 이상에서만 적용됩니다.


이 사항들은 최근의 Daily Build에서 바뀐 내용들의 일부분일 뿐입니다. 새로운 API를 사용해서 sprite들을 trim 하는 기능도 있구요. 그리고 다른 작은 추가되는 사항들과 변경되는 사항들이 있습니다.


이 기능들은 최근의 daily build 에서 사용 가능하시구요. 이 버전은 유료 사용자만이 사용하실 수 있읍니다.


반응형

Moving On and Thanks (Carlos icaza)

2012. 4. 15. 11:05 | Posted by 솔웅


반응형

4월 13일 Corona SDK 를 공동 창업했던 Carlos icaza 가 일선에서 물러나서 고문역할을 하게 됐습니다.


중국계 개발자인 Walter Luh 와 Carlos icaza는 2008년에 공동으로 Ansca를 창업해서 Corona SDK 를 배포하기 시작했는데요. (원래는 Adobe - 어도비 -  사의  Flash 개발 팀에 있었다고 합니다.)

짧은 4년 간동안 Corona SDK 를 아주 성공적으로 이끌어 왔는데요.

이제 일선에서 물러나서 Ansca (Corona SDK)는 Walter Luh 중심으로 운영이 될 것 같습니다.


작년에 작은 질문을 Carlos에게  메일로 보냈더니 금방 답장이 와서 놀랐었거든요. 덕분에 저도 더 관심을 갖고 공부하게 됐었습니다.


얼마전까지 홍길동처럼 여기저기 미국 전역을 다니면서 meetup 을 진행하던 아주 의욕적이고 활동적인 모습이 기억 나네요.


Carlos 가 떠나면서 남긴 편지를 소개해 드릴께요.




Moving On and Thanks


Saying goodbye is always hard, but I have decided this is the right time for me to move on from Ansca’s day-to-day operations. Now I don’t want you all to get worked up. This is sudden, but it’s for personal reasons. And I’ll still be around as an advisor to the company – which is as strong as it has ever been.


이별인사를 하는 것은 언제나 힘듭니다. 하지만 지금이 Ansca의 일선에서 물러나야할 바로 그 시간이라고 마음 먹었습니다. 동요하지는 마세요. 개인적인 일로 갑작스럽게 결정 된 겁니다. 그리고 앞으로도 계속 회사의 고문으로서 열심히 도움을 줄 것입니다.


When we started on this crazy journey of ours 4 years ago, no one knew who we were. Walter and I were just two individuals interested in mobile who decided to start a company in mid-2008 to create apps for our own.


4년동안의 이 미친 여정을 시작할 때 우리가 누군지 아무도 몰랐습니다. 월터와 나 이렇게 단 둘이 모바일에 관심을 가졌고 오리의 기술로 앱을 개발하기 위해 2008년 중반 쯤 회사를 창업하기로 결정했습니다.


I had no clue where the idea of making mobile apps would take us, but it has taken us where we are today. And I am very proud of what we have become, and, like I always say, “The Journey Is The Reward”, and this has been one hell of a fulfilling journey. It is truly the reward.


처음에는 모바일 앱을 만든다는 것 자체가 막막했지만 그 일을 시작함으로서 지금의 우리가 있을 수 있었습니다. 그리고 저는 지금까지 우리가 한 일에 대해서 아주 긍지를 가집니다. 제가 항상 얘기하듯이 "그 과정이 바로 그 성과자체이다" 라고 생각합니다. 이 여정은 풍요로운 성취의 여정이었고 그것이 진정한 우리의 성과입니다.


To the Corona community, thank you for being so incredibly passionate and supportive, don’t worry, I’ll be around on twitter, and other venues.

To the previous and current Ansca team members, continue to change the world one developer at a time, and continue to change the world of the developer.


코로나 커뮤니티에 말씀 드리고 싶습니다. 그동안 열정적으로 성원해 주심에 진심으로 감사드립니다. 염려 마세요. 저는 트위터를 통해서 그리고 다른 곳에서도 계속 만나실 수 있을 겁니다. 이전의 그리고 현재의 Ansca 팀 멤버들에게 말씀드리고 싶습니다. 계속해서 세상을 바꿔주세요. 한번에 한 개발자 씩. 그리고 계속 개발자의 세상을 바꿔주세요.

Carlos


반응형

Tutorial: Detecting Touches in Corona

2012. 4. 12. 22:03 | Posted by 솔웅


반응형

Tutorial: Detecting Touches in Corona

오늘날 가장 구별되는 모바일 디바이스의 특징은 Touch screen 이라는 겁니다. 그러니까 개발자로서 코로나로 만드는 앱에 대해 유저에게 좀 더 리얼하고 풍부한 효과를 주기 위해  어떻게 user의 touch를 감지하는지를 정확히 아는 것은 중요합니다.

이 touch 에 대해 여러분들이 생각하는 것보다 더 많은 생각해야 할 것이 있습니다. 이 튜도리얼에서는 단지 touch를 어떻게 감지하는지 이외에도 user touch의 다양한 경우에 대해서도 생각해 보고 이것을 앎으로서 구현하고자 하는 기능을 좀 더 정확히 구현할 수 있도록 도움을 드리고자 합니다.

이 튜토리얼을 끝내시게 되면 touch phases, focus, dragging 같은 것들에 대해 좀 더 친숙해 지실겁니다. 이 튜토리얼은 가장 single touch 에 대해서만 다루겠습니다. Multi-touch는 좀 더 깊이 들어가야 할 주제입니다. 이 주제에 대해서는 나중에 다루겠습니다. 그 멀티 터치에 대해서 알기 위해서도 이 기본 touch 이벤트에대해 먼저 이해하는 것이 중요합니다.

만약 이 글을 읽고 계시는 분이 Corona event들에 대해 친숙하지 않으시다면 Corona Event Model Explained 를 먼저 읽어 보시기를 권합니다. 그 글을 읽으시면 이벤트와 리스너에 대해 이해하실 수 있을 겁니다. 그 글을 통해서 touch event에 대한 기본적인 내용도 아실 수 있습니다. event model에 대해 읽어 보신 후 이 튜토리얼로 돌아와서 보신다면 완벽하게 이해하실 수 있을 겁니다.





Detecting User Touches

User touch는 두가지 방법으로 감지 됩니다. 각 객체단위로 감지될 수 있고 전체 스크린 단위로 감지될 수 있습니다. (Runtime이나 global touch 가 전체 스크린 단위에서 감지 되는 겁니다.) 이 두가지가 어떻게 다른지에 대해 이해하는 것은 아주 중요합니다.

Per-object touches

우선 다른 특정한 이벤트가 감지되기 전에 이벤트를 add 해야 합니다. add 방법은 두가지 방법이 있습니다. table 리스너를 이용하던가 function 리스너를 이용하는 방법입니다.
아래 두개에 대한 예제가 있습니다.

Table Listener A와 Table Listener B는 기본적으로 같습니다. 약간의 다른점만이 있을 뿐입니다. 예제를 보면서 그 다른 점을 공부해 보세요.


* Table Listener A


local obj = display.newImage( "image.png" )

-- touch listener
function obj:touch( event )
    -- 'self' parameter exists via the ':' in function definition
end

-- begin detecting touches
obj:addEventListener( "touch", obj )


* Table Listener B

local obj = display.newImage( "image.png" )

-- touch listener
local function onObjectTouch( self, event )
    -- 'self' parameter must be defined via function argument
end

-- begin detecting touches
obj.touch = onObjectTouch
obj:addEventListener( "touch", obj )


* Function Listener

local obj = display.newImage( "image.png" )

-- touch listener
local function onObjectTouch( event )
    -- no 'self' parameter exists in this scenario
end

-- begin detecting touches
obj:addEventListener( "touch", onObjectTouch )


리스너 함수 안에서 어떤 일이 벌어지고 있는지에 대해서는 잠시 후에 다루겠습니다. 여기서는 객체에 어떻게 리스너가 add 되는지에 대해 주목해 주세요. 위 예제는 코로나에서 touch 이벤트에 대해 리스너를 다는 모든 방법에 대해 보여줍니다. 세번째 예제를 예를 들어 설명해 볼께요.

"유저가 obj를 touch 하면 onObjectTouch() 함수를 call 한다."


NOTE : 한 번 touch를 하면 touch event는 여러번 dispatch 됩니다. 그 이유는 touch 이벤트 안에는 여러개의 phases가 있기 때문입니다. 이 부분은 중요합니다. 잠시 후에 여기에 대해서 자세히 다루겠습니다.

Runtime Touches

여러분은 또한 Runtime 에 global 하게 touch 리스너를 add 할 수 있습니다. 그렇게 하면 전체 screen에서 touch 이벤트를 감지하게 될 겁니다. Runtime touch는 function listener 만 사용할 수 있습니다. 아래 예제가 있습니다.

local function onScreenTouch( event )
    -- no 'self' parameter
end

-- begin listening for screen touches
Runtime:addEventListener( "touch", onScreenTouch )


How to STOP detecting touches

특정 object에 대한 (global Runtime object도 포함해서) touch 이벤트 listening을 중지하시려면 addEventListener() 하셨던 방법대로 간단히 removeEventListener()를 call 하시면 됩니다.

-- example 1:
obj:removeEventListener( "touch", obj )

-- example 2:
obj:removeEventListener( "touch", onObjectTouch )

-- example3 :
Runtime:removeEventListener( "touch", onScreenTouch )


VERY IMPORTANT: Runtime 이벤트 리스너는 절대 자동적으로 remove 되지 않습니다. 만약 global Runtime object에 어떤 리스너를 add 하셨다면 이 리스너가 필요 없게 될 때 반드시 여러분이 직접 remove 해 주셔야 합니다. 그렇지 않으면 버그나 충돌이 일어날 수 있습니다.

개별적인 객체에 add된 이벤트 리스너는 그 객체(object)가 remove 될 때 자동적으로 remove 됩니다. 하지만 그 객체에 있는 리스너가 필요 없을 때 여러분이 직접 remove 해 주실것을 권장합니다. 항상 같은 객체에 같은 이벤트를 여러번 add 하는 일이 없도록 주의하셔야 합니다.

Touch Event Phases

초보 코로나 개발자분들은 touch listener를 사용하면서 몇가지 문제점에 당면하기 쉽습니다. 왜냐하면 유저가 한번 touch 할 때마다 listener fucntion이 한번만 call 될 걸로 기대하고 있기 때문입니다. 하지만 유저가 한번 Touch 한다고 그 리스너 함수가 한번만 call 되는 것이 아닙니다. 터치 이벤트가 발생하면 아래와 같은 phases 가 있습니다.

    began – 유저가 touch 하는 순간에 감지 됨
    moved – 유저가 터치한 손가락을 움직일 때 감지 됨
    ended & cancelled – 유저가 터치한 손가락을 화면에서 뗄 때 감지됨. 혹은 어떤 이유에서건 이 touch 이벤트가 cancel 됐을 때 감지 됨


이 touch phase가 감지될 때마다 지정한 터치 이벤트 리스너 함수가 call 되는 것입니다. 유저가 터치할 때마다 최소한 두번 내지는 세번 이 함수가 call 되는 것입니다.

그렇기 때문에 여러분들은 터치 했을 때 구현될 동작들이 어떤 phase에서 할 것인지 결정 하셔야 합니다. 그리고 나서 각 phase가 일어날 때 그 동작을 하도록 코딩을 하셔야 합니다. 아래 그 예제가 있습니다.

local function onObjectTouch( self, event )
    if event.phase == "began" then

        -- Touch has began

    elseif event.phase == "moved" then

        -- User has moved their finger, while touching

    elseif event.phase == "ended" or event.phase == "cancelled" then

        -- Touch has ended; user has lifted their finger
    end

    return true    -- IMPORTANT
end


위 예제 처럼 각 phase 를 if 문에서 감지하고 해당 phase에 여러분들이 넣고 싶은 동작들을 넣으시면 됩니다. 한번 터치 할 때마다 4가지 phase가 발생하고 이 phase가 발생할 때마다 onObjectTouch 함수가 call 되는 겁니다. 위의 예제처럼 대부분 ended와 cancelled phase는 같이 다룹니다.

To return true, or not to—THAT is the question.

위 예제 마지막에 보면 제가 OMPORTANT라고 주석을 단 것을 보실 수 있을 겁니다. 함수 끝에는 이와 같이 true 나 false 가 return 되어야 합니다.

touch 리스너가 true를 return 하면 그 touch 가 successful 하다는 의미입니다. touch 된 그 객체는 그 시간에 touch 됐음을 알립니다. 그렇게 함으로서 그 다음 event 가 제대로 dispatch 되게 됩니다. 그 object 밑에 touch 될 다른 object가 있다면 그 touch는 그 아래 object 에는 해당되지 않을 겁니다. 왜냐하면 그 위의 object 가 이미 그 touch에 대해 사용했기 때문입니다.

만약 리스너가 false를 return 했다면 (아무것도 return 하지 않아도 false를 return 한 것과 같습니다.) 그 touch는 뭔가 잘 못 됐다고 판단될 것이고 오직 began phase 만이 감지되고 끝날 겁니다. 이 경우 만약에 그 객체 밑에 터치 리스너를 감지하는 다른 객체가 있다면 그 터치 이벤트는 그 다음 객체에 전달이 될 겁니다. (이것을 이용하면 한 번의 터치로 두개의 object 에서 어떤 동작이 일어나도록 할 수 있을 겁니다. 단지 fault를 return 한 함수에서는 began phase 밖에 사용 못 하겠죠.)

이 부분이 새로 코로나 개발을 시작하는 분 들에게 혼동을 주기도 합니다. 이러한 touch 이벤트를 사용할 경우에 꼭 함수 끝날 때 true를 return 해야 한다는 것만 잊지 마세요.

Touch Focus

터치 리스너를 셋업했다면 아마 아래와 같은 모습을 하고 있을 겁니다.

local function onObjectTouch( self, event )
    if event.phase == "began" then

        -- specify the global touch focus
        display.getCurrentStage():setFocus( self )
        self.isFocus = true

    elseif self.isFocus then
        if event.phase == "moved" then

            -- do something here; or not

        elseif event.phase == "ended" or event.phase == "cancelled" then

            -- reset global touch focus
            display.getCurrentStage():setFocus( nil )
            self.isFocus = nil
        end
    end

    return true
end


해당 객체에 대한 터치 이벤트가 감지 됐을 때 touch focus를 global로 선언하는 것도 중요합니다. 이것은 began phase 단계에서 해야 합니다. 그리고  ended/cancelled phase 에서 이 Touch focus를 reset 시키게 됩니다. 그래야지 다른 객체들에 대한 touch 를 감지할 수 있게 됩니다. 이러한 내용들은 위 예제에 모두 구현돼 있습니다.

이 touch focus를 사용하신다면 힘들게 type 할 필요 없이 그냥 저 위의 예제를 복사해서 붙여 넣기만 하시면 됩니다.

Other Event Properties

터치 이벤트에는 phase 이외에도 여러가지 프로퍼티들이 있습니다. 아래 내용을 참고하세요.

    event.id – 해당 touch 이벤트에 대한 유닉한 구분자. (multi-touch에서 주로 사용됨)
    event.name – 해당 이벤트의 이름
    event.phase – 유저가 touch 한 현재의 phase 상태. began, moved, ended, cancelled 등이 있습니다.
    event.target – touch 된 object; self랑 똑 같은 의미임
    event.time – 이벤트가 일어난 이후부터 지금까지의 시간
    event.x, event.y – 이벤트가 일어난 x,y 좌표
    event.xStart, event.yStart – 최초 이벤트가 일어난 x,y 좌표. (began의 좌표가 됨). 유저가 drag 하게 될 경우 현재의 위치와 최초의 위치를 구분해서 사용할 수 있음
. 사용 예제를 보시려면 여기를 클릭 하세요.

프로퍼티에 대해 좀 더 자세한 내용을 알고 싶으시면 event API reference page를 참조하세요.

코로나에서는 이 touch 이벤트 이외에 tap 이벤트도 지원합니다. 이것은 touch 이벤트이지만 phase가 없습니다. 이것은 유저가 스크린 내 한 객체에 아주 빠른 tap이 일어나는것을 감지하고자 할 때 유용합니다.

tap 이벤트에 대한 자세한 정보는 Basic Interactivity 에 있습니다. 터치 이벤트에 대해 좀 더 자세히 할고 싶으시면 Events and Listeners documentation의 Touch Event 섹션을 보실것을 권장합니다.

반응형


반응형

오늘도 어제에 이어서 코로나에서 SQLite 다루는 방법에 대한 튜토리얼을 정리하겠습니다.

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


Inserting new rows into a table

새로운 row를 만드는 것은 INSERT 문을 통해서 할 수 있습니다. 우선 아주 기초적인 사용법을 보여 드리겠습니다. 그리고 나서 좀 더 다이나믹한 예제를 보여 드릴께요.

local insertQuery = [[INSERT INTO test VALUES (NULL, 'John Doe','This is an unknown person.', 'http://www.example.com/'); ]]
db:exec( insertQuery )


그냥 딱 봐도 알겠죠? 그래도 설명을 드리자면, 이전 에제에서 test라는 테이블을 생성했습니다. 그리고 이 예제에서는 그 test라는 테이블에 row를 생성한 겁니다.

주의하셔야 할 것은 컬럼의 순서에 맞춰서 value를 넣어 주셔야 합니다. 그 컬럼 순서는 테이블을 만들 때 사용했던 순서 입니다.

    id → NULL
    name → John Doe
    description → This is an unknown person.
    website → http://www.example.com/


이전 예제에서 테이블을 만들 때 id는 auto-increment로 설정 했습니다. 자동적으로 row 번호를 매기도록 하기 위해서 입니다. 그래서 id 값은 NULL 로 넣었습니다. 그러면 NULL이 들어가는 것이 아니라 자동적으로 숫자가 들어갈 겁니다. SQLite가 알아서 하는 부분이니까 별로 신경 안 쓰셔도 됩니다.

이제 좀 더 다이나믹한 예제를 볼까요? 좀 더 창의력을 발휘해 보겠습니다. 아래 예제는 루아 테이블로부터 value들을 가져와서 SQL 테이블에 row들을 insert 합니다.

local people =
{
    {
        name = "John Doe",
        description = "This is an unknown person.",
        website = "http://www.example.com/"
    },
    {
        name = "Jane Doe",
        description = "The wife of an unknown person.",
        website = "http://www.example2.com/"
    },
    {
        name = "Oscar",
        description = "Green guy lives in trash can.",
        website = "http://www.example3.com/"
    }
}

for i=1,#people do
    local q = [[INSERT INTO test VALUES (NULL, ']] .. people[i].name .. [[',']] .. people[i].description .. [[', ']] .. people[i].website .. [['); ]]
    db:exec( q )
end


NOTE : 여러분들이 입력하고자 하는 값에 따옴표가 있으면 그 따옴표 옆에 역슬래시를 넣어 주어야 합니다. 그렇지 않으면 에러가 발생할 겁니다.


 Updating existing rows

항상 새 row를 만드는 일만 하는 것은 아니죠? 사실 실전에서는 기존에 있던 row의 데이터를 업데이트 하는 일이 더 자주 있습니다. 아래 예제는 테이블에 이미 3개의 row들이 있다고 가정하고 만든 예제입니다. (위의 예제에서 만들었던 3개의 row들이라고 가정합시다.)

local q = [[UPDATE test SET name='Big Bird' WHERE id=3;]]
db:exec( q )


위 예제의 쿼리가 하는 일은 id가 3인 row를 찾아서 그 중의 name 컬럼의 값을 Big Bird 로 바꾸는 일을 합니다. 이전 예제에서 만들었던 세번째 row의 name인 Oscar 가 Big Bird가 되겠죠. 꼭 id로 특정 row를 찾아야 되는 것은 아니지만 대개 이렇게 하는게 간편합니다. (그 값은 unique 해서 항상 딱 1개의 row만 해당 되거든요.)

Deleting a row from an SQL table

delete는 update와 비슷합니다. 다른점은 UPDATE 대신 DELETE를 사용한다는 것이죠. 아래 예제에서는 id가 1인 row를 delete 합니다. John Doe가 있는 row가 delete 되겠네요.

local q = [[DELETE FROM test WHERE id=1;]]
db:exec( q )


Retrieving data with “SELECT”

SQL 데이터베이스에서 데이터를 검색할 때 다양한 필요에 의해 행해지게 됩니다. 어떤 때는 단 1줄만 필요할 때도 있고 특정 값을 가진 (예를 들어 서울에 사는 사람들 등) row들을 모두 검색해야 할 때도 있습니다.

이 모든 경우를 다루지는 않겠습니다. 다만 아래 예제를 통해 기존에 있던 데이터베이스에서 SELECT 쿼리를 통해 얻은 값을 루아 배열에 담는 과정을 보여드리겠습니다.

require "sqlite3"

local path = system.pathForFile( "data.db", system.DocumentsDirectory )
local db = sqlite3.open( path )

local people = {}  -- starts off emtpy

for row in db:nrows("SELECT * FROM test") do
    print( "Row " .. row.id )

    -- create table at next available array index
    people[#people+1] =
    {
        name = row.name,
        description = row.description,
        website = row.website
    }
end


여기서 가장 중요한 부분은 8번째 줄인 SELECT 구문이 있는 곳입니다. nrows() 함수를 이용해서 for 루프를 돌리도록 합니다. 이렇게 해서 루아 배열에 값을 넣고 그 값을 가지고 앱 내에서 이런 저런 프로그래밍을 할 수 있습니다.

SELECT 와 관련되서 좀 더 자세히 알고 싶으시면 이 글을 읽어 보세요.

Closing the database

데이터베이스와 관련된 작업이 끝났다면 데이터베이스와의 연결을 끊어 줘야 합니다. 이것은 굉장히 중요한 부분 입니다. close() 메소드를 사용해서 연결을 끊는데요. 필요할 때는 언제든지 사용하실 수 있습니다. 하지만 되도록이면 applicationExit 시스템 이벤트가 발생할 때 사용할 것을 권장 합니다. 이렇게 되면 앱이 종료할 때 데이터베이스 연결이 끊어지게 됩니다.

local function onSystemEvent( event )
    if event.type == "applicationExit" then
        if db and db:isopen() then
            db:close()
        end
    end
end
Runtime:addEventListener( "system", onSystemEvent )


위 코드는 여러분의 앱내 어느 부분에 있어도 됩니다. 단지 데이터베이스를 오픈한 이후가 되도록 하는게 좋겠죠. 위의 경우는 db 객체가 생성된 이후가 좋겠죠. 그리고 데이터베이스를 닫아야 하는 시점과 관련된 위치가 좋겠구요.

Further Reading

이것이 코로나에서 데이터베이스를 이용하는 대략적인 Tutorial 입니다. 코로나에서 SQLite으로 어떤 일을 할 수 있는지 살짝 맛만 보인겁니다. 더 많은 정보들은 여러분 스스로 찾으셔야 합니다. 인터넷에는 수 많은 SQLite + Lua 관련된 자료들이 있습니다. 그러니까 앱을 만들 때 데이터베이스를 좀 더 효과적으로 이용하시려면 더 많은 공부가 필요할 겁니다.

우선 SQL의 다양한 쿼리 사용법에 익숙해 지는것이 좋습니다. 이것만 해도 수 많은 Tutorial들을 만들 수 있습니다. 이 글에서 다룬 내용은 단지 처음 시작할 수 있도록 기본적인 내용만 다룬겁니다.

SQLite에 대해 좀 더 깊은 정보를 원하신다면 zetcode.com 의 SQLite tutorial을 보실것을 권장합니다.

반응형


반응형

이번주 코로나 Blog Tutorial 은 데이터베이스 입니다.

모바일기기에서는 SQLite을 사용하는데요.

이번엔 내용이 좀 기네요.

이번주 튜토리얼을 2회나 3회로 나눠서 소개해 드리겠습니다.

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

Database Access in Corona with SQLite   

프로그래밍 세계에서 특히 웹 프로그래머한테 데이터베이스 기술은 아주 큰 부분을 차지합니다. 데이터베이스는 아주 많은 데이터를 저장할 수 있는 훌륭한 기술입니다. 그것만이 아니라 그 저장한 데이터를 나중에 찾아서 사용할 수도 있습니다. 이것이 가장 중요한 역할이죠.

예를 들어 note 앱을 만든다면 유저 개개인이 만든 note들을 데이터베이스에 저장해야 할 겁니다. 물론 각각의 note를 텍스트 파일로도 저장할 수 있을 겁니다. 하지만 그러면 아마 수많은 파일을 관리해야 될겁니다. (데이터베이스를 사용하면 그냥 한게의 .db 파일만 있으면 되겠죠.) 그리고 데이터를 저장하고 찾고 하는 방법도 데이터베이스 이용과 다른 방법을 사용해야 합니다.




데이터베이스 파일은 SQL 테이블에 데이터가 저장이 됩니다.

그런데 이렇게 데이터를 저장하고 다시 나중에 검색하고 하는 일을 이전에 우리가 다루지 않았었나요?

이전에 JSON tutorial에서 제가 JSON은 같은 형태의 정보를 쉽게 저장할 수 있는 좋은 도구라고 말했었습니다. 코로나에서 디코드된 JSON 스트링이 루아 테이블로 컨트롤 하는 겁니다.


그래서 데이터베이스와 연관되서 JSON을 사용할 때 아미면 데이터베이스의 내용을 JSON으로 보낼 때 두 부분 모두 아주 파워풀하게 사용될 수 있습니다. 이런 방법들은 그 나름대로의 특징이 있습니다. 앱을 만들 때 필요에 따라 이러한 데이터를 다루는 기술을 이용하시면 됩니다.

이러한 방법들 중 어떤 방법을 사용할까를 정하는 기본적인 룰은 아주 큰 용량의 데이터를 다루게 되면 (특히 그 데이터를 search하고 앱 내에 저장되어야 한다면) 데이터베이스 기술을 사용하는것이 좋을 겁니다. 작은 용량의 데이터라면 예를 들어 configuration data나 case 들 같은 경우는 단순하게 Lua table에 저장해서 파일로 저장하고 나중에 이 파일을 이용해야 합니다. 이 경우에는 JSON으로 간단하게 처리하면 됩니다.

사실 많은 경우 큰 용량의 데이터를 저장해야할 앱을 다룰 때 SQLite와 JSON을 함께 사용하게 됩니다. JSON 객체가 단지 string일 경우 JSON blobs 를 데이터베이스에 저장할 수 있습니다. 그리고 그것을 나중에 Lua 변수로 로드하고 JSON 라이브러리를 사용해서 그 string을 table로 convert 하게 됩니다. JSON은 좀 더 작은 data chunk를 관리 합니다. 그리고 데이터베이스는 이 JSON blobs들의 모임인 큰 data structure를  organize 하게 되는 겁니다.

JSON과 함께 사용하면 데이터베이스를 사용하는데 훨씬 간편하게 사용할 수 있는 부분이 있습니다. 이와 관련해서는 나중에 다루겠습니다.

이 튜토리얼에서는 database를 create하고 파일로 저장을 하고 정보를 저장하고 데이터를 검색하는 기능을 코로나 앱에서 어떻게 해야 하는지에 대해 다루겠습니다.

Creating a database

데이터베이스를 생성하는 방법에는 두가지가 있습니다. 첫번째는 메모리에 데이타베이스를 만드는 방법으로 이 경우에는 앱이 사용중일 때만 만들어지고 사용되고 이 앱이 꺼지면 없어지게 됩니다. 그리고 두번째 방법은 데이터베이스 파일에 생성하는 겁니다. 이렇게 되면 언제든지 로드될 수 있겠죠. 이 튜토리얼에서는 메모리에서 데이터베이스를 다루는 방버은 커버하지 않을 겁니다.

데이터베이스를 사용하는 예제가 아래에 있습니다. 데이터베이스를 생성하고 save된 데이터베이스를 오픈하기 위해서 아래 작업들을 해야 합니다.

require "sqlite3"

local path = system.pathForFile( "data.db", system.DocumentsDirectory )
local db = sqlite3.open( path )


NOTE : 데이터베이스를 만드는 장소는 system.DocumentsDiretory를 사용할것을 추천합니다. 프로젝트 리소스 디렉토리는 writable 하지 않고 temp/cache 디렉토리는 OS에 의해서 순식간에 정리될 수도 있습니다. 그러므로 system.DocumentsDirectory 가 가장 안전한 곳입니다.

다시 예제로 돌아가서요. 첫번째 줄은 sqlite3 namespace를 통해서 SQLite 함수를 만드는 겁니다. 마지막줄은 특정 위치에 있는 데이터베이스 파일을 로드하기 위해 (혹은 그 위치에 데이터베이스가 없으면 생성하기 위한) sqlite3.open()을 하는 겁니다.

Creating a Table

테이블 (루아 테이블이 아닌 SQL 테이블), 컬럼, row 등과 같이 SQLite 데이터베이스를 사용하게 되면 일상에서 사용하는 용어들을 접하게 됩니다. 테이블은 데이터의 카테고리를 연상하실 수 있을 겁니다. 저 위에 note 앱을 예로 들을 때 얘기 한건데요. 앱 세팅, 유저 세팅 그리고 유저가 생성한 노트를 보관하기 위해서 각각 다른 테이블들을 가질 수 있습니다.

각각의 SQL 테이블은 복수의 컬럼들을 가질 수 있습니다. 예를 들어 id, name, description, website 등등. 프로퍼티라고 생각할 수 있겠죠. 테이블에 insert 된 각각의 아이템들은 row라고 합니다. Row는 실제로 다루게 되는 데이터들이 됩니다. 이 row들을 만들기 위해서 먼저 컬럼들을 만들어야 하는 것이죠.

local tablesetup = [[CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY autoincrement, name, description, website);]]
db:exec( tablesetup )


위의 예제에 있는 tablesetup 변수에는 SQL Query 가 string으로 저장돼 있습니다. 이 쿼리는 데이터베이스가 무엇을 해야 하는지 정리해 놓은 겁니다. 그 다음에 우리는 이 쿼리를 실행하게 되죠. db.exec로 실행을 합니다. 그러면 이 쿼리가 데이터베이스에 전달 되서 데이터베이스가 그 쿼리대로 일을 합니다. 위 예제에서는 text 라는 테이블이 만들어 지고 그 테이블에는 4개의 컬럼들이 있게 됩니다.

    id (primary key that will auto-increment upon inserting new rows)
    name
    description
    website


NOTE 1 : 대개 테이블의 첫번째 컬럼은 id 입니다. 이것은 primary key로 세팅 됩니다. (모든 테이블은 한개의 primary key 가 있어야 됩니다.) auto-increment flag는 row가 추가 될 때마다 이 컬럼의 값이 자동적으로 그 다음 id number로 설정 된다는 겁니다. (1,2,3,4 이렇게 순서가 매겨 지겠죠.) 그러니까 개발자는 이 컬럼의 row 값들을 따로 입력할 필요가 없습니다.

NOTE 2 : 위 예제에서 query string이 따옴표 대신  double brackets ([[ 와 ]]) 로 싸여져 있는 것을 보실 수 있을 겁니다. 왜냐하면 SQL query 를 만들 때 그 안에 큰 따옴표나 작은 따옴표가 사용되어야 하기 때문에 [[와 ]] 를 사용해서 좀 더 안전하게 코딩할 수 있도록 한 겁니다.

이제 새롭게 만든 test라는 SQL 테이블에 각각의 row들을 insert 할 수 있습니다. 모든 row들은 id,name,description, website 프로퍼티들이 있습니다. 그리고 각 row들은 이에 대해 각각 다른 값들을 가지고 있을 수 있습니다. 조금 전에 얘기했듯이 컬럼은 테이블에서 row에 대한 프로퍼티들로 생각할 수 있습니다.

반응형


반응형

모바일 애플리케이션으로 수익을 올리는 것을 보면 단연 애플의 앱스토어가 구글의 구글 플레이 (옛날 구글 마켓) 보다 훨씬 유리합니다.

다운수도 더 많고 유료 앱 구매자도 더 많고 심지어는 광고 클릭율도 더 높습니다.

아마존 앱스토어는 어떨까요?

아마존 앱스토어가 구글 플레이보다 훨씬 더 앱으로 수익을 올릴 수 있다는 분석 결과가 나왔네요.

아래 그 글 소개해 드릴께요.



Hey devs, Amazon apps can make almost as much as iOS apps




현재 모바일 시장에서 iOS와 안드로이드는 Top에 있는 애들입니다. 그리고 그 다음 순위는 누가차지하느냐에 대해서는 치열합니다. 예전에 BlackBerry에 대해 썼었습니다. 그리고 그 글을 뒷받침하는 글이 그 주 목요일에 있었죠. 윈도우즈 폰은 내 의견으로는 넘버 3가 되기 위해 훨씬 좋은 위치에 있는 것 같습니다. 하지만 전문 분석기관인 Flurry는 좀 다른 시각을 보이기도 하지요. 수많은 데이터를 근거로 Flurry 는 아마존이 주의 깊게 살펴 보아야 한다고 말합니다. 아마존이 안드로이드 플랫폼을 사용하고 있음에도 말이죠.

Flurry의 연구 결과의 키 포인트는 앱스토어와 구글 플레이(구글 마켓) 그리고 아마존 앱스토어에서 모두 가능한 앱을 대상으로 합니다. 똑같은 앱의 수입에 대해 IOS 를 100으로 하고 구글 플레이와 아마존 앱스토어를 비교했을 때 아마존은 89% 인데 반해 구글은 23%에 불과 합니다.




 Flurry 는 이렇게 말합니다.

    이 결과를 다른 말로 설명하면 앱 스토어에서 앱이 1달러를 벌 때마다 아마존에서는 0.89달러 그리고 구글 플레이에서는 0.23달러를 벌어들인다는 겁니다.


이 결과는 두가지 중요한 의미를 포함하고 있습니다. 첫번째로 안드로이드 개발자가 앱을 개발할 때 아마존 앱스토어를 먼저 고려할지 말지를 고민해야 합니다. 두번째로는 안드로이드 앱으로도 돈을 벌 수 있다는 것이죠. 아마존과 구글 플레이를 합하면 ios의 앱스토어와 거의 같아지게 됩니다. 그리고 긴 관점으로 봤을 때 아마존에서 지속적으로 promotion을 펴는것이 더 전망이 있을 수도 있지 않을까요?

제 생각엔 이 부분은 아마존 앱의 성공요소 중 일 부분일 뿐이라고 생각합니다. 구글은 첫번째로 검색엔진 회사라는 이미지가 강합니다. 그리고 나머지는 second 입니다. 구글인 디지털 미디어나 앱이라는 브랜드로 알려져 있지 않습니다.

아마존과 비교하면 아마존은 세계 최고의 retail 브랜드 입니다. 지난해 아마존의 브랜드 가치는 최고의 retail 브랜드 였던 월마트를 앞질렀습니다. 또한 아마존은 digital content - e-book, music and video 등- 을 가장 안전하게 구매할 수 있는 장소입니다. 똑같은 것들을 구글 플레이에서도 판매하지만 아마존의 브랜드 이미지가 훨씬 더 안전한 거래라는 이미지를 줍니다.
또한 결론적으로 소비자들은 애플 브랜드와 앱스토어를 가장 선호하고 있습니다.
그러므로 모바일 앱 개발자들은 iOS에 포커스를 맞추고 그 다음에 아마존에 맞추는 것이 좋을 겁니다.

~~~~~~
반응형