手把手教你开发一款IOS飞行射击游戏(六)

原创 2017年01月03日 23:25:12

这一篇我们为我们的飞船添加各种敌人飞船。

首先,我们准备一下敌人飞船的各种图片:

boss.png:

2014年05月14日 - Daniel - KHome

bigdaddy.png:

2014年05月14日 - Daniel - KHome

powermaker.png:

2014年05月14日 - Daniel - KHome

speedkiller.png:

2014年05月14日 - Daniel - KHome

littleworm.png:

2014年05月14日 - Daniel - KHome

自己随便画的,名字瞎起的,勿喷O_o。

接着我们用TexturePacker将这些敌人飞船纹理图和敌人的4种子弹组装起来,publish生成4个文件:

enemy-ships-hd.pvr.gz

enemy-ships-hd.plist

enemy-ships.pvr.gz

enemy-ships.plist

接着把这些文件添加到Resources中。

 

下面我们添加代码。由于敌人飞船在属性上有自己的一些特性,所以这里我们在Entity的基础上,再抽象出一个EnemyShip类,接着不同的敌人我们由EnemyShip派生出不同的子类。

来看EnemyShip.h的定义:

#import"Entity.h"

#import"AirCraft.h"

 

@interfaceEnemyShip : Entity{

   float shootFrequency;

   ccTime nextShootTime;

   ccTime shootTotalTime;

   ccTime movedTime;

   ccTime changeDirectionTime;

   int currentMoveX;   //+-1

   int currentMoveY;   //+-1

   int enemyScoreWorth;

}

 

-(id)initWithSpriteCache:(CCSprite*) spriteCache andSpeed:(float) speedandHealth:(float) health andBulletType:(BulletTypes) bulletTypeandShootFrequency:(float) shootFreq;

- (void)reset;

-(void)shootBullets;

-(void)moveWithLength:(float) length andAreaLimitation:(float) areaLimitationmovedTime:(float)delta;

 

@property(readonly) int scoreWorth;

 

@end

注意我们这里导入了AirCraft.h这个头文件,原因是,后面在派生敌人飞船的子类的时候,我们会实现敌人飞船向我们的飞船射击的方法,这些方法里面会用到AirCraft类,所以这里我们在EnemyShip这个父类里面导入这个头文件。

下面看一下EnemyShip的实现:

EnemyShip.m:

#import"EnemyShip.h"

#import"CommonUtility.h"

#import"BulletCacheManager.h"

 

@implementationEnemyShip

 

-(id)initWithSpriteCache:(CCSprite*) spriteCache

                andSpeed:(float) s

               andHealth:(float) h

           andBulletType:(BulletTypes)bulletType

       andShootFrequency:(float) shootFreq{

   if (self = [super init]) {

       speed = s;

       health = h;

       healthRecord = h;

       shootFrequency = shootFreq;

       entitySprite = [spriteCache retain];

       entitySprite.anchorPoint = CGPointZero;

       entitySprite.position = CGPointMake([CommonUtility utility].screenWidth,([CommonUtility utility].screenHeight-300)*CCRANDOM_0_1()+200);

       entitySprite.visible = NO;

       currentMoveX = -1;

       currentMoveY = -1;

   }

    

   return self;

}

 

- (void)reset{

   entitySprite.position = CGPointMake([CommonUtility utility].screenWidth,([CommonUtility utility].screenHeight-300)*CCRANDOM_0_1()+200);

   entitySprite.color = ccWHITE;

   entitySprite.visible = YES;

   [self unscheduleAllSelectors];

   [self schedule:@selector(showUp:)];

}

 

-(void)shootBullets{

   //left empty, for child class to overwrite

}

 

-(void)update:(ccTime)delta{

   //    shootTotalTime += delta;

   //    if (shootTotalTime > nextShootTime) {

   //        [self shootBullets];

   //        nextShootTime = shootTotalTime +shootFrequency;

   //    }

}

 

-(void)showUp:(ccTime)delta{

   if (self.position.x >= [CommonUtility utility].screenWidth - [entitySpritecontentSize].width-50) {

       [self moveByX:-(300*delta) andY:0];

   }else{

       [self unschedule:_cmd];

       nextShootTime = 0;

       [self scheduleUpdate];

   }

}

 

