Xcode에 있는 ARMv6용 썸 편집물을 끄고 ARMv7용 썸 편집물을 켜세요. (썸 편집물 : 32비트 ARM CPU에서 16비트를 지원하는 명령어세트인 THUMB을 기반으로 컴파일한 프로그램을 썸편집물 로 보는것이 타당합니다. 이하 '썸'으로 통칭하겠습니다.)
Director:
DisplayLink를 사용하세요. DisplayLink는 최고의 Director입니다. 하지만 SDK 3.1 이나 이후버전에서만 사용 가능합니다. DisplayLink가 지원되지 않는다면 MainLoop나 ThreadMainLoop를 사용하세요.// must be called before any other call to the director if( ! [CCDirector setDirectorType:kCCDirectorTypeDisplayLink] ) [CCDirector setDirectorType:kCCDirectorTypeMainLoop];
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 대신에 CCLabelBMFont나 CCLabelAtlas를 사용할 때. CCTMXTileMap나 CCTileMapAtlas를 렌더 타일하기위해 사용할 때.이 객체들의 도해 버전은 복잡한 코드와 기술을 희생해가면서 더욱 빠른 렌더링을 제공합니다. 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비트 텍스쳐를 사용하려고 시도하세요.
텍스쳐를 읽어들이기 전에 다음의 라인을 추가하세요:
[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 파티클을 사용하는 “느린” 접근을 시도하세요.
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
NSTimer를 사용하려고 하지 마시고 대신에 cocos2d의 스케쥴러를 사용하세요./**********************************************************/ // 아주 좋아~~~~~~~~~~~~~~ /**********************************************************/ -(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 }
/**********************************************************/ // 아주 좋아 ~~~~~~~~~~~~~~~~ /**********************************************************/ -(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 }
replaceScene instead of pushScenepushScene 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
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 } }
malloc()를 수없이 요구할 수도 있습니다. 예를 들어서: CCSpawn 의 CCSequence 이 CCRotateBy 를 호출하면 또 다른 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하게 만드세요. 그 결과, 나는 “그냥 초기화 해버리면 되요”라는 조언이 만약 몇몇의 재초기화가 있는 경우 충분하다는 사실을 믿지 않습니다. - 의역 : 기존의 함수를 그냥 쓰지 마시고, 위에서 언급한대로 함수를 만들어 재 초기화를 하세요.
this is not a best practice but a Tip
MenuItemImage and place your menu using menu.position = ccp(x,y). See the MenuTest example for more details.
this is not a best practice