iOS_31_cocos2d_微信飞机

最终效果图:

纹理素材

场景

//
//  GameScene.m
//  31_cocos2D入门
//
//  Created by beyond on 14-9-27.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  雷电,游戏场景

#import "GameScene.h"
#import "Hero.h"
// 背景音乐
//#import "SimpleAudioEngine.h"
#import "OALSimpleAudio.h"
// 子弹精灵
#import "Pellet.h"
// 敌机
#import "Enemy.h"

// 一次性初始化的子弹的最大数量
#define kPelletMaxCount 10
// 子弹两次出现之间的总的累计时间间隔
#define kPelletTotalIntervalTime 0.3

// 敌机的最大数量
#define kEnemyMaxCount 5

@interface GameScene()
{
    // 因为一个spriteBatchNode对应一个纹理(图片),因此,从纹理相册裁剪出来的小精灵(帧),全部交给spriteBatchNode统一管理,场景只需要 与 spriteBatchNode打交道
    CCSpriteBatchNode *_batch;
    // 背景2图片 始终在背景1图片的头顶上
    CCSprite *_bg1, *_bg2;

    // 英雄,主角
    Hero *_hero;
    // 标记 是否正在运行
    BOOL _isGameRuning;

    // 重要~~~~子弹缓存
    NSMutableArray *_pelletArr;
    // 成员变量 用于记住 累加的间隔时间,它当达到一定量时(如0.3秒),才发射一串子弹
    // 子弹两次出现之间的总的间隔(累积)时间
    CGFloat _pelletTotalIntervalTime;

    // 重要~~~~敌人缓存
    NSMutableArray *_enemyArr;

}
@end

@implementation GameScene

#pragma mark - 覆盖父类方法
-(id)init
{
    if (self=[super init]) {

        // 1.基本初始化
        [self setupBasic];

        // 2.初始化背景
        // 初始化背景 ,并添加到batchNode中,统一管理,在时钟方法里,滚动背景
        [self setupBg];

        // 3.初始化英雄
        // 初始化英雄 ,并添加到batchNode中,统一管理,在时钟方法里,碰撞检测
        [self setupPlayer];

        // 4.初始化子弹
        // 初始化指定数量的子弹 ,并添加到batchNode中,统一管理,在时钟方法里,射出子弹
        [self setupPelletArr];

        // 5.初始化敌机
        [self setupEnemyArr];

        // 6.开始游戏
        [self startGame];
    }
    return self;
}

#pragma mark - 初始化

#pragma mark 1.基本初始化
- (void)setupBasic
{

    // 1.加载纹理相册 到精灵帧缓存
    [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"gameArts.plist"];

    // 2.创建sprite批处理
    _batch = [CCSpriteBatchNode batchNodeWithFile:@"gameArts.png"];
    [self addChild:_batch];

    // 3.添加一个按钮,暂停或继续游戏
    [self setupPauseButton];
}
// 4.添加一个按钮,暂停或继续游戏
- (void)setupPauseButton
{
    // 调用父类封装的方法,绑定监听方法:gameControlBtnClicked
     [self addBtn:@"暂停/继续" position:ccp(0.5, 0.5) target:self sel:@selector(gameControlBtnClicked)];

}
#pragma mark 2.初始化背景
- (void)setupBg
{

    NSString *bgPicName = @"background_2.png";
    _bg1 = [CCSprite spriteWithImageNamed:bgPicName];
    _bg1.anchorPoint = CGPointZero;

    // 背景2图片 始终在背景1图片 的头顶上
    _bg2 = [CCSprite spriteWithImageNamed:bgPicName];
    _bg2.anchorPoint = CGPointZero;

    [_batch addChild:_bg1];
    [_batch addChild:_bg2];
}
#pragma mark 3.初始化玩家
- (void)setupPlayer
{
    _hero = [Hero node];
    // 因为是从同一个大纹理中,根据key裁剪出来的,所以可以加到同一个精灵batchNode,由它统一管理
    [_batch addChild:_hero];
}
#pragma mark 4.初始化子弹缓存
// 初始化指定数量的子弹 ,并添加到batchNode中,统一管理,在时钟方法里,射出子弹
- (void)setupPelletArr
{
    _pelletArr = [NSMutableArray array];
    // 初始化指定数量的子弹 ,并添加到batchNode中,统一管理,在时钟方法里,射出子弹
    for (int i = 0; i<kPelletMaxCount; i++) {
        // 默认 就是先隐藏的
        Pellet *b = [Pellet node];
        // 类型为:大子弹
        b.type = kPelletTypeBig;
        // 添加到数组中
        [_pelletArr addObject:b];
        // 添加到spriteBatchNode
        [_batch addChild:b];
    }

}