-(void)moveWithLength:(float) length andAreaLimitation:(float) areaLimitationmovedTime:(float)delta{

   movedTime += delta;

   if (movedTime > changeDirectionTime) {

       [self resetCurrentMoveXandY];

       changeDirectionTime = movedTime+4;

   }

   float xMove = length*currentMoveX;

   float yMove = 0;

   float selfX = self.position.x;

   float selfY = self.position.y;

   float selfHeight = self.height;

   float selfWidth = self.width;

    

   yMove = length*currentMoveY;

   if (yMove+selfY < [CommonUtility utility].enemyMovementAreaHeight

       || yMove+selfY+selfHeight > [CommonUtility utility].screenHeight) {

       yMove = -yMove;

       currentMoveY = -currentMoveY;

   }

   if (xMove+selfX < areaLimitation || xMove+selfX+selfWidth >[CommonUtility utility].screenWidth) {

       xMove = -xMove;

       currentMoveX = -currentMoveX;

   }

   [self moveByX:xMove andY:yMove];

}

 

-(void)resetCurrentMoveXandY{

   if (CCRANDOM_0_1() > 0.5) {

       currentMoveX = 1;

   }else{

       currentMoveX = -1;

   }

   if (CCRANDOM_0_1() > 0.5) {

       currentMoveY = 1;

   }else{

       currentMoveY = -1;

   }

}

 

- (int)scoreWorth{

   return enemyScoreWorth;

}

 

- (BOOL)visible{

   return entitySprite.visible;

}

 

- (void)dealloc{

   [super dealloc];

}

 

@end

 

解释一下两个属性,shootFrequency是敌人射击的频率,我们自己的飞船是通过按钮进行射击的,敌人飞船是通过这个时间间隔自动发射子弹的;enemyScoreWorth是这个敌人飞船代表的分数,玩家打掉这个类型的飞船后得到得响应分数,敌人飞船越厉害,自然这个属性就越高。

初始化方法和Reset方法中,敌人飞船对应的精灵均被置为不可见,showUp方法是做什么用的呢?其实就是我们之前提到的,让敌人从屏幕外面飞入屏幕中的方法。还有一个地方要提一下,moveWithLength:andAreaLimitation:movedTime:这个方法中,areaLimitation是敌人飞船水平移动范围,加入这个限制是因为我们不想让敌人的飞船在整个屏幕上乱飞,他们只需要在屏幕右侧飞行并且射击就好了。同样,[CommonUtilityutility].enemyMovementAreaHeight这个属性是敌人飞船垂直飞行的限制,我们知道前景的山这个图层会挡住所有的飞船,那么敌人飞船如果一直在玩家的是野外,游戏就不好玩儿了,所以我们加一个高度限制,让敌人飞船不能低于这个高度飞行。你可能要问,为什么水平范围要用参数来限制,这里我们想让不同的敌人水平活动范围不同,所以这里用参数来控制。

接着,我们从EnemyShip派生出敌人飞船类,这里我们派生出5中敌人飞船类:BigDaddyShip、LittleWormShip、BOSSShip、SpeedKillerShip和PowerMakerShip,附上他们的代码(我们这里略去他们的.h文件,只贴出.m文件,这些子类均继承EnemyShip类,并且不包含任何本地变量、属性、方法声明):

BigDaddyShip.m:

#import"BigDaddyShip.h"

 

@implementationBigDaddyShip

 

-(id)initWithSpriteCache:(CCSprite *)sprite andSpeed:(float)spdandHealth:(float)life andBulletType:(BulletTypes)btandShootFrequency:(float)sf{

   if (self = [super initWithSpriteCache:sprite andSpeed:spd andHealth:lifeandBulletType:bt andShootFrequency:sf]) {

       enemyScoreWorth = 300;

   }

    

   return self;

}

 

-(void)shootBullets{

   [self shootBulletAtPosition:[self gunPosition] bulletType:BigEnemyBullet];

}

 

-(CGPoint)gunPosition{

   return ccp(entitySprite.position.x + entitySprite.contentSize.width * 93 / 198,entitySprite.position.y + entitySprite.contentSize.height * 3 / 71);

}

 

-(void)update:(ccTime)delta{

   [super update:delta];

   shootTotalTime += delta;

   if (shootTotalTime > nextShootTime) {

       [self shootBullets];

       nextShootTime = shootTotalTime + shootFrequency;

   }

   [self moveWithLength:speed*delta andAreaLimitation:[CommonUtilityutility].enemyMovementSmallAreaWidth movedTime:delta];

}

 

