Basic Screen Shapes
너비와 높이가 360×570인 이미지가 있다고 가정해 봅시다. 우리는 실제 화면보다 더 큰 배경이미지를 만들겁니다. 왜냐구요? 그 이미지를 여러 디바이스에서 다 사용할 거거든요. 안쪽 사각셩( inner rectangle)은 320×480 block 입니다. 아마 이미지의 맨 가장자리 부분은 화면 밖으로 나갈 겁니다. 이것을 iPhone 5 나 대부분의 안드로이드 폰 같은 tall device 에서는 이 이미지의 full height를 이용할 겁니다. 그 경우에도 왼쪽과 오른쪽 가장자리는 화면 밖으로 나가게 될 겁니다. 여러분이 좀 더 정사각형에 가까운 iPad 를 가지고 있다면 그 이미지는 위와 아래쪽 가장자리가 잘리고 왼쪽과 오른쪽은 모두 다(full width) 보일 겁니다. 이렇게 밖으로 나가는 부분은 “bleed area” 라고 합니다. 일반 인쇄를 할 때 종이 여백에 잉크가 번질 수도 있는 그런 여분의 공간을 말할 때 그 말을 사용합니다.
이제 어떻게 background 가 사용되는지 이해하고 직접 볼 수 있습니다. 바로 config.lua file 에 셋업하시면 됩니다. 이 파일은 standard Corona Lua file 이기 때문에 아래 사항을 구현하기 위해 몇가지 API 를 사용할 수 있습니다.
- read the pixel width/height of the device. 디바이스 너비 높이 얻기
- use math for various calculations. 다양한 계산을 위해 math 사용하기
- read the device model number. 디바이스 모델 번호 얻기
- perform string manipulations. string manipulation 사용하기
- use conditional “if-then-else” logic. if 문 사용하기
iPad Configuration
우리가 할 첫번째 작업은 앱이 실행되는 기기가 아이패드일 경우에 대한 코딩입니다. 아래 Corona API 로 모델 number 를 얻을 수 있습니다.
system.getInfo("model")
실제 지금 아이패드에서 실행하면 string iPad를 결과 값으로 얻으실 겁니다. 그런데 아마 애플은 조만간 이것을 바꿀 수도 있습니다. iPad Retina 뭐 이런걸로요. 그러니까 if 문을 사용해서 이런 경우에도 대비를 해 두는게 낫겠죠.
if ( string.sub( system.getInfo("model"), 1, 4 ) == "iPad" ) then
application = { content = { width = 360, height = 480, scale = "letterBox", xAlign = "center", yAlign = "center", imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, }, }, }
코로나는 루아의 string.sub() 함수를 사용합니다. 디바이스 모델을 읽은 뒤 앞의 4글자만 취하게 되죠. 그러니까 애플이 iPad 뒤에 무엇을 넣던지 이 로직에서는 상관이 없겠죠. 이 경우 얻은 글자가 iPad이면 content table을 작성할 건데요. width and height parameters 들은 각각 360 and 480 으로 합니다. 여기서 너비를 360으로 하는 이유는 우리가 사용하는 샘플 이미지의 너비가 360 픽셀이기 때문입니다. 우리는 이 이미지를 아이패드 스크린에 맞게 이미지를 늘릴겁니다. 코로나는 기본으로 portrait 을 사용합니다. 만약 여러분 앱이 landscape 모드를 사용한다면 그 이미지를 portrait orientation 을 가정해서 거기에 맞게 너비와 높이를 정해야 합니다. 그러면 코로나가 자동으로 알아서 기기를 세웠을 때와 뉘었을 때에 맞게 알아서 이미지를 돌려 줍니다.
너비가 360 이니까 이제 높이를 계산해야죠. 이 높이도 iPad 의 화면에 딱 맞게 해야 합니다. iPad 스크린은 768X1024 입니다. 그리고 Retina iPad 인 경우는 1536X2048 이죠. (정확히 두배입니다. 그러니까 그 비율은 정확히 같은 겁니다.) 우선 첫번쨰로 1024를 768로 나눕니다. 그 결과는 1.33 이 됩니다. 그리고 높이를 얻기 위해 360X1.33을 합니다. 그러면 480이 되겠죠.
1024 / 768 = 1.33 --screen ratio (height:width) 1.33 x 360 = 480
iPhone5 Configuration
elseif ( string.sub( system.getInfo("model"), 1, 2 ) ==
"iP" and display.pixelHeight > 960 ) then
application = { content = { width = 320, height = 568, scale = "letterBox", xAlign = "center", yAlign = "center", imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, }, }, }
아이폰의 경우는 모델 string 에서 첫 두글자만 취하겠습니다. iPad 하고 iPod Touch 둘 다 iP 로 시작하는데 왜 그렇게 하냐구요? 그래서 이것 말고 디바이스의 pixelHeight 를 구할 거거든요. (이 pixelHeight 프로퍼티는 Corona build #971 에서부터 지원했습니다. 그러니까 그 아래 버전을 사용하시는 분은 그 상위 버전을 download 하세요.) 만약 그 pixel heignt 가 960 보다 크다면 그 디바이스는 iPhone 5 가 되는 겁니다. (아니면 iPod Touch 최신버전이던가요.) 그 디바이스의 해상도는 640 X 1136 이니까 이것을 320 pixel로 그 비율을 맞춘다면 320×568 이 됩니다.
그래서 너비와 높이늘 320×568 로 해 주시면 됩니다.
위 계산대로 하면 배경 이미지의 높이가 iPhone 5 의 높이에 딱 맞게 표시 될 겁니다. iPhone 5의 실제 해성도는 640X1136 이구요 우리 이미지의 안쪽 사각형 (inner rectangle" 이 너비가 320 이니까 이걸 가지고 아래처럼 간단히 계산하면 그 비율에 맞는 높이를 구할 수 있습니다.
320 / 640 = 0.5 --inner rectangle width / device pixel width = factor 1136 × 0.5 = 568 --device pixel height × factor = config.lua 'height' setting
우리가 가지고 있는 샘플 배경 이미지의 높이는 570 입니다. 그러니까 iPhone 5 화면에서는 위와 아래쪽에 각각 1pixel 씩 화면 밖으로 나갈 겁니다.
iPhone 3,4 and Older iPod Touch
elseif ( string.sub( system.getInfo("model"), 1, 2 ) == "iP" ) then
application = { content = { width = 320, height = 480, scale = "letterBox", xAlign = "center", yAlign = "center", imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, }, }, }
위쪽에서 이미 iPhone 5 를 사용했으니까 다음 else if 문에서 모델이 iP 로 시작하는 스트링을 얻는다면 그것은 이전 버전의 iPhone 이나 iPod Touch 가 될 겁니다. 해상도는 320X480 과 640X960 이렇게 두 종류가 있죠. 이 경우에는 우리가 가지고 있는 이미지의 inner rectangle 인 320X480 을 사용할 수 있습니다.
Android, Kindle Fire, and Nook
마지막으로 우리는 16:9 인 안드로이드 디바이스와 5:3 인 NOOK 과 Kindle Fire 디바이스를 따로 작성해야 합니다. 16:9 device 들은 그 비율이 1.777:1 이 됩니다. Nook 과 Kindle Fire 는 1024X600 에 가깝구요 그 비율은 1.7:1 이 됩니다. 그러니까 이 경우 화면 크기 비율을 계산하기 위해 pixelHeight and pixelWidth를 사용할 수 있겠죠. 만약 그것이 1.72 보다 크면 iPhone 5 와 비슷한 16:9 로 계산하면 될 겁니다. 만약 그렇지 않으면 그 기기에 맞도록 너비와 높이를 세팅해야 겠죠.
elseif ( display.pixelHeight / display.pixelWidth > 1.72 ) then
application = { content = { width = 320, height = 570, scale = "letterBox", xAlign = "center", yAlign = "center", imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, }, }, }
else application = { content = { width = 320, height = 512, scale = "letterBox", xAlign = "center", yAlign = "center", imageSuffix = { ["@2x"] = 1.5, ["@4x"] = 3.0, }, }, }
end
Important Notes
여기에 완성된 파일이 있습니다. 이 파일만 사용하시면 현재까지 나온 대부분의 디바이스들이 cover 될 겁니다. 아래 사항들을 기억해 두세요.
- On some devices parts of the background will be off screen, so don’t put anything “critical” in the bleed areas.
- Objects positioned using fixed numbers like player.x = 64 and player.y = 64 will always be 64 points away from the top and left edges, but based on the device will be closer or further away from center. Likewise, objects placed using the right and bottom edges will stay the prescribed distance away from those edges (player.x = display.contentWidth-64 will stay 64 points away from the right edge) but they will move closer or further from the center too. Objects positioned based on a center coordinate (player.x = display.contentCenterX+100) will stay in the same relative position regardless of the screen shape.
Dynamic Image Selection
각 configuration block 에는 아래와 같이 imageSuffix table 이 있습니다.
imageSuffix =
{ ["@2x"] = 1.5, ["@4x"] = 3.0,},
만약 코로나를 처음 접해 보신다면 이 방법이 바로 코로나 SDK 가 Dynamic Image Selection을 지원하는 부분이라는 점을 알고 계시면 됩니다. 예를 들어 여러분이 Retina iPad 와 iPhone 3GS 에 같은 이미지를 사용하지 않고 해상도를 충분히 지원해 주는 그런 이미지를 별도로 사용하고 싶으실 수 있을 겁니다. 그러면 이 image sets 를 일반 디바이스와 Retina/HD 디바이스에 맺게 각각 다르게 세팅하시면 그 디바이스 해상도에 맞게 작업하신 이미지를 자동으로 바꿔서 display 할 수 있습니다.
imageSuffix table 은 두개의 부분으로 구성돼 있습니다.
["@2x"] = --append this suffix to all images designed for those device(s) (decimal value) --scale factor that Corona uses to pick the proper assets
첫번째 값은 여러분이 이름을 정해 주시면 됩니다. 두번째 값은 아래 공식에 의해 계산된 값입니다.
device width / config.lua 'width' = scale factor
아래와 같이 세팅하시면 될 겁니다.
["@2x"] = 2.0 ["@4x"] = 4.0
저희들이 계산한 아래 예제들을 참조하세요.
600 / 320 = 1.875 --Kindle Fire & Nook 640 / 320 = 2.0 --iPhone 5 768 / 360 = 2.13 --iPad 800 / 320 = 2.5 --Kindle Fire HD / Nexus7 1200 / 320 = 3.75 --Kindle Fire HD 8.9 1536 / 360 = 4.26 --Retina iPad
만약 여러분이 4.0 으로 세팅했다면 이것은 Retina iPad 에만 적용 되고 Kindle Fire HD 8.9 이하에는 적용되지 않을 겁니다. 즉 Retina iPad 전용 이미지가 되는 것이죠.
그런데 대개 Kindle Fire HD 8.9 와 Retina iPad 에는 같은 이미지를 사용해도 문제가 없습니다.
그래서 다운 받은 configuration file 에는 아래와 같이 세팅 돼 있을 겁니다.
["@2x"] = 1.5, ["@4x"] = 3.0,
이렇게 하면 해당 “@4x”
image 는 Retina iPad, Kindle Fire HD
8.9, and the Nexus 10 같은 고 해상도 디바이스용 이미지를 별도로 사용할 때 유용할 수 있습니다. 그 이외의 디바이스들은 “@2x”
images 를 사용할 겁니다.
끝으로 중요한 것 한가지 더 언급해 드린다면 배경을 display 하기 위해 display.newImageRect() 를 사용하시라는 겁니다.
local background = display.newImageRect( "background.png", 360, 570 )
끝의 두 숫자 360과 570 은 1X 에 근거한 이미지의 너비와 높이 입니다. 샘플 파일에서는 lowest resolution target device 가 original Kindle Fire 와 NOOK Color 로 돼 있습니다. 이 디바이스들과 “@2x” bracket 에 속하는 다른 디바이스들은 코로나에서 720X1140 을 사용할 거고 “@4x” version 에서는 1440X2280 을 사용할 겁니다. 이런 작업들은 코로나가 알아서 할 거니까 별로 크게 신경 안 쓰셔도 됩니다.
In Summary…
이 튜토리얼은 약간 detail 한 부분까지 설명 했습니다. 코로나를 처음 접해 보시는 분들에게는 좀 더 간단히 설명해 드릴 필요가 있을 텐데요. 위에 저희가 샘플 파일을 다운로두 받을 수 있도록 했으니 그 config.lua file 을 받으셔서 잘 분석해 보시고 또 실제로 적용해 보시면 이해하시는데 도움이 되실 겁니다. 아직 다운 받지 않으신 분들을 위해서 여기 다운 받으실 링크를 다시 알려 드릴께요.
Multi-Element Physics Body 다루기 (0) | 2013.01.11 |
---|---|
내 앱에 애플의 iAds 광고 달기 (0) | 2013.01.03 |
코로나의 Holiday Gifts : Android Push Notification 등 등 (0) | 2012.12.30 |
iOS 에 구글 맵이 돌아왔다. (Corona의 구글 맵 지원 기능 소개) (2) | 2012.12.19 |
간단하게 Device 분별하는 예제 (0) | 2012.12.13 |
physics engine (물리엔진)의 새로운 기능 event.contact 소개 (0) | 2012.11.29 |
새 위젯 사용하기 Part 1 (0) | 2012.11.08 |
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
'Corona SDK > Corona Doc' 카테고리의 다른 글
내 앱에 애플의 iAds 광고 달기 (0) | 2013.01.03 |
---|---|
코로나의 Holiday Gifts : Android Push Notification 등 등 (0) | 2012.12.30 |
iOS 에 구글 맵이 돌아왔다. (Corona의 구글 맵 지원 기능 소개) (2) | 2012.12.19 |
간단하게 Device 분별하는 예제 (0) | 2012.12.13 |
다양한 디바이스 해상도에 맞게 이미지 표시하기 - config.lua file- (0) | 2012.12.06 |
새 위젯 사용하기 Part 1 (0) | 2012.11.08 |
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
'Corona SDK > Corona Doc' 카테고리의 다른 글
코로나의 Holiday Gifts : Android Push Notification 등 등 (0) | 2012.12.30 |
---|---|
iOS 에 구글 맵이 돌아왔다. (Corona의 구글 맵 지원 기능 소개) (2) | 2012.12.19 |
간단하게 Device 분별하는 예제 (0) | 2012.12.13 |
다양한 디바이스 해상도에 맞게 이미지 표시하기 - config.lua file- (0) | 2012.12.06 |
physics engine (물리엔진)의 새로운 기능 event.contact 소개 (0) | 2012.11.29 |
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
스토리 보드 기본 사용법 (1) | 2012.08.23 |
'Corona SDK > Corona Doc' 카테고리의 다른 글
iOS 에 구글 맵이 돌아왔다. (Corona의 구글 맵 지원 기능 소개) (2) | 2012.12.19 |
---|---|
간단하게 Device 분별하는 예제 (0) | 2012.12.13 |
다양한 디바이스 해상도에 맞게 이미지 표시하기 - config.lua file- (0) | 2012.12.06 |
physics engine (물리엔진)의 새로운 기능 event.contact 소개 (0) | 2012.11.29 |
새 위젯 사용하기 Part 1 (0) | 2012.11.08 |
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
스토리 보드 기본 사용법 (1) | 2012.08.23 |
메모리 부족 경고 시 처리 방법 (2) | 2012.08.17 |
'Corona SDK > Corona Doc' 카테고리의 다른 글
간단하게 Device 분별하는 예제 (0) | 2012.12.13 |
---|---|
다양한 디바이스 해상도에 맞게 이미지 표시하기 - config.lua file- (0) | 2012.12.06 |
physics engine (물리엔진)의 새로운 기능 event.contact 소개 (0) | 2012.11.29 |
새 위젯 사용하기 Part 1 (0) | 2012.11.08 |
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
스토리 보드 기본 사용법 (1) | 2012.08.23 |
메모리 부족 경고 시 처리 방법 (2) | 2012.08.17 |
화면 전환 하면서 state(상태) 관리하기 (0) | 2012.08.09 |
화요일의 Tutorial이 다시 돌아왔습니다. 오늘의 튜토리얼은
Brent
Sorrentino 가 작성한 건데요. Northern Colorado 에서 Corona Ambassador 로 활동하고 있습니다. Brent는 2년여 코로나 커뮤니팅서 활발히 활동하고 있습니다. 그는 프리랜서 여행사진작가이고 코로나 개발자이며 그래픽 디자이너 입니다. 그만의 앱을 개발하기 위해 코로나를 사용하고 있습니다. 또한 정기적으로 포럼에서 여러사람에게 도움을 주고 있고 여러 이슈들을 해결해 주고 있습니다 그의 웹사이트를 보시려면 여기를 클릭하세요.
오늘의 튜토리얼은 어떻게 animated sprite를 implement 할 것인가와 그와 관련된 API 들에 관한 겁니다. 아마 이전 튜토리얼에서 다룬 내용도 있을 겁니다. 올해 초 현재의 스프라이트 시스템이 소개 된 이후 몇가지 주요 개선사항이 있었습니다. 그리고 많은 개발자들이 아직도 코로나에서 어떻게 sprite를 implement 하는지에 대해 혼동을 하고 있습니다. 이 sprite를 사용하는 방법에는 두가지가 있습니다.
- The old (and now depreciated) sprite.* library.
- The current sprite APIs that work cohesively with image sheets and the display.* library.
이렇게 코로나의 스프라이트 라이브러리가 변화를 보였는데요. 그 중에서 현재 버전을 사용할 것을 강력히 추천합니다. 현재 방법을 사용하지 않았거나 코로나에서 스프라이트를 한번도 사용해 보지 않았다면 이 튜토리얼이 많이 도움이 될 겁니다.
코로나의 basic animation에 이미 익숙하신 분이라면 이 튜토리얼이 sprite event listeners에 대한 모든 정보를 제공하고 어떻게 implement 할 것인지를 가이드 해 드릴 겁니다.
Tutorial Contents
- Configuring a Basic Image Sheet or “Sprite Sheet”
- Defining Animation Sequences
- Declaring a Sprite Object
- Sprite Control Methods — managing playback and sequences
- Sprite Properties — accessing and setting various sprite properties
- Sprite Event Listeners — detecting sequence events such as “ended”, “loop”, and “next”
- Frame Trimming Support
Configuring a Basic Image Sheet or “Sprite Sheet”
정확히 image sheet 이 뭘까요? 한번 상상해 보세요. 여러분들의 animated object 들을 위해 각각 의 프레임들을 그린 한장의 종이가 있다고요. 코로나에서 다른 전문적인 용어로는 texture atlas, image map, or sprite sheet 라고 합니다. 이걸 그냥 간단히 image sheet라고 부를께요. 이것은 static 이든 animated object 이든지 상관없이 활용할 수 있습니다.
graphics.newImageSheet() API에 대한 자세한 사용법과 샘플들은 여기에 있습니다. 이 튜토리얼에서는 그중에서 어떻게 animated sprite를 위해 image sheets를 사용할지에 대해 다루겠습니다.
아래 그림은 running cat 을 표현하는 샘플 image sheet 입니다. 이 튜토리얼을 공부하면서 이 이미지를 사용하시려면 여기에 hi-resolution version 이미지가 있습니다. 이 sheet 에는 8개의 프레임이 순서대로 있습니다. 디폴트로 애니메이션은 top-left frame 부터 시작해서 오른쪽으로 진행하죠. 오른쪽 끝까지 가면 그 다음 줄로 갑니다. 그리고 전체 프레임을 다 돌면 중지합니다.
코로나에서 이 image sheet 을 어떻게 다루는지 보겠습니다. 우선 uniform-sized frame 인 basic image sheet 를 위해 indexed table을 setup 합니다.
local sheetData = {
width = 512,
--the width of each frame height = 256,
--the height of each frame numFrames = 8,
--the total number of frames on the sheet sheetContentWidth = 1024,
--the total width of the image sheet (see note below)
sheetContentHeight = 1024
--the total height of the image sheet (see note below)
}
IMPORTANT: sheetContentWidth 와 sheetContentHeight는 overall 1:1 dimensions of the image sheet (전체 가로 세로)를 나타냅니다.1:1 content scale 은 여러분이 앱의 config.lua file에 set up 한 내용을 기준으로 합니다. 이렇게 하면 다른 디바이스별로 다른 이미지를 사용할 수 있도록 합니다. 예를 들어 @1 sheet는 original iPad 에 맞는 이미지를 사용하고 high-resolution @2 sheet 는 Retina iPad 에 맞는 이미지를 사용할 수 있습니다. 그러니까 1:1 sheet이 1024×1024 pixels 이라면 2:1 sheet 는 2048×2048 인 이미지가 되는거죠. image sheet setup에는 항상 1:1 dimensions를 사용하세요. config.lua file 세팅이 정확하다면 그 다음부터는 코로나가 알아서 처리할 겁니다.
이제 실제 image sheet 를 정의하세요. 괄호 안에 image file 과 위에 정의한 data table을 넣어주시면 됩니다. 아래처럼 파일이름만 넣으면 그 이미지 파일을 여러분 프로젝트 디렉토리의 root 에서 찾을 겁니다.
local mySheet = graphics.newImageSheet( "runningcat.png", sheetData )
Defining Animation Sequences
여러분은 두가지 방법으로 animated frame 순서를 정하실 수 있습니다.
- consecutively using a starting frame index and frame count
- non-consecutively using a specific order of frames
이 두 가지 방법으로 코로나에서 sprite system 을 아주 flexible 하게 사용하실 수 있습니다. 하나의 image sheet 으로 여러 animation sequences를 사용해서 활용할 수가 있죠. 두 경우 모두 sub-table에서 comma-separated array 로 sequences를 define 하시면 됩니다.
Consecutive frames
local sequenceData = {
{ name = "normalRun", --name of animation sequence
start = 1, --starting frame index
count = 8, --total number of frames to animate consecutively before stopping or looping
time = 800, --optional, in milliseconds; if not supplied, the sprite is frame-based
loopCount = 0, --optional. 0 (default) repeats forever; a positive integer specifies the number of loops
loopDirection = "forward" --optional, either "forward" (default) or "bounce" which will play forward then backwards through the sequence of frames
} --if defining more sequences, place a comma here and proceed to the next sequence sub-table
}
Non-consecutive frames
local sequenceData = {
{ name = "fastRun",
frames = { 1,2,4,5,6,7 }, --specific order of frame indexes from the image sheet
time = 250, loopCount = 0
} --if defining more sequences, place a comma here and proceed to the next sequence sub-table
}
Mixed sequences (both consecutive and non-consecutive sequences)
local sequenceData = {
{ name="normalRun", start=1, count=8, time=800 },
{ name="fastRun", frames={ 1,2,4,5,6,7 }, time=250, loopCount=0 }
}
Declaring the Sprite Object
현재의 sprite method를 사용하려면 display.newSprite() API 로 sprite를 선언하셔야 합니다. 신택스는 간단합니다.
display.newSprite( [parent,] imageSheet, sequenceData )
- parent = The parent display group in which to insert the sprite (optional).
- imageSheet = The image sheet which the sprite should utilize.
- sequenceData = The array of animation sequences which you set up. The sprite will default to the first sequence in the array unless you specify otherwise (see Sprite Control Methods below).
이 튜토리얼에 나온 예제로 한다면 sprite 선언은 아래와 같을 겁니다.
local animation = display.newSprite( mySheet, sequenceData )
이제 이 sprite 는 display object가 됐습니다. 그냥 일반 static image, vector objects 같은 것들과 같게 됐죠. 이제 이 sprite 는 움직일 수도 있고 manipulated 될 수도 있고 physics body 를 입힐 수도 있고... 등등을 할 수 있습니다. 이 sprite object 를 remove 시키려면object:removeSelf() 나 display.remove( object ) 를 사용하시면 됩니다. remove 한 다음에 nil로 세팅하는 것을 잊지 마세요.
Sprite Control Methods
이 스프라이트 시스템은 4가지 주요 control methods를 제공합니다. 여러분들은 이것으로 스프라이트의 playback과 sequence 를 control 하실 수 있습니다.
- animation:play()
Start the animation playing. Animations do not begin playing when you create them — you must start each animation manually using this command. - animation:pause()
Pauses the animation. There is no “stop” control method; instead, pause the animation using this method. - animation:setFrame( frame )
Immediately set or skip to the indicated frame index. If you want to “stop and reset” an animation sometime after you have started playing it, use the :pause() and :setFrame( frame ) commands consecutively, setting the frame back to the beginning of the sequence. - animation:setSequence( sequence )
Set the sprite to a specific sequence that you declared in your sequence array. For example, if you want to change your cat animation from “normalRun” to “fastRun”, you would use animation:setSequence( “fastRun” ) and use animation:play() to begin playing it, since the animation will not play automatically after you change the sequence.
Putting It Together
전체 애니메이션을 함께 넣어보죠. 달리는 고양이를 normalRun 과 fastRun 두가지로 셋업할 겁니다. 아래 예제가 있습니다.
local sheetData = { width=512, height=256, numFrames=8,
sheetContentWidth=1024, sheetContentHeight=1024 }
local mySheet = graphics.newImageSheet( "runningcat.png", sheetData )
local sequenceData = {
{ name = "normalRun", start=1, count=8, time=800 },
{ name = "fastRun", frames={ 1,2,4,5,6,7 }, time=250 }
}
local animation = display.newSprite( mySheet, sequenceData )
animation.x = display.contentWidth/2 --center the sprite horizontally
animation.y = display.contentHeight/2 --center the sprite vertically
animation:play()
Sprite Properties
Corona provides several properties which can yield information about existing sprites. You can even modify the timeScale (relative speed) of a particular sprite. These properties are as follows:
코로나에는 현재의 스프라이트에 적용할 수 있는 몇가지 프로퍼티들을 제공합니다. 특정 스프라이트의 timeScale (relative speed)를 modify 할 수도 있습니다. 아래 프로퍼티들을
- object.frame
A read-only property that represents the currently shown frame index of the loaded sequence. This does not set the frame — use the :setFrame() command to explicitly set an animation frame. - object.isPlaying
Returns true if the animation is currently playing; false if it is not. - object.numFrames
A read-only property that represents the number of frames in currently loaded sequence. - object.sequence
A read-only property that returns the name of the currently playing sequence. - object.timeScale
Gets or sets the scale to be applied to the animation time. This is used to control a sprite’s animation speed dynamically. For example, a time scale of 1.0 (default) runs the animation at normal speed. A time scale of 2.0 runs the animation twice as fast. A time scale of 0.5 runs the animation at half speed. The maximum allowed value is 20.0 and the minimum allowed value is 0.05. The value supports up to 2 decimal places.
Sprite Event Listeners
이제 basic sprite 선언과 두개의 sequences (“normalRun” , “fastRun”) 가 생겼습니다.
이제 sprite event listener를 살펴보죠. 그리고 그것을 어떻게 implement 하는지에 대해 알아보겠습니다. sprite event listener 의 정의는 'sprite의 activity를 "listens" 하고 그 정보를 listener function에 전달하는 것' 입니다.
예를 들어 여러분의 달리는 고양이를 "normalRun" sequence로 4번(4 cycles)를 돌게 한 다음에 "fastRun" sequence로 바꿀 수 있습니다. 이것은 standard timer 로 표현하기에는 불가능한 효과죠. 그래서 그 대신에 sprite event listener를 implement 하는 겁니다.
예제를 보기 전에 sprite에서 사용 가능한 5가지 를 event phases보겠습니다.
이 phases 들은 최근의 코로나 Public Release 인 (2012.894) 버전 이후부터 사용하실 수 있습니다.
- began = The sprite has started playing.
- ended = The sprite has finished playing.
- bounce = The sprite has bounced from forward to backward while playing.
- loop = The sprite has looped to the beginning of the sequence.
- next = The sprite has played a subsequent frame that’s not one of the above phases.
이 phases 를 어떻게 listen 할지에 대해 다루겠습니다. 근데 우선 달리는 고양이에 loopCount = 4를 추가해서 normalRun 의 sequence를 바꾸고 시작하도록 하죠. 이렇게 하면 4번의 loop가 끝나면 ended phase를 받을 수 있도록 해 줍니다.
local sequenceData = {
{ name = "normalRun", start=1, count=8, time=800, loopCount=4 }, --add loopCount=4
{ name = "fastRun", frames={ 1,2,4,5,6,7 }, time=250 }
}
Now, let’s write the listener function and add the actual event listener to the running cat. You can place this at the end of your sample code, after the sequences are declared and the sprite object placed on the screen.
이제 listener function을 만들어 봅시다. 그리고 달리는 고양이에 실제 event listener를 달아보죠. 아래 내용을 위 샘플 코드의 마지막 부분에 sequence 가 선언된 다음에 추가하시면 됩니다.
local function mySpriteListener( event )
if ( event.phase == "ended" ) then
local thisSprite = event.target --"event.target" references the sprite thisSprite:setSequence( "fastRun" ) --switch to "fastRun" sequence thisSprite:play() --play the new sequence; it won't play automatically! end
end
animation:addEventListener( "sprite", mySpriteListener ) --add a sprite listener to your sprite
하나의 sprite listener를 모든 sprite 에 대해 사용하실 수 있습니다. listener 함수에서 event.target을 사용해서 원하는 스프라이트를 catch 해서 사용하실 수 있는겁니다.
Frame Trimming Supported
최근의 Public Build (2012.894) 에서는 frame trimming 도 지원합니다. 3rd-party sprite utilities 인 SpriteLoq 와 TexturePacker 같은 곳에서 이 기능을 제공하고 있습니다. 그리고 코로나에서도 이 어플리케이션과 호환성 있게 이 기능을 사용할 수 있도록 하고 있습니다.
frame trimming 예제는 current sprite methods 를 사용하고 있는데 이것은 여러분 시스템의 코로나 어플리케이션에 있는 “HorseAnimation” sample
project에서 확인 하실 수 있습니다.
CoronaSDK → SampleCode → Sprites → HorseAnimation
이와 관련해서는 다음 튜토리얼에서 다뤄지게 될 것 같습니다. 그동안 여러분은 샘플 프로젝트를 보셔도 되고 여기에서
imageSheet documentation를 보시면 많은 도움이 되실 겁니다.
In Summary
이 튜토리얼은 current sprite methods 의 대부분을 다뤘습니다. 여기에 basic image sheets, animation sequences 정의하기, sprite playback 다루기, 다양한 sprite property들 다루기 그리고 sprite event listener 사용하기 등을 추가로 다루고 있습니다. 모쪼록 이 튜토리얼이 개발자 여러분에게 스프라이트를 이용해서 앱을 만드는데 도움을 드릴 수 있기를 바라겠습니다. 특히 이전 버전의 sprite library 를 사용하시던 분들에게 새로 바뀐 sprite library 를 사용하시는데 도움이 되기를 바라구요.
'Corona SDK > Corona Doc' 카테고리의 다른 글
다양한 디바이스 해상도에 맞게 이미지 표시하기 - config.lua file- (0) | 2012.12.06 |
---|---|
physics engine (물리엔진)의 새로운 기능 event.contact 소개 (0) | 2012.11.29 |
새 위젯 사용하기 Part 1 (0) | 2012.11.08 |
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
스토리 보드 기본 사용법 (1) | 2012.08.23 |
메모리 부족 경고 시 처리 방법 (2) | 2012.08.17 |
화면 전환 하면서 state(상태) 관리하기 (0) | 2012.08.09 |
Storyboard: Scene Purging vs. Removal (0) | 2012.08.02 |
오늘은 여러분과 같이 Lua 에서 module들은 정확히 어떻게 작동을 하는지에 대해 몇가지 실습을 해 보고 설명도 덧 붙이겠습니다. 이 글을 읽으시면 모듈 내의 코드가 실행되거나 built-in require() function 을 call 했을 때 어떤 코드가 run 하지 않는지 등에 대해 이해 하실 수 있을 겁니다.
Including External Modules
아래 정말 간단한 모듈이 있습니다. example1.lua 인데요. 터미널에 한 문장을 print 하고 빈 테이블을 return 하는 것입니다.
example1.lua
print( "example1.lua has been loaded." )
return t
이제 main.lua를 볼까요? 여기서 우선 example1.lua를 require 합니다.
main.lua
ex1.testvar = "Hello world"
예상한대로 ex1은 빈 테이블입니다. example1.lua에서 빈 테이블을 return 했으니까요. 그리고 “example1.lua has been loaded.” 라는 문장이 터미널에 쓰여질 겁니다. 그 다음에 위에 보면 ex1 테이블에 어떤 프로퍼티를 할당했습니다.
이 부분을 주목해 보세요. 여기 약간의 트릭이 있습니다. 다른 모듈에서 이 example1.lua를 require 해 봅시다. scene1.lua라는 모듈에서요. 이미 main.lua에서 example1.lua를 require 했었죠. 이제 어떤 일이 일어나는지 볼까요?
scene1.lua (previous main.lua still applies)
local examp1 = require "example1"
print( examp1.testvar )
-- ...
scene1.lua에서 example1.lua를 require 하면 “example1.lua has been loaded” 이 터미널에 뿌려지지 않습니다. 그리고 ex1.testvar 값을 print 하면 터미널에 “Hello World” 가 뿌려집니다. (이 의미는 뭐냐하면 testvar 프로퍼티가 존재한다는 것이죠.
여기서 뭘 알 수 있나요?
첫번쨰로 “example1.lua has been loaded” 라는 문장에 터미널에 뿌려지지 않은 이유는 그 모듈이 이미 main.lua에서 로드 됐기 때문이죠. 모듈이 한번 로드 되면 그 안의 코드가 다 실행되게 되죠. 그리고 모듈의 return 값은 package.loaded라고 하는 글로벌 테이블에 저장됩니다.
여러분이 require를 call 하면 첫번째로 이전에 이 모듈이 이미 로드 된 것인지 아닌지 확인하기 위해 package.loaded table 을 살펴 봅니다. 만약에 있으면 외부 모듈을 새로 require 하는 대신 package.loaded 에 저장된 return value를 return 합니다. 이 return 된 value는 copy가 아니라 reference 입니다. 그러니까 여러분의 모듈이 테이블을 return 한다면 미래에 같은 모듈에 대해 require를 call 하면 같은 테이블을 get 하게 될 겁니다.
만약에 package.loaded 안에 그 모듈이 없으면 그 모듈이 로드 될 겁니다. (그 모듈안의 코드들이 실행 되겠죠.) 그리고 그 모듈의 return value가 package.loaded table안에 저장될 겁니다. (미래에 사용하기 위해 저장하는 거겠죠.) 그래서 두번째에서는
“example1.lua has been loaded.” 이 터미널에 뿌려지지 않은 겁니다. require() 가 call 됐을 떄 global package.loaded table 안에 이미 그 모듈이 존재하면 그 모듈을 re-load 하지 않으니까요.
모듈 안에 있는 코드를 두번 실행하도록 하는 방법에는 두가지가 있습니다.
- 코드를 모듈 내에서 함수 안에 넣고 그 함수를 부르는 경우
- package.loaded table 에서 그 모듈을 remove 한 다음에 다시 require 하는 경우
첫번째 시나리오에 대한 예제입니다.
example2.lua
print( "example2.lua has been loaded." )
t.hello = function()
print( 'Hello world.' )
end
return t
main.lua
-- Terminal: example 2 has been loaded.
ex2.hello()
-- Terminal: Hello world.
scene1.lua
examp2.hello()
-- Terminal: Hello world.
예제에서 보듯이 example2.lua를 두개의 다른 모듈(main.lua and scene1.lua)에서 require 했습니다. 첫번째 print statement는 오직 한번 보여집니다. 첫번쨰로 그 모듈이 require 됐을 때죠.
두번째 print statement는 hello() 함수 안에 있습니다. 이것은 hello() 함수가 call 될 때마다 실행되겠죠. 그 코드가 한번 이상 실행되기를 원한다면 함수를 table에 attach 해서 모듈 마지막 부분에서 return 되게 하세요. (또는 단지 require 만 했을 떄 print 되지 않도록 할 때도 그렇게 하면 되겠죠.)
Removing from package.loaded
그러면 example2.lua의 return value 가 package.loaded table 에 저장 될 겁니다.
package.loaded["example2"]
만약 example2.lua에 있는 코드가 다시 execute 될 필요가 있다면 package.loaded table 에서 remove 한 다음에 다시 call 하시면 됩니다.
아래 그 예제가 있습니다.
main.lua
-- Terminal: example2.lua has been loaded.
package.loaded["example2"] = nil
require "example2"
-- Terminal: example2.lua has been loaded.
require "example2"
-- Terminal:
This is Universal
여러분이 만든 모듈이든 아니면 다운로드 된 모듈이든 혹은 built-in 모듈이든 이 모듈들을 다룰 때는 위에 설명드린 대로 외부 모듈들이 작동합니다.스토리 보드의 scene들을 다룰 때 그 scene이 로드될 떄 스토리보드 리스너 함수안에 있는 코드들이 어떤 것은 실행되고 어떤 것은 실행되지 않는지에 대한것도 궁금하실 겁니다.
거기에 대한 것은 다음 기회에 다루도록 하겠습니다.
'Corona SDK > Corona Doc' 카테고리의 다른 글
physics engine (물리엔진)의 새로운 기능 event.contact 소개 (0) | 2012.11.29 |
---|---|
새 위젯 사용하기 Part 1 (0) | 2012.11.08 |
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
스토리 보드 기본 사용법 (1) | 2012.08.23 |
메모리 부족 경고 시 처리 방법 (2) | 2012.08.17 |
화면 전환 하면서 state(상태) 관리하기 (0) | 2012.08.09 |
Storyboard: Scene Purging vs. Removal (0) | 2012.08.02 |
Tap 이벤트로 간단하게 touch 감지하기 (0) | 2012.07.26 |
오늘은 이 간단한 Storyboard API를 정말 간단하게 사용하고 싶은 분들에게 기본적인 스토리보드 사용법에 대해 안내를 할 까 합니다. 아마 Director Class 만큼이나 간단할 겁니다. 스토리보드에는 많은 유용한 기능이 있지만 이 기능들이 항상 사용되야만 하는 것은 아닙니다. 그러니까 처음부터 이 모든걸 다 이해할 필요는 없습니다.
이 튜토리얼은 스토리보드 API를 빠르고 쉽게 사용할 수 있는 기본적인 기능에 대해서 다루려고 합니다.
Setup
스토리보드 API는 대부분의 다른 3rd party
scene management libraries 하고는 약간 다른것들이 있습니다. 특히 화면 전환 부분이 그렇죠. 디폴트로 스토리보드의 scene 들은 화면전환 (scene transiton) 할 때 이전 scene들이 removed or purged 되지 않습니다. 대부분의 third-party
scene management libraries 에서는 화면이 전환 될 때마다 이전 화면(scene)이 remove 되죠. Storyboard API에서도 이렇게 할 수가 있는데요. 자동으로 이전 scene들을 remove 하려면 함수가 call 될 때마다 inactive scene들을 purge 되도록 main.lua에 세팅할 수 있습니다.
main.lua
storyboard.purgeOnSceneChange = true
완전 간단하죠?
Scene Modules
Director class 에서는 scene 모듈은 new()라는 한개의 함수로 만들어 졌었습니다. 이 함수는 scene이 로딩 될 때마다 call 되게 되죠. 옵션으로 scene이 unload 될 때 call 되는 clean() 함수도 있었습니다. 아래는 Director Class에서 보여지는 scene 코드 입니다.
Director Class Scene
-- setup function:
function new()
local localGroup = display.newGroup()
local img = display.newImage( "hello.png" )
localGroup:insert( img )
return localGroup
end
-- cleanup function:
function clean()
print( "Called when scene is unloaded." )
end
Storyboard API 를 사용할 때도 비슷한 structure와 로직이 적용될 수 있습니다. (위에 Setup 섹션에서 보실 수 있습니다.). Director Class 에서 위와 같이 사용해서 얻는 기능과 비슷하게 Storyboard API에서도 아래와 같이 코딩을 할 수 있습니다.
Storyboard Scene
local scene = storyboard.newScene()
-- setup function:
function scene:createScene( event )
local img = display.newImage( "image.png" )
self.view:insert( img )
end
scene:addEventListener( "createScene" )
-- cleanup function:
function scene:destroyScene( event )
print( "Called when scene is unloaded." )
end
scene:addEventListener( "destroyScene" )
return scene
많이 다르지는 않죠? 코딩은 약간 다르지만 그 로직은 완전히 같습니다. createScene 이벤트 리스너에 모든 scene creation과 로직을 넣으시면 됩니다. 그리고 모든 cleanup 코드는 “destroyScene” event listener 에 넣으시면 되죠.
createScene 리스너는 Director의 new 함수와 비슷한 기능을 합니다. 그리고 destroyScene 리스너는 clean 함수와 하는 기능은 거의 같죠. main.lua 파일에 storyboard.purgeOnSceneChange를 true 로 하는 것을 잊지 마세요. 그렇게 하지 않으면 화면은 전환 할 때마다 destroyScene 이벤트가 자동적으로 dispatch 되지 않을 겁니다.
이제 여러분의 Storyboard API의 scene들을 어떻게 하면 Director 클래스와 비슷하게 셋업할 수 있는지 알게 됐습니다. 이제 storyboard.gotoScene() 를 사용해서 화면 전환을 하시기만 하면 됩니다.
Conclusion
Storyboard API 에 가시면 훨씬 더 많은 기능을 보실 수 있을 겁니다. 그 기능들은 필요하실 때만 가져다가 쓰시면 됩니다. 대부분의 경우 특히 Director Class를 사용하시다가 Storyboard로 전환하시는 분들에게는 이 튜토리얼이면 충분히 쉽게 스토리보드를 이해하시고 사용하실 수 있을겁니다.
'Corona SDK > Corona Doc' 카테고리의 다른 글
새 위젯 사용하기 Part 1 (0) | 2012.11.08 |
---|---|
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
메모리 부족 경고 시 처리 방법 (2) | 2012.08.17 |
화면 전환 하면서 state(상태) 관리하기 (0) | 2012.08.09 |
Storyboard: Scene Purging vs. Removal (0) | 2012.08.02 |
Tap 이벤트로 간단하게 touch 감지하기 (0) | 2012.07.26 |
System Events 사용해서 앱의 현 상태 저장하기 (0) | 2012.07.20 |
오늘 다룰 주제에서는 이 low memory warning이 왔을 때 어떻게 대응할 것인가 입니다. 그리고 crash를 방지하기 위해 해야 할 몇가지를 추천해 드릴거구요.
NOTE: Low memory warnings들은 현재 안드로이드 플랫폼에서는 제공하지 않습니다. 그러니까 오늘의 튜토리얼은 대부분 iOS에 포커스를 둔 겁니다. 하지만 예방 방법은 모든 플랫폼에 마찬가지로 적용할 수 있을 겁니다.
Responding to the Warnings
Runtime:addEventListener( "memoryWarning", onMemoryWarning )
만약 memoryWarning 이벤트 리스닝을 중지하고 싶으면 아래처럼 이벤트 리스너를 제거하면 됩니다.
Runtime:removeEventListener( "memoryWarning", onMemoryWarning )
만약 main.lua 가 아닌 다른 모듈에서 이 momoryWarning을 적용한다면 그 이벤트 리스너가 앱이 처음 시작할 때 로딩되지 않을 겁니다.
The Listener
이제 onMemoryWarning 함수에 실제로 무엇을 넣을지는 여러분이 정하실 사항입니다. 왜냐하면 각 앱마다 로직이 다 다르고 그 자세한 사항은 여러분 만이 알 것이기 때문이죠.
그 작업을 할 때 아래 사항들을 염두에 두시고 하세요.
- 필요하지 않은 객체들은 가능한 모두 Unload 한다.
- 필요하지 않은 이벤트 리스너들 특히 enterFrame 리스너 같은 것들은 stop 시킨다.
- 현재 active 되 있지 않은 scene들은 Parge 하고 remove 시킨다. (try: storyboard.removeAll())
- 제일 핵심사항은 필요하지 않은 것들은 다 제거한다 입니다.
아래 예제가 있습니다.
audio.dispose( someAudioHandle )
storyboard.removeAll()
end
Runtime:addEventListener( "memoryWarning", onMemoryWarning )
Preventing Memory Warnings
여러분이 할 수 있는 최선의 방법은 우선 memory warning이 일어나지 않도록 예방하는 겁니다. 정확히 무엇을 해야 된다라고 딱 찝어 내서 얘기할 수는 없습니다. 왜냐하면 여러분이 앱을 개발하는 사람이기 때문입니다. 그래도 몇가지 아이디어는 드릴 수 있습니다.
- heavy scene으로 전환하기에 앞서 다른 모든 scene들을 purge 시키세요. (혹은 여러분의 scene을 생성할 때 그 이전의 모든 scene들을 purge 시키세요)
See: storyboard.purgeAll() - 다양한 플랫폼과 디바이스에서 작업을 하신다면 프로그램 내에서 그 디바이스가 lower-performance device인지를 체크하세요. 그렇다면 그런 디바이스에는 다른 그래픽 set을 로드하시거나 좀 더 작은 객체들을 로드하도록 하세요.
- 뭐가 필요하고 뭐가 필요 없는지 판단해서 불필요한 것들은 버리세요.
- 코드를 한줄 한줄 다시 살펴 보세요. 혹시 어디엔가 메모리 누수현상이 없는지......
여러분들 앱에 맞게 여러분이 할 수 있는 다른 많은 것들이 있을 겁니다. 명심할 것은 memory warning 이 일어나기 전에 가능한 많은 리소스들을 free up 시키자는 겁니다. memoryWarning 이벤트에서는 더 말할 나위가 없겠죠. 그렇게 함으로서 OS 가 여러분 App 을 Kill 하는 것을 막는게 목표입니다.
'Corona SDK > Corona Doc' 카테고리의 다른 글
Blend Modes 사용해서 Creative Effects 내기 (1) | 2012.11.01 |
---|---|
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
스토리 보드 기본 사용법 (1) | 2012.08.23 |
화면 전환 하면서 state(상태) 관리하기 (0) | 2012.08.09 |
Storyboard: Scene Purging vs. Removal (0) | 2012.08.02 |
Tap 이벤트로 간단하게 touch 감지하기 (0) | 2012.07.26 |
System Events 사용해서 앱의 현 상태 저장하기 (0) | 2012.07.20 |
Best Practices for Organizing Projects (2) | 2012.07.11 |
Managing State Between Scenes
이게 왜 애매하냐 하면 대부분의 스토리보드 scene들이 각 모듈별로 (e.g. scene1.lua, scene2.lua) 관리 되고 이렇게 다른 파일들간에 왔다 갔다 할 때 어떻게 파일들간에 데이터를 공유할 것인지를 다루는게 쉽지는 않기 때문이죠. 특히 scene들이 어느때든지 create 되고 destory 될 수 있기 때문에 더 그렇습니다.
오늘의 튜토리얼에서 저는 scene들 사이에서 데이터를 공유할 수 있는 몇가지 방법을 보여드릴 겁니다. 그리고 여러 scene들의 로딩과 unloading 을 거치면서도 여러분 앱 안에서 singular overall "state"를 관리하는 방법들에 대해서도 보실 수 있을 겁니다.
Parameter Passing
아래 예제에서 우리는 score 변수를 gameplay scene에서 gameover scene으로 pass 할 겁니다.
gameplay.lua
storyboard.gotoScene( "gameover", {
effect = "fade",
time = 800,
params = {
score = 100
}
})
-- ...
gameover.lua
function scene:enterScene( event )
local score = event.params.score
print( "You scored: " .. score )
end
scene:addEventListener( "enterScene", scene )
-- ...
Persistent Variables
이런 경우 global 변수를 사용하거나 (그렇게 추천할 문한 방법은 아닙니다.) 혹은 모든 scene에서 access 가능한 스토리보드 객체에 attach 되는 state 테이블을 생성하실 수 있습니다. (모든 scene들은 반드시 storyboard 모듈을 require 합니다.)
아래에 global 변수를 사용하지않고 모든 scene들에서 접근 가능한 score 프로퍼티를 어떻게 사용하는지에 대한 예제가 있습니다.
main.lua
storyboard.state = {}
storyboard.state.score = 0
-- ...
gameplay.lua
-- ...
storyboard.state.score = storyboard.state.score + 100;
storyboard.gotoScene( "gameover", {
effect = "fade",
time = 800
})
-- ...
gameover.lua
-- ...
function scene:enterScene( event )
print( "Your score is: " .. storyboard.state.score );
end
scene:addEventListener( "enterScene", scene )
-- ...
모든 scene들은 require( “storyboard” )를 반드시 해야 됩니다. 그러면 그 scene들은 common object를 share 하게 되는 거죠. main.lua에서 state 테이블을 선언했습니다. 그러면 그 테이블에 원하는 만큼의 변수를 추가할 수 있게 됩니다. 그 변수들은 require( “storyboard” )를 한 모든 모듈에서 접근 가능하게 되는 것이죠. global namespace를 사용해서 소스를 지저분하게 하지 않고서두요.
scene들 사이에 데이터를 공유하는 다른 방법들도 있을 겁니다. 위에 제시한 방법은 저희들이 추천드리는 방법입니다. 여러분들이 사용하시는 multiple modules and scenes 사이에서 데이터를 share 하는 방법은 뭐가 있습니까?
'Corona SDK > Corona Doc' 카테고리의 다른 글
원근감을 주는 parallax scrolling 구현하기 (0) | 2012.10.18 |
---|---|
Sprite 로 애니메이션 표현하기와 그 methods 들 (0) | 2012.10.11 |
코로나에서 외부 모듈은 어떻게 작동 될까? (0) | 2012.08.29 |
스토리 보드 기본 사용법 (1) | 2012.08.23 |
메모리 부족 경고 시 처리 방법 (2) | 2012.08.17 |
Storyboard: Scene Purging vs. Removal (0) | 2012.08.02 |
Tap 이벤트로 간단하게 touch 감지하기 (0) | 2012.07.26 |
System Events 사용해서 앱의 현 상태 저장하기 (0) | 2012.07.20 |
Best Practices for Organizing Projects (2) | 2012.07.11 |
코로나에서 객체와 변수 확실하게 제거하기 (0) | 2012.07.04 |