본문 바로가기

Starling

Starling - Introducing 번역 4 > 무비클립, 퍼포먼스 최적화




목차

First Flight ------------------------------------------------------------------------------------------------- 


What Is Starling? 

Why Starling? 

Philosophy 

Intuitive 

Lightweight 

Free 

How 

Layering Restrictions 

Getting Started 

Setting Up Your Scene 

Wmode Requirements 

Stage Quality 

Progressive Enhancements 

The Display List 

Event Model 

Event Propagation 

Touch Events 

Simulating Multi-touch 

Texture 

Image 

Compressed Textures 

Collision Detection 

Drawing API 

Filters 

MovieClip 

Optimizing for Performance 

Release Build 

CPU Bound vs GPU Bound 

ActionScript Optimizations

Running Hardware Accelerated 

State Changes 

The Painter’s Algorithm 

Texture Atlas 

Flat Sprites 

Batching with the QuadBatch API 

Disable Blending 

Use Stage.color 

Accessing Width and Height 

Disable Interactivity 

Optimized Event Model 

Handle Lost Context 

Juggler 

Button 

TextField 

Embedded Fonts 

Native Display List Overlay 

Bitmap Fonts 

RenderTexture 

Tweens

Asset Management

Multi Resolution Development

Static Approach 

Dynamic Approach 

Handling Screen Resizes 

Plugging Starling with Robotlegs 

Plugging Starling with Box2D 

Particles

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




바빠서 미루고 피곤하다고 미루고 군단의 심장이 나왔다고 미루고 하다보니

이미 몇달전에 끝났어야 번역이 많이 늦어졌습니다.


언제나 처럼 번역은 여기저기에 의역과 오역이 혼재되어 있는 막번역이므로 감안해서 보셔야 합니다.





MovieClip



우리는 앞에서 Staring에서 Sprite 를 어떤식으로 사용하는지 알아보았다.

하지만 MovieClip 같은 애니메이션은 어떻게 해야할까?


모든 플래시 개발자는 무비클립에 대한 개념에 친숙하며,

몇년 전부터 많은 AS3 개발자가 MovieClip의 독릭적인 프레임레이트를 Bitmap을 활용하여

BitmapData를 기반으로 렌더링을 가속하고 MovieClip API를 재현하였다.



그림 33은 MovieClip 의 각프레임을 보여주는 sprite atlas  이다.


Figure 33. 러닝보이에 대한 sprite atlas.




아이디어는 아래와 같다.


GPU 에 올릴 각 프레임의 표본을 얻고

각프레임의 텍스쳐를 갱신하며 화면에 표시하여 무비클립의 개념을 재현하는 것.



자, 그래서 우린 어떻게 이런 애니메이션을 만들 수 있는가?



Flash Pro 는 애니메이션의 각프레임을 연속적인 사진으로 내보내는 가장 좋은 도구이다.


