Здравствуйте, хабражители!

Первая моя игра была написана iPhone SDK про писающего мальчика, она очень тормозила на 3G и 3GS. Вторую сделал с меньшей нагрузкой на процессор, при этом я уже слышал о cocos2d, прочитав документацию про него, я решил к SDK, больше не возвращаться и начал программировать под эту платформу. В этой статье я не буду описывать как устанавливать cocos2d, это описано здесь, постараюсь не повторяться с этим постом. Могу лишь добавить есть стабильная 1.0.1 версия. В этой статье я расскажу как создать меню, анимацию и переход между слоями.

Итак, к делу.

Создаем проект на cocos2d, ориентируем его на iPad, переходим к файлу HelloWorldLayer.m и в методе -(id) init создаем спрайт для заднего фона:

-(id) init
{
	if( (self=[super init])) {
        
                // автоматически определяет размеры экрана, в зависимости от девайса
                 CGSize size = [[CCDirector sharedDirector] winSize];
		
		//Создаем backgroung
                CCSprite * background = [CCSprite spriteWithFile:@"clean bg.png"];
                //Распологаем наш спрайт по центру
                background.position = ccp(size.width/2, size.height/2);
                //добовляем наш спрайт на CCLayer при этом он должен быть на заднем фоне,
                //за это отвечает z:-1
                [self addChild:background z:-1];    
	}
	return self;
}

могу добавить, что когда добавляем наш спрайт на слой можно добавить тег: [self addChild:background z:-1 tag:100]; это делается для того что бы можно было найти спрайт по тегу в другом методе или классе, это делается так: CCSprite *spr = (CCSprite *)[self getChildByTag:100]; потом делаете что хотите с этим спрайтом.

Далее, здесь же создаем меню:

//Создаем ячейки меню
        
        //Ячейка с картинкой
        CCMenuItemImage * image = [CCMenuItemImage itemFromNormalImage:@"new_game.png" 
                                             selectedImage:@"new_game.png" target:self
                                              selector:@selector(perehod_v_igru)];
        //Распологаем нашу ячейку относительно меню(начало координат в центре,
        //там где мы расположили наше меню)
        image.position = ccp(0, 50);
        
        //Ячейка с font
        CCMenuItemFont * font = [CCMenuItemFont itemFromString:@"Опции" target:self 
                        selector:@selector(options)];
        font.position = ccp(0, -50);
        
        //Создаем меню
        //Заносим в меню наши ячейки
        CCMenu * menu = [CCMenu menuWithItems:image, font, nil];
        
        //Распологаем по центру
        menu.position = ccp(size.width /2 , size.height/2);
        
        //Добавляем наше меню
        [self addChild:menu];


меню cocos2d является альтернативой кнопок iPhone SDK, здесь мы рассмотрели 2 вида ячеек(картинка и надпись), как видете они ссылаются на некие методы, в нашем случае это переходы на другие слои:

-(void)perehod_v_igru
{   
    //Заменяем слой главного меню на слой самой игры
    [[CCDirector sharedDirector] replaceScene:[CCTransitionPageTurn transitionWithDuration:1
               scene:[Game node]]];
}


CCTransition отвечает за эффект перехода с одного слоя на другой в течении определенного времени.

-(void)options
{
    //Накладываем слой опции на текущий
    [[CCDirector sharedDirector] pushScene:[Options node]];
}


В этом случае pushScene применяется для временного наложения слоя.

Создаем файлы Options, нажимаем команд + N:

image

image

image

как видно на последнем скриншоте мы создает кастомный слой, по умолчанию он черный, но поигравшись в RGB вы можете поставить любой цвет.

Далее создаем CCMenu и метод возвращающий обатно в главно меню:

-(id) init {
    //В RGB можем настроить цвет слоя
    if ((self = [super initWithColor:ccc4(255, 0, 0, 155)])) {  
        
                CGSize size = [[CCDirector sharedDirector] winSize];
        
                CCMenuItemFont * font = [CCMenuItemFont itemFromString:@"В МЕНЮ" target:self 
                selector:@selector(backItem)];
                font.position = ccp(0, 0);
        
                CCMenu * menu = [CCMenu menuWithItems: font, nil];
                menu.position = ccp(size.width /2 , size.height/2);
                [self addChild:menu];

	}
	return self;
}

-(void)backItem{
    //Переходим обратно в главное меню
    [[CCDirector sharedDirector] popScene];
}


popScene убирает текущий слой. Будьте осторожны под этим слоем должен быть любой другой, как писалось выше, мы именно накладываем слой, в противном случае выдаст ошибку.

Далее создаем слой Game:

image

image

image

Создаем задний фон и ставим задержку перед созданием другого спрайта в файле Game.m:

-(id) init
{
	if( (self=[super init])) {
        
                CGSize size = [[CCDirector sharedDirector] winSize];
		
		//Создаем background
                CCSprite * background = [CCSprite spriteWithFile:@"clean bg.png"];
        
                //anchorPoint это точка от которой происходят манипуляции со спрайтом, по умолчанию
                //background.anchorPoint = ccp(0.5f,0.5f); все манипуляции происходят в середине спрайта
                //в нашем случае я поставил anchorPoint = ccp(1, 1); все манипуляции начинаются с правого 
                // верхнего угла, при (0, 0) левый нижний угол
                background.anchorPoint = ccp(1, 1);
        
                background.position = ccp(size.width, size.height);
                [self addChild:background z:-1];
        
                //Создадим спрайт после задержки в 0,5 секунды
                [self performSelector:@selector(sozdanie_CCSprite) withObject:self afterDelay:0.5];
	}
	return self;
}


здесь я применил anchorPoint, далее увидим его реальное применение:

-(void)sozdanie_CCSprite
{
            //Впринцепе так же делается как и background
            CCSprite * tarakan = [CCSprite spriteWithFile:@"tarakan0.png"];
            tarakan.position = ccp(512, 100);
            tarakan.anchorPoint = ccp(0,0);    
            [self addChild:tarakan];
    
            //Actions
            //Отвечает за смещение на определеное количество пикселей за определеный промежуток времени
            id move = [CCMoveBy actionWithDuration:2 position:ccp(0, 500)];
            //Отвечает за ускорение и замедление
            id accel = [CCEaseInOut actionWithAction:move rate:5];
            //Действие вращения
            id rotate = [CCRotateBy actionWithDuration:2.0f angle:360];
            //Запускаем движение
            [tarakan runAction:[CCSequence actions:accel, rotate, nil]];
    
            //Запустим анимацию
            [self performSelector:@selector(animation) withObject:self afterDelay:3.5];
    
}


здесь мы применяем разные действия над тараканом. Когда скомпилируем и увидем, что таракан двигается с ускорением, а потом вращается, при этом точка вращения левый нижний угол, это и есть тот anchorPoint которому мы указали (0, 0). Мы указали движение таракана, за перемещение отвечает CCMoveBy, за плавность ускорения и замедления во время перемещения отвечает CCEaseInOut, за вращение CCRotateBy. Так же мы тут видим применение CCSequence, эта команда применяется для того, что бы действия над спрайтом шли по очереди.

И последнее, создаем анимацию после задержки:

-(void)animation {
            CGSize size = [[CCDirector sharedDirector] winSize];
    
            //Указываем plist с кадрами и картинку с текстурами 
            [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"tarakan.plist"
                    textureFile:@"tarakan.png"];
            //CCSpriteBatchNode это особый класс в cocos2d, который может выступать в качестве родителя 
            //к целому ряду спрайтов
            //Его используют для экономии памяти в проекте
            CCSpriteBatchNode * bowSheet = [CCSpriteBatchNode batchNodeWithFile:@"tarakan.png"];
    
            NSString *topbird = @"tarakan";
            NSMutableArray *walkAnimFrames = [NSMutableArray array];
            //Прогоняем кадры в цикле
            for(int i = 1; i <= 4; ++i) {
                        CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] 
                                   spriteFrameByName: topbird stringByAppendingString:[
                                   NSString stringWithFormat:@"%d.png", i]]];
                        [walkAnimFrames addObject:frame];
            }
            //Создаем анимацию в которой кадры меняются за определеный промежуток времени
            CCAnimation *walkAnim = [CCAnimation animationWithFrames:walkAnimFrames delay:0.1f];        
    
            NSString *bowFrame = [topbird stringByAppendingString:@"1.png"];
            //Создаем спрайт с первым кадром
            CCSprite * bow = [CCSprite spriteWithSpriteFrameName:bowFrame];
            bow.position = ccp(size.width/2 , -100);
            [bowSheet addChild:bow];
    
            //CCAnimate присваевает имена спрайтов CCAnimation 
            //Создаем действие из анимации и выделяем память под CCAnimate
            CCAnimate * bowAnim = [[CCAnimate actionWithAnimation:walkAnim restoreOriginalFrame:YES] 
                      retain];
            [self addChild:bowSheet];
    
            //Создаем повторяемое действие
            id walkAction = [CCRepeat actionWithAction:bowAnim times:5]; 
            //Создаем движение
            id da = [CCMoveBy actionWithDuration:2 position:ccp(0, 600)];
            //Применяем одновремено все действия спрайту
            [bow runAction:[CCSpawn actions:da, walkAction, nil]];    
}


большую часть я прокомментировал, добавлю что текстуру я создавал с помощью zwoptexapp.com, это бесплатно, там я получил plist и png файлы, перетащил их в проект. Так выглядит tarakan.plist файл:

image

а так tarakan.png файл:

image

Так же видно, при применении действия вместо CCSequence, применили CCSpawn, эта команда применяется для того, что бы действия над спрайтом шли одновременно.

Часто вижу на форумах проблемы с созданием анимации на cocos2d, поэтому включил её в эту статью. Надеюсь эта статья будет кому-то полезна.

Проект можно скачать здесь.