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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

오랜만에 Sencha Touch를 들여다 보게 됐네요.
몇개의 튜토리얼을 정리했는데요. 아직 제대로 제가 감을 못 잡은 것 같아서요.

오늘은 샘플코드를 구해서 분석해 봤습니다.
Shopping List 를 Sencha Touch 로 구현한 샘플코드인데 독일의 Nils Dehl 이라는 개발자가  프랑크프루트 컨퍼런스에서 강의한 코드입니다.

일단 저도 Sencha Touch를 시작하는 사람으로서 이 소스코드를 자세하게 분석하지는 못합니다. 이 소스코드를 통해서 제가 공부할 목표는 아래 두가지 입니다.

1. MVC 모델 프로그래밍을 위한 디렉토리 및 파일 구조 파악
2. 실전에서 자주 쓰이는 API에 대한 감을 익혀서 튜토리얼 공부할 때 집중할 수 있도록 하기

이 이상은 지금 수준에서는 아직 할수가 없다고 봅니다.

일단 이 앱의 Storyboard 를 보죠.

1. 이 앱의 인트로 화면입니다. 실행하면 이 화면이 떴다가 잠시 후에 자동으로 다음 화면으로 넘어갑니다.



2. 앱의 첫 화면입니다. + 를 누르면 데이터를 입력할 수 있는 화면이 나옵니다.



3. 이름과 갯수 그리고 단위를 입력하고 Save를 누르면 2번화면으로 가고 입력한 데이터가 표시됩니다.



4. 3번화면을 통해서 여러 물품을 입력하면 아래와 같이 그 리스트가 뜹니다.
    오른쪽 마크 버튼을 누르면 색이 변합니다.


화면은 몇개 안 되지만 직접 만들려면 만만치 않을것 같네요.

그럴듯하게 쇼핑카트가 완성 됐죠?

이 앱에서는 MVC 모델과 list 그리고 localstorage, form 과 관련된 기술이 사용됐습니다.
그리고 CSS를 보다 간편하게 사용하기 위해서 SASS 를 사용했구요.

자세히는 아니지만 이 기술들도 간단히 살펴 보겠습니다.
아직 저는 센차터치의 MVC 구성과 실전에서 자주 사용되는 API와 그 사용법 파악이 주 목적이니까 그 부분에 집중해서 공부하겠습니다.

이 앱의 소스파일은 아래로 가시면 받아 보실 수 있습니다.

http://dl.dropbox.com/u/7549925/shoppinglist.zip

소스는 받아서 그냥 실행하시면 됩니다.
이 앱은 Sencha Touch 1.1.0을 사용했습니다.
그리고 Step1부터 Step 7 까지 단계별로도 소스를 따로 모았습니다.

이 단계는 컨퍼런스 때 강의를 하기 위해 나눈것인데요.
동영상으로도 있습니다.


Creating a sample Touch app from Grgur Grisogono on Vimeo.

오늘은 위에 동영상까지 올리겠습니다.

소스 받아서 보시고 동영상도 보시면 많은 공부가 될 겁니다.

저도 공부해서 나름대로 정리할 내용을 정리할 계획입니다.

지난주에는 Corona SDK + JQuery Mobile + HTML5 + CSS3 기술을 이용한 앱을 하나 만들었습니다.
Corona SDK를 이용한 Hybrid App 을 만들 목적이었는데요.
좋은 조합일 수도 있고 또 제한 사항들이 있어서 컨트롤하기 힘든 부분도 있더라구요.
원래 standard 조합인 Phonegap + JQuery Mobile 을 이용해서 Hybrid App을 만들어 보아야 겠어요.
그래야지 비교할 수 있고 서로간의 장 단점을 알 수가 있을 것 같아서요.

일단 오늘은 이 쇼핑카트 앱 소스를 공부해서 필요한 부분을 정리해야겠습니다.

다음 글에 제가 공부한 내용을 올릴께요. 그럼......


P.S. 이 소스는 저의 경우 크롬과 사파리 브라우저에서만 동작하고 오페라,익스플로러,파이어폭스에서는 작동 안하더라구요.

반응형


반응형

오늘도 어제에 이어서 코로나에서 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에 포커스를 맞추고 그 다음에 아마존에 맞추는 것이 좋을 겁니다.

~~~~~~
반응형


반응형

오늘 오랜만에 맨하튼 나갔습니다.

투표하러요.

재외 국민선거 제도가 올해부터 시행 되서 외국에서도 투표할 수 있게되서 너무 좋네요.


투표 장소는 뉴욕 UN 본부 건너편에 있는 건물에서 있었습니다.

미국에서는 투표소가 몇군에 있는지는 모르겠지만.. 뉴욕 뿐만이 아니라 뉴저지, 팬실배니아, 메사추세츠 뭐 이런데서도 다 여기 뉴욕으로 와서 투표해야 할 겁니다.

왠만한 주가 우리나라보다 커서 일부러 투표하러 오기 어려운 사람들도 많을 겁니다.

저는 뉴저지에 살아서 버스타고 20분 가고 걸어서 20분 가서 도착했어요. 사람들이 많이 없지 않을까 하는 생각을 했는데 의외로 건물 주변부터 투표하러 오는 한국분들이 많더라구요. 특히 보시듯이 아이들 손 잡고 온 젊은 개념 부모들이 많아서 기분 좋았어요.


여긴 3월 28일부터 투표가 시작 됐어요. 4월 2일까지 하는데요.

바로 길 건너가 UN 본부니가 반기문 사무총장님도 여기서 하루 전에 투표 하셨다고 하더라구요.


저 중에 하나가 저예요.

한국에서는 청와대가 민간인 사찰을 했다느니 김재동 비리를 캤다느니 뭐 이런 기사들이 많이 보이던데요.

모든 선거는 이전 선거부터 지금까지 한 일들에 대한 평가를 하는 성격이 있다고 봐요.

이번 선거도 국민이 지난 일들에 대해 심판을 해야 한다고 보구요.

저는 어렵게 만든 그리고 많은 분들이 목숨까지 바친 민주주의가 다시 후퇴하지는 않았으면 좋겠어요.

오늘 미얀마에서도 아웅산 수지 여사가 선거에서 이겼다고 하던데요.
미얀마에도 민주주의가 꽃피길 바라겠고 우리나라도 후퇴하는 민주주의가 다시 바로 잡혔으면 좋겠습니다.

그 마음 갖고 투표했습니다.

여러 분들도 투표 꼭 하세요~~~~~~~

추신)

투표장소 옆에 두분이 나와서 제주도 해군기지 건설 반대 피케팅을 하고 계시더라구요.

반응형

Storyboard API 추가 사항 안내

2012. 4. 2. 10:49 | Posted by 솔웅


반응형

Storyboard Scene Events Explained  

Posted by Jonathan Beebe

지난 11월에 Storyboard API를 소개했을 때 (한글, 영어) 이 스토리보드 API 소개와 함께 어떻게 사용할 것인가에 대한 간단한 설명을 한 이후로 이 API에 대한 추가적인 가이드나 튜토리얼을 소개해 드리지 못했습니다.

그래서 오늘 스토리보드 API 전체를 구성하고 움직이게 하는 각각의 개별 이벤트들에 대해 설명하려고 합니다. 그리고 이 각기 다른 이벤트들이 어떻게 조화를 이루도록 하는지에 대해 보여 드리겠습니다. 여러분 중 scene 이벤트들에 대한 이해가 부족해서 스토리보드 API를 사용하시는데 문제가 있으셨던 분들은 이 글이 많은 도움이 되실 겁니다.