#pragma mark 5.初始化敌机缓存
// 初始化指定数量的敌机 ,并添加到batchNode中,统一管理,在时钟方法里,安排敌机出场
- (void)setupEnemyArr
{
    // 1.初始化 敌机缓存
    _enemyArr = [[NSMutableArray alloc] init];

    for (int i = 0; i<kEnemyMaxCount; i++) {
        // 默认 就是先隐藏的
        Enemy *e = [Enemy node];
        // 类型为:敌机_1
        e.type = kEnemyType_1;
        // 添加到 敌机数组中
        [_enemyArr addObject:e];
        // 添加到spriteBatchNode
        [_batch addChild:e];
    }

}
#pragma mark - 游戏控制按钮点击
- (void)gameControlBtnClicked
{
    // 如果 正在游戏,就暂停;反之继续游戏
    if (_isGameRuning) {
        // _isGameRuning = NO;
        [self pauseGame];
    } else {
        // _isGameRuning = YES;
        [self startGame];
    }
}
#pragma mark 开始
- (void)startGame
{
    // 1.首先置标记为 1
    _isGameRuning = YES;
    // 允许交互
    self.userInteractionEnabled = YES;

    // 2.播放背景音乐

    [[OALSimpleAudio sharedInstance] preloadBg:@"game_music.mp3"];
    [[OALSimpleAudio sharedInstance] playBgWithLoop:YES];
//    [[OALSimpleAudio sharedInstance]playBg:@"game_music.mp3" loop:YES];
    // 3.初始化 子弹两次出现 之间需要的总的累计间隔时间,如 0.3秒
    // 这样一设置之后,game一开始就有子弹射出去了
    _pelletTotalIntervalTime = kPelletTotalIntervalTime;

}
#pragma mark 暂停
- (void)pauseGame
{
    // 1.首先置标记为 0
    _isGameRuning = NO;
    // 停止交互(触摸移动)
    self.userInteractionEnabled = NO;

    // 2.停止所有消息调度
    // 同时,也要让spriteBatchNode中管理的所有成员,执行 unscheduleAllSelectors 方法
     [_batch.children makeObjectsPerformSelector:@selector(unscheduleAllSelectors)];

    // 3.暂停背景音乐

    [[OALSimpleAudio sharedInstance]stopBg];
    [[OALSimpleAudio sharedInstance]stopAllEffects];

}
#pragma mark 结束
- (void)endGame
{
    // 1.首先置标记为 0
    _isGameRuning = NO;
    self.userInteractionEnabled = NO;

    // 2.停止所有消息调度

    // 同时,也要让spriteBatchNode中管理的所有成员,执行 unscheduleAllSelectors 方法
    [_batch.children makeObjectsPerformSelector:@selector(unscheduleAllSelectors)];

    // 3.停止背景音乐

}
#pragma mark - 时钟方法
- (void)update:(CCTime)delta
{
    // 如果 游戏暂停中,则不更新任何状态
    if (!_isGameRuning) {
        return;
    }

    // 1.背景动画(始终向下滚动)
    [self bgAnimation];

    // 2.子弹动画(射出,运行轨迹)
    [self pelletAnimation:delta];

    // 3.敌机出场作战
    [self enemyAnimation:delta];

    // 4.碰撞\边界检测
    [self collsionAndBoundaryCheck];
}