- (void)dealloc{

   [super dealloc];

}

 

@end

 

我们重载了并调用父类的initWithSpriteCache方法进行初始化,在其基础上为enemyScoreWorth属性特殊赋值,重载了父类的shootBullets方法,定义了gunPosition方法来返回子弹的发射位置(参考AirCraft类的类似方法)。在update方法中操作敌人飞船移动和射击。

 

LittleWormShip.m:

#import"LittleWormShip.h"

 

@implementationLittleWormShip

 

-(id)initWithSpriteCache:(CCSprite *)sprite andSpeed:(float)spdandHealth:(float)life andBulletType:(BulletTypes)btandShootFrequency:(float)sf{

   if (self = [super initWithSpriteCache:sprite andSpeed:spd andHealth:lifeandBulletType:bt andShootFrequency:sf]) {

       enemyScoreWorth = 120;

   }

    

   return self;

}

 

-(void)shootBullets{

   [self shootBulletAtPosition:[self gunPosition] atTarget:[AirCraftsharedAirCraft].aimPos bulletType:SmallEnemyBullet];

}

 

-(CGPoint)gunPosition{

   return ccp(entitySprite.position.x, entitySprite.position.y +entitySprite.contentSize.height * 19 / 73);

}

 

-(void)update:(ccTime)delta{

   [super update:delta];

   shootTotalTime += delta;

   if (shootTotalTime > nextShootTime) {

       [self shootBullets];

       nextShootTime = shootTotalTime + shootFrequency;

   }

   [self moveWithLength:speed*delta andAreaLimitation:[CommonUtilityutility].enemyMovementSmallAreaWidth movedTime:delta];

}

 

- (void)dealloc{

   [super dealloc];

}

 

@end

 

PowerMakerShip.m:

#import"PowerMakerShip.h"

 

@implementationPowerMakerShip

 

-(id)initWithSpriteCache:(CCSprite *)sprite andSpeed:(float)spdandHealth:(float)life andBulletType:(BulletTypes)btandShootFrequency:(float)sf{

   if (self = [super initWithSpriteCache:sprite andSpeed:spd andHealth:lifeandBulletType:bt andShootFrequency:sf]) {

       enemyScoreWorth = 150;

   }

    

   return self;

}

 

-(void)shootBullets{

   [self shootBulletAtPosition:[self gunPositionAtIndex:1]bulletType:PoweredEnemyBullet];

   [self shootBulletAtPosition:[self gunPositionAtIndex:2]bulletType:PoweredEnemyBullet];

}

 

-(CGPoint)gunPositionAtIndex:(int) gunIndex{

   if (gunIndex == 1) {

       return ccp(entitySprite.position.x + entitySprite.contentSize.width * 4 / 118,entitySprite.position.y + entitySprite.contentSize.height * 40 / 58);

   }else{

       return ccp(entitySprite.position.x + entitySprite.contentSize.width * 20 / 118,entitySprite.position.y + entitySprite.contentSize.height * 18 / 58);

   }

}

 

-(void)update:(ccTime)delta{

   [super update:delta];

   shootTotalTime += delta;

   if (shootTotalTime > nextShootTime) {

       [self shootBullets];

       nextShootTime = shootTotalTime + shootFrequency;

   }

   [self moveWithLength:speed*delta andAreaLimitation:[CommonUtilityutility].enemyMovementSmallAreaWidth movedTime:delta];

}

 

- (void)dealloc{

   [super dealloc];

}

 

@end

 

SpeedKillerShip.m:

#import"SpeedKillerShip.h"

 

@implementationSpeedKillerShip

 

-(id)initWithSpriteCache:(CCSprite *)sprite andSpeed:(float)spdandHealth:(float)life andBulletType:(BulletTypes)btandShootFrequency:(float)sf{

   if (self = [super initWithSpriteCache:sprite andSpeed:spd andHealth:lifeandBulletType:bt andShootFrequency:sf]) {

       enemyScoreWorth = 180;

   }

    

   return self;

}

 

