下午我将第十部分教程发布到首页,希望大家多多支持
我们的游戏大部分功能已经实现了接下来我们就要来完善npc有关内容了,
昨天有个朋友说序章中遇到仙子是有一个剧情的,这个确实有而且游戏中
还有很多npc的剧情,今天我们就开始添加这部分内容吧!
首先我们要添加一个用于创建npc剧情的类:TalkTonpc,要知道游戏中有很
多与npc交谈的剧情,我们如何用这个类来添加所有的剧情呢,下面我们就来
说一下这些剧情的共性与区别在哪里:
第一、他们都是由勇士和npc组成,所以我们把这个场景分为两部分一个是
勇士部分,一个是npc部分。
第二、勇士部分和npc部分都是由一个个谈话窗体组成,所以我们需要再建
一个谈话窗体类TalkCell。
第三、谈话窗体部分,只有文本内容不一样其它的都是相同的,所以这里我
们还需要在建一个用于控制文本内容的类:TalkCell。
讲到这里我们的剧情就只差一个文本内容了,那么我们就需要建一个数据类
(NpcTalkText)来存储这些谈话文本了,由于这个类内容太多这里我就不粘贴
代码了,在我们把另外三个类讲解完之后在讲一下这个类。
下面我们就要开始添加代码部分了:
TalkTonpc.h代码:
#import <Foundation/Foundation.h> #import "cocos2d.h" #import "TalkCell.h" #import "NpcTalkText.h" @interface TalkTonpc : CCLayer { //谈话对象npc名称 NSString *npcName; //勇士 NSString *hero; TalkCell *seltalkCell; //npc谈话内容 NpcTalkText *npcTalkText; //跳过菜单 CCMenuItemFont *Skip; //当前选中npc对话内容 NSMutableArray *selnpcTalkText; //文本编号 NSInteger textID; //当前npc类型 int selnpcType; } @property (nonatomic,assign) bool talking; -(void)updateWith:(int) type; -(void)removeTalking; @end
#import "TalkTonpc.h" @implementation TalkTonpc @synthesize talking; -(id)init { if ((self = [super init])) { npcTalkText = [NpcTalkText getNpcTalkText]; //跳过对话 Skip = [CCMenuItemFont itemFromString:@"--Skip--" target:self selector:@selector(removetext)]; Skip.fontSize = 30; CCMenu *menu = [CCMenu menuWithItems:Skip, nil]; menu.position = ccp(455, 100); [self addChild:menu]; } return self; } -(void)addTalking { TalkCellText *cellText = [selnpcTalkText objectAtIndex:textID]; seltalkCell = [[TalkCell alloc] initWith:cellText]; if (cellText.name == @"勇士") { seltalkCell.position = ccp(200, 240); } else seltalkCell.position = ccp(100, 420); [self addChild:seltalkCell]; } -(void)updateWith:(int) type { self.talking = NO; textID = 0; selnpcType = type; switch (type) { case 0: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc0; break; case 1: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc1; break; case 2: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc2; break; case 3: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc3; break; case 4: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc4; break; case 6: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc6; break; case 7: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc7; break; case 8: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc8; break; case 9: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc9; break; case 10: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc10; break; case 11: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc11; break; case 12: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc12; break; case 13: selnpcTalkText = nil; selnpcTalkText = npcTalkText.npc13; break; default: break; } [self addTalking]; } -(void)removeTalking { if (textID >= (selnpcTalkText.count - 1)) { self.talking = YES; } if (self.talking) { [self removeChild:seltalkCell cleanup:YES]; [self.parent talkTonpc:selnpcType]; [self.parent removeChild:self cleanup:YES]; } else { [self removeChild:seltalkCell cleanup:YES]; textID += 1; [self addTalking]; } } -(void)removetext { [self removeChild:seltalkCell cleanup:YES]; [self.parent talkTonpc:selnpcType]; [self.parent removeChild:self cleanup:YES]; } @end
#import <Foundation/Foundation.h> #import "cocos2d.h" #import "TalkCellText.h" @interface TalkCell : CCLayer { //谈话窗体背景 CCTMXTiledMap *background; CCLabelTTF *name; CCLabelTTF *celltext1; CCLabelTTF *celltext2; CCMenuItemFont *enter; } -(id)initWith:(TalkCellText*) text; @end
#import "TalkCell.h" @implementation TalkCell -(id)initWith:(TalkCellText*) text { if ((self = [super init])) { //背景 background = [CCTMXTiledMap tiledMapWithTMXFile:@"fightbg.tmx"]; background.position = ccp(0, 0); background.scaleX = 1.6; [self addChild:background]; //名称 name = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%@:",text.name] fontName:@"Verdana-Bold" fontSize:35]; name.anchorPoint = ccp(0, 0); name.position = ccp(10, 110); [self addChild:name]; //谈话内容 celltext1 = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%@",text.labelText1] fontName:@"Verdana-Bold" fontSize:24]; celltext2 = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%@",text.labelText2] fontName:@"Verdana-Bold" fontSize:24]; celltext1.anchorPoint = ccp(0, 0); celltext2.anchorPoint = ccp(0, 0); celltext1.position = ccp(30, 70); celltext2.position = ccp(10, 30); [self addChild:celltext1]; [self addChild:celltext2]; //确定按钮 enter = [CCMenuItemFont itemFromString:@"确定" target:self selector:@selector(removetext)]; enter.fontSize = 28; CCMenu *menu = [CCMenu menuWithItems:enter, nil]; menu.position = ccp(455, 10); [self addChild:menu]; } return self; } -(void)removetext { [self.parent removeTalking]; } @end
#import <Foundation/Foundation.h> #import "cocos2d.h" @interface TalkCellText : NSObject @property (nonatomic,retain) NSString *name; @property (nonatomic,retain) NSString *labelText1; @property (nonatomic,retain) NSString *labelText2; @end
#import "TalkCellText.h" @implementation TalkCellText @synthesize name; @synthesize labelText1; @synthesize labelText2; -(id)init { if ((self = [super init])) { } return self; } @end
下面我们说一下TalkCellText这个类,这个类很简单,但是很重要,大家看到了
它有三个属性,大家一看就明白了,不过这里的两个label其实可以合成一个的
我当时写的时候没想那么多,这里我就不修改了,你们可以自己修改一下试试。
接着我们讲一下NpcTalkText这个类,首先这个类要写成单例模式,并且我们
要定义一些可变数组用于存储我们的文本内容,下面我以其中一个npc对话为例
子讲一下,代码如下:
-(void)addNPC1 { TalkCellText *text1 = [[[TalkCellText alloc] init] autorelease]; text1.name = yong; text1.labelText1 = @"您已经得救了!"; text1.labelText2 = @""; [self.npc1 addObject:text1]; TalkCellText *text2 = [[[TalkCellText alloc] init] autorelease]; text2.name = @"神秘老人"; text2.labelText1 = @"哦,太感谢你了!我这里有一个宝物,就送给"; text2.labelText2 = @"你了!孩子再见"; [self.npc1 addObject:text2]; TalkCellText *text3 = [[[TalkCellText alloc] init] autorelease]; text3.name = yong; text3.labelText1 = @"???怎么不见了?考,你这退场方式太牛"; text3.labelText2 = @"逼了,变魔术的吧!"; [self.npc1 addObject:text3]; TalkCellText *text4 = [[[TalkCellText alloc] init] autorelease]; text4.name = @"神秘老人"; text4.labelText1 = @"...远处传来...哈哈,导演就是这么安排的,"; text4.labelText2 = @"没办法,其实哥也想低调一点.不要崇拜哥哦!"; [self.npc1 addObject:text4]; TalkCellText *text5 = [[[TalkCellText alloc] init] autorelease]; text5.name = yong; text5.labelText1 = @"..........."; text5.labelText2 = @""; [self.npc1 addObject:text5]; }
呵呵,很简单吧,使用的时候我们就从相应的数组中提取相应的文本就行了。
这里我对其文本内容略加修改,改的不好仅供参考。
其实有时候我们要有自己的想法,不要拘泥于形式,想到什么就可以去尝试修改一下
也许就有意想不到的效果。
好了让我们继续我们的游戏制作吧:
我们先说一下TalkTonpc类中的updateWith: 这个方法,我们接下来在Game01中添加
的内容就跟它有关,这个方法通过接收一个int值来获取相应的文本数组,然后调用方
法:addTalking来添加勇士和npc的谈话内容。在我们点击确定按钮是调用切换谈话内
容的方法:removeTalking 这里我们通过textID来获取下一个谈话内容。
下面让我们添加Game01中的代码吧,先修改if(npc_tileGid)中的switch循环的内容
case 0: [self addChild:talkTonpc]; [talkTonpc updateWith:type]; break; case 1: [self addChild:talkTonpc]; [talkTonpc updateWith:type]; break; case 2: [self addChild:talkTonpc]; [talkTonpc updateWith:type]; break; case 3: if (thiefID == 1) { [self addChild:talkTonpc]; [talkTonpc updateWith:3]; //打开二楼的门 TitledMap *twofloor = [self.model.titleMapArray1 objectAtIndex:2]; CGPoint point = ccp(1, 6); [twofloor.door removeTileAt:point]; thiefID = 2; } else { if (canopen) { [self addChild:talkTonpc]; [talkTonpc updateWith:4]; TitledMap *floor = [self.model.titleMapArray1 objectAtIndex:18]; CGPoint point = ccp(5, 8); CGPoint point2 = ccp(5, 9); [floor.other removeTileAt:point]; [floor.other removeTileAt:point2]; } } _hero.isFighting = NO; break; case 8: [self addChild:talkTonpc]; if (herohp.Coin >= 500) { [talkTonpc updateWith:8]; } else { [talkTonpc updateWith:6]; } break; case 9: [self addChild:talkTonpc]; if (herohp.Experience >= 500) { [talkTonpc updateWith:9]; } else { [talkTonpc updateWith:7]; } break; case 10: [self addChild:talkTonpc]; [talkTonpc updateWith:10]; break; case 21: _hero.isFighting = NO;
我们还要在Game01初始化方法里实例化talkTonpc。
修改过这部分代码我们就能在游戏中看到与npc的交谈了,不过我们还要再添加一个
交谈结束时相应事件的方法:
-(void)talkTonpc:(int) type { switch (type) { case 0: herohp.YellowKey ++; herohp.BlueKey ++; herohp.RedKey ++; [herohp updateKey1]; [self.curtitleMap.npc removeTileAt:towerLoc]; _hero.isFighting = NO; break; case 1: _hero.Defense += 30; [herohp updateHeroDefense]; [self.curtitleMap.npc removeTileAt:towerLoc]; _hero.isFighting = NO; break; case 2: _hero.Attack += 30; [herohp updateHeroAttack]; [self.curtitleMap.npc removeTileAt:towerLoc]; _hero.isFighting = NO; break; case 6: _hero.isFighting = NO; break; case 7: _hero.isFighting = NO; break; case 8: _hero.Defense += 120; herohp.Coin -= 500; [herohp updateHeroDefense]; [herohp updateCoin]; [self.curtitleMap.npc removeTileAt:towerLoc]; _hero.isFighting = NO; break; case 9: _hero.Attack += 120; herohp.Experience -= 500; [herohp updateHeroAttack]; [herohp updateExperience]; [self.curtitleMap.npc removeTileAt:towerLoc]; _hero.isFighting = NO; break; case 10: [self.curtitleMap.other removeTileAt:CGPointMake(10, 10)]; //self.curtitleMap.hiddenFloor = NO; _hero.isFighting = NO; break; case 11: canAttack = YES; _hero.isFighting = NO; break; case 12: //win = [[[GameWin alloc] init] autorelease]; //[self addChild:win]; break; case 13: self.selenemy.enemyID = 0; [self removeEnemy]; break; default: break; } }
到后面的文章里在讲,今天的内容也挺多的大家好好看看,消化一下。
下面我将一些题外话,就是给大家推荐一下himi的博客,其实我就是看himi的文章
自学的,感觉不错,大家有兴趣的可以去看一下。