
紋理素材


場景
//
// 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= 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
子彈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