-(void)shootFastBullets{

   Entity* player = [AirCraft sharedAirCraft];

   [self shootBulletAtPosition:[self gunPositionAtIndex:1] atTarget:player.aimPosbulletType:SmallEnemyBullet];

   [self shootBulletAtPosition:[self gunPositionAtIndex:2] atTarget:player.aimPosbulletType:SmallEnemyBullet];

}

 

-(void)shootPoweredBullet{

   [self shootBulletAtPosition:[self gunPositionAtIndex:3]bulletType:PoweredEnemyBullet];

}

 

-(CGPoint)gunPositionAtIndex:(int) gunIndex{

   if (gunIndex == 1) {

       return ccp(entitySprite.position.x + entitySprite.contentSize.width * 9 / 80,entitySprite.position.y + entitySprite.contentSize.height * 50 / 65);

   }else if (gunIndex == 2){

       return ccp(entitySprite.position.x + entitySprite.contentSize.width * 39 / 80,entitySprite.position.y + entitySprite.contentSize.height * 50 / 65);

   }else{

       return ccp(entitySprite.position.x + entitySprite.contentSize.width * 8 / 80,entitySprite.position.y + entitySprite.contentSize.height * 20 / 65);

   }

}

 

-(void)update:(ccTime)delta{

   [super update:delta];

   shootTotalTime += delta;

   if (shootTotalTime > nextShootTime) {

       if (CCRANDOM_0_1() > 0.3) {

           [self shootFastBullets];

       }else{

           [self shootPoweredBullet];

       }

       nextShootTime = shootTotalTime + shootFrequency;

   }

   [self moveWithLength:speed*delta andAreaLimitation:[CommonUtilityutility].enemyMovementSmallAreaWidth movedTime:delta];

}

 

- (void)dealloc{

   [super dealloc];

}

 

@end

 

这里我们的SpeedKillerShip能够发射两种不同的子弹,选择发射那种子弹随机决定。

 

BOSSShip.m:

#import"BOSSShip.h"

#import"GameLayer.h"

#import"SimpleAudioEngine.h"

 

@implementationBOSSShip

 

staticNSMutableArray* bossGunPositionsData;

 

-(id)initWithSpriteCache:(CCSprite *)sprite andSpeed:(float)spdandHealth:(float)life andBulletType:(BulletTypes)btandShootFrequency:(float)sf{

   if (self = [super initWithSpriteCache:sprite andSpeed:spd andHealth:lifeandBulletType:bt andShootFrequency:sf]) {

       enemyScoreWorth = 1000;

   }

    

   return self;

}

 

+(NSMutableArray*) bossGunPositions{

   if (bossGunPositionsData == nil) {

       bossGunPositionsData = [[NSMutableArray arrayWithObjects:

                                [NSValue valueWithCGPoint:ccp(10, 30)],

                                [NSValuevalueWithCGPoint:ccp(11, 40)],

                                [NSValue valueWithCGPoint:ccp(12, 50)],

                                [NSValue valueWithCGPoint:ccp(13, 60)],

                                [NSValue valueWithCGPoint:ccp(14, 70)],

                                [NSValue valueWithCGPoint:ccp(15, 80)],

                                [NSValue valueWithCGPoint:ccp(16, 90)],

                                [NSValue valueWithCGPoint:ccp(16, 100)],

                                [NSValuevalueWithCGPoint:ccp(17, 110)],

                                [NSValue valueWithCGPoint:ccp(20, 40)],

                                [NSValue valueWithCGPoint:ccp(30, 50)],

                                [NSValue valueWithCGPoint:ccp(40, 60)],

                                [NSValue valueWithCGPoint:ccp(40, 80)],

                                [NSValue valueWithCGPoint:ccp(41, 100)],

                                [NSValue valueWithCGPoint:ccp(42, 120)],

                                [NSValuevalueWithCGPoint:ccp(44, 140)],

                                [NSValue valueWithCGPoint:ccp(45, 160)],

                                [NSValue valueWithCGPoint:ccp(74, 143)],

                                [NSValue valueWithCGPoint:ccp(84, 141)],

                                [NSValue valueWithCGPoint:ccp(94, 138)],

                                [NSValue valueWithCGPoint:ccp(107, 135)],

                                [NSValue valueWithCGPoint:ccp(119, 131)],

                                [NSValuevalueWithCGPoint:ccp(129, 128)],

                                [NSValue valueWithCGPoint:ccp(143, 114)],

                                [NSValue valueWithCGPoint:ccp(89, 93)],

                                nil] retain];

   }

   return bossGunPositionsData;

}

 

