前言

去年的回忆。另外,在第三、他们开发了他们的第一场比赛四月,它是游戏。所以我决定走上独立开发的道路上。了。第一款游戏达到它应有的盈利水平。然而这款游戏开发后的时间里。都没再取得还有一款令自己惬意的作品。

直到今年的三、四月,我使用cocos2d-x开发出我的第一款文字游戏。

第一款游戏的传送门

第一款文字游戏的传送门

自从使用cocos2d-x后。发现自己爱上了这个引擎。

它也许还不够强大和完好。可是使用它。能够体验编码的乐趣。还能够为我重拾C++这门技术(究竟对C++有多么的执着啊),还能增进NDK和JNI的学习。恰恰满足我各种各样的追求。

这个第一款文字游戏。名字我取作Anagram Puzzle。事实上这款游戏是參照RayWenderlich上的这篇教程来改写的。教程里使用的是iOS的UIKit编写。虽说原理相通。可是在改写过程中还是遇到不少折腾的地方。因为初次编写cocos2d-x游戏。所以错误难免百出,希望阅读者们高抬贵手,点到即止……废话不多说,立即開始coco2d-x之道~怎样制作第一款文字游戏!

Anagram简单介绍

Anagram是一种把单词或短语的字母顺序打乱,又一次排列后变成一个新单词或短语的游戏。

比如,单词cinema能够又一次排列成iceman。游戏中就要求玩家进行你所提供单词或短语的又一次排列。完毕游戏的画面会如图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTc4MTgzNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

在开发这个游戏过程中,会接触到下面这些知识:

  • MVC型的游戏结构
  • 怎样从文件配置载入级别
  • 载入第三方字体
  • 简单使用音乐音效
  • 分离HUD层与游戏层
  • 手势拖动及动画
  • Particle的效果
还有其它的一些cocos2d-x的基础知识,都会在开发过程中接触到。

初始化project

首先最重要的当然是使用命令行来创建cocos2d-xproject,当然也有其它方法也能够创建project。可是我觉得掌握命令行来创建是必须的基本功。

创建方法能够在这里找到。创建完毕后各个平台的project目录都有了。我们的主要project目录是proj.android和proj.ios两个。

整个开发过程,我使用Mac OS来开发,所以编码是在XCode上进行,而Androidproject的编译则使用命令行,具体教程能够參考这里

建立好project后,先把所需的资源文件复制到Resource目录中。打开Xcodeproject,眼下Resource目录下还是原来的资源文件,通过右击Resource目录 -> Add Files to ...,把资源文件都加到project里。编辑后project会如图

1)载入级别配置文件

打开level1.plist,能够看到里面内容

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTc4MTgzNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

有三个最顶端的key,各自是:

pointsPerTile: 每一个单词填对后获得的分数。

timeToSolve: 解决这一关的时间(秒)。

anagrams: 是题目的列表,包括两个item。各自是原始的短语以及最后要拼出的短语。

level文件的介绍就到此为止。以下開始编写Level类,在Level.h中加入以下内容

class Level:public CCObject{
public:
static Level * levelWithNum(int levelNum); public:
int mPointPerTile;
int mTimeToSovle;
CCArray * pAnagrams;
};

当中,三个变量相应level文件中的三个最顶端的item。另一个初始化函数。是给外部调用初始化level文件。

如今。打开Level.cpp。实现levelWithNum函数

Level * Level::levelWithNum(int levelNum){
char fileName[50];
char fullPath[150];
sprintf(fileName,"level%d.plist",levelNum);
CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(fileName,fullPath);
CCDictionary * pListDict = CCDictionary::createWithContentsOfFile(fileName); if(pListDict == NULL){
CCLog("level config not found");
} Level * l = new Level();
CCString * tempStr;
tempStr = dynamic_cast<CCString*>(pListDict->objectForKey("pointsPerTile"));
l->mPointPerTile = tempStr->intValue();
tempStr = dynamic_cast<CCString*>(pListDict->objectForKey("timeToSolve"));
l->mTimeToSovle = tempStr->intValue();
l->pAnagrams = dynamic_cast<CCArray*>(pListDict->objectForKey("anagrams"));
l->pAnagrams->retain(); return l;
}

这里首先用CCDictionary读出level文件里数值,然后就是读取出相应key里的值,并存储起来。

如今。打开主界面文件。默认是HelloWorldScene类,可是我改写成MainScene,当中MainScene.h是这种

class MainScene : public cocos2d::CCLayer
{
public:
~MainScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init(); // there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene(); // implement the "static node()" method manually
CREATE_FUNC(MainScene);
private:
Level * pLevel;
};

可见。添加了Level变量。在MainScene.cpp中的init函数。编写

pLevel = Level::levelWithNum(1);

当然。这里能够通过CCLog来打印出pLevel里的内容来看看。会得到如图所看到的

在MainScene里加入个新的函数

void dealRandomAnagram();

详细实现要这样

void MainScene::dealRandomAnagram(){
Common::random(0, pLevel->pAnagrams->count() - 1);
int randomIndex = Common::random(0, pLevel->pAnagrams->count() - 1); CCAssert((randomIndex >= 0 && randomIndex < pLevel->pAnagrams->count()),"error random index!"); CCArray * anagram = (CCArray*)pLevel->pAnagrams->objectAtIndex(randomIndex); CCString * ana1 = (CCString*)anagram->objectAtIndex(0);
CCString * ana2 = (CCString*)anagram->objectAtIndex(1); int ana1len = ana1->length();
int ana2len = ana2->length();
}

Common::random是我自己编写的。生成两个数值之间的随机数

int Common::random(int s,int e){
float i = CCRANDOM_0_1()*(e-s+1)+s;
return (int)i;
}

这样就把初始状态的短语和终于状态的短语获取到了,把dealRandomAnagram函数加入到MainScene的init函数里。

pLevel = Level::levelWithNum(1);
dealRandomAnagram();

2)创建单词的View

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTc4MTgzNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

在project中新增一个继承于CCNode的类,名字叫做TileView,在TileView.h中加入下面代码

public:
static TileView * initWithLetter(const char * l,float sideLen); private:
CCSprite * pSprite;
char mLetter;
bool mIsMatch;

当中initWithLetter是初始化函数,pSprite是显示的精灵。mLetter是相应的字母。mIsMatch表示结果是否已经配对上(就是找到字母所应该在的位置)。

在TileView.cpp里。加入下面代码

#include "TileView.h"

TileView * TileView::initWithLetter(const char * l, float sideLen){
TileView * tile = new TileView();
CCSprite * bg = CCSprite::create("tile.png");
tile->addChild(bg);
tile->pSprite = bg;
float scale = sideLen / bg->getContentSize().width;
bg->setScale(scale); char chLetter[2];
sprintf(chLetter,"%c",l[0] - 32);
CCLabelTTF * letter = CCLabelTTF::create(chLetter,"Arial",75 * scale);
letter->setColor(ccWHITE);
tile->addChild(letter); tile->mIsMatch = false;
tile->mLetter = chLetter[0]; return tile;
}

函数中,首先的是创建一个以tile.png为图案的精灵。然后创建图案上的字母

接下来就要在界面中显示出来了。在MainScene中加入

private:
Level * pLevel;
CCArray * pTiles;
CCArray * pTargets;

pTiles是TileView的数组,pTargets是TargetView的数组,当中TileView是放在底部给出的短语的各个单词,TargetView是目标短语的各个单词。在MainScene.cpp的dealRandomAnagram函数中继续加入代码

int ana1len = ana1->length();
int ana2len = ana2->length(); float tileSide = ceilf( Common::getCameraWith()*0.9 / (float)std::max(ana1len, ana2len) ) - kTileMargin; float xOffset = (Common::getCameraWith() - std::max(ana1len,ana2len) * (tileSide + kTileMargin)) / 2;
xOffset += tileSide/2;

此时,開始计算各个TileView的位置。

首先,比較得出原始短语和目标短语中长度最长的。然后算出各个View所需的宽度tileSide,以及各个View之间的间隔xOffset

对了,不要忘了定义全局的空隙

#define kTileMargin 20

接着,就要创建我们的TileView了

	pTiles = CCArray::createWithCapacity(ana1len);

	const char * ana1Letter = ana1->getCString();
for(int i = 0;i < ana1len; i++){
char letter[3];
sprintf(letter,"%c",ana1Letter[i]); if(letter[0] != ' '){
TileView * tile = TileView::initWithLetter(letter,tileSide);
tile->setPosition(ccp(xOffset + i * (tileSide + kTileMargin),Common::getCameraHeight() / 4));
this->addChild(tile);
pTiles->addObject(tile);
}
}
pTiles->retain();

创建方法比較简单。可是要注意的是,原始短语中能够会有空字符。空字符的地方须要留空。如图所看到的

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTc4MTgzNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

3)单词View优化

方方正正的TileView看着有些拘谨,以下进行一些优化来让它们生动一些。

在TileView中加入randomize函数

void TileView::randomize(){
float rotation = Common::random(0,50) /(float)100 - 0.2;
this->setRotation(rotation * 10); int yOffset = Common::random(0,10);
this->setPositionY(this->getPositionY() + yOffset);
}

让TileView稍作旋转和偏移,然后在MainScene的dealRandomAnagram函数中的 this->addChild(tile); 语句后加入以下语句

tile->randomize();

4)加入TargetView

有了原始短语,以下就要開始创建目标短语的View了。对照TileView。TargetView要相对简单一些。由于它是固定位置及不须要显示字母。

TargetView.h中加入以下代码:

class TargetView : public CCNode
{
public:
TargetView(void);
~TargetView(void); static TargetView * initWithLetter(const char * l,float sideLen); private:
CCSprite * pSprite;
char mLetter;
bool mIsMatch;
};

与TileView相类似的。一个初始化函数,三个私有变量。

与TileView的是一一相应。

TargetView * TargetView::initWithLetter(const char * l, float sideLen){
TargetView * tile = new TargetView();
CCSprite * bg = CCSprite::create("slot.png");
tile->addChild(bg);
tile->pSprite = bg; float scale = sideLen / bg->getContentSize().width;
bg->setScale(scale); char chLetter[2];
sprintf(chLetter,"%c",l[0] - 32);
/*
CCLabelTTF * letter = CCLabelTTF::create(chLetter,"Arial",78 * scale);
letter->setColor(ccWHITE);
tile->addChild(letter);*/ tile->mIsMatch = false;
tile->mLetter = chLetter[0]; return tile;
}

TargetView的initWithLetter函数中,凝视的语句是为显示一下结果。可是在实际游戏中是不显示TargetView上的字母。

接下来,就要把TargetView显示到场景上了。找到MainScene的dealRandomAnagram方法,在末尾处加入上下面代码

	pTargets = CCArray::createWithCapacity(ana2len);

	const char * ana2Letter = ana2->getCString();
for(int i = 0;i < ana2len; i++){
char letter[3];
sprintf(letter,"%c",ana2Letter[i]); if(letter[0] != ' '){
TargetView * target = TargetView::initWithLetter(letter,tileSide);
target->setPosition(ccp(xOffset + i * (tileSide + kTileMargin),Common::getCameraHeight() / 4 * 3));
this->addChild(target);
pTargets->addObject(target);
}
}
pTargets->retain();

是否可看到TargetView也出来,这里。我们就完毕了AnagramPuzzle的第一部分开发工作,最后上个截图

感觉还不错吧,轻松的把所须要的游戏界面展示出来。

这次接触到cocos2d-x知识还是比較少。主要是如何往主场景中加入内容,如何创建精灵。下一次,我们就要编写一些有点挑战性的东西了。比方怎么拖动精灵,怎么推断是否摆在正确的位置,怎么进行倒计时等等,真正的Code乐趣快要上场!

请听下回分解。


版权声明:本文博客原创文章,博客,未经同意,不得转载。

最新文章

  1. Swift 和 C# 的语法比较
  2. Timus 2068. Game of Nuts 解题报告
  3. mysql常用命令集锦
  4. The maximum number of cell styles was exceeded. You can define up to 4000 styles
  5. 模仿微博 用OC语言编写
  6. html-01
  7. ftp服务器测试
  8. hdu4336压缩率大方的状态DP
  9. Comparer&lt;T&gt; IComparer&lt;T&gt; IComparable&lt;T&gt;
  10. hdu_5752_Sqrt Bo(xjb搞)
  11. vim7.3中文乱码问题
  12. hdu 5517 Triple(二维树状数组)
  13. [转]现代Linux系统上的栈溢出攻击
  14. MARKY一下。
  15. java中的超类是什么
  16. 辗转相除法(GCD)求左旋转字符串
  17. FineUIPro v4.0.0 发布了,全新 CSS3 动画惊艳登场!
  18. centos修改主机名 root@后面的名字
  19. django权限管理(Permission)
  20. kali Linux下wifi密码安全测试(1)虚拟机下usb无线网卡的挂载 【转】

热门文章

  1. java 获取当期时间之前几小时的时间
  2. Echart饼图、柱状图、折线图(pie、bar、line)加入点击事件
  3. CacheHelper工具类的使用
  4. mysql视图学习总结
  5. ArcGIS 10.2 操作SQLite
  6. ORA-12520错误解决一则
  7. 将行政区域导入SQL SERVER
  8. The Django template language 阅读批注
  9. 【译】ASP.NET MVC 5 教程 - 7:Edit方法和Edit视图详解
  10. 前端编程提高之旅(六)----backbone实现todoMVC