我们的游戏大部分功能已经实现了接下来我们就要来完善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
TalkTonpc.m代码:
#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
TalkCell.h代码:
#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
TalkCell.m代码:
#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
TalkCellText.h代码:
#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
TalkCellText.m代码:
#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];
}
我们的数组里面存储的是实例化的TalkCellText,我们只需要对其三个属性赋值就行了
呵呵,很简单吧,使用的时候我们就从相应的数组中提取相应的文本就行了。
这里我对其文本内容略加修改,改的不好仅供参考。
其实有时候我们要有自己的想法,不要拘泥于形式,想到什么就可以去尝试修改一下
也许就有意想不到的效果。
好了让我们继续我们的游戏制作吧:
我们先说一下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;
}
}
这样我们npc这块就基本结束了,这里面还有几个boss的谈话场景和一些特殊事件
到后面的文章里在讲,今天的内容也挺多的大家好好看看,消化一下。