本文共 12778 字,大约阅读时间需要 42 分钟。
接下来,我们将完成剩下的游戏界面部分。连连看我们可以看做是一个m行乘以n列的一个矩行,其中我们规定0为空的,其余数字可以看作是图片的引用id,通过这个id,我们可以直接找到这个图片,有了图片,我们就可以初始化出这个对应的精灵。然后通过touch事件判断出是否选中或是没选中这个精灵,然后通过相应的算法,算出所选两个精灵对象是否是一样的,并且符合我们的游戏规则,符合就消掉,不符合再重新选取。。。。。。
00001000200003
10000300000002
00040000040000
OK,,我们先新建一个类,叫MapLayer,这个类主要是游戏地图层的部分
//地图层class MapLayer :public cocos2d::CCLayerColor{ public: virtual bool init(); CREATE_FUNC(MapLayer); void initUI(void); void initData(void); ~MapLayer(); private: };上面部分就是新建一个类,定义一些初始化的函数。对于数据部分,你可以存储在一个一维数组里,当然也可以存储到文件中,只要你能获取到数据,那你怎么存都OK的~~~
这里,我们把数据存到一个plist文件里,plist可以看作是一个xml,我们新建一个plist,叫levelinfo.plist
我们定义第一关001,里面有total_x,列数,total_y,行数,也就是上面我们定义了一个5*9的一个矩形,array里面存了图片对应的id,0表示无,没有。
OK。。接下来,我们来解析这个xml,,代码如下
//读取plist数据文件 const char *plistPath=CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile("levelinfo.plist","levelinfo.plist"); CCDictionary *plistDic=CCDictionary::createWithContentsOfFile(plistPath); CCDictionary *levelDic=dynamic_cast这样,我们就读取到plist里相应的数据,接下来,我们定义一个类,叫MapNode类,它就提供两个属性,order跟id,代码如下(plistDic->objectForKey("001")); CCString *xstring=dynamic_cast (levelDic->objectForKey("total_x")); total_x=xstring->intValue(); CCString *ystring=dynamic_cast (levelDic->objectForKey("total_y")); total_y=ystring->intValue(); CCArray *array=CCArray::create(); array=dynamic_cast (levelDic->objectForKey("imageidarr"));
class MapNode :public cocos2d::CCObject{public: //序号 int order; //图片的id int imgid;};接下来,我们对把plist的array里的数据取出来,然后赋值给MapNode的imgid属性,代码如下
mapArray=CCArray::create(); mapArray->retain(); CCArray *array2=CCArray::create(); //种子 srandom((unsigned int)time(NULL)); for (int i=0; i<(total_x-1)*(total_y-1); i++) { MapNode *node=new MapNode(); node->autorelease(); //产生唯一的orderid node->order=(int)(CCRANDOM_0_1()*INT_MAX)%(int)(CCRANDOM_0_1()*INT_MAX); CCString *idString=(CCString *)(array->objectAtIndex(i)); node->imgid=idString->intValue(); array2->addObject(node); } //排序 qsort(array2->data->arr, array2->data->num, sizeof(long),compare); for (int x=0; xmapArray里存的都是经过排序后的mapnode,c排序函数autorelease(); node->order=0; node->imgid=0; mapArray->addObject(node); }else { int i = (y - 1) * (total_x - 1) + x - 1; mapArray->addObject(array2->objectAtIndex(i)); } } }
void qsort(void *, size_t, size_t,int (*)(const void *, const void *));第一个参数是数组头部首地址,第二个参数数组长度,第三个是数组每个元素大小size,第四个是一个int型函数指针,
//排序比较int compare(const void *a,const void *b){ MapNode *node1=(MapNode *)a; MapNode *node2=(MapNode *)b; if (node1->order>node2->order) { return 1; } else if (node1->order==node2->order) { return 0; } else { return -1; }}OK,接下来,我们来布局我们的图片sprite,代码如下
//布局sprite for (int y = 0; y < total_y; ++y) { for (int x = 0; x < total_x; ++x) { int index=y*total_x+x; if (this->imageFilename(index)) { CCSprite *sprite=CCSprite::createWithSpriteFrameName(this->imageFilename(index)->getCString()); sprite->setScale(1.0); sprite->setPosition(ccp(OFFSET_X * x + (SIZE_W / 2) + SIZE_W * x, OFFSET_Y * y + (SIZE_H / 2) + SIZE_H * y)); this->addChild(sprite, 1, TAG_START_SPRITE+index); } } }
//获取图片CCString* MapLayer::imageFilename(int index){ int n=((MapNode *)(mapArray->objectAtIndex(index)))->imgid; // CCLOG("n------:%d",index); if (n>=1 && n<=20) { return CCString::createWithFormat("%d.png",n); } else { return NULL; } }我们运行下,看下效果
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
接下来,我们加入触摸事件,代码如下
在
MapLayer.h中加入
virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent); virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
MapLayer.cpp中加入
//添加touch监听 CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 1, true);
//bool MapLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){ return true;}//void MapLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){ }我们将在touchend里处理事件,我们获取手指触摸点的坐标,然后把它转换成本地坐标,不然获取的坐标是整个下层的坐标,再把本地坐标转换成地图坐标,就像坦克大战里的,比如(1,2)之类的,看代码
//bool MapLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){ CCPoint location = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView()); //在这个层区域内返回true if (this->boundingBox().containsPoint(location)) { return true; } //否则返回false,阻止接下来的touch函数 return false;}//void MapLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){ CCPoint location = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView()); location = this->convertToNodeSpace(location); //location=CCPointMake(location.x, location.y-40); location=this->pointOfView(location); // CCLOG("x:%f",location.x); // CCLOG("y:%f",location.y); }
//屏幕坐标转换成地图坐标CCPoint MapLayer::pointOfView(cocos2d::CCPoint point){ int x = -1; int y = -1; if (point.x > 0 && point.x < total_x * SIZE_W + OFFSET_X * (total_x-1)) x = (point.x ) / (SIZE_W+OFFSET_X); if (point.y > 0 && point.y < (total_y-1)* OFFSET_Y + total_y * SIZE_H ) y = (point.y) / (SIZE_H+OFFSET_Y); return CCPoint(x, y); }OK。。。。接下来,我们会把剩下的一些算法,判断函数全部写下来,大家直接看代码吧
//是否在有效范围内bool MapLayer::isValiableNode(cocos2d::CCPoint point){ return point.x >= 0 && point.x < total_x && point.y >= 0 && point.y < total_y;}//是否是空的坐标点bool MapLayer::isEmptyNode(cocos2d::CCPoint point){ int index=this->indexFromPoint(point); MapNode *node=(MapNode *)mapArray->objectAtIndex(index); return (node->imgid==0); }//每个sprite的indexint MapLayer::indexFromPoint(cocos2d::CCPoint point){ return point.y * total_x + point.x; }//是否是相同的点bool MapLayer::isSamePoints(cocos2d::CCPoint p1, cocos2d::CCPoint p2){ return (p1.x == p2.x && p1.y == p2.y);}//清除void MapLayer::clearNode(cocos2d::CCPoint point){ int index=this->indexFromPoint(point); MapNode *node=(MapNode *)mapArray->objectAtIndex(index); node->imgid=0;}//判断两个是否可以消除bool MapLayer::canClearTwo(cocos2d::CCPoint pointpre, cocos2d::CCPoint pointcurrent){ bool bMatch = false; int pre = this->indexFromPoint(pointpre); int current = this->indexFromPoint(pointcurrent); int p = ((MapNode *)(mapArray->objectAtIndex(pre)))->imgid; int c = ((MapNode *)(mapArray->objectAtIndex(current)))->imgid; if (p == c && this->match(pointcurrent, pointpre)) { bMatch = true; } return bMatch;}//放大缩小动画void MapLayer::scaleAnimation(cocos2d::CCSprite* sprite){ CCScaleTo *ac1=CCScaleTo::create(0.07f, 1.0); CCScaleTo *ac2=CCScaleTo::create(0.07f, 0.9); CCScaleTo *ac3=CCScaleTo::create(0.07f, 1.0); CCSequence *seq=CCSequence::create(ac1,ac2,ac3,NULL); sprite->runAction(seq); }
//三种匹配算法//一直线bool MapLayer::match_direct(cocos2d::CCPoint a, cocos2d::CCPoint b){ if (!(a.x == b.x || a.y == b.y)) { return false; } int i; bool match_x = false; if(a.x == b.x) { match_x = true; if(a.y > b.y) { for(i = a.y - 1; i > b.y; --i) { CCPoint point = CCPointMake(a.x, i); if(!this->isValiableNode(point) || !this->isEmptyNode(point)){ match_x = false; } } } if(b.y > a.y) { for(i = b.y - 1; i > a.y; --i) { CCPoint point = CCPointMake(a.x, i); if(!this->isValiableNode(point) || !this->isEmptyNode(point)) { match_x = false; } } } } bool match_y = false; if(a.y == b.y) { match_y = true; if(a.x > b.x) { for(i = a.x - 1; i > b.x; --i) { CCPoint point = CCPointMake(i, a.y); if(!this->isValiableNode(point) || !this->isEmptyNode(point)) { match_y = false; } } } if(b.x > a.x) { for(i = b.x - 1; i > a.x; --i) { CCPoint point = CCPointMake(i, a.y); if(!this->isValiableNode(point) || !this->isEmptyNode(point)) { match_y = false; } } } } return match_x || match_y;}//一个拐点的bool MapLayer::match_one_corner(cocos2d::CCPoint a, cocos2d::CCPoint b){ CCPoint point = CCPointMake(b.x, a.y); if( this->isValiableNode(point) && this->isEmptyNode(point) && this->match_direct(a, point) && this->match_direct(b, point)){ return true; } point = CCPointMake(a.x, b.y); if( this->isValiableNode(point) && this->isEmptyNode(point) && this->match_direct(a, point) && this->match_direct(b, point)){ return true; } return false;}//两个拐点的bool MapLayer::match_two_corner(cocos2d::CCPoint a, cocos2d::CCPoint b){ for(int i = a.x - 1; i >= 0; --i) { CCPoint point = CCPointMake(i, a.y); if (!this->isValiableNode(point) || !this->isEmptyNode(point)) { break; } else { if (this->match_one_corner(point, b)) { return true; } } } for(int i = a.x + 1; i < total_x; ++i) { CCPoint point = CCPointMake(i, a.y); if (!this->isValiableNode(point) || !this->isEmptyNode(point)) { break; } else { if (this->match_one_corner(point, b)) { return true; } } } for(int i = a.y - 1; i >= 0; --i) { CCPoint point = CCPointMake(a.x ,i); if (!this->isValiableNode(point) || !this->isEmptyNode(point)) { break; } else { if (this->match_one_corner(point, b)) { return true; } } } for(int i = a.y + 1; i < total_y; ++i) { CCPoint point = CCPointMake(a.x ,i); if (!this->isValiableNode(point) || !this->isEmptyNode(point)) { break; } else { if (this->match_one_corner(point, b)) { return true; } } } return false;}bool MapLayer::match(cocos2d::CCPoint a,cocos2d::CCPoint b){ if (this->match_direct(a, b)) { return true; } if (this->match_one_corner(a, b)) { return true; } if (this->match_two_corner(a, b)) { return true; } return false;}重新写touch事件
//bool MapLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){ CCPoint location = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView()); //在这个层区域内返回true if (this->boundingBox().containsPoint(location)) { return true; } //否则返回false,阻止接下来的touch函数 return false;}//void MapLayer::ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){ CCPoint location = CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView()); location = this->convertToNodeSpace(location); //location=CCPointMake(location.x, location.y-40); location=this->pointOfView(location); CCLOG("x:%f",location.x); CCLOG("y:%f",location.y); if (this->isValiableNode(location)==false) { return; } if (this->isEmptyNode(location)) { return; } SimpleAudioEngine::sharedEngine()->playEffect("12.wav"); if (this->isSamePoints(location, prePoint)) { return; } //点击当前精灵 CCSprite *spritecurrent=(CCSprite *)this->getChildByTag(TAG_START_SPRITE+this->indexFromPoint(location)); spritecurrent->setScale(1.3); CCLOG("%d",this->indexFromPoint(location)); if (this->isValiableNode(prePoint)) { //前一个 CCSprite *spritepre=(CCSprite *)this->getChildByTag(TAG_START_SPRITE+this->indexFromPoint(prePoint)); if (this->canClearTwo(prePoint, location)) { SimpleAudioEngine::sharedEngine()->playEffect("4.wav"); this->clearNode(location); this->clearNode(prePoint); spritecurrent->setVisible(false); spritepre->setVisible(false); } else { spritepre->setScale(0.9); this->scaleAnimation(spritepre); } } prePoint=location; }运行,效果如下 选中的时候,放大精灵~~~~
~~~~~这里时间有限,下一篇的文章将探讨一些自动消除,还有用粒子效果来实现消除时的动画等,还有一些其他问题~~~
转载地址:https://blog.csdn.net/kuloveyouwei/article/details/13004465 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!