-(void)shootCircleBullets{

   if ([AirCraft sharedAirCraft].position.x < self.position.x) {

       for (int i = -80; i < 90; i += 10) {

           [self shootBulletAtPosition:[self gunPositionAtIndex:24] atAngle:ibulletType:BOSSBullet];

       }

   }else{

       for (int i = 100; i < 260; i += 10) {

           [self shootBulletAtPosition:[self gunPositionAtIndex:24] atAngle:ibulletType:BOSSBullet];

       }

   }

}

 

-(void)shootRandomBullets{

   for (int i = 0; i < 30; i++) {

       [self shootBulletAtPosition:[self gunPositionAtIndex:i]atAngle:CCRANDOM_0_1()*360 bulletType:SmallEnemyBullet];

   }

}

 

-(void)shootAtPlayer{

   int gunCount = [[BOSSShip bossGunPositions] count];

   CGPoint playerPos = [AirCraft sharedAirCraft].aimPos;

   float x = playerPos.x+gunCount;

   float y = playerPos.y-gunCount;

   for (int i = 0; i < gunCount; i++) {

       [self shootBulletAtPosition:[self gunPositionAtIndex:i] atTarget:ccp(x-2*i,y+2*i) bulletType:BOSSBullet];

   }

}

 

-(CGPoint)gunPositionAtIndex:(int) index{

   index = index%[[BOSSShip bossGunPositions] count];

   CGPoint gunPos = [[[BOSSShip bossGunPositions] objectAtIndex:index]CGPointValue];

   return ccp(entitySprite.position.x + entitySprite.contentSize.width *gunPos.x/178, entitySprite.position.y + entitySprite.contentSize.height *gunPos.y/185);

}

 

-(void)update:(ccTime)delta{

   [super update:delta];

   shootTotalTime += delta;

   if (shootTotalTime > nextShootTime) {

       float rand = CCRANDOM_0_1();

       if (rand > 0.7) {

           [self shootCircleBullets];

       }else if (rand > 0.3){

           [self shootRandomBullets];

       }else{

           [self shootAtPlayer];

       }

       nextShootTime = shootTotalTime + shootFrequency;

   }

   [self moveWithLength:speed*delta andAreaLimitation:[CommonUtilityutility].enemyMovementLargeAreaWidth movedTime:delta];

}

 

- (void)explode{

}

 

- (void)dealloc{

   if (bossGunPositionsData != nil) {

       [bossGunPositionsData release];

       bossGunPositionsData = nil;

   }

   [super dealloc];

}

 

@end

 

BOSS的子弹发射位置比较多,我们定义了一个数组方便我们获取,此外,BOSS能够发射三种子弹,代码比较容易懂,就不多做解释了。

 

好了,貌似离胜利不远了,我们下面开始考虑向场景中添加敌人了。首先,我们的场景中除了BOSS之外,其他类型的敌人飞船也会有很多一起出现,那么又回到那个问题,他们使用相同的纹理贴图!这个时候我们很自然地想到CCSpriteBatchNode,没错,还是用Cache来做。

首先我们添加EnemyShipCache类,EnemyShipCache.h定义如下:

#import"CCNode.h"

#import"EnemyShip.h"

#import"cocos2d.h"

#import"BigDaddyShip.h"

#import"LittleWormShip.h"

#import"SpeedKillerShip.h"

#import"PowerMakerShip.h"

#import"BOSSShip.h"

 

@interfaceEnemyShipCache : CCNode{

   int nextIdleEnemyCachePosData;

   CCSpriteBatchNode* enemysSpriteBatchNode;

   NSMutableArray* enemyCaches;

}

 

@property(readonly) CCSpriteBatchNode* enemysSpriteBatchNode;

 

-(id)initWithFrameName:(NSString*) frameName

            cacheCount:(int) cacheCount

              andSpeed:(float) speed

             andHealth:(float) health

         andBulletType:(BulletTypes) bulletType

     andShootFrequency:(float) shootFreq

         enemyShipType:(EnemyShipTypes) enemyShipType;

-(EnemyShip*)nextIdleEnemyShip;

 

@property intnextIdleEnemyCachePos;

 

@end

 

EnemyShipCache.m的代码:

#import"EnemyShipCache.h"

 

@implementationEnemyShipCache

 

+(Class)getClassFromShipType:(EnemyShipTypes) shipType{

   switch (shipType) {

       case LittleWorm:

           return [LittleWormShip class];

       case BigDaddy:

           return [BigDaddyShip class];

       case SpeedKiller:

           return [SpeedKillerShip class];

       case PowerMaker:

           return [PowerMakerShip class];

       case BOSS:

           return [BOSSShip class];

            

       default:

           return nil;

           break;

   }

}  //getClassFromShipType

 

-(id)initWithFrameName:(NSString*) frameName

            cacheCount:(int) cacheCount

              andSpeed:(float) speed

             andHealth:(float) health

         andBulletType:(BulletTypes) bulletType

     andShootFrequency:(float) shootFreq

         enemyShipType:(EnemyShipTypes) enemyShipType{

   if (self = [super init]) {

       nextIdleEnemyCachePosData = 0;

       enemyCaches = [[NSMutableArray arrayWithCapacity:cacheCount] retain];

       CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];

       CCSpriteFrame* frame = [frameCache spriteFrameByName:frameName];

       enemysSpriteBatchNode = [CCSpriteBatchNode batchNodeWithTexture:frame.texture];

       enemysSpriteBatchNode.tag = 2000;

       for (int i = 0; i < cacheCount; i++) {

           CCSprite* enemyShipCache = [[CCSprite spriteWithSpriteFrameName:frameName]autorelease];

           [enemysSpriteBatchNode addChild:enemyShipCache];

           EnemyShip* enemyCache = [[[[EnemyShipCache getClassFromShipType:enemyShipType]alloc] initWithSpriteCache:enemyShipCache andSpeed:speed andHealth:healthandBulletType:bulletType andShootFrequency:shootFreq] autorelease];

           [enemyCaches addObject:enemyCache];

       }

   }

    

   return self;

}  //initWithFrameName

 

-(CCSpriteBatchNode*)enemysSpriteBatchNode{

   return enemysSpriteBatchNode;

}  //enemysSpriteBatchNode

 

-(EnemyShip*)nextIdleEnemyShip{

   EnemyShip* ship = [enemyCaches objectAtIndex:self.nextIdleEnemyCachePos];

   if (ship.visible == NO) {

       return ship;

   }else{

       return nil;

   }

}  //nextIdleEnemyShip

 

-(int)nextIdleEnemyCachePos{

   int tempId = nextIdleEnemyCachePosData;

   nextIdleEnemyCachePosData++;

   if (nextIdleEnemyCachePosData >= [[enemysSpriteBatchNode children] count]) {

       nextIdleEnemyCachePosData = 0;

   }

    

   return tempId;

}  //nextIdleEnemyCachePos

 

-(void)setNextIdleEnemyCachePos:(int)nextIdleEnemyCachePos{

   nextIdleEnemyCachePosData = nextIdleEnemyCachePos;

}  //setNextIdleEnemyCachePos

 

- (void)dealloc{

   [enemyCaches removeAllObjects];

   [enemyCaches release];

   [super dealloc];

}  //dealloc

 

@end

 

唯一和之前BulletCache不同的是我们把EnemyShip的CCSprite属性添加到了CCSpriteBatchNode中去,这是因为EnemyShip不继承CCSprite,不能直接添加到CCSpriteBatchNode里,此外,我们添加了一个枚举和类转化的静态方法,剩下的其他的方法都和BulletCache类似。

接着我们来添加EnemyShipCacheManager类:

EnemyShipCacheManager.h:

#import"CCNode.h"

#import"EnemyShip.h"

#import"EnemyShipCache.h"

 

@interfaceEnemyShipCacheManager : CCNode{

   NSMutableDictionary* enemyshipCacheMapData;

}

 

+(EnemyShipCacheManager*) sharedEnemyShipCacheManager;

 

-(EnemyShip*)getEnemyShip:(EnemyShipTypes) enemyShipType;

-(void)addEnemyShipCacheWithType:(EnemyShipTypes) enemyShipType

                      bulletType:(BulletTypes) bulletType

                  shipCacheCount:(int) shipCacheCount

                   shipFrameName:(NSString*) shipFrameName

                       shipSpeed:(float) speed

                      shipHealth:(float) health

                   shipShootFreq:(float) shootFreq;

 