이러한 이미지들은 TexturePacker (http://www.texturepacker.com) 같은 툴을 통해 로드된 후

하나의 텍스쳐로 융합되어 우리의 MovieClip 에 공급된다.



Flash Pro CS6 은 무비클립에서 Starling 에서 사용될 sprite atlase 를 바로 생성할 수 있다.

이러한 견고한 통합(Flash 와 Starling) 을 통해 당신은 혜택을 받을 수  있을 것이다.




그림 34는 sprite atlas 의 프레임이다.


그림 34. sprite atlas 의 프레임




만일 당신의 sprite atlas 를 밉맵 해야 한다면

반드시 각 프레임 사이의 간격이 2픽셀은 되도록 해야만 밉매핑 시 문제가 발생하지 않는다.


이젠 텍스쳐 크기에 대한 몇가지 제한이 있다는 것을 기억하자.


Stage3D(몰힐) 은 모바일을 염두해두고 디자인 되었다는 것을 기억해 내야 한다.

그 결과, Stage3D 는 '2제곱승의 텍스쳐' 등과 같은 OpenGL ES2 제한을 엄격하게 따른다.


TexturePacker 나  Flash Pro CS6 은 이러한 제한을 존중하면서 작업을 도와주며

AutoSize 같은 괜찮은 기능도 포함되어 있다. (그림 35)


이는 텍스쳐의 최대 너비와 폭을 바탕으로 가장 좋은 너비와 폭을 결정한다.

(Starling 제한은 2048*2048).


그림 35. TexturePacker 의 Autosize 기능 




앞서 말한것 처럼 Starling 은 자동으로 2의 제곱승 크기를 사용한다.


이 규칙을 지키지 않으면,

Starling 은 당신을 위해 이것을 책임지려고 자동적으로 이미지를 사용가능한 2제곱 크기로 찾고 잘라낸다.


Starling 이 텍스쳐로 이루어진 각 프레임들이 어디에 위치해 있는지 알수 있도록 하기 위해선

TextureAtlas 객체를 생성할 때 XML 파일을 제공해야 한다.


TexturePacker 는 스프라이트시트 를 생성할때 XML 또한 자동적으로 생성해주며

XML ,JSON 기타등등의 포맷을 선택 할 수 있다.


Starliong 은 XML을 지원한다. XML 파일은 아래와 같은 형태이다.





각프레임과 FPS를 전적으로 제어하는 것이 가능하고

다수의 무비클립이 독립된 프레임레이트를 사용할 수 있도록 하는 점은 환상적이다.


어쨌든 Starling 은 GPU 위에서도 같은 기법을 적용하고 있으며 무비클립의 생성자는 아래와 같다.



public function MovieClip(textures:Vector.<Texture>, fps:Number=12)



아래의 코드에서 , 우리는 무비클립에 사용될 프레임들이 모두 포함된 텍스쳐를  생성한다.





그리고 XML 정보를 이용해 spritesheet 의 매프레임의 위치를 결정한다.




그럼 우리는 런닝보이에 관련된 프레임을 검색할 수 있다.


var frames:Vector.<Texture> = sTextureAtlas.getTextures("running_");


여기에서 전달된 인수 "running_" 는 sprite sheet 에서 이것과 관련된 프레임만을 원한다는 의미이다.




우리는 정의만 되어 있다면 다른 "jump","fire" 등등 또다른 시퀀스도 요청할 수 있다.


완성된 코드를 보자.




테스트 하면 그림 36과 같은 결과를 얻는다.


그림 36. 러닝보이가 렌더링 되고 있다.




후에 우리는 재사용되는 에셋에 대해 간단한 캐싱 기법을 포함시켜

어플리케이션이 실행되는 동안 실체화된(instanciate) 객체의 수를 제한하도록 할 것이다.





고전적인 Flash API, scaleX 속성을 사용하여 무비클립을 뒤집고

현재 위치에 너비를 추가하여 정확히 원래의 장소로 위치를 재이동시키자.






그림 37과 같은 결과를 얻을 것이다.


Figure 37. 뒤집힌 러닝보이




이전의 작업들은 매우 흔한 작업이며, 사실 당신의 자원(asset) 모두를 단일 텍스쳐 파일에 놓는 좋은 연습이 된다.



이 작업은 간단하고, 당신의 게임의 자원들은 모두 하나의 텍스쳐 파일에 저장되었다.

단일 텍스쳐를 사용하는 것은 GPU 에 업로드 하는 회수를 줄일 수 있다.


기억하자. GPU 에 업로드하는것은 '특히 모바일에서' 매우 비용이 많이 드는 행위이다.


그러므로 업로드 수는 줄이면 줄일수록 좋은 것이다.


그리고 특정 텍스쳐에서 다른 텍스쳐로의 전환은 '상태 변화' 를 유발하며 이 역시 비용이 많이 든다. 

그러므로  끊임없이 텍스쳐를 변경하는것 보다는 당신의 자원들이 단일 텍스쳐를 가지도록 하자.

우리는 이 주제에 대해 나중에 다시 다룰 것이다.



이제 퍼포먼스에 대해 조금 알아보자.


Starilng은  추상적인 GPU 프로그래밍을 해야하는 개발자의 삶은 조금 쉽도록 해주며 높은 레벨의 API를 제공한다.

하지만 Starling 이 최선의 실행을 하도록 만드는 몇가지를 알아야 할 필요가 있다.

왜 그래야 하는지, 퍼포먼스 최적화에 대해 시간을 투자하기로 하자.








Optimizing for Performance

(퍼포먼스 최적화)



Starling 은 매우 쉽고 생산적인 프레임워크이지만 최상의 결과물을 얻기위해선 어떻게 해야되는지 이해할 필요가 있다.

우리는 Starling 의 퍼포먼스 최적화를 위해 당신이 알아야할 중요한 것들의 대부분을 다룰 것이다.






Release Build



Release Build 이것은 퍼포먼스 최적화에 대해 알아야 할 첫번째이다.


어플리케이션의 진짜 퍼포먼스를 측정하기 위해 릴리즈 빌드로 내보내자.

플래시 빌더에선 프로젝트의 Export Release Build 을 클릭하면 된다.

ActionScript3 컴파일러는 어떤 디버깅 정보를 포함하지 않고 런타임시의 퍼포먼스로 바꿔 SWF를 내보낼 것이다.


만약 IOS 를 대상으로 했다면 어플리케이션을 adt (Adobe AIR를 위한 패키징툴) 로 포장할때

“ipa-ad-hoc” 나 “ipa-appstore” 옵션 사용을 하도록 하자.






CPU Bound vs GPU Bound (CPU 영역 VS GPU 영역 )



최적화를 하게 된다면, 우선은 당신의 컨텐트는 CPU 혹은 GPU가 혼합이 되기 때문에

느려지는 이유는 2가지로 나뉜다는 것을 기억하는 것이 중요하다.


CPU가 혼합이 되면 

GPU 는 CPU 가 무엇을 할지 알기 위해 기다리기 때문에 퍼포먼스에 영향을 끼치게 되는데

GPU 가 기다리며 게을러지는 것은 분명 피하고 싶은 상황이다.


그러므로  CPU에서 많은 일을 하는 것 (물리법칙, 복잡한 게임로직, 등등) 은

GPU 직접적으로 영향을 끼친다는 것을 잊지말자.


훌륭한 퍼포먼스의 열쇠는 GPU 와 CPU 가 서로 병행하며 부드럽게 대화를 하는 것이다.


당신이 대부분의 시간을 코드를 보며 지옥을 경험하는 것을 도와주고자

어도비는 이전의 ActionScript 개발자들에겐 노출되지 않았던 세부사항을 전달해주는

혁명적인 분석기 (코드네임 Monocle 로 불리어졌던) 를  제공하여 준다.


반드시 Adobe Scount 를 실행시켜보고 Adobe site 를 통해 더 많은 정보를 얻도록 하자.



또한 삼각형을 그리는 모든 함수는 CPU 비용에 관련되어있으므로

최대한 많은 삼각형을 한번의 draw call 로 함께 제출해야 주어진 삼각형을 렌더링 하는 CPU작업이 최소화 된다.


이것이 바로 draw call 을 batch (일괄처리) 해야하는 이유이고 이는 이후에 다시 다룰 것이다.





ActionScript Optimizations (액션스크립트 최적화)



책 전체를 ActionScript 최적화에 관해 쓸수도 있지만

여기서는 최적화에 있어 자주 적용할 수 있는 필수적인 몇가지를  다루려고 한다.


이미 알고 있겠지만,


가비지 컬렉터는 매우 예민하며 컨텐츠의 퍼포먼스에 매우 높은 영향을 끼친다.

이것을 이해하기 위해 알아야 할 중요한 포인트는

가비지 컬렉터는 언제나 트리거 되고, 동기적으로 작동한다는 것이다.


이는 가비지컬렉터가 UI 흐름(맥락) 를 방해하고 당신의 컨텐트를 부드럽게 실행되지 않게 할 수 있다는 의미이다.



수많은 객체의 할당으로 가비지컬렉터에 많은 압력을 주어

가비지 컬렉터가 자주 작업을 해야 하는 상황을 당신은 원하지 않을 것이다.


당신이 바라는 것은 반복해서 객체를 재생성하는 대신에  필요로 할 때 재사용하기 위해

객체를 최소한으로 인스턴스화 하고 저장하는 것이다.



다른 한편으로는 모든 것을 저장하고 뭐든지 다시 할당하지 않는 것 역시 바라지 않을 것이다.

이것의 부작용은 가비지컬렉터가 더미의 모든 객체를 추적해야 한다는 점이다.


그러므로 당신은 이 둘중에서 적당한 지점을 찾아야 한다.



예를 들어 , 반복문에선 아래와 같은 코드는 사용하지 말자.




매 반복 마다 Rectangle 객체를 재생성 하면 많은 메모리를 사용하게 되고 가비지컬렉터에 부담을 주게 된다.

대신에, 아래처럼 처리하자.



이러한 룰은 매우 다양한 객체가 포함된 많은 상황에 적용할 수 있다. 



앞에서 언급 했듯이, 또 다른 테크닉은 재사용객체가 담겨있는 풀링을 이용하는 것이다.


앱이 초기화 되는 동안 다수의 객체를 생성,정의하고 그것들을 pool 안에 배열이나 Vector 객체로 저장한다.

일단 객체가 생성되면, 당신은 그객체의 재생성을 금지하여 더이상의 CPU 리소스를 소모하지 않고

모든 상호 참조를 제거한다.


그리고 사용이 완료된 객체는 pool 로 다시 넣어야 한다. 그리고 새로운 객체를 필요로 할때 다시 꺼내어 쓴다.


아래의 코드는 객체의 풀링 테크닉을 보여준다.






반복문 역시 액션스크립트 개발자에 있어 필수적인 것이기 때문에

당신은 사용되는 반복문에 주의해야 한다


반복문에선 length 를 매번 평가하는 대신 반드시 저장하고 사용하도록 하자.





배열이나 Vector 에 접근하거나 사용하거나 수학적인 작업을 실행할때, 인덱스는 int 로 던져야 한다.


그렇지 않았다면 (보통 인덱스를 Number) 작업을 실행할 때

다시 int 로 변환하는 과정이 일어나게 되고 이는 작업을 느리게 한다.





SpritePool 클래스에서는 최적화된 방법을 쓰고 있는것을 주목하자.



하나 더, 항상 배열 대신에 Vector를 사용하자.

Vector 의 퍼포먼스는 배열을 능가한다.

몇몇의 상황에서 배열대신에 Vector 를 사용하자 퍼포먼스가 5배로 올랐다.



Flash Builder 4.7 에 포함된 최신 액션스크립트 3 컴파일러를 (ASC2.0) 사용할 때

inlining 기능은 inline 함수의 실행 수를 최소화 하도록 해준다.

아래의 코드에서 ,inline 함수인  calculateDistance 는  함수 호출에 따른 비용을 제거한다.




[Inline] 메타태그의 사용법을 주목하자.


완벽하게 인라인 기능을 활성화 하려면, 컴파일러 인자 (compiler argument)  역시 -inline 으로 설정해야한다.





Running Hardware Accelerated (하드웨어 가속)



Strling 은 데스크탑에서 기본적으로  Flasy Player 11.4 및 AIR 3.4 에서 도입된

Stage3D 모드에서의 사용으로 제약된다.


이는 하드웨어가 가속된 최고의 환경인 Stage3D를 실행하는 것을 보장한다.


하지만 몇몇의 상황에서 당신의 컨텐츠는 퍼포먼스에 대단한 악영향을 끼치게 될 software 에서 실행될수도 있다.


만약 Starilng 이 소프트웨어에서 실행된다면 Starling.current.driveInfo 속성을 통하여 감지할수 있다.


Flasy Player 11.3 과 AIR 3.3 부터 왜 컨텐츠가 소프트웨어에서 실행되는지 역시 알수 있게 되었다.


아래의 목록은 driverInfo 속성이 가질 수 있는 모든 값을 나타낸다.



Software Hw_disabled=userDisabled

설정UI 의 하드웨어 가속 설정 확인란이 선택되어 있지 않아 하드웨어 가속은 실패하여

소프트웨어 렌더링되는 상태.



Software Hw_disabled=oldDriver

하드웨어의 그래픽 드라이버로 인한 이슈로 인해 차단되어 소프트웨어 렌더링이 되는 상태.

드라이버를 업데이트 하면 해결된다.


Software Hw_disabled=explicit

requestContext3D 로 인해 소프트웨어에서 실행되도록 명시적으로 요청되어 소프트웨어로 렌더링되는 상태.


Software Hw_disabled=unavailable

드라이버의 역량 문제 혹은 , 종합적인 차단목록,

혹은 하드웨어 그래픽 초기화의 실패등으로 소프트웨어로 렌더링 되는 상태.




어떤상황에 해당하는 대비책( fallback ) 으로 소프트웨어로 실행되었는지 알수있는 것은 매우 중요하다.


대부분의 경우 당신은 사용자에게 무엇이 왜 일어났는지 설명할 수 있을 것이다.


dirverInfo 속성에 의해 반한된 값이 "Software Hw_disabled=oldDriver" 인 경우

당신은 유저에게 게임의 퍼포먼스 향상을 위해 드라이버를 업데이트 하라고 알리면 된다.


만약 반환된 값이 "Software Hw_disabled=userDisabled" 라면 당신은 하드웨어 가속설정이 꺼져있다는 것을 


UI 상에서 유저에게 강조할 것이고 유저는 더 나은 퍼포먼스를 위해 하드웨어 가속을 허용 할 것이다.





State Changes (상태 변화)



퍼포먼스 최적화를 이해하기 위한 또다른 중요한 행위는 상태 변화에 대한 개념이다.


이건 뭘까?


GPU 프로그램에서 상태는 특정시간의 파이프라인의 구성과 관련되어 있다.

일부 상황에서 GPU의 상태 변화는 정말로 퍼포먼스를 끝장 내버릴 수 있다.


아래는 상태변화와 관련된 특성들이다.


• 텍스쳐 (다른 텍스쳐라도 같은 atlas 라면 괜찮음)

• 표시객체의 블렌드 모드

• 이미지의 smoothing 

• The repeat mode of textures (??)

• quad의 색변화




객체의 텍스쳐들은 캐쉬되어 매우 빠르게 접근 가능해진다.


이전에 언급한 것 처럼, 텍스쳐를 바꾸는 것은 일반적으로 GPU상에서는 느리고 퍼포먼스에 큰 영향을 끼친다.

그러므로 게임을 설계할 때 가능한 상태변화가 일어나지 않도록 해야 한다.


이를 위한 훌륭한 전략(계획) 은 컨텐츠의 레이어 구성에 대해 고려하고,

레이어 구성을 염두에 두고 디자인된 자원을 이용하여 작업하는 것이다.


실제로 이 문제에 대해 조금더  알아보도록 하자.







The Painter’s Algorithm (페인터 알고리즘)



Starling 은 화면을 그릴 때 Flash 와 같은 테크닉을 사용한다.


화가가 화폭에 그림을 그리는 것처럼, 표시목록의 가장 아래에 있는 것 부터 시작하여 점차적으로 위의 객체를 그리게 된다.



그림38 Painter’s algorithm



만약  위의 그림을 Starling 으로 표시하려고 할 때 

화면의 모든 요소(산,언덕,나무) 가 포함된 이상적인 한장의 단일 sprite atlas 를 사용한다면

전체화면을 한번의 draw call 로 렌더링 할 수 있게 된다.





Texture Atlas (텍스쳐 아틀라스)



만일 텍스쳐 아틀라스에 모든 자원들은 단일 텍스쳐에 포함되어 있다면

Starling 은 배칭(batching) 이 가능하게 되고,

이를 통해 각각의 이미지들 사이에서 상태가 전환되지 않는다면 하나의 atals 를 사용하여

단 한번의 draw call 로 모든 이미지를 그릴 수 있게 된다.


상태는 앞에서 언급한 특성들에 의해  영향을 받는다는 것을 기억해야 한다.


그러니 자원을 패키징 할때 , 항상 이것을 염두에 두자.



물론 많은 자원을 가지고 있고,

스프라이트시트가 2048 x 2048 픽셀 ( 몇몇 모바일 하드웨어에서 이것이 가장 큰 텍스쳐사이즈이다 ) 보다

클 수 없다는 점을 고려한다면 우리는 다수의 atlas를 만들어야 할 필요도 있다.


이때 중요한 것은 각 atlas 엔 가능한한 많이, 그리고  레이어 별로 현명하게, 요소를 채우는 것이다.

이렇게함으로써 화면이 필요로하는 텍스쳐들의 전환 수를 줄이고 

Starling 은 제한된 draw call 로 모든것을 그릴 수 있게 된다.


텍스쳐 아틀라스의 또하나의 장점은 메모리 최적화 이다.

텍스쳐 크기는 2의 제곱승 이어야 한다는 조건을 고려해 볼때,

스프라이트시트에는 약간의 공간이 남는 경우가 생길 수 있다.



예를들어 그림 33을 보자


Figure 33. 러닝보이에 대한 sprite atlas.


아래에 사용되지 않는 공간이 보이는가?  분명 이 빈공간은 그래픽 요소로 빽빽하게 채워질 수 있다.


아래의 예제는 둘 모두 2개의 아틀라스를 사용하고 있다. (같은 아틀라스는 같은색으로 표현);


그림 39의 왼쪽의 표시 목록들은 매 객체마다 상태변화를 일으키는 반면, 

오른쪽은 단 두번의 draw call 로 모든 객체를 그리는 것이 가능하다.



그림39. 틀린 draw call 로 그려진 객체 드로잉




이젠 우리의 예제에 적용시켜 보자.


우린 같은 아틀라스에 또다른 연속프레임을 추가하여 모든 캐릭터를 포함 시켰다.

더 많은 캐릭터를 여기에 포함시킬 수도 있지만 , 일단은 이걸로 하자.



그림 40. 모든 자원이 포함된 텍스쳐아틀라스





XML 파일은 이젠 프랑스 정육점 아저씨도 포함한다.

 



TextureAtlas 클래스의 getTexture 메소드를 사용하여 원하는 대상의 프레임을 참조할 수 있다.


이젠 정육점 아저씨는 그림 41에서 보여지는 것처럼 러닝보이 옆에 나란히 나오게 되었다.



그림 41. 같은 스프라이트시트(텍스쳐아틀라스) 로부터 만들어진 2개의 무비클립 샘플.



단 한번의 draw call 로 모든 캐릭터를 렌더링한 것이 보이는가? ( 그림이 작아서 잘안보임; )


같은 텍스쳐 아틀라스에 담겨 있었기 때문에 스탈링은 능률적이고 일괄적으로(batch) 렌더링 하게 되었다.


항상 stats 창을 주시하고 draw call 이 적절하게 유지되는지 확인하도록 하자.

앞서 우리는 갑자기 의심 될 정도의 높은값으로 치솟는 걸 본적이 있다.


무비클립은 화면에 생성은 되어 있지만 재생되지는 않는다.

이들을 재생하려면, Juggler 객체를 사용해야 한다.


기본적으로 juggler 는 Starling 객체의 juggler 속성을 통해 사용가능하다.

소년과 정육점 아저씨를 재생시키기 위해선 아래의 코드를 추가 해야 한다.



// animate them

Starling.juggler.add ( mMovie );

Starling.juggler.add ( mMovieButcher );



코드가 추가되면 무비클립들은 이제 재생된다!  물론 언제든지 재생을 일시정지 혹은 정지 할 수 있다.



// pause or stop the playback

mMovie.pause();

mMovie.stop();



이 둘의 미묘한 차이에 주목하자.


puase 메서드는 프레임이 현재상태에서 다음으로 넘어가는 것을 멈추지만

stop 메서드는 플레이헤드 를 제일 처음 프레임으로 되돌린다.


(번역자 주)

기존 무비클립 stop 역할을 하는것은 pause 이다.

스탈링 무비클립의 stop 은 기존의 gotoAndStop(1) 과 같다.

처음에 이걸 알지못해서 이상하다? 하면서 헤맨 기억이 있음 ㅋㅋ



이젠 MovieClip 객체에서 사용가능한 전체 API 를 살펴 보도록 하자.

이중 몇가지는 아마 플래시 개발자들에게 매우 친숙한 것들이며

특정 프레임레이트로 설정하거나, 프레임을 대체,추가 하는 등의 유용한 것들도 있다.


• currentFrame

현재프레임


• fps

초당 프레임 재생회수. duration 이 지정되지 않은 프레임을 재생할 때 사용된다.

(번역자 주 : Strling 에서는 프레임마다 각각 다른 duration 을 지정함으로써 fps를 조절 할 수 있다.)


• isPlaying

무비가 현재 재생되고 있는지를 나타낸다.


• loop

무비의 반복 여부를 나타낸다.


• numFrames

무비클립의 프레임 수


• totalTime

모든 프레임의 누적된 시간


• addFrame

명시된 duration 으로 프레임 추가


• addFrameAt

특정 index에 프레임 삽입



• getFrameDuration

지정된 인덱스 프레임의 duration(초단위) 반환


• getFrameSound

    지정된 인덱스 프레임에 포함된 사운드를 반환


• getFrameTexture

지정된 인덱스 프레임의 텍스쳐를 반환


• pause

재생 일시정지


• play

재생시작. 무비클립은 저글러에 포함되어 있어야 한다.


• removeFrameAt

지정된 인덱스의 프레임 제거


• setFrameDuration

지정된 프레임의 duration 을 설정


• setFrameSound

지정된 프레임에 sound 설정. 해당 프레임이 재생될때 사운드도 자동으로 재생된다.


• setFrameTexture

지정된 프레임에 텍스쳐 설정



아래의 코드는 5 프레임이 2초의 지속시간을 가지도록 한다.



// frame 5 will length 2 seconds

mMovie.setFrameDuration(5, 2);



특정 프레임에 동적으로 사운드를 추가할 수도 있다.



// frame 5 will length 2 seconds and play a sound when reached

mMovie.setFrameDuration(5, 2);

mMovie.setFrameSound(5, new StepSound() as Sound);




이것은 동적으로 로드되거나 임베드된 자원들을 통해  런타임에서 완전히 무비클립을

재구성하는 것이 가능한 극도로 강력한 기능이다. 이러한 API 들에 감사하자.


이러한 API 들 (addFrameAt, removeFrameAt, 등등 )의 사용이 필요한 일반적인 상황은

하나의 무비클립으로 그룹화 된 애니메이션을 다양한 상태를 재생시키고 싶을 때이다.


기존의 무비클립 API은,  부모 무비클립의 각 프레임이 각각의 무비클립을 가질 것이고,

프레임이 다른프레임으로 전환 될때 상태는 재생 될 것이다.


Starling의 무비클립은 컨테이너가 아니다.

그렇기 때문에 우리는 무비클립을 원하는 상태로 재생하기 위해 동적으로 프레임을 변화 시켜야 한다.


마지막으로 , 마치 게임에서 컨트롤 하는 것 같은 키보드 조작을 러닝보이에게 넣어보자.


만약 애니메이션의 마지막 순간을 알아야 한다면 , Event.COMPLTE 이벤트로 청취 ( listen ) 할 수 있다.


// listen to the end of the animation

mMovie.addEventListener(Event.MOVIE_COMPLETED, onAnimationComplete);




이 예제에서는 Juggler 객체를 사용 했다, 


ok . 최적화 테크닉으로 돌아가서 다음 주제인 flat sprites 를 보자.






Flat Sprites


starling 은 엄청한 퍼포먼스 향상을 가져다줄 flat sprite 라 불리우는 강력한 기능을 포함하고 있다.


기본적으로 표시목록이 어떻게 작동하는지 이해하기 위해 여러객체가 함께 중첩된 어플리케이션의

전형적인 디스프레이 트리인 그림 42를 보자.

Figure 42. 각각의 버텍스와 인덱스 버퍼를 가질 수 있는 자식들 


그림 42 에서 볼수 있는 것처럼

스탈링의 자식들을 그들의 각각의 버텍스와 인덱스 버퍼, 많은 계산을 필요로 하는 행위들을  독립적으로

처리할 수 있으며 이는 때때론 퍼포먼스에 영향을 끼치기도 한다.


스탈링은 모든 자식들의 기하학 구조를 수집하여 하나의 큰 버텍스 버퍼에 모든  자식( 컨테이너와 그에 포함되어 있는 자식 )

을 단 한번의 draw call 로 그릴 수 있다. (물론 자식들은 같은 텍스쳐를 공유해야 한다 )

그림 43을 보자.


Figure 43. flatten 되면 자식들은 한번의 draw call 로 그려지게 된다.

( 번역자 주 : flatten 을 뭐라고 번역해야 될지; 적당한 단어가 생각이 안남... )


기존 플래시의 표시목록 리스트에서 지원되는 cacheAsBitmap ( 비트맵 캐싱 ) 과 비슷한 기능으로

생각할 수 있다.


단 트리목록에 포함된 자식들에게 변경이 일어나도 자동으로 다시 그려지지는 않는다.

그러므로 변화된 점을 확인하기 위해 확실하게 flatten API를 호출해야 한다.

아래는 사용할 수 있는 API 목록이다.


flatten

가능한 빠르게 콘텐츠를 표시하고 싶을 때  flatten 을 호출 한다.

호출이 되면,스탈링은 표시목록을 그릴 때 필요한 모든 기하학 구조를 수집하고

하나의 버퍼에 모든 데이터를 그룹화 하여 마치 간단한 텍스쳐를 그리는 것처럼 컨텐츠는 하나의 draw call 로 그려지게 된다.

물론 이 기능은 제약이 있는데, 한번 호출이 되면 

다시 명시적으로 flatten 을 호출 하기 전까진 자동으로 자식목록의 변화가 반영되지 않는다.


unflatten

flatten 기능을 끈다.


isFlatenned

sprite 가 현재 flatten이 되었는지 아닌지 알려준다.



이제 한번 사용해보자.

아래의 코드에서 우리는 sprite 속에 다수의 이미지를 추가하고 매프레임 회전시킨다.




이 테스트에서 애니메이션은 60 pfs 에서 부드럽게 재생된다.

하지만 사용된 CPU는 45%로 이중 대부분은 컨테이너의 각자식들의 설정 계산에 사용되고 있다.

우리는 이것을 최적화 할 수 있다. flatten API 를 호출 해 보자.


// 자식들을 고정한다.(freeze the children)

container.flatten();


데스크탑에서 fps 는 별다른 성능 차이가 나타나지 않을 수 있다. 하지만 cpu사용에서 많은 차이점을 보이게 된다.

이 예제는 몇가지 테스트를 통해 하나의 API를 호출 함으로써 cpu 사용을 45% 에서 15%로 약 30% 를 줄였다. 나쁘지 않다.


만약 자식들이 하나의 텍스쳐를 공유하지 않는다면

스탈링은 draw call 을 나누게 되고,

이러한 상태에서는 flatten 기능의 혜택은 감소되게 된다.

대체적으로 게임을 레이어 개념으로 디자인 하자.

각 레이어의 모든 요소가 같은 스프라이트 시트의 일부가 되어야 한다.



이 기능은 모바일에서 많은 도움이 될 것이다.

이기능의 또다른 장점은 이기능은 동적으로 설정할 수 있다는 것이다.

unflatten 을 호출 한뒤 재배치 하여 다시 flatten 할 수 있다.

이방법으로 당신은 동적인 스프라이트에서 텍스쳐를 컴파일 할 수 있다.

언제든지, flatten 을 다시 명시적으로 호출 한다면 자식들의 변화되었을 경우 그 변화는 스크린에 반영되게 된다.


flatten 기능은 정적 콘텐츠 (Sprite ) 에 대해서만 작동되고,

스탈링은 현재 MovieClips 에는 비슷한 최적화를 제공하지 않는다는 것을 기억하자.

그러한 기능은 나중에 추가될 것이다.


flatten 기능은 이것이 전부이다. 최적화에서 또다른 중요한 기능인 batching 에 대해서 시간을 할애해보자.




QuadBatch API 를 통한 Batching


근데 batching 이 뭐지?


이 애매한 이름 뒤에 사실 정말 간단한 일이 숨겨져 있다.

가능한한 draw call 수를 최소화 시키는 것. 


GPU 는 한번에 아주 많은 삼각형을 매우 빠르게 그리지만

데이터를 받기 위해 대기할때 확실히 느려지는 경향이 있다.

batching 은 성능을 최적화 할 수 있는 일반적인 방법이다.


작동방법은 간단하다.

batch 에는 모든 버텍스와 인덱스( primitives ) 가 필수적으로 들어가 있고 모든 객체를 한번에 그린다.

하지만 이 것이 가능하려면

그려질 삼각형은 반드시 같은 렌더링 상태( 텍스쳐,블렌드모드,스무싱 등등) 여야만 한다.


이젠 당신은 이렇 궁금증이 생길 수도 있다.

왜 스탈링은 매번 자동으로 batching  하지 않는가?


 만약 당신이 당신의 화면은 적당하게 ( 레이어등을 통해 ) 만들었다면 스탈링은 가능한한 많이 batching 할 수 있다.

하지만 배칭이 불가능한 상황은 분명 존재 한다.

비록 그것이 기술적으로 흥미로운 도전이 될지라도 게임 전체를 하나의 draw call 로 그릴 수 있는 방법은 존재 하지 않는다.


flat sprite 는 매우 빠르지만 사용이 Sprite 로 제한되고

Sprite 는 가벼운 Image 객체와 비교하였을때 무거운 클래스이다.


Image 나 Quad 객체같은 간단한 요소를 렌더링 해야할 때는 낮은 수준의 (low level)  API 인 QuadBatch 를 이용해야 한다.

QuadBatch API 는 사실 스탈링 내부적으로 사용되지만 필요하다면 사용자도 임의적으로 사용이 가능하다.

아래의 코드는  한번의 draw call 로 100개의 같은 이미지를 그린다.


var quadBatch:QuadBatch = new QuadBatch();

var image:Image = new Image(texture);

quadBatch.addImage(image);

for (var i:int=0; i<100; ++i)

{

image.x += 10;

quadBatch.addImage(image);

}


QuadBatch API 는약간의 제한이 있다.


• Image, Quad 혹은 QuadBatch 클래스의 객체만 추가할 수 있다.

• 단일 방향이다.  객체를 추가할 수 있지만 제거할 수 없다. 객체를 제거할 유일한 방법은 batch를 재설정 하는 것이다.

• 추가된 모든 객체는 같은 상태를 가져야 한다( 즉 같은 텍스쳐 혹은 아틀라스가 사용되어야 한다 )

QuadBatch 에 추가된 첫 이미지에 따라 상태가 결정되며 완전히 재설정 하기 전까지는 상태를 바꿀 수 없다.



보시다시피, 이러한 제약으로 인해  QuadBatch 는 매우 구체적인 상황에서의 사용으로 제한되지만 매우 빠르다!

그러므로 활용을 주저해서는 안된다.




Blending 끄기


투명도가 필요하지 않은 이미지는 투명지원을 중지하자.

만약 완전히 불투명한 사각형의 텍스쳐라면 blendMode 속성을 통해 블렌딩사용을 중지 하면 된다.


backgroundImage.blendMode = BlendMode.NONE;


Alpha 블렌딩은 내부적으로 두번의 GPU 대역폭을 이용한다. 그러므로 이는 간단하지만 강력한 최적화이다.


이는 매우큰 백그라운드 이미지에서 특히 유용하다.

블렌딩모드의 변화는 상태를 변화시키지만 그만한 가치가 있다는 것을 알게 될것이다.

그러니 망설이지 말자!




Stage.color 의 사용


컨텐트 내에서 단일색상의 배경이 필요하다면 단색의 Quad 나 Image 를 사용하는 실수를 하지 말고

SWF 메타태그중 하나인 backgroundColor 를 활용하자.

액션스크립트3의 컴파일러는 자동으로 배경색을 설정한다.


[SWF(backgroundColor="#CCCCCC")]

public class Startup extends Sprite { // ... }


간단하고, 쉽고, 비용이 없다.



폭과 높이에 대한 접근


width 와 height 속성은  특히 sprite 에서 계산할 때 비용이 많이 든다.

( 매트릭스는 모든 자식들의 각 버텍스를 곱연산으로 계산해야 한다.)


그러므로 루프등의 반복문에서 반복적으로 접근하는것을 방지해야 한다.

어떤경우엔 심지어 상수 대신 사용하는 경우도 있다.





상호작용 끄기


마우스나 손가락을 스크린에서 움직이게 되면

스탈링은 마우스,손가락과 충돌 된 객체를 찾으려고 하게 된다.

이것은 매우 비싼 동작이다.

왜냐하면 이것은 모든 표시목록 객체를 반복하며 그들의 hitTest 메소드를 호출하게끔 되어 있기 때문이다.

그러므로 객체가 touch 에 신경쓰지 않아도 될 경우 객체를 untouchable 로 설정하면 도움이 된다.


가능한 컨테이너의 터치 기능을 끄는것이 좋다. ( 이러면 스탈링은  그들의 자식들에 대해 반복하며 touch 검사를 하지 않는다)





이벤트모델 최적화


스탈링 1.2 버전부터 이벤트를 디스패치하는 새로운 메소드가 생겼다.


// classic way:

object.dispatchEvent(new Event("type", bubbles));

// new way:

object.dispatchEventWith("type", bubbles);


새로운 방식은 이전의 방식과 같은 이벤트 객체를 디스패치 하지만

내부적으로 당신을 위해 이벤트객체를 풀링한다.( 풀링, 기억하고 있겠지?)

이말은 새로운 방법을 사용하면 가비지컬렉터에 몇가지 작업을 저장한다는 것을 의미한다.

이 방법은 코딩시 조금 더 적은 코드가 필요하며 빠르기 때문에 이벤트를 전달하기 위해 선호되는 방법이다.

당신이 Event 객체를 상속한 커스텀한 하위클래스를 사용한다면 이방법을 사용할 수 없다.


(번역자 주: Starling 은 오픈 소스 이므로 원한다면 dispatchEventWith 메소드를 수정하여

자신만의 커스텀 이벤트도 같은 방식으로 풀링되고 전파되도록 수정할 수 있다. 스탈링의 경우

event 관련해서 접근자에 namespace 등을 쓰는 등 일부사용자들에겐 생소할 수도 있는데,

굳이 원본 메서드를 수정하지 않고 각자의 방식으로 풀링 시스템을 만들어도 무방하다.)


Handle Lost Context


GPU 에서 작업하게 되면,  GPU 손실 개념에 대해 이해해야 한다.

기본적으로, 일부 시나리오의 일부 플랫폼에서 GPU에 대한 처리 권한이 손실 될 수 있다.

(번역자 주: the handle to the GPU can be lost. ... 여기서 handle 에 대한 적당한 단어가 생각이 안남ㅋㅋ;; )


예를 들어 윈도우에선 gpu 가속을 활용하는 화면 보호기가 실행되면 발생한다.

모바일에선, 안드로이드의 경우, 장치를 회전할 때 종종 손실 될 수 있다.


이것을 처리하기 위해 속성은 아래와 같다.

Starling.handleLostContext = false;


true 설정하면 스탈링은 자동으로 분실된 장치의 컨텍스트를 복구한다.

이 기능은 메모리사용에 큰 영향을 끼친다는 것을 주의하자.

이기능은 안드로이드 및 윈도우에서는 권장되지만 iOS 나 맥에서는 해제 하는 것이 좋다.


중요한 최적화 기법은 끝났다.

이젠 객체에 생명을 불어 넣는 Juggle API 를 살펴보자.


to be continued..