Dieses Dokuwiki verwendet ein von Anymorphic Webdesign erstelltes Thema.

cocos2d Best Practices

Improving performance

Xcode Thumb

Xcode에 있는 ARMv6용 썸 편집물을 끄고 ARMv7용 썸 편집물을 켜세요. (썸 편집물 : 32비트 ARM CPU에서 16비트를 지원하는 명령어세트인 THUMB을 기반으로 컴파일한 프로그램을 썸편집물 로 보는것이 타당합니다. 이하 '썸'으로 통칭하겠습니다.)

  • 썸 컴파일을 하면 부동연산에 문제는 있지만 더작게 컴파일된 코드가 생성됩니다
  • Non-thumb(32비트 ARM) code에 비해서 Thumb(16비트) code 는 매우느립니다
  • 프로젝트의 이설정을 바꾸는 설명서는 여기에 있습니다.

CCDirector

Director:

  • DisplayLink를 사용하세요. DisplayLink는 최고의 Director입니다. 하지만 SDK 3.1 이나 이후버전에서만 사용 가능합니다. DisplayLink가 지원되지 않는다면 MainLoopThreadMainLoop를 사용하세요.
// must be called before any other call to the director
if( ! [CCDirector setDirectorType:kCCDirectorTypeDisplayLink] )
	[CCDirector setDirectorType:kCCDirectorTypeMainLoop];
  • Or use NSTimer CCDirector with a very low (quick) interval like 1/240
// If you are using "NSTimer" Director you could set a very low interval
[[CCDirector sharedDirector] setAnimationInterval:1/240.0];

텍스쳐 도해

가능하면 텍스쳐 도해를 사용하려고 시도하세요:

  • 스프라이트시트 객체에 상응하는 (것으로부터) CCSprite를 만들때.
  • CCLabelTTF 대신에 CCLabelBMFontCCLabelAtlas를 사용할 때.
  • CCTMXTileMapCCTileMapAtlas를 렌더 타일하기위해 사용할 때.

이 객체들의 도해 버전은 복잡한 코드와 기술을 희생해가면서 더욱 빠른 렌더링을 제공합니다. The Atlas versions utilize an AtlasManager that keeps one large image with multiple frames, and the individual Atlas object refer to a frame of that larger image. 텍스쳐수를 감소시키면서 OpenGL ES 호출을 빠르게 해줍니다.

도해 = 일러스트레이션이나 다이어그램의 묶음(책). 지금의 문맥에서는 여러분의 opengl texture에 읽혀들여진 하나의 큰 이미지(실제로는 작은 이미지의 시리즈)를 의미합니다. 모든 작은 이미지 하나하나가 각각의 텍스쳐에 적재되는 것과는 대조적인것 입니다.

텍스쳐

가능하면 4비트나 16비트 텍스쳐를 사용하려고 시도하세요.

  • PNG/GIF/BMP/TIFF images를 위해서는 16-bit 텍스쳐를 사용하세요.
  • 4-bit 또는 2-bit 텍스쳐: PVRTC textures를 사용하세요.
  • 32-bit 텍스쳐는 마지막에만 의지할 대상입니다

텍스쳐를 읽어들이기 전에 다음의 라인을 추가하세요:

[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA4444]; // add this line at the very beginning

배경이미지를 위해서 당신은 RGB565 포맷을 사용하는것으로 알파채널을 떻어트릴수 있습니다. 이 포맷은 RGBA4444를 사용하는 것보다 시각적인 품질이 나은 이점을 가지고 있습니다.

단순히 픽셀의 색상세팅을 줄여봐야 품질은 떨어지면서 사이즈는 여전히 큰 불이익이 있다는 점을 기억해야 합니다.

Dithering TODO: explain dithering.

PVR textures TODO: explain the benefits of PVR TODO: explain .pvr.gz / .pvr.ccz

The PVR format lets you create RGBA8888, RGBA4444, RGBA5551 and RGB565 textures

Using PVR-Sprites:

CCSprite *sprite = [CCSprite spriteWithFile: @"sprite.pvr"];

파티클

* 두가지 파티클 타입 : Qual 와 Point 파티클 시스템 * Point 파티클 시스템은 1세대와 2세대 디바이스에서는 빠른것처럼 보이지만, 3세대 이후의 디바이스나 iPad에서는 대단히 느리다.

실시간으로 디바이스를 체크하든지 또는 Quad 파티클을 사용하는 “느린” 접근을 시도하세요.

메모리 사용량 줄이기

  • 16-bit나 4-bit 텍스쳐를 사용하세요( 퍼포먼스 증진시키는 방법 쪽을 보세요 )
  • CCTextureCache를 사용하세요
    • CCTextureCache는 모든 이미지를 캐쉬합니다.
    • 이미지가 더이상 사용되지 않아도 메모리에는 남아있게 됩니다.
    • 그것(사용되지 않는 메모리)을 메모리에서 제거하려면:
// textures with retain count 1 will be removed
// you can add this line in your scene#dealloc method
[[CCTextureCache sharedTextureCache] removeUnusedTextures]; // since v0.8
 
// removes a certain texture from the cache
CCTexture2D *texture = [sprite texture];
[[CCTextureCache sharedTextureCache] removeTexture: texture]]; // available in v0.7 too
 
// removes all textures... only use when you receive a memory warning signal
[[CCTextureCache sharedTextureCache] removeAllTextures];    // available in v0.7 too

타이머

  • Cocoa의 NSTimer를 사용하려고 하지 마시고 대신에 cocos2d의 스케쥴러를 사용하세요.
  • cocos2d의 스케쥴러를 사용하면 다음과 같은 것을 얻을수 있습니다:
    • 자동 정지/재시작
    • CCLayer (CCScene, CCSprite, CCNode)가 스테이지에 들어가면 타이머가 자동으로 활성화되고 스테이지를 떠나가게 되면 타이머도 자동으로 비활성화됩니다.
    • 타겟/셀렉터는 델타타임으로 호출되게 됩니다.
/**********************************************************/
// 아주 좋아~~~~~~~~~~~~~~
/**********************************************************/
-(id) init
{
    if( (self=[super init] ) ) {
        // schedule a callback
        [self scheduleUpdate];  // available since v0.99.3
        [self schedule: @selector(tick2:) interval:0.5];
    }
 
    return self;
}
 
-(void) update: (ccTime) dt
{
    // bla bla bla
}
 
-(void) tick2: (ccTime) dt
{
    // bla bla bla
}
 
/**********************************************************/
// 아주 나빠~~~~~~~~~~~~~~~~~~
/**********************************************************/
// Why BAD ?
// You can't pause the game automatically.
-(void) onEnter
{
    [super onEnter];
    timer1 = [NSTimer scheduledTimerWithTimeInterval:1/FPS target:self selector:@selector(tick1) userInfo:nil repeats:YES];
    timer2 = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(tick2) userInfo:nil repeats:YES];
}
-(void) onExit
{
    [timer1 invalidate];
    [timer2 invalidate];
    [super onExit];
}
-(void) tick
{
    // bla bla bla
}
 
-(void) tick2
{
    // bla bla bla
}

그리기 대 갱신하기

  • draw selector 안에서는 어떤 상태변수도 갱신하려고 하지 마세요.
  • schedule selector 안에서는 어떤 것도 그리려고 하지 마세요.
  • Instead update the state variables inside a scheduled selector.
  • Instead draw everything inside the draw selector
  • draw selector 에서 상태변수를 갱신하면 정지/재시작이 기대하는것만큼 동작하지 않을것입니다.
  • draw는 모튼 프레임에서 호출됩니다.
  • 어떤 프레임 비율에서도 schedul된 selector는 호출됩니다, 하지만 어플리케이션의 FPS 비율보다 자주 호출되지는 않습니다.
/**********************************************************/
// 아주 좋아 ~~~~~~~~~~~~~~~~
/**********************************************************/
-(void) draw
{
    [item draw];    // OK: DRAW INSIDE DRAW
}
-(void) update:(ccTime) dt
{
    item.position = dt * finalPosition; // OK, UPDATE STATE IN SCHEDULED SELECTOR
}
 
/**********************************************************/
// 나빠 ~~~~~~~~~~~~~~~~~~~~~
/**********************************************************/
-(void) draw
{
    dt = [self calculateDelta];         // DONT UPDATE STATE IN DRAW.
    item.position = dt * finalPosition; // Pause won't work
 
    [item draw];
}
 
/**********************************************************/
// 아주 나빠 ~~~~~~~~~~~~~~~~
/**********************************************************/
-(void) update:(ccTime) dt
{
    item.position = dt * finalPosition;
    [item draw];            // <--- DON'T DRAW IN SCHEDULED SELECTOR
    // because transformations won't alter your image
}

Director 흐름제어

  • If possible try to use replaceScene instead of pushScene
  • pushScene is very handy, but it will put the pushed scene into memory, and memory is a precious resource in the iPhone.
  • 가능하면 pushScene 대신에 replaceScene를 사용하려고 노력하세요.
  • pushScene는 아주 편리하죠, 하지만 씬을 메모리에 (고정적으로) 올려놓게되는데 메모리는 iPhone 에게 있어서 너무나 중요한 자원입니다.
// TRY TO AVOID A BIG STACK OF PUSHED SCENES
-(void) mainMenu()
{
    // etc
    [[CCDirector sharedDirector] pushScene: gameScene];
}
// stack:
//   . game  <-- running scene
//   . mainMenu
 
-(void) game
{
    [[CCDirector sharedDirector] pushScene: gameOverScene];
}
// stack:
//   . gameOver  <-- running scene
//   . game
//   . mainMenu
 
-(void) showGameOver
{
    [[CCDirector sharedDirector] pushScene: hiScoreScene];
}
// stack:
//   . scores  <-- running scene (4 pushed scenes... expensive)
//   . gameOver
//   . game
//   . mainMenu

Node 만들기 (CCSprite, CCLabel, 등등)

  • 가능하면 CCNode 객체 (CCSprite, CCLabel, CCLayer, 등등) 나 다른 어떤종류의 객체도 init 셀렉터에서만 생성하시고 draw 나 다른어떤 schedule된 selector에서는 생성하려고 하지 마세요.
  • 노드의 생성은 댓가가 비쌀지도 모릅니다, 그러니 먼저 생성한후에 가지고 있으세요.
  • 다른말로 하자면, 메모리(관리)에 주의 하세요, 불필요한 객체는 메모리에 올려놓지 마세요.
/**********************************************************/
// OK, MOST OF THE TIME
/**********************************************************/
-(id) init
{
    // etc...
 
    sprite1 = [CCSprite create];     // <-- USUALLY IT IS BETTER TO CREATE OBJECTS IN INIT
 
    // etc...
}
 
-(void) tick: (ccTime) dt
{
    // etc...
    if( someThing ) {
        [sprite1 show];         // <--- BUT IF YOU DON'T USE THEM FREQUENTLY, MEMORY IS WASTED
    }
}
 
/**********************************************************/
// BAD, MOST OF THE TIME
/**********************************************************/
-(void) tick: (ccTime) dt
{
    // etc...
    if( someThing ) {
        sprite = [CCSprite create];      // <--- EXPENSIVE
        [sprite1 show];
 
        //...
 
        [sprite1 release];      // <-- AT LEAST MEMORY IS RELEASED
    }
 
}

계층 레이어(Hierarchy of Layers)

  • 쓸데없이 큰 계층레이어를 생성하지 마세요. 가능하면 작은상태를 유지하세요.

액션(Actions)

  • 정확한 액션을 생성하려면 비용이 많이 들게 됩니다. malloc()를 수없이 요구할 수도 있습니다. 예를 들어서: CCSpawnCCSequenceCCRotateBy 를 호출하면 또 다른 CCSequence를 참조하고… 등등등 ( 누가 교정좀 해주세요.. ) (뭐하나 구현하려고 치러야하는 댓가가) 너무 비싸게 먹힙니다.
  • 그래서 액션을 재사용 합니다.
  • 액션이 사용된 후에는, 그런 형식의 액션을 다시 실행 하게될 것이라면 나중을 위해서 저장하세요. 새로운 액션을 할당받는 대신에 여러분은 초기화만 하면 됩니다.

2010.09.26 - This is confusing because most ObjectiveC classes do NOT expect their init method to be called again on an already initialized object. And this will NOT work for some CCAction subclasses, CCIntervalAction as an example. CCSequence will leak memory if you call InitOne:Two: on it a second time. Etc. To make CCSequence reusable I think you'd have to write a setActionOne:andTwo: and code the class to release the previous actions and then retain the new ones. As a result, I do not believe this “you can just initialize it” advice is good or complete enough if there is some other kind of re-initialization that will work.

대부분의 ObjectiveC 클래스들은 초기화가 완료된 객체에 대해 다시 init 함수를 쓰기를 원치 않기 때문에 혼동될 수도 있습니다. 그리고 이것은 예를 들어 몇몇의 CCAction / CCIntervalAction 클래스에서는 작동을 안할 수도 있습니다. CCSequence에서 InitOne:Two: 함수를 두 번 호출한다면 메모리 누출이 발생할 것입니다. CCSequence를 재사용가능하게 하려면, setActionOne:andTwo: 함수를 만들어 이 클래스가 이전의 action들을 release하게 하시고 새로운 action들을 retain하게 만드세요. 그 결과, 나는 “그냥 초기화 해버리면 되요”라는 조언이 만약 몇몇의 재초기화가 있는 경우 충분하다는 사실을 믿지 않습니다. - 의역 : 기존의 함수를 그냥 쓰지 마시고, 위에서 언급한대로 함수를 만들어 재 초기화를 하세요.

Buttons

FIXME this is not a best practice but a Tip

  • Use a Menu with a MenuItemImage and place your menu using menu.position = ccp(x,y). See the MenuTest example for more details.
  • MenuItemImage를 사용해 메뉴를 구성하세요. 그리고 당신의 menu에 menu.position = ccp(x,y)를 사용하세요
  • 더 자세한 정보를 보시려면 “MenuTest” 예제를 참고하세요.

How does the pause/resume works ?

FIXME this is not a best practice

  • when the director receives the pause message it won’t call any scheduled target/selector.
  • but the draw selector will be called at a rate of 4 FPS (to reduce battery consumption)
  • when the director receives the resume message, the scheduled target/selectors will be called again every frame.
  • director가 pause message를 받을 때, 어떤 scheduled target / selector 도 호출하지 않습니다.
  • 하지만 draw selector는 4FPS 마다 호출됩니다. (배터리 소모를 줄이기 위함)
  • director가 resume message를 받을 때, scheduled target/selector 들은 모든 프레임마다 다시 불러질 것입니다.
ko/prog_guide/best_practices.txt · Last modified: 2011/09/30 06:10 by kwosu
Trace: translations autorotation sample_games 0_8_2_rc0 setup_buffers 0_8_2_beta cocos2d_cookbook 0_99_0_final samples_and_tests best_practices
Dieses Dokuwiki verwendet ein von Anymorphic Webdesign erstelltes Thema.
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0