@property(readonly) NSMutableDictionary* enemyshipCacheMap;

 

@end

 

EnemyShipCacheManager.m:

#import"EnemyShipCacheManager.h"

 

@implementationEnemyShipCacheManager

 

staticEnemyShipCacheManager* sharedEnemyShipCache;

 

+(EnemyShipCacheManager*) sharedEnemyShipCacheManager{

   if (sharedEnemyShipCache == nil) {

       sharedEnemyShipCache = [[[EnemyShipCacheManager alloc] init] autorelease];

   }

    

   return sharedEnemyShipCache;

}  //sharedEnemyShipCacheManager

 

- (id)init{

   if (self = [super init]) {

       enemyshipCacheMapData = [[NSMutableDictionary dictionaryWithCapacity:5]retain];

       [self addEnemyShipCacheWithType:SpeedKiller bulletType:SmallEnemyBulletshipCacheCount:40 shipFrameName:@"speedkiller.png" shipSpeed:240shipHealth:100 shipShootFreq:1.1];

       [self addEnemyShipCacheWithType:PowerMaker bulletType:PoweredBulletshipCacheCount:30 shipFrameName:@"powermaker.png" shipSpeed:100shipHealth:500 shipShootFreq:1.2];

       [self addEnemyShipCacheWithType:LittleWorm bulletType:SmallEnemyBulletshipCacheCount:40 shipFrameName:@"littleworm.png" shipSpeed:150shipHealth:200 shipShootFreq:0.8];

       [self addEnemyShipCacheWithType:BigDaddy bulletType:BigEnemyBulletshipCacheCount:20 shipFrameName:@"bigdaddy.png" shipSpeed:60shipHealth:1500 shipShootFreq:1.3];

       [self addEnemyShipCacheWithType:BOSS bulletType:BOSSBullet shipCacheCount:1shipFrameName:@"boss.png" shipSpeed:30 shipHealth:10000shipShootFreq:1.6];

   }

    

   return self;

}  //init

 

-(void)addEnemyShipCacheWithType:(EnemyShipTypes) enemyShipType

                      bulletType:(BulletTypes) bulletType

                  shipCacheCount:(int) shipCacheCount

                   shipFrameName:(NSString*) shipFrameName

                       shipSpeed:(float) speed

                      shipHealth:(float) health

                   shipShootFreq:(float) shootFreq{

   EnemyShipCache* enemyShipCache = [[[EnemyShipCache alloc]initWithFrameName:shipFrameName cacheCount:shipCacheCount andSpeed:speedandHealth:health andBulletType:bulletType andShootFrequency:shootFreqenemyShipType:enemyShipType] autorelease];

   [self.enemyshipCacheMap setObject:enemyShipCache forKey:[NSNumbernumberWithInt:enemyShipType]];

   [self addChild:enemyShipCache];

}  //addEnemyShipCacheWithType

 

-(EnemyShip*)getEnemyShip:(EnemyShipTypes)enemyShipType{

   EnemyShipCache* enemyShipCache = [self.enemyshipCacheMap objectForKey:[NSNumbernumberWithInt:enemyShipType]];

   return [enemyShipCache nextIdleEnemyShip];

}  //getEnemyShip

 

-(NSMutableDictionary*)enemyshipCacheMap{

   return enemyshipCacheMapData;

}  //enemyshipCacheMap

 

- (void)dealloc{

   [enemyshipCacheMapData removeAllObjects];

   [enemyshipCacheMapData release];

   [sharedEnemyShipCache release];

   sharedEnemyShipCache = nil;

   [super dealloc];

}  //dealloc

 

@end

 

和BulletCacheManager类似,我们也不多做说明了。

 

接着,我们需要在BulletCacheManager中添加敌人飞机的子弹Cache,修改BulletCacheManager的init方法如下:

- (id)init{

   if (self = [super init]) {

       bulletCacheMapData = [[NSMutableDictionary dictionaryWithCapacity:5] retain];

       [self addBulletCacheWithType:PoweredBullet bulletCacheCount:100bulletFrameName:@"bullet.png" bulletSpeed:CGPointMake(500, 0)bulletDamage:80];

       [self addBulletCacheWithType:SmallRoundBullet bulletCacheCount:300bulletFrameName:@"roundBullets.png" bulletSpeed:CGPointMake(800, 0)bulletDamage:40];

       [self addBulletCacheWithType:SmallEnemyBullet bulletCacheCount:300bulletFrameName:@"smallenemybullet.png" bulletSpeed:CGPointMake(-550,100) bulletDamage:20];

       [self addBulletCacheWithType:BigEnemyBullet bulletCacheCount:200bulletFrameName:@"bigenemybullet.png" bulletSpeed:CGPointMake(-380,0) bulletDamage:50];

       [self addBulletCacheWithType:BOSSBullet bulletCacheCount:200bulletFrameName:@"bossbullet.png" bulletSpeed:CGPointMake(-280, 100)bulletDamage:80];

       [self addBulletCacheWithType:PoweredEnemyBullet bulletCacheCount:100bulletFrameName:@"poweredenemybullet.png"bulletSpeed:CGPointMake(-330, 0) bulletDamage:150];

   }

    

   return self;

}  //init

 

接着我们修改GameLayer来测试一下:

首先在GameLayer的initCaches方法中添加下面的代码:

[frameCacheaddSpriteFramesWithFile:@"enemy-ships.plist"];

EnemyShipCacheManager*enemyShipCacheManager = [EnemyShipCacheManager sharedEnemyShipCacheManager];

   [self addChild:enemyShipCacheManager z:-1 tag:EnemyShipCacheManagerTag];

   for (EnemyShipCache* enemyShipCache in [[enemyShipCacheManagerenemyshipCacheMap] objectEnumerator]) {

       [self addChild:enemyShipCache.enemysSpriteBatchNode];

   }

将敌人飞船的纹理贴图加载到Cache中,并且将敌人飞船的CCSpriteBatchNode加入当前层(不然无法渲染)。接着我们添加一个测试方法:

-(void)addEnemies{

   EnemyShip* enemyShip = [[EnemyShipCacheManager sharedEnemyShipCacheManager]getEnemyShip:BOSS];

   [self addChild:enemyShip z:3];

   [enemyShip reset];

   enemyShip = [[EnemyShipCacheManager sharedEnemyShipCacheManager]getEnemyShip:BigDaddy];

   [self addChild:enemyShip z:3];

   [enemyShip reset];

   enemyShip = [[EnemyShipCacheManager sharedEnemyShipCacheManager]getEnemyShip:LittleWorm];

   [self addChild:enemyShip z:3];

   [enemyShip reset];

   enemyShip = [[EnemyShipCacheManager sharedEnemyShipCacheManager]getEnemyShip:SpeedKiller];

   [self addChild:enemyShip z:3];

   [enemyShip reset];

   enemyShip = [[EnemyShipCacheManager sharedEnemyShipCacheManager]getEnemyShip:PowerMaker];

   [self addChild:enemyShip z:3];

   [enemyShip reset];

}

这个方法向当前层中添加了各种类型的敌人飞船用于测试。

然后再init方法中在添加玩家飞船之后调用[selfaddEnemies];

好了,我们编译运行一下,效果如下图:

2014年05月14日 - Daniel - KHome

这一篇就到这儿,下一篇我们会完成GameLayer的制作,把所有的基本元素都补全。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

手把手教你开发一款IOS飞行射击游戏(七)

开发一款IOS飞行射击游戏

手把手教你开发一款IOS飞行射击游戏(三)

开发一款IOS飞行射击游戏

手把手教你开发一款IOS飞行射击游戏(四)

开发一款IOS飞行射击游戏

手把手教你开发一款IOS飞行射击游戏(完)

开发一款IOS飞行射击游戏

手把手教你开发一款IOS飞行射击游戏(二)

开发一款IOS飞行射击游戏

手把手教你制作一款Box2D小游戏(一)

利用Box2D物理引擎来制作一款类似于下楼梯的小游戏

手把手教你制作一款Box2D小游戏(二)

利用Box2D物理引擎来制作一款类似于下楼梯的小游戏

手把手教你制作一款Box2D小游戏(三)

利用Box2D物理引擎来制作一款类似于下楼梯的小游戏

JS初学者使用jQuery开发一款弹幕射击游戏

简介DooMissO是本人使用JS、jQuery开发的一款弹幕射击游戏,现已推出1.8版 Js和jQuery代码混搭得比较厉害,后续几个版本会陆续修正统一github仓库地址:https://git...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)