일단 스토리보드 의 scene 객체들이 무엇인지 그리고 각 scene들의 view display group과 scene을 purge 한다는게 무슨 의미인지에 대해 설명 드리겠습니다. 스토리보드 scene 이벤트들을 사용하시면서 view group이나 purge, remove 같은 개념들을 이해하시는 것은 중요한 일입니다.






Scene Objects

Storyboard API의 가장 핵심 객체는 scene 객체 입니다. 이 객체는 단지 특정 프로퍼티들과 이벤트들로 구성된 테이블입니다.

모든 scene 객체들은 storyboard.newScene() 함수를 사용해서 생성됩니다. 여러분은 여러분들이 원하는 만큼의 scene을 만들 수 있습니다. 하지만 일반적으로 새로운 모듈의 top에서 storyboard.newScene() 함수를 한번 call 하게 됩니다. 그리고 모듈의 마지막 부분에 이것을 return 합니다. (그 사이에 scene event-handling 하는 부분이 있겠지요.) 이 방법을 따른다면 scene들은 각 루아 모듈(루아 파일) 마다 하나씩 나오게 됩니다. 그리고 이렇게 정석대로 개발하게 되면 코딩이 더 쉬워지고 가독성도 훨씬 올라가게 됩니다.


The “view” display group

모든 scene들은 display group으로 구성됩니다. 이 display group에 각 scene의 display 객체들이 포함되게 됩니다. 이 display group은 view 프로퍼티를 통해서 access 될 수 있습니다.

sceneObject.view  -- Corona display group

이 display group은 항상 현재 상태인 것은 아닙니다. scene들이 루아 모듈들과 서로 관계하면서 부터 가끔씩  모듈 자체가 로드 되게됩니다. 이 때 scene 객체는 active 상태가 됩니다.  하지만 view display group은 그렇지 않습니다. scene이 purged 상태일 때 주로 그렇습니다. 이것은 스토리보드 API를 이용할 때 자주 발생하게 됩니다.

Scene Purging

scene이 purged 된다는 것은 view display group이 removed 됐다는 걸 의미합니다. scene이 purged 됐을 때 scene object는 아직 메모리에 있는 상태입니다. 하지만 눈에 보이는 상황은 아니죠. 이것은 조만간에 다시 이 scene을 로드할 때 유용합니다. 메모리에 있기 때문에 빨리 불러 올 수가 있죠. 실제 texture 메모리를 차지하지는 않으면서 단지 메모리에 존재하는 상태이기 때문에 빨리 불러 올 수 있는 겁니다.

Scene Events

코로나 SDK로 이벤트를 작업는것과 같은 개념으로 스토리보드 API가 설계 됐습니다.

scene이 생성하고 purge , remove 하고 scene들 사이에서 서로 왔다갔다 하는 것들을 모두 API를 통해 콘트롤 할 수 있습니다. 각각의 상황에 맞는 이벤트들이 존재하고 또 연관을 맺게 됩니다. 이 이벤트들이 있음으로 해서 특정 액션이 일어나기 직전이나 일어난 이후에 어떠한 일을 할 수가 있게 됩니다.
아래에 scene 과 관련한 이벤트 들이 열거돼 있습니다.

- createScene
- enterBegan (requires build 2012.773 or later)
- enterScene
- exitScene
- exitEnded (requires build 2012.773 or later)
- destroyScene



createScene

이 이벤트는 scene의 view display group이 생성 될 때 dispatch 됩니다. 그러니까 일반적으로 storyboard.gotoScene()에 의해 call 되는 사이에 dispatch 되게 되죠. 그런데 storyboard.gotoScene() 이 call 됐는데 view display group이 이미 있다면 어떻게 될까요? (이 얘기는 이전에 이 scene이 불려져서 view 객체들이 화면에서는 없어졌지만 메모리에는 아직 남아있는 purge 상태라는 거죠.) 이럴때는 이 createScene 이벤트가 call 되지 않습니다. 곧바로 enterBegan-enterScene 이벤트로 가게 되죠.

createScene 이벤트 리스너 함수내에서는 그 scene에 등장해야 할 display 객체들을 생성하고 그 객체들을 그 scene의 view display group에 insert 하는 일을 하게 됩니다.
아래에 createScene 이벤트 리스너 관련 예제가 있습니다.

local storyboard = require "storyboard"
local scene = storyboard.newScene()

-- forward declarations
local object1, object2

function scene:createScene( event )
    local group = self.view

    object1 = display.newImage( "image1.png" )
    object2 = display.newImage( "image2.png" )

    group:insert( object1 )
    group:insert( object2 )
end
scene:addEventListener( "createScene", scene )

return scene


Side note : 이 객체를 선언할 때는 creaScene 바깥에서 로컬로 선언을 합니다. 그리고 구체적인 이미지나 텍스트 할당을 createScene 함수 안에서 하게 되는거죠. 이렇게 해야지 그 객체들을 다른 이벤트 리스너 (enterScene 등) 에서 사용할 수 있습니다.

enterBegan

NOTE : 이 이벤트는 Corona build 2012.773 버전에서 추가 됐습니다. 그 이전 버전에서는 사용하실 수 없습니다.

storyboard.gotoScene()이 call 됐을 때 그 scene의 view display group이 생성 될 것입니다. (이미 있지 않으면) 바로 그 다음에 그리고 다른 transition이 일어나기 전에 enterBegin 이벤트가 실행 될 겁니다.

enterBegan 이벤트 리스너를 통해 enterBegin 하는 순간에 원하는 일을 할 수 있습니다. pre-loading 을 한다거나 데이터를 저장한다거나 하는 일들을요. 객체들이 실제 화면에 뜨기 바로 직전에 어떠한 일을 할 수가 있는 겁니다. 아래 예제가 있습니다.

local storyboard = require "storyboard"
local scene = storyboard.newScene()

-- forward declarations
local object1, object2

function scene:createScene( event )
    local group = self.view

    object1 = display.newImage( "image1.png" )
    object2 = display.newImage( "image2.png" )

    group:insert( object1 )
    group:insert( object2 )
end
scene:addEventListener( "createScene", scene )

function scene:enterBegan( event )
    object1.isVisible = false
    object2.isVisible = false
end
scene:addEventListener( "enterBegan", scene )

return scene


이 예제에서 createScene 이벤트 리스너와 enterBegan 이벤트 리스너가 어떻게 역할 분담을 해서 일을 하게 할 수 있는지에 대해 보실 수 있을겁니다.

enterScene


이 이벤트는 enterBegan이랑 비슷합니다. 단지 이 이벤트는 scene transition이 일어난 이 후에 call 된다는 것만 다릅니다. 객체들을 특정 지점에 positioning 하거나 유저에게 메세지를 보여주거나 physics를 시작하거나 touch나 enterFrame 같은 이벤트 리스너들을 추가하거나 하는 일들을 이 enterScene 이벤트 리스너에서 하시면 됩니다.

storyboard.gotoScene()에서 enterScene 이벤트까지 어떠한 과정들이 있는지 아래 그림을 통해 보실 수 있습니다.

exitScene


storyboard.gotoScene() 으로 다른 scene을 call 했을 때 현재의 scene에서는 어떠한 일이 일어날까요? 첫번째로 exitScene 이벤트가 dispatch 될 겁니다. 이 이벤트는 현재의 scene이 transition out 되기 전에 일어나게 됩니다.

이 exitScene에서는 어떤일을 주로 하는게 좋을까요? 여기서는 touch, enterFrame 같은 이벤트 리스너들을 remove 하고 애니메이션을 stop 시키고 physics를 pause 시키는 일들을 해야 합니다.

다시 정리하자면 유저가 storyboard.gotoScene()을 call 하면 현재의 scene에서 exitScene 이벤트가 첫번째로 dispatch 될 겁니다. 저 위에 있는 다이어그램을 다시 보시면 이 exitScene 다음에는 어떤 이벤트가 그 다음에 dispatch 되는지 아실 수 있죠?

exitEnded

NOTE : 이 이벤트는 Corona build 2012.773 에서 새롭게 추가 됐습니다. 그러므로 이전 버전에서는 사용하실 수 없습니다.

exitScene은 현재의 scene이 transition out 되기 전에 dispatch 됩니다. 그리고 exitEnded 이벤트는 그 scene이 완전히 transition out 된 직후에 dispatch 됩니다. 그러니까 그 다음 scene이 나오기 바로 직전에 dispatch 되는 겁니다. 아래에 이 5개의 다른 scene 이벤트들에서 어떠한 일들을 시켜야 하는지에 관한 예제가 있습니다.

local storyboard = require "storyboard"
local scene = storyboard.newScene()

-- forward declarations
local object1, object2

-- enterFrame event listener function
local function onUpdate( event )
    -- do something here
end

function scene:createScene( event )
    local group = self.view

    object1 = display.newImage( "image1.png" )
    object2 = display.newImage( "image2.png" )

    group:insert( object1 )
    group:insert( object2 )
end
scene:addEventListener( "createScene", scene )

function scene:enterBegan( event )
    object1.isVisible = false
    object2.isVisible = false
end
scene:addEventListener( "enterBegan", scene )

function scene:enterScene( event )
    object1.isVisible = true
    object2.isVisible = true
  
    Runtime:addEventListener( "enterFrame", onUpdate )
end
scene:addEventListener( "enterScene", scene )

function scene:exitScene( event )
    object1.isVisible = true
    object2.isVisible = true

    Runtime:removeEventListener( "enterFrame", onUpdate )
end
scene:addEventListener( "exitScene", scene )

function scene:exitEnded( event )
    print( "This scene has fully transitioned out and is no longer the active scene." )
end
scene:addEventListener( "exitEnded", scene )

return scene


destroyScene


이 이벤트는 그 scene의 view display group이 remove 될 때 dispatch 됩니다. 이 이벤트는 view display group이 모두 remove 되기 전에 display object들과 관련된 어떠한 일들 (이벤트 리스너를 없앤다던가 특정 scene 객체들을 manually 없앤다던가 하는) 일들을 하기에 좋습니다.

scnen이 purge 될 때마다 destroyScene은 dispatch 됩니다. scene purging은 다음과 같은 상황에서 발생하게 됩니다.

    - storyboard.purgeScene() 이나 storyboard.purgeAll()이 call 됐을 때
    - storyboard.removeScene() 이나 storyboard.removeAll() 이 call 됐을 때 (scene은 scene objects 들이 remove 되기 전에 먼저 purged 됩니다.)
    - OS 가 메모리 부족 경고 메세지를 보낼 때 가장 최근에 사용된 scene은 자동적으로 purged 됩니다. (모듈은 load 된 상태로 남아 있습니다. 다만 view display group은 texture memory 공간을 확보하기 위해서 remove 됩니다.)


Putting it all together

지금까지 모든 events 에 대해 어떻게 동작들을 하는지 설명했습니다. 그리고 이 각각의 이벤트들이 서로 어떻게 연관을 맺으면서 일을 하게 되는지를 보여주는 간단한 예제들을 보여 드렸습니다. 그런데 이 다른 스토리보드 이벤트들을 필요에 따라 어떻게 활용해야 할까요? 이건 기억해 두세요. 이 모든 이벤트들을 다 활용할 필요는 없습니다. 이 이벤트들은 당신이 필요로 할 때 사용할 수 있도록 만들어져 있지 당신이 모두 사용해야만 하도록 만들어 진 것은 아닙니다.

그리고 일단 createScene 이벤트 리스너에는 객체를 생성하는 코드를 넣으세요. 리스너를 달고 객체들의 위치를 잡고 physics를 시작하고 하는 일들은 대개 enterScene 리스너에서 하게 됩니다. 그리고 객체와 리스너를 remove 하고 physics를 없애고 하는 일들은 exitScene에서 하게 됩니다. (이 exitScene에서는 주로 이렇게 어떤 것들을 해제하거나 없애는 장소 입니다. 다른 화면으로 넘어가기 전에 현재 화면해서 메모리를 잡아 먹고 있는 것들을 다 해제해 주는 작업을 하는 것이죠.)

SampleCode/Interface/Storyboard에 있는 샘플 코드를 실행해 보세요. 터미널에 transition이 시작되거나 끝날 때 이러한 이벤트들이 dispatch 되는 로그들이 찍힐 겁니다.

그리고 이 글을 읽고 난 후에 직접 한번 만들어 보세요. 금방 하실 수 있을 겁니다. 그리고 API의 더 다양한 메소드와 관련된 정보를 얻으시려면 Storyboard Reference를 참조하세요.


아주 오랜만에 글을 올립니다. 개인적으로 좀 일이 있어서요.

오랜만에 올렸는데...
오랜만에 추천도 꾸욱~~ 해 주세요. :)

반응형

Developing for iPad Retina Display

2012. 3. 23. 12:01 | Posted by 솔웅


반응형
애플이 얼마전 새로운 아이패드를 만듦으로서 iOS 용 앱도 이제 3~4가지 해상도를 고려해서 개발을 해야 되네요.
안드로이드까지 합쳐지면 해상도 종류가 굉장히 많아지죠?

일단 이미지를 Display 할 때 이미지가 찌그러지거나 흐리게 나오거나 하는 문제들이 있습니다.

각기 다른 해상도에서도 선명한 이미지를 보여줄 수 있는 방법에 대해 이번에 Corona에서 블로그에 포스팅을 해 주었네요.

Android Native Language로 할 때는 px 말고 div인가? 뭐 그런 이미지 사이즈 단위를 사용하는 방법도 있고 또 코드 내에서 디바이스 프로파일 정보를 얻어서 다른 이미지를 출력하는 방법 또는 layout xml을 디바이스별로 다르게 준비해서 사용하는 방법이 있고 그렇죠?
Android Native Language로 개발한지 오래 되서 잘 모르겠네요.

하여간 코로나에서는 비교적 간단하게 이 부분을 해결 할 수 있습니다.

이번에 코로나에서 아주 정리를 깔끔하게 잘 해서 올려 준 것 같습니다.
원본은 여기로 가시면 보실 수 있습니다.



Developing for iPad Retina Display

Corona SDK는 현재 공식적으로 New iPad (이 후에는 iPad 3라고 부르겠습니다.) 를 support하고 있습니다. 이 support는 일반 공개버전이나 유료사용자를 우한 Daily Builds 모두에서 지원하고 있습니다.

이 iPad 3는 원래 iPad 보다 3배나 많은 픽셀을 지원합니다. 그래서 개발자들은 이 해상도를 위해 최적화 된 그래픽을 지원하는 방법에 대해 혼란스러워 하고 있습니다.

좋은 소식은 현재의 iPhone이나 iPod touch 를 위한 retina display에서 여러분이 작업을 했다면 새 iPad3도 기본적으로 똑 같다는 겁니다. 하지만 좀 혼동할 수 있는 부분도 있을 것 같아 이 Tutorial에서 그 부분에 대해 설명 하겠습니다.

이 글은 몇개의 다른 시나리오로 나뉠겁니다. 특정 configuration을 이용하는 방법과 여러분의 app이 target 하는 특정 디바이스의 타입에 대해 해야 하는 일 등으로 나뉠겁니다. 여러분은 그냥 필요로하는 부분에 대해 읽고 따라하시면 됩니다.

iPad-only Apps

이 시나리오는 여러분의 앱이 iPad 형식의 디바이스를 위해 만들어지는 경우를 가정한 겁니다. (그러니까 다른 tablet들에도 해당이 됩니다.)

쉬운 방법은 아이폰을 위한 앱을 만들 경우 일단 아이폰에 맞게 작업을 하고 그 다음에 새로운 아이폰에 맞춰 작업하는 겁니다. 그리고 이 방법이 정상적입니다.

그래픽 이미지들을 평상시처럼 만드세요. 그라고 나서 똑같은 이미지를 width와 height가 두배로 키워서 만드세요. 두배로 큰 이미지는 이미지 이름에 공통된 접두어같은 것을 넣어 두세요. (나중에 config.lua 파일에서 사용할 겁니다.) 그렇게 되면 코로나 엔진이 상황에 맞게 필요한 이미지를 가져다가 display 할 겁니다.

그냥 이미지 관련 프로그램으로 원래 이미지를 두배 늘리는 일은 하지 마세요. 그러면 이미지가 번지거나 흐려지게 될 거예요. 원래 목적이 큰 해당도에서도 깨끗한 이미지를 보여주기 위한 거니까 두배로 큰 이미지는 크면서도 깨끗하게 보일 수 있도록 따로 작업하세요. 큰 이미지를 먼저 만들고 나서 작은 이미지로 크기를 줄이는 방법도 좋을 겁니다.

아래 두 개의 작은 해상도를 위한 이미지와 큰 해상도를 위한 이미지에 대한 파일 이름과 관련한 예제가 있습니다.
큰 이미지에는 @2x라는 접미어가 똑같이 붙어있습니다.

    star.png – 128 x 128
    star@2x.png – 256 x 256
    background.png – 768 x 1024
    background@2x.png – 1536 x 2048

그리고 이를 config.lua에서 어떻게 처리해야 하는지 아래에 예제가 있습니다.

application =
{
    content =
    {
        width = 768,
        height = 1024,
        scale = "letterbox",

        imageSuffix =
        {
            ["@2x"] = 2,    -- images with "@2x" appended will be used for iPad 3
        }
    }
}

어떤 화면 방향을 taget으로 하던지 width와 height는 항상 portrait 를 기준으로 config.lua에 명시하셔야 합니다. (그러니까 width는 항상 height보다 작겠지요?)

위 config.lua에서 imageSuffix 테이블에는 @2x 라는 아이템이 있습니다. 이는 코로나 엔진에게 해상도가 두배인 디바이스인 경우에는 이 @2x가 붙은 이미지를 사용하라고 얘기하는 겁니다. (만약에 있으면)

위에 iPad  해상도의 width와 height를 정해 줬죠? iPad 3의 해상도는 이 보통 아이패드의 딱 두배 입니다. 그러니까 위의 예제 config.lua를 사용하시면 이미지를 사용할 때 iPad 3 이면 그 이미지 이름 뒤에 @2x가 붙은 이미지를 사용할 겁니다. (만약에 @2x 가 붙은 이미지가 없으면 원래 이미지를 씁니다.)

여러분이 이렇게 config.lua만 제대로 세팅해 놓으면 코로나는 알아서 디바이스의 크기를 체크하고 이미지를 불러올 때마다 거기에 맞는 이미지를 display 합니다.

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

위와 같이 이미지를 불러오고 위에 제시한 config.lua를 사용한다면 background.png는 iPad 와 iPad 2 에서 display 될 겁니다. 그리고 iPad 3 에서는 background@2x.png가 display 될 겁니다.


iPad + iPhone (Universal) Apps

이 시나리오는 iPhone 해상도 (320X480)에 맞게 작업을 하고 코로나의 dynamic content-scaling 기능을 이용해서 iPad 에 맞게 자동적으로 이미지가 늘어나서 화면에 꽉 차게 display하는 방법을 사용하는 방법입니다.

이 시나리오대로 하기 위한 config.lua 예제가 아래에 있습니다.

application =
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox",

        imageSuffix =
        {
            ["@2x"] = 2,    -- for iPhone, iPod touch, iPad1, and iPad2
            ["@4x"] = 4,    -- for iPad 3
        }
    }
}


위 config.lua를 사용하면 여러분의 앱은 iPhone 해상도에 맞게 작업이 이뤄질 겁니다. 어떤 디바이스이든지 상관 없이 안의 로직은 똑 같이 적용되서 돌아갈 겁니다. 하지만 이미지는 해상도에 맞게 별도로 display 할 수 있습니다. @2x 나 @4x 라는 글자가 추가된 이미지들이 디바이스에 맞게 선택되서 출력 될 겁니다.

@2x와 @4x 뒤에 붙은 2와 4의 의미는 320X480을 기준으로 해상도가 2배 이면 @2x가 붙은 이미지를 보여주고 해상도가 4배이면 @4x가 붙은 이미지를 보여주라는 뜻 입니다.

Getting the Scale Factor

아래에 scale 과 관련한 약간의 트릭이 있습니다. 코로나 시뮬레이터에는 다양한 디바이스에 맞는 시뮬레이터 스킨이 있는데요 아래 코드를 main.lua에 넣고 시뮬레이터를 실행해 보세요.

local deviceWidth = ( display.contentWidth - (display.screenOriginX * 2) ) / display.contentScaleX
local scaleFactor = math.floor( deviceWidth / display.contentWidth )
print( scaleFactor )

위 코드가 하는 일은 device의 width을 얻어내서 이것을 content width로 나눕니다. 이러면 config.lua에 있는 해상도와 비교해서 지금 디바이스 해상도의 크기가 몇배인지 대략적으로 알 수 있습니다.

코로나 시뮬레이터(Corona Simulator)에서 각각의 device skin들을 바꿔가면서 테스트 해 보세요. 그러면 숫자가 바뀌는 걸 보실 수 있으실 겁니다. @2x 에 해당하는 값을 보시려면 iPhone4 시뮬레이터 스킨을 실행해 보시면 됩니다. 그러면 터미널에 2가 찍힐 겁니다. 그리고 iPad Retina 도 선택해 보세요. 그러면 숫자 4가 찍힐 겁니다. New ipad 이전의 iPad는 iPhone 해상도의 두 배 입니다.


Cross-Platform Apps

이 시나리오는 iPad 3를 비롯한 여러개의 디바이스에서 동시에 사용할 수 있도록 앱을 개발하려고 할 때 dynamic content scaling 을 사용할 수 있는 방법입니다.

좋은 소식은 바로 전에 보여드렸던 예제대로 하시면 된다는 겁니다. 단지 좀 더 많은 image suffixes 들이 config.lua의 imageSuffix 테이블에 정의 되어야 겠죠. 또한 이미지들도 여러 사이즈에 맞도록 미리 준비가 되어 있어야 하겠구요.

아래 예제가 있습니다.

application =
{
    content =
    {
        width = 320,
        height = 480,
        scale = "zoomStretch",

        imageSuffix =
        {
            ["@1-5"] = 1.5, -- for Droid, Nexus One, etc.
            ["@2x"] = 2,    -- for iPhone, iPod touch, iPad1, and iPad2
            ["@3x"] = 3,    -- for various mid-size Android tablets
            ["@4x"] = 4,    -- for iPad 3
        }
    }
}

이렇게 하시면 됩니다.

여기까지만 아시면 다양한 해상도를 가진 디바이스들에 (애플(Apple)의 뉴 아이패드(New iPad)를 포함해서) 맞는 이미지를 보여주기 위한 기본 세팅 방법은 모두 알고 계신 겁니다.

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

이런 방법으로 코딩은 아주 간단하게 해결할 수 있는데 해상도가 다르더라도 선명한 이미지를 보여주기 위해서는 아주 많은 이미지를 사용해야 하네요.
디자인 실력이 없는 프로그래머로서 이미지 하나 만드는것도 많이 신경쓰이고 시간이 많이 걸리는데..
이거 해결해줄 프로그램은 어디 없을까요???
반응형


반응형
App 마케팅과 관련한 기사가 떠서 소개해 드립니다.
Corona 에 대해 아주 좋게 얘기가 나와서 Corona에서 홍보를 했네요.
언론사의 기사라기엔 특정 회사의 이름이 너무 부각된게 아닌가 하는 느낌이 있긴 하네요.
(Corona 말고 GreatApps라는 회사도 나옵니다.)

하지만 앱 마케팅에 도움이 되는 기사이긴 합니다.
내 앱을 홍보하기 위해서는 앱에 대해 관심있는 사람들이 모이는 싸이트에서 열심히 활동하고 인정을 얻는것. 그래서 내가 글을 올렸을 때 좋은 반응을 얻게 만드는 것.
(이 글에서는 동양식으로 좋은 업보를 쌓으라고 표현했네요...)

예전에 SEO 강좌에서도 비슷한 내용이 언급 됐죠?
앱이 나왔을 때 뭐 마케팅할 방법이 뭐가 있지? 라고 고민하기 보단 평상시에 온라인을 통해 정보를 얻고 활동을 하고 좋은 네트워크를 만들고 이런 활동이 필요합니다.
오프라인에서도 아주 오랫동안 좋은 관계를 유지한 사람한테 일 새로 시작했는데 물건 하나 사주세요 라던지 우리한테 일을 맡겨주세요 라고 말하면 더 쉽게 영업을 할 수 있듯이 온라인도 마찬가지 아닐까요?

이런 활동도 하지 않으면서 마케팅 할 수 있는 방법이 왜 이렇게 없지? 라고 헤매는 사람이 되지 말아야 겠어요.

이 기사의 원본은 여기로 가시면 보실 수 있습니다.


5 Ways to Make Your App Take Off

Want your app to be the next Angry Birds or Pinterest? Try these expert strategies for getting it downloaded by the masses.
There are more than a million apps you can download to your mobile device. That’s good news for consumers, but not so great for developers. There’s so much competition in this noisy space that becoming the next Angry Birds or Pinterest is no simple feat. But there are a few things you can do to get your app noticed. Try these expert suggestions:

여러분 앱이 제2의 앵그리 버드나 Pinterest가 되길 원하세요? 그러면 이 전문적인 전략을 사용해 보세요.
여러분의 모바일 device에 다운로드 받을 수 있는 앱은 수백만개 됩니다. 소비자에게는 좋은 소식이죠? 하지만 개발자게에게는 그렇게 좋은 소식만은 아닙니다. 경쟁력이 너무 심해서 제2의의 앵그리버드나 Pinterest 가 되기는 그렇게 쉽지가 않습니다. 여기 여러분의 앱이 주목을 받게 할 몇가지 방법이 있습니다. 이 전문가의 추천을 참고해서 적용해 보세요.

1. Market your app far ahead of launching it.
1. 앱을 launching 하기 전에 마케팅을 하라.

According to Jesse Waites, author of “The Secrets Of My App Success,” it’s critical that you understand who your target market is and where they hang out online during initial product development. Find relevant Internet forums and meet-up groups and make them aware of your upcoming product. This is a great way to get feedback about your app before you even launch, as well as collect a database of potential customers. He says you should also have a widget on your website to collect the email addresses of these future customers so you can notify them when you finally release your product.

내 앱의 성공 비밀을 쓴 저자 Jesse Waites에 따르면 앱을 개발 할 때 이 앱의 타겟이 될 미래 고객을 분석하고 그들이 지금 온라인에서 어떻게 움직이고 있는지를 고려하는 것이 중요하다고 말합니다. 여러분이 개발하고 있는 앱과 관련있는 인터넷 포럼이나 동호회를 찾으세요. 그리고 그들에게 여러분의 앱이 조만간 출판 될 거라는 것을 알리세요. 이렇게 함으로서 여러분 앱이 다 개발되서 마켓에 나가기 전에 여러분의 앱에 대해 feedback을 받을 수 있는 아주 훌륭한 방법입니다. 그리고 잠재적인 고객에 대한 데이터를 모으세요. 저자는 말하길 여러분의 웹사이트에 이 미래의 고객들 이메일을 모을 수 있는 방법을 마련해야 한다고 합니다. 그런 후에 여러분의 상품이 release 될 때 그들에게 notify를 할 수 있습니다.

2. Get reviewed.
2. review를 받아라

Getting your app reviewed favorably is obviously a fantastic way to get people downloading it. iOS developers should definitely check out ManiacDev.com, which has compiled an exhaustive list of Apple app review sites listed in order of Alexa ranking. Many of these sites also review Android apps.

마켓에 올린 후에는 유저들이 댓글(review)를 좋게 올리도록 하는 것이 다른 사람들이 여러분 앱을 다운로드 받게 하는 아주 훌륭한 방법입니다. iOS 개발자들은 ManiacDev.com을 체크해야 합니다. ManiacDev.com은 Alexa ranking의  애플 앱에 대한  review 순위를 보여 줍니다. 또한 안드로이드 앱에 대한 review도 있습니다.

3. Try Corona by Ansca Mobile.
3. Ansca Mobile의 Corona를 이용하라.

Corona is the world’s No. 1 mobile app development platform and many developers have found that by using it not only do their apps work better, but they get more downloads. That’s because Ansca Mobile has partnered with some review sites and podcasts for apps such as 148apps.com, CrazyMikeApps.com, AppShrink.com, Experimental Game Dev Podcast, and MadDog Podcast.

코로나는 세계 제 1의 모바일 앱 개발 플랫폼입니다. 그리고 많은 개발자들이 이 플랫폼을 사용함으로서 앱 개발이 쉬워졌음은 물론이고 다운로드 수도 늘었습니다. 그 이유는 Ansca Mobile은 몇개의 review site들의 파트너사이고 148apps.com, CrazyMikeApps.com, AppShrink.com, Experimental Game Dev Podcast, and MadDog Podcast 샅은곳에 팟캐스트를 하고 있습니다.

Another great feature of the Corona platform is that it can quickly publish an app to multiple marketplaces simultaneously: the Apple App Store, Google Play (Android’s new name for its marketplace), Amazon (for the Kindle Fire) and Barnes and Noble (for the Nook Color tablet). And it’s cheap; a yearly subscription is only $349 or $199 if a developer only wants to build to one platform.

코로나 플랫폼의 또 다른 좋은 점은 빠른시간에 앱을 개발할 수 있고 동시에 애플 앱스토어, 구글 플레이 (안드로이드 마켓의 새 이름), 아마존 (킨들파이어), 반스 앤 노블즈 (Nook color tablet)에 올릴 수 있기 때문입니다. 그리고 코로나 SDK의 가격도 저렴합니다. 연 349불이고 한 마켓에만 올리기를 원하면 연 199불만 내시면 됩니다.

4. Use your online karma.
4. 온라인 업보(Karma)를 쌓아라

Denis Harscoat, co-founder of the action-tracking app DidThis recently got tech pundit Robert Scoble to feature a video blurb about the app on his YouTube channel. But before approaching Scoble about DidThis, Harscoat spent quite a bit of time making thoughtful commentary on Scoble’s blog posts so that when he wanted Scoble to check out his app (at a conference they were both attending), it was easier to get his attention.

액션 트래킹 앱인 DidThis를 공동 개발한 Denis Harcoat는 최근에 그의 유튜브 채널에 앱에 대한 비디오 안내문을 유명한 유튜브 파워블로거인 Robert Scoble의 블로그에 포스팅 되게 됐습니다. 이 DidThis 앱에 대해서 Scoble에게 approach하기 전에 Harscoat는 Scoble의 블로그에 많은 시간을 들여서 여러 충실한 댓글을 달았습니다. 그런 결과 harscoat가 Scoble에게 자신의 앱에 대한 검토를 부탁했을 때 (둘이 같이 참석한 컨퍼런스에서 부탁했답니다.) 그의 관심을 쉽게 끌 수 있었습니다.

Harscoat says DidThis also gleaned a lot of exposure after accumulating Karma points on Hacker News by engaging on the site. Later when he submitted to the site a link that touted his app, Harscoat’s network of supporters strategically up-voted it. “The key is to be genuinely part of a community where people care about certain things your app has a match with,” He says.

Harscoat는 이 DidThis 앱은 자신이 Hacker News 등에서 열심히 활동해 좋은 업보를 쌓은 덕분에 온라인 상에서 많이 노출되는 기회를 얻었다고 말합니다. 나중에 그 싸이트에 그의 앱에 대한 링크를 올렸을 때 Harscoat의 네트워크 지지자들이 많이 투표를 해 주었습니다. "키포인트는 진정성입니다. 사람들이 앱에 대해서 관심있어서 모이는 커뮤니티에 진정으로 열심히 참여하고 진정한 한 일부분이 되서 좋은 업보를 쌓아 두는 것입니다." 라고 그는 말합니다.

5. Get found when someone searches for “great apps.”
5. 누군가가 "좋은 앱"으로 검색할 때 나오게 하라

For as little as $95 you’ll get a year’s worth of promotion on GreatApps, which by way of its URL alone is getting about 40,000 unique visitors every month.  The marketing company also owns the singular domain GreatApp (minus the “s”) so when someone searches the Internet for “great apps” or “great app,” GreatApps almost always lands at the top of the search rank (even without quotes). And for every 50 apps that join its platform, Great Apps issues a press release touting them to more than 2,000 media outlets, although if you want to be included you’ll have to buy the highest level of membership, which is $495.

연 95불을 들여서 GreatApps의 프로모션에 투자를 하면 매달 4만의 방문자가 생길 수 있습니다. 이 마케팅 회사는 GreatApp이라는 단독 도메인을 소유하고 있기도 합니다. 그래서 누군가 인터넷으로 'great apps' 나 'great app' 으로 검색을 하게 되면 거의 항상 이곳이 top에 랭크 됩니다. 또한 그 플랫폼에 join한 50개의 앱들에 대해 Great Apps는 기사를 내 놓기도 합니다. 이 기사는 2천개가 넘는 미디어 싸이트에 광고 됩니다. 만약 여러분의 앱이 이 안에 들게 하고 싶으면 높은 레벨의 멤버가 되야 하구요 가격은 495불입니다.

Have other strategies worked well for you? If so, tell us in the comments about your app and how you’ve had success marketing it.
여러분 위 5개 이외에 여러분들이 사용한 다른 마케팅 전략이 잘 적용 되셨나요? 그렇다면 댓글로 남겨주세요. 어떤식으로 마케팅을 하셨는지요.

Christina DesMarais is an Inc.com contributor who writes about the tech start-up community, covering innovative ideas, news, and trends. Follow her tweets @salubriousdish or add her to one of your circles on Google+. Have a tip? Email her at christinadesmarais (at) live (dot) com. @salubriousdish


반응형

새로 추가된 이미지 캡쳐 기능

2012. 3. 21. 11:05 | Posted by 솔웅


반응형
Taking Snapshots of Objects and Groups

Corona Daily Build 2012.768 에서는 display.capture() 함수를 call 함으로서 간단히 display object (혹은 group) 를 snapshot 하는 새로운 기능이 추가 됐습니다.

이전에는 display.save() 함수를 사용해서 화면의 display 객체들을 저장했었습니다. 이번 display.capture()에서는 save to disk 부분을 거치지 않아도 됩니다. 그리고 snapshot의 새로운 display object로서 사용할 수도 있습니다.

이것은 기본적으로 display.captureScreen()과 같습니다. (display object를 return 한다는 점에서) 하지만 display.captureScreen()에서는 특정 display object나 display group을 따로 캡쳐할 수는 없습니다. display.captureScreen()은 화면 전체의 snapshot을 가져올 뿐입니다.

이번에 새로 추가된 display.capture()함수는 특정 객체나 그룹에 대해서만 snapshot을 할 수가 있습니다. 이 기능을 이용하면 아주 많은 부분에서 활용이 가능 하실 겁니다.

그리고 이 새로운 기능에서는 캡쳐된 스냅샷의 배경을 투명 처리 할 수도 있습니다. (display.captureScreen()과 display.save() 모두 백그라운드를 투명처리하지 못했습니다.)

NOTE : 안드로이드에서는 display.save() 기능이 업데이트 되서 백그라운드를 투명처리할 수 있게 됐습니다. 이것은 daily build 2012.768 부터 가능합니다. 아직까지 iOS에서는 지원이 안 됩니다.



Wait, display.save() can do the same thing!

display.capture() 가 아주 좋은 기능이라고 생각 되시죠? 그런데 display.save() 만 사용해서 저장된 이미지를 새로운 display 객체로 display.newImage()를 사용해서 로드할 수 있을까요?

배경 화면을 투명처리하는 것만 빼고는 가능합니다. display.capture() 가 하는 일과 똑 같이 display.save()를 사용해서도 할 수 있습니다. 그런데 여기에는 좀 큰 단점이 있습니다. 이미지를 디스크에 저장하고 이것을 다시 로드하는 과정에서 퍼포먼스에 큰 영향을 미치게 될 겁니다. 그러므로 display.save를 사용해서 하는 것보다 display.capture()를 사용하는 편이 훨씬 이로울 겁니다.

file I/O 과정을 생략하고 새로운 display 객체로 바로 이미지를 렌더링하는 것, display.capture()는 이런 점에서 display.save()를 사용하는 것 보다 훨씬 빠를 겁니다. 물론 display.save()도 아주 유용한 부분이 있죠. 이미지를 특정 위치에 save 해야 할 때는 display.save()를 사용 하셔야 합니다.

display.capture() Usage

신택스는 아래와 같습니다.
display.capture( displayObject [, saveToPhotoLibraryFlag ] )

아주 간단하죠? 아래 파라미터에 대한 설명이 있습니다.

displayObject — snapshot을 하고 싶은 display 객체나 그룹 입니다.

saveToPhotoLibraryFlag — 이 부분은 필수사항은 아닌데요. true로 설정하면 (디폴트는 false입니다.) 캡쳐된 객체는 display.captureScreen()의 같은 파라미터가 하듯이 디바이스의 photo library로 저장이 될 겁니다.

아래에 display.capture()를 사용하는 예제가 있습니다.

  local group = display.newGroup()

    local image1 = display.newImage( group, "image1.png" )
    local image2 = display.newImage( group, "image2.png" )

    -- take snapshot of the entire group
    local snapshot = display.capture( group )

    -- the object 'snapshot' is now another display object
    snapshot:translate( 100, 100 )
   
주의하셔야 할 부분은 display object가 return 됐을 때 이것은 캡쳐한 object 처럼 캡쳐되기 전과 같은 위치에 잊지 않을 거라는 겁니다. 디폴트로 return 된 display object는 0,0 에 위치합니다. 그러니까 좌상단에 위치하게 되죠. (디폴트로 이미지의 기준점은 이미지의 중앙이니까 실제로는 좌 상단을 더 벗어 나겠네요.)

반응형


반응형
Image Groups

Image Groups는 이번에 새로 소개되는 Corona의 기능입니다. 조금 전에 다뤘던 image sheets 와 이름이 비슷하긴 하지만 완전 다른 기능입니다. Image Groups는 일반 display groups의 sub class 입니다.

Here are the primary differences between Image Groups and normal Display Groups:
아래에 Image Groups가 일반 Display Groups 와 다른 점을 적어놓았습니다.

    Image sheet 객체로부터 생성된다.
    children은 반드시 같은 image sheet에서 나온 것이어야 한다.
    image group내의 모든 child 객체들에대해 제한을 갖는다.
    Image Groups는 nested 될 수 없다. (다른 image groups에 insert 될 수 없다.)

한개의 image sheet에서 나와야 한다? child 객체들에 제한이 있다? 여러분들은 이렇게 제한이 있으면 왜 일반적인 groups를 사용하지 않고 이 Image Groups를 사용해야 하는지 의아해 할 수 있습니다. 정말 그렇습니다. 하지만 여기 이 image groups를 사용함으로서 얻는 장점들도 있습니다.

객체들이 image group에 insert 될 때 일반 display object 들은 할 수 없는 몇가지 이미지 최적화 기능들을 사용할 수 있습니다. 여러분 앱이 최대의 퍼포먼스를 필요로 할 때 그리고 내부적인 그래픽 최적화를 필요로 할 때 바로 이 Image Groups 라는 것을 사용하시면 됩니다. 다음의 제한 사항이 여러분의 앱에 별 상관을 미치지 않을 때 사용하시면 되겠죠?

    image group에 insert 된 객체들은 개별적으로 Mask를 적용할 수 없다.
    nested image groups는 없다. 그러므로 같은 image sheet 안에 있는 다른 곳에 group화 되지 않은 객체만이 같은 image group에 insert 될 수 있다.
    per-object blend mode 가 없다. (image group에 insert 된 객체들에 대해)


How to Use Image Groups

Image Groups는 Image Sheets와 직접적으로 연결이 돼 있습니다. (그러니까 image sheet 을 제대로 보지 못했다면 Image Groups를 보기 전에 이전 글인 image sheet를 보셔야 합니다.)

Image Group Syntax:
display.newImageGroup( imageSheet )

imageSheet 파라미터는 graphics.newImageSheet()를 사용해서 생성한 image sheet 객체를 참고합니다. 한번 Image Group을 만들면 해당 imageSheet에 있는 객체들을 child 객체들로 image Group에 insert 할 수 있습니다.

아래 예제를 참고하세요.

-- assumes an image sheet has already been created
local imageGroup = display.newImageGroup( imageSheet )

local object1 = display.newImage( imageSheet, 1 )
local object2 = display.newImage( imageSheet, 2 )
local object3 = display.newImage( otherImageSheet, 2 )
local object4 = display.newImage( "image.png" )

-- insert objects into image group
imageGroup:insert( object1 )
imageGroup:insert( object2 )

-- lines below result in errors because 'object3' and 'object4'
-- do not belong to same image sheet as imageGroup
imageGroup:insert( object3 )
imageGroup:insert( object4 )

위 예제에서 보듯이 imageGroup은 약간 까다롭습니다. object3,object4 같이 다른 imageSheet나 imageSheet를 사용하지 않은 일반 이미지 객체는 위에서처럼 imageGroup에 insert 될 수 없습니다. 하지만 이렇게 사용하기 조금 불편하고 제약이 있음에도 불구하고 이 image group을 잘 사용하면 그렇지 않았을 경우에 나왔던 단점들을 훌륭하게 극복할 수 있습니다.

코로나는 일부 device에서 퍼포먼스의 문제가 있었습니다. 하지만 이 image groups를 사용함으로서 이러한 퍼포먼스 문제가 깨끗이 해결 됐습니다.
(저도 fireman -iPhone,iPad-, firefighter -Android- 앱을 개발 한 후에 퍼포먼스 문제로 아주 고민을 많이 했었거든요. 이 문제가 해결 됐다니 아주 반갑네요.)

Removing Image Groups

다른 display 객체들 처럼 image groups도 간단히 remove 할 수 있습니다. object:removeSelf()와 display.remove(object) 로 image groups도 remove 합니다. 이 작업을 한 다음에 nil을 대입해 주시는 걸 잊지 마세요.

image group이 child 객체들을 가지고 있다면 그 child들을 개별적으로 remove 한 다음에 image group을 remove 하시기를 권장해 드립니다.

Sprites

새로운 API인 image sheets, image groups 가 나오면서 기존에 있던 애니메이션을 위한 Corona Sprite API도 좀 더 쉽게 사용할 수 있도록 바뀌었습니다. 아래에 바뀐 sprite API에 대한 summary 가 있습니다.

    이전의 sprite sheets나 sprite sets 같은 혼란스러운 개념들 대신 그냥 image sheets를 사용해서 sprite animation 기능을 사용하시면 됩니다.
    변경된 API는 좀 더 직관적이고 이해하기 쉽습니다.
    image sheets를 사용함으로서 dynamic 하게 이미지 해상도에 맞게 작업을 해 줍니다. 다른 말로 이제 sprite를 사용함으로서 retina graphics를 아주 쉽게 사용할 수 있습니다.
    좀 더 파워풀하고 유연한 기능을 위해 새로운 프로퍼티들과 메소드들이 제공됩니다.
   
   
또한 sprite 객체들이 같은 image sheet에 있다면 image groups에 insert 할 수 있습니다. 이것을 사용하면 이전에 image groups에서 얘기했던 제한들이 sprite 객체에도 적용되게 됩니다.

Syntax
display.newSprite( [parent, ] imageSheet, sequenceData )
[Editors Note: Multisprites are not available yet. Sorry for the confusion]
[멀티 스프라이트는 아직 지원되지 않습니다. 혼돈을 드려서 죄송합니다.]

display.newSprite는 single image sheet에서 애니메이션 효과를 주는 객체를 생성하기 위해 사용하는 함수 입니다.
display.newMultiSprite()는 여러 image sheet으로부터 애니메이션 효과를 주기 위한 frame들을 불러와서 애니메이션 효과를 줄 때 사용합니다. 하지만 아직까지는 이 multi sprites는 지원되지 않습니다.

sequenceData는 특적 sequence에 대한 데이터를 가지고 있는 테이블 입니다. 혹은 single object에 대해 1개의 애니메이션 sequence 이상의 sequence를 가지고 있다면 sequenceData는 각각의 sequence에 대한 데이터를 가지고 있는 테이블 배열이 될 겁니다. 예를 들어 charactor 객체를 가지고 있다고 상상해 보면, 걷기, 점프하기, 수영하기 등의 각기 다른 애니메이션 효과를 가지고 있을 수 있습니다.
sequence는 해당 imagesheet의 순서대로 1,2,3,4 가 될 수 있고 1,3,4,6,9 처럼 순서대로 안 돼 있을 수 있습니다. 이 두 경우에 대한 예제를 모두 보시겠습니다.

Single Sequence; Consecutive Frames

아래의 경우는 1,2,3,4 처럼 한개의 image sheet에 있는 frame 순서대로 sequence가 이뤄지는 경우 입니다.

-- Example assumes 'imageSheet' already created from graphics.newImageSheet()

-- consecutive frames
local sequenceData = {
    name="walking",
    start=3,
    count=6,
    time=100, -- Optional. In ms. If not supplied, then sprite is frame-based.
    loopCount = 0 -- Optional. Default is 0 (loop indefinitely)
    loopDirection = "bounce" -- Optional. Values include: "forward","bounce"
}

local character = display.newSprite( imageSheet, sequenceData )

Single Sequence; Non-Consecutive Frames

아래 예제는 frame의 순서와 상관없이 sequence가 이뤄지는 경우인데요. 기본적으로 위의 예제와 같습니다. 다만 frames라는 배열을 넣어야 하는데 이것은 image sheet 안의 frame들의 index들을 넣은 배열입니다.

-- Example assumes 'imageSheet' already created using graphics.newImageSheet()

-- non-consecutive frames
local sequenceData = {
    name="walking",
    frames= { 3, 4, 5, 6, 7, 8 }, -- frame indexes of animation, in image sheet
    time = 50, -- Optional. In ms. If not supplied, then sprite is frame-based.
    loopCount = 0 -- Optional. Default is 0.
}

local character = display.newSprite( imageSheet, sequenceData )

Multiple Sequences

아래 예제는 하나의 sprite 객체에 어떻게 여러개의 애니메이션 sequence들을 가질 수 있는지를 보여 줍니다.
보시면 각 애니메이션 별로 1,2,3,4 처럼 순서대로 index를 사용할 수 있고 비 순서적으로 frame 인덱스를 넣어서 애니메이션을 만드실 수도 있습니다.

-- Example assumes 'imageSheet' already created using graphics.newImageSheet()

local sequenceData = {
    { name="walking", start=1, count=3 },
    { name="running", frames={ 3, 4, 5, 6, 7, 8 }, time=50, loopCount=4 },
    { name="jumping", start=9, count=13, time=300 }
}

local character = display.newSprite( imageSheet, sequenceData )

start/count, frame 파라미터이외에 다른 sequenceData 파라미터들이 있습니다.
아래 내용을 참조하세요.
   
    name - sequence에 대한 unique한 이름 애니메이션이 실행 될 때 이 name을 사용해서 sequence를 load 합니다.
    start & count - consecutive-frame sequences (순차적인 frame 시퀀스)를 위한 파라미터 입니다. start는 시작하는 frame이고 count는 start 부터 끝나는 frame 까지의 index 갯수를 말합니다.
    frames - non-consecutive-frame sequence (비 순차적인 frame 시퀀스)를 위한 파라미터 입니다. 애니메이션을 위해 play 되는 frame 들의 순차적이지 않은 index 데이터를 말합니다.
    time - 각 frame들 사이의 시간 (밀리세컨드)을 말합니다. 이 숫자를 지정하지 않으면 여러분 앱의 기본 framerate을 사용하게 됩니다.
    loopCount - 애니메이션이 몇번 일어나는지 그 숫자를 써 넣으시면 됩니다. 1을 넣으면 애니메이션이 1번 일어나고 멈추게 됩니다. 디폴트는 0이구요 애니메이션이 계속 반복되는 겁니다.
    loopDirection - forward 와 bounce가 있습니다. 둘 중에 아무것도 지정하지 않으면 디폴트인 forward가 지정됩니다. bounce는 forward로 진행했다가 다시 start로 가지 않고 backward로 진행하는 겁니다.
    imageSheet - 이 파라미터는 multi-sprite를 사용할 경우에 필요한 겁니다. (display.newMultiSprite). 해당 시퀀스가 속한 image sheet를 표시합니다. 하지만 아직까지는 multi sprite를 지원하지 않기 때문에 이 파라미터를 사용할 일은 없습니다.

Using “Old” Spritesheet Data

많은 third-party 툴들이 old spritesheet 데이터 포맷을 사용해서 작업을 합니다. 그래서 image sheet 객체를 생성할 때 이 데이터 포맷을을 사용할 수 있도록 했습니다. 아래 그 방법을 보시죠.

local oldStyleSpriteSheetData = require("uma").getSpriteSheetData()

local options =
{
    spriteSheetFrames = oldStyleSpriteSheetData.frames
}

local imageSheet = graphics.newImageSheet( "uma.png", options )

Sprite Properties

일반적인 display object 프로퍼티 이외에 sprite에서 사용하는 프로퍼티들이 있습니다.

    spriteObject.frame – Read-only – 로드된 시퀀드싀 frame index를 보여 줌
    spriteObject.numFrames – Read-only – 로드된 시퀀스의 frame 갯수를 보여 줌
    spriteObject.isPlaying – Read-only – 이름 그대로 현재 플레이되고 있는지 여부를 알려 줌.

Sprite Methods

아래는 display.newSprite()로 생성된 모든 object들과 연관된 sprite만의 메소드들입니다.

    spriteObject:setSequence( name ) – name을 가지고 애니메이션 시퀀스를 로드함. name 파라미터가 없을 경우 현재 로드된 시퀀스의 첫번째 프레임이 보여지게 됩니다.
    spriteObject:play() – 현재 로드된 시퀀스를 플레이 합니다.
    spriteObject:pause() – 시퀀스내의 현재 보여지는 프레임에서 pause 합니다.

Sprite Listener

old API를 보시면 sprite 객체들은 리스너 함수를 사용해 sprite event를 listen 할 수 있습니다. 이벤트 프로퍼티가 변경됐는데요, 지금은 began과 ended event phase 가 있습니다.

Here’s an example:

local function spriteListener( event )
    if event.phase == "began" then
        -- sequence has began playing; do something

    elseif event.phase == "ended" then
        -- sequence has reached the last frame; do something
    end
end
 
-- Add sprite listener
spriteObject:addEventListener( "sprite", spriteListener )

우리는 이 스프라이트 리스너 함수를 좀 더 유용하게 사용할 수 있도록 작업을 하고 있습니다. 조만간에 공개 될 겁니다.

Removing Sprite Objects

sprite 객체들은 다른 일반 display 객체들을 remove 하듯이 remove 하시면 됩니다. object:removeSelf()를 사용하시고 display.remove(object) 도 사용하세요. 이 작업을 한 다음에 nil값을 대입시키는 것도 잊지 마시구요.

Frame Trimming Not Yet Supported

Image Sheets 나 새로운 Sprite API에서 아직 지원하지 못하는 부분이 있는데 그것은 tril/crop frames 기능입니다. 이 기능이 가능할 수 있도록 지금 현재 작업중에 있습니다. 완료되면 공개 하겠습니다.



Wrapping it all up…

여러 이미지를 하나의 이미지 파일에 넣어서 각각의 이미지를 image sheet나 sprite API를 사용한 애니메이션으로 사용하는 방법을 다뤘습니다.
그런데 저는 개발자로서 그래픽 작업하는게 많이 부담 됩니다.
여러 이미지를 하나의 파일로 만들어야 되고 각각의 이미지들 규격도 알아내야 되고...
이러한 작업을 해 주는 third-party 제품들이 있습니다.
코로나에서는 SpriteLoqTexture Packer 를 추천하고 있습니다.
필요하신 분 잘 활용하세요..
저도 필요하긴 합니다.
요즘 시간적인 여유가 좀 생겨서 개인 프로젝트를 시작하려고 하는데요.
그래픽 부분이 부담 되서....
하여간 새로운 기술들을 잘 활용해서 개성있는 앱을 하나 만들어 보려고 합니다.
반응형