#pragma mark 1.滚动背景
// 1.背景动画(始终向下滚动)
- (void)bgAnimation
{
    // 2张背景图片,始终相差一张图片的高度(无论屏幕多高)
    CGFloat height = _bg1.contentSize.height;
    CGFloat bg1_Y = _bg1.position.y;
    // 向下走
    bg1_Y--;
    // 临界点
    // 向下走过程中,如果 1 超出屏幕了,将1 拉回去(2的y取决于1的y,因此,只要设置1的y)
    if (bg1_Y <= -height) {
        bg1_Y = 0;
    }
    _bg1.position = ccp(0, bg1_Y);
    // 2始终在1的头顶上
    _bg2.position = ccp(0, bg1_Y + height);
}
#pragma mark 2.子弹动画
- (void)pelletAnimation:(CCTime)delta
{
    // 先累加 delta时间,到一定量时,再发射子弹
    _pelletTotalIntervalTime += delta;
    // 如果累计间隔时间达到了 预订的值:如0.3秒,可以发射子弹,位置是:英雄头顶
    if (_pelletTotalIntervalTime >= kPelletTotalIntervalTime) {

        Pellet *pellet;
        for (pellet in _pelletArr) {
            // 如果数组中,还有 子弹不可见,说明在屏幕外;因此,可回收循环使用;只需重新调整位置 发射出去
            if (pellet.visible == NO) {
                CGPoint from = ccp(_hero.position.x, CGRectGetMaxY(_hero.boundingBox));
                [pellet emitFrom:from velocity:ccp(0, 200)];
                break;
            }
            // 如果,数组中没有一个可以用的....那么遍历完后,只能创建新的了,(记得也要加到数组中去哦~)
            pellet = nil;
        }

        // 如果,数组中没有一个可以用的....那么遍历完后,只能创建新的发射了,(记得也要加到数组中去哦~)
        // 没有可循环利用的子弹
        if (pellet == nil) {
            // 其实,内部已经封装了,默认创建出来的新子弹是不可见,只有在发射emit时,才可见
            Pellet *p = [Pellet node];
            // 大子弹
            p.type = kPelletTypeBig;
            // 重要~~~一定要,记得,添加到数组中
            [_pelletArr addObject:p];

            // 添加到精灵batchNode
            [_batch addChild:p];

            // 射出新子弹
            CGPoint from = ccp(_hero.position.x, CGRectGetMaxY(_hero.boundingBox));
            [p emitFrom:from velocity:ccp(0, 200)];
        }
        // 用于记录的成员变量,清零
        _pelletTotalIntervalTime = 0;
    }
}

#pragma mark 3.敌机出场作战
- (void)enemyAnimation:(CCTime)delta
{
    Enemy *enemy;
    for (enemy in _enemyArr) {
        // 如果数组中,还有 敌机不可见,说明在屏幕外;因此,可回收循环使用;只需重新调整位置 参加战场
        if (enemy.visible == NO) {
            // 具体如何 运动,内部自己决定
            [enemy attendTheBattle];
            // 一次时钟周期,送一个敌机上战场
            break;
        }
    }

}

#pragma mark 碰撞\边界检测
- (void)collsionAndBoundaryCheck
{
    // 子弹检测
    Pellet *pellet;
    for (pellet in _pelletArr) {
        // 只有在屏幕范围内,可见的,才需要进行碰撞检测;如不可见,直接,分析下一个子弹
        if (pellet.visible == NO) continue;

        // 1.子弹 与 屏幕 检测
        // 2.子弹 与 敌机 检测
        [self checkPellet:pellet];

    }// 遍历子弹缓存数组 结束

}
// 1.子弹 与 屏幕 检测
// 2.子弹 与 敌机 检测
- (void)checkPellet:(Pellet *)pellet
{
    // 子弹边框与屏幕边框 进行交集检测
    if (!CGRectIntersectsRect(self.boundingBox, pellet.boundingBox)) {
        // 1.离开屏幕了(再无交集),子弹消失
        [pellet dismiss];

    } else {
        // 2.子弹还在屏幕内,才要进行,与敌机的 碰撞检测
        // 敌机检测
        Enemy *enemy;
        for (enemy in _enemyArr) {
            // 如果不可见,不需要检测
            // 只有在屏幕范围内,可见的,才需要进行碰撞检测;如不可见,直接,分析下一个
            if (enemy.visible == NO) continue;
            // 1.敌机与屏幕rect检测
            // 2.敌机与子弹检测
            // 3.敌机与英雄检测
            [self enemy:enemy checkWithPellet:pellet];

        }// 遍历子弹缓存数组 结束
    }// 子弹 和 敌机的 碰撞检测
}

// 1.敌机与屏幕rect检测
// 2.敌机与子弹检测
// 3.敌机与英雄检测
- (void)enemy:(Enemy *)enemy checkWithPellet:(Pellet *)pellet
{
    // 敌机 边框与屏幕rect边框 进行交集检测
    if (!CGRectIntersectsRect(self.boundingBox, enemy.boundingBox)) {
        // 如果 没有交集,代表,敌机 逃离屏幕范围,故隐藏 敌机;
        [enemy hide];

    } else if (CGRectIntersectsRect(pellet.boundingBox, enemy.boundingBox)) {
        // 只有在屏幕范围内的敌机,才需要 和 (在屏幕范围内的)子弹 进行交集检测
        // 首先,隐藏子弹
        [pellet dismiss];

        // 然后,敌机中弹
        [enemy gotHit];
    } else {
        // 自定义方法,英雄与敌机 交集检测
        [self enemyCheckWithHero:enemy];
    }
}
// 自定义方法,英雄与敌机 交集检测
- (void)enemyCheckWithHero:(Enemy *)enemy
{
    // 子弹 虽然 没有打中,但是 英雄与敌机 相撞,结果还是,game over
    if (CGRectContainsRect(_hero.boundingBox, enemy.boundingBox)) {
        [_hero dieWithEnemyTogether];

        // game over,结束游戏
        [self endGame];
    }
}
#pragma mark - 触摸事件
// 必须有 touch began ,否则 不能响应
- (void)touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{

}
- (void)touchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
    // 1.当前点
    CGPoint curPoint = [[CCDirector sharedDirector] convertToGL:[touch locationInView:touch.view]];

    // 2.上一个点
    CGPoint prePoint = [[CCDirector sharedDirector] convertToGL:[touch previousLocationInView:touch.view]];

    // 3.设置飞机的位置
    CGPoint newPosition = ccpAdd(_hero.position, ccpSub(curPoint, prePoint));

    // 4.拖动过程中,边界检测,不能出屏幕
    CGFloat _heroWidth = _hero.contentSize.width;
    CGFloat _heroHeight = _hero.contentSize.height;
    if (newPosition.x <  _heroWidth*0.5) {
        return;
    } else if(newPosition.x > self.contentSize.width - _heroWidth*0.5){
        return;
    }else if (newPosition.y < 0){
        return;
    }else if(newPosition.y > self.contentSize.height - _heroHeight){
        return;
    }
    _hero.position = newPosition;
}
@end<span style="font-family:Courier New;color:#393939;"><span style="font-size: 24px; line-height: 32px; background-color: rgb(245, 245, 245);"><strong>
</strong></span></span>

子弹Pellet

//
//  Pellet.h
//  31_cocos2D入门
//
//  Created by beyond on 14-9-28.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "CCSprite.h"

typedef enum {
    // 小子弹
    kPelletTypeSmall,
    // 大子弹
    kPelletTypeBig
}PelletType;

@interface Pellet : CCSprite
// 子弹类型
@property (nonatomic,assign) PelletType type;
// 子弹速度 (Y方向,和X方向)
@property (nonatomic, assign) CGPoint velocity;

// 发射 emit,参数:射出的点  射出的速度
- (void)emitFrom:(CGPoint)from velocity:(CGPoint)velocity;
// 消失/隐藏
- (void)dismiss;

@end
//
//  Pellet.m
//  31_cocos2D入门
//
//  Created by beyond on 14-9-28.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "Pellet.h"

// 精灵帧 用到
#import "cocos2d.h"
// 音效
//#import "SimpleAudioEngine.h"
#import "OALSimpleAudio.h"

@implementation Pellet

#pragma mark - 父类方法

-(id)init
{
    if (self=[super init]) {
        // 子弹创建时,默认隐藏,只有当调用发射emit方法时,才显示
        self.visible = NO;
    }
    return self;
}
#pragma mark - 拦截setter
- (void)setType:(PelletType)type
{
    _type = type;

    // 更换子弹精灵的 图片
    NSString *imgName = _type == kPelletTypeSmall ? @"bullet1.png" : @"bullet2.png";
    CCSpriteFrame *frame = [CCSpriteFrame frameWithImageNamed:imgName];
    [self setSpriteFrame:frame];
}

#pragma mark - 供外界调用
// 发射 emit,参数:射出的点  射出的速度
- (void)emitFrom:(CGPoint)from velocity:(CGPoint)velocity{
    self.visible = YES;

    // 设置位置
    self.position = from;

    // 设置速度
    self.velocity = velocity;
    // 音效播放
    //    [[SimpleAudioEngine sharedEngine] playEffect:@"Pellet.mp3"];
    [[OALSimpleAudio sharedInstance]playEffect:@"bullet.mp3"];
}
// 消失/隐藏
- (void)dismiss
{
    self.visible = NO;

    [self unscheduleAllSelectors];
}

#pragma mark - 时钟方法(飞行)
- (void)update:(CCTime)delta
{
    // 当子弹消失后,不再更新position...
    if (!self.visible) {
        return;
    }
    // deltaTime 时间内,移动(飞行)一段距离
    // 路程s = 速度v * 时间t
    CGPoint s = ccpMult(self.velocity, delta);
    self.position = ccpAdd(self.position, s);
}
@end

英雄Hero

//
//  Hero.h
//  31_cocos2D入门
//
//  Created by beyond on 14-9-27.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "CCSprite.h"

@interface Hero : CCSprite

// 简单处理,英 雄与敌机 相撞,结果还是,game over
- (void)dieWithEnemyTogether;
@end
//
//  Hero.m
//  31_cocos2D入门
//
//  Created by beyond on 14-9-27.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  主角,代表玩家的 英雄

#import "Hero.h"
#import "cocos2d.h"
#import "CCDirector.h"
#import "CCAnimation.h"
@implementation Hero

// 初始化玩家(的飞机)
- (id)init
{
    // 其实,磁盘里没有hero_fly_1.png 图片,它是到大图片的帧缓存中,根据key取出(裁剪)小图片
    if (self = [super initWithImageNamed:@"hero_fly_1.png"]) {
        // 1.初始化位置,底部,中间
        self.anchorPoint = ccp(0.5, 0);
        // 从导演那儿拿到viewSize就是屏幕的size
        CGSize fullScreenSize = [[CCDirector sharedDirector] viewSize];
        self.position = ccp(fullScreenSize.width * 0.5, 0);

        // 2.创建 帧动画 需要的两个精灵帧
        CCSpriteFrameCache *cache = [CCSpriteFrameCache sharedSpriteFrameCache];
        CCSpriteFrame *frame1 = [cache spriteFrameByName:@"hero_fly_1.png"];
        CCSpriteFrame *frame2 = [cache spriteFrameByName:@"hero_fly_2.png"];

        NSArray *spriteFramesArr = @[frame1, frame2] ;

        // 3.为精灵添加动画
        CCAnimation *animation = [CCAnimation animationWithSpriteFrames:spriteFramesArr delay:0.1];
        CCActionAnimate *animate = [CCActionAnimate actionWithAnimation:animation];
        // 4.播放帧动画
        [self runAction:[CCActionRepeatForever actionWithAction:animate]];
    }
    return self;
}
// 简单处理,英 雄与敌机 相撞,结果还是,game over
- (void)dieWithEnemyTogether
{
    // 停止之前的帧动画
    [self stopAllActions];

    // 直接播放 爆炸 帧动画
    NSMutableArray *frames = [NSMutableArray array];

    for (int i = 1; i<=4; i++) {
        NSString *name = [NSString stringWithFormat:@"hero_blowup_%d.png", i];
        CCSpriteFrame *f = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:name];
        [frames addObject:f];
    }

    CCAnimation *animation = [CCAnimation animationWithSpriteFrames:frames delay:0.1];
    [self runAction:[CCActionAnimate actionWithAnimation:animation]];
}
@end

敌机Enemy(有待发散)

//
//  Enemy.h
//  31_cocos2D入门
//
//  Created by beyond on 14-9-28.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "CCSprite.h"
//对应plist文件中 5种图片
typedef enum {
    kEnemyType_1 = 1,
    kEnemyType_2 = 2,
    kEnemyType_3 = 3,
    kEnemyType_4 = 4,
    kEnemyType_5 = 5
} EnemyType;

@interface Enemy : CCSprite

@property (nonatomic, assign) EnemyType type;
// 出现在游戏中,出场,加入战斗
- (void)attendTheBattle;
- (void)hide;
// 被击中
- (void)gotHit;
@end
//
//  Enemy.m
//  31_cocos2D入门
//
//  Created by beyond on 14-9-28.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "Enemy.h"
#import "cocos2d.h"
#import "OALSimpleAudio.h"
#import "CCAnimation.h"
#import "CCDirector.h"

@interface Enemy()
{
    // 最大的生命值
    int _maxHp;
    // 生命值
    int _hp;
}
@end

@implementation Enemy

#pragma mark - 父类方法

-(id)init
{
    if (self=[super init]) {
        // 敌机创建时,默认隐藏,只有当调用出场,参加战斗 时,才显示
        self.visible = NO;
    }
    return self;
}

#pragma mark - 拦截setter方法
- (void)setType:(EnemyType)type
{
    _type = type;

    // 根据 敌人类型,设置 敌人显示的图片
    [self setEnemyImage];

    // 根据 敌人类型,设置 敌人最大生命值
    switch (type) {
        case kEnemyType_1:
            _maxHp = 1;
            break;
        case kEnemyType_2:
            _maxHp = 2;
            break;
        case kEnemyType_3:
            _maxHp = 3;
            break;
        case kEnemyType_4:
            _maxHp = 4;
            break;
        case kEnemyType_5:
            _maxHp = 5;
            break;

        default:
            break;
    }
}

#pragma mark - 时钟方法
- (void)update:(CCTime)delta
{
    // 同其他的子弹、英雄一样,只有在显示时,才需要更新位置
    // 当敌人处于不可见时,说明被打死了,或逃出屏幕了,因此无需更新其位置
    if (!self.visible) {
        return;
    }
    // 不断调整敌人的位置 (速度 可以和最大生命值一样,设置不同的...)
    self.position = ccpAdd(self.position, ccp( 0, -100 * delta));
}
#pragma mark - 供外部调用
// 出现在游戏中,出场,加入战斗
- (void)attendTheBattle
{
    // 出场时,满血
    _hp = _maxHp;
    // 出场时,显示
    self.visible = YES;
    // 出场时,位置,从屏幕顶部俯冲下来
    self.anchorPoint = ccp(0.5, 0);

    CGSize winSize = [CCDirector sharedDirector].viewSize;
    // 重要~~~之所以要减一,是因为...出场时,要让它一只脚 踏进屏幕,与屏幕窗口的rect有交集
    self.position = ccp(winSize.width * CCRANDOM_0_1(), winSize.height - 1);
    // 边界检测

}
// 被击中
- (void)gotHit
{
    _hp--;

    if (_hp == 0) {
        // 1.播放对应的被打中时 的音效
        [self playHitSound];
        // 2.播放对应的被爆炸动画
        [self playExplodeAnimation];

    }
}
// 消失
- (void)hide
{
    self.visible = NO;

    [self unscheduleAllSelectors];
}

#pragma mark - 抽取方法
// 根据 敌人类型,设置 敌人显示的图片
- (void)setEnemyImage
{
    // 根据 敌人类型,设置 其图片
    NSString *name = [NSString stringWithFormat:@"enemy%d_fly_1.png", _type];
    // 从精灵帧缓存中,取出精灵帧,从而设置到精灵身上,显示
    CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:name];
    [self setSpriteFrame:frame];
}

// 播放对应的被打中时 的音效
- (void)playHitSound
{
   [[OALSimpleAudio sharedInstance] playEffect:[NSString stringWithFormat:@"enemy%d_down.mp3", _type]];
}
// 播放爆炸动画,爆炸完,隐藏,最后重新设置显示图片,为参加下一次战斗作准备
- (void)playExplodeAnimation
{
    NSMutableArray *frames = [NSMutableArray array];
    // 这个爆炸效果的 4 应该动态变化 ....
    for (int i = 1; i<=4; i++) {
        NSString *name = [NSString stringWithFormat:@"enemy1_blowup_%d.png", i];
        CCSpriteFrame *f = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:name];
        [frames addObject:f];
    }
    // 名词,动画
    CCAnimation *animation = [CCAnimation animationWithSpriteFrames:frames delay:0.1];
    // 动作_1 爆炸
    CCActionAnimate *explosion = [CCActionAnimate actionWithAnimation:animation];
    // 动作_2 不可见
    CCActionHide *hide = [CCActionHide action];
    // 动作_3 因为爆炸后,精灵的显示图片变了,所以要重新设置回来,以便下一次 参加战斗
    CCActionCallFunc *func = [CCActionCallFunc actionWithTarget:self selector:@selector(setEnemyImage)];
    // 动作_4 用序列包装
    CCActionSequence *sequence = [CCActionSequence actions:explosion,hide,func, nil];
    // 执行动作
    [self runAction:sequence];
}
@end

时间: 2024-08-01 22:19:28

iOS_31_cocos2d_微信飞机的相关文章

用Swift语言和Sprite Kit复制微信飞机大战游戏

先上GitHub链接: https://github.com/songrotek/PlaneWar.git 接下来稍微讲解一下! 这个程序还有点Bug,见谅! 1 说明 游戏采用了Sprite kit最新的Per pixel for physic 技术,就是直接使用texture纹理作为sprite的physics body . 游戏的texture.atlas从别的打飞机项目中拷之并辛苦地分解了. 游戏编写借鉴了网上的objc代码! 2 游戏编写过程 添加背景-> 添加控制的飞机-> 添加发

微信飞机大战游戏开发

原文出自:方杰|http://fangjie.sinaapp.com/?p=366转载请注明出处 这学期上了一学期的Windows游戏开发课程,学期末的时候所以决定做一个微信飞机大战的小游戏. 不同于微信手机上的飞机大战,这是一个Win32平台下游戏.Win32项目,VS2008开发平台,利用我的老师写的TinyEngine微型游戏引擎开发. TinyEngine引擎的相关源码及介绍参见:https://github.com/JayFang1993/TinyEngine 飞机大战游戏的相关源码参

Cocos2d-x 3.0final 终结者系列教程16-《微信飞机大战》实现

看到cocos2d-x推出了3.1版本,真是每月一次新版本,速度, 还有一个好消息就是http://cn.cocos2d-x.org/上线了,祝贺!啥时候把我的视频和教程放上去呢?!!! 本文介绍一款纵版射击游戏的实现,开发环境: win7 vs2012 cocos2d-x3.0final android adt android ndk r9 首先看下最后的效果: (图1,微信飞机大战运行效果) 源码下载地址:http://download.csdn.net/detail/sdhjob/7513

cocos2d-x-3.3-022-仿微信飞机大战-开篇介绍

原文同步发布于我的wiki,查看原文或更新请移步: 点击打开链接 写在最前面 微信飞机大战,触控的大神JackyStudio 已经在他的专栏微信飞机大战讲解中完整细致的实现了一遍,基于cocos2d-x-v2.2.0和cocos2d-x-3.0,推荐大家阅读.同时该系列的资源代码等全部开源(地址见文后链接),利于新手运用和学习.感谢分享. 我是新手,刚懂点cocos的基础.我这系列将沿着大神的足迹前进,更进一步去体会理解cocos的魅力.本系列将记录我个人在实践之路上的体会. 本系列将基于coc

【一】仿微信飞机大战cocos2d-x3.0rc1

參考 [偶尔e网事] 的 [cocos2d-x入门实战]微信飞机大战  cocos2dx 2.0版本号,偶尔e网事他写的很具体,面面俱到,大家很有必要看下.能够通过以下链接跳转: cocos2d-x入门实战 这里面我以[cocos2d-x入门实战]微信飞机大战 为蓝本,用cocos2dx 3.0rc1翻版.安装环境什么的,我就不说了,网上都能够找到,我直接从游戏開始界面说起. 想往下看的话,你必须会的一件事,就是你已经能创建出cocos2dx3.rc1的helloworldproject. 以下

500行代码,教你用python写个微信飞机大战

这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手. 帮助蹲厕族.YP族.饭圈女孩在无聊之余可以有一样东西让他们振作起来!让他们的左手 / 右手有节奏有韵律的朝着同一个方向来回移动起来! 这是史诗级的发明,是浓墨重彩的一笔,是-- 在一阵抽搐后,我结束了游戏,瞬时觉得一切都索然无味,正在我进入贤者模式时,突然想到,如果我可以让更多人已不同的方式体会到这种美轮美奂的感觉岂不美哉? 所以我打开电脑,创建了一个 plan_game.py-- 先

cocos2d-x-3.3-024-仿微信飞机大战-如何引爆炸弹-实现范围攻击

原文同步发布于我的wiki,查看原文或更新请移步: 点击打开链接 承上文 先回答拓展思考里的问题,'物理引擎可否用来做碰撞检测?',答案是肯定的,具体见下面 cocos2d-x-3.3-019-碰撞检测1-矩形区域是否相交 cocos2d-x-3.3-020-碰撞检测2-物理引擎初探 cocos2d-x-3.3-021-碰撞检测3-物理引擎碰撞过滤 子弹如何杀伤敌人在上面的系列中已经实现.本节要实现的功能点是,继续利用碰撞检测实现飞机大战里炸弹的全屏范围攻击 本文DEMO 基于cocos2d-x

cocos2d-x-3.3-023-仿微信飞机大战-总体分析和建模

原文同步发布于我的wiki,查看原文或更新请移步:点击打开链接 总体分析 一开始得想明白了的问题 游戏里面的可见元素,采用is-a精灵,还是采用has-a精灵好: 直接继承精灵使用于相对简单的情形:而对于复杂的UI构成采用组合策略, 这时候用继承Node,并采用has-a精灵的关系是不错的选择. 子弹发射这个动作的思考(包括产生敌机,英雄出场,补给出场等都适用这个问题),cocos提供的导演和场景是用于流程控制的:层是画布:而精灵则是画布上的元素,故在发射或者创建一个子弹时要指定他所属于的画布.

大志非才不就,大才非学不成

零.苦逼码农的自我修养系列 PS:为什么此部分序号是零而不是一?因为这是作为一个码农所应该具有的基础之中的基础,要想做个好码农,此部分还得花大力气啃书啊,这决定了我们看待计算机程序的高度. 0.1 数据结构与算法学习总结系列 (1)你必须知道的指针基础系列: { 预备篇 gcc开发环境搭建 } { 指针的声明和使用.数组与指针的关系 } { 指针的移动.指针的危险 } { sizeof计算长度.strcpy的安全性问题 } { 应用篇 自己实现strlen函数,endsWith函数 } { 内存