消除类游戏核心算法
来源:互联网 发布:relief算法原理 编辑:程序博客网 时间:2024/04/26 13:27
如今消除类游戏很多,比如:消灭寿司,消灭星星等。这篇文章我就共享下我这方面的理解,希望对大家有帮助,如有不好的地方也希望大家指出。
这是我用到资源。同种颜色的2个或者2个以上的就可以消除,消除的越多分越高。
首先,我们来定义一些要用到的变量:
<pre class="cpp" name="code">static const int GRID_COUNT_LANDSCAPE = 10;//方块横总长度static const int GRID_COUNT_PORTRAIT = 10;//方块竖总长度static const string GRID_PIC_PATHS[GRID_TYPE_COUNT] = {string("hongse.png"), string("huangse.png"), string("lanse.png"), string("lvse.png"), string("zise.png")};static const int GRID_TYPE_COUNT = 5;static const int GRID_EMPTY_DATA = GRID_TYPE_COUNT+1;char m_gridData[GRID_COUNT_LANDSCAPE * GRID_COUNT_PORTRAIT];std::vector<GridPos> m_promptGrids;//提示的格子bool m_scaledPromptGrids;//已经缩小的提示格子 cocos2d::gui::Widget *m_gridContentLayer;struct GridPos{ GridPos(int x = 0, int y = 0):m_x(x), m_y(y){ } int m_x; int m_y;};struct EliminateGrid{ EliminateGrid(const GridPos &pos, int type):m_gridPos(pos), m_type(type){ } GridPos m_gridPos; int m_type;};
在GaeScene中初始化:
bool GameScene::init(){ do{ C_BREAK_IF(!TouchGroup::init()); for (int i=0;i<GRID_COUNT_PORTRAIT * GRID_COUNT_LANDSCAPE; i++) { m_gridData[i] = GRID_EMPTY_DATA; } m_gridContentLayer = Widget::create(); CC_BREAK_IF(!m_gridContentLayer); m_gridContentLayer->retain(); m_gridContentLayer->setAnchorPoint(ccp(0,0)); m_gridContentLayer->setPosition(ccp(0, 0)); this->addWidget(m_gridContentLayer); return true; }while(0); return false;}
得到屏幕上的像素坐标:
void GameScene::getGridPosition(int x, int y, CCPoint &point){ point.x = GRID_WIDTH / 2 + GRID_WIDTH * x; point.y = GRID_HEIGHT / 2 + GRID_HEIGHT * y;<span style="color:#000000;">}</span>
把屏幕上的像素坐标转换成我们的坐标
bool GameScene::getPointGridPos(const CCPoint &point, GridPos &pos){ float x = point.x - GRID_BEGIN_X; float y = point.y - GRID_BEGIN_Y; if (x < 0 || x > GRID_WIDTH * GRID_COUNT_LANDSCAPE || y < 0 || y > GRID_HEIGHT * GRID_COUNT_PORTRAIT) { return false; } pos.m_x = ((int)x) / GRID_WIDTH; pos.m_y = ((int)y) / GRID_HEIGHT; return true;}
这里把屏幕上的像素方块坐标转换成我们的坐标是为了我们好操作,这里转换的坐标相当于方块数组的下标,后面有转换的方法。
得到方块的颜色:
std::string GameScene::getGridPath(int data){ if (data == GRID_EMPTY_DATA || data >= GRID_TYPE_COUNT) { return ""; }else{ return GAME_SCENE_ROOT_PATH + GRID_PIC_PATHS[data]; }}
创建一个10*10的方块组:
void GameScene::initGridsData(){ for(int i=0;i<GRID_COUNT_PORTRAIT * GRID_COUNT_LANDSCAPE; i++){ m_gridData[i] = rand() % (GRID_TYPE_COUNT); }}
得到方块的下标:
static int getGridIndex(const GridPos &pos){return getGridIndex(pos.m_x, pos.m_y);}
显示方块:
void GameScene::showGrids(float duration){ this->removeChildByTag(LEVEL_PASS_AMN_TAG, true); for (int x = 0; x < GRID_COUNT_LANDSCAPE; x++) { for (int y=0;y<GRID_COUNT_PORTRAIT;y++) { int index = x * GRID_COUNT_PORTRAIT + y; string path = getGridPath(m_gridData[index]); if (path.length() > 0) { ImageView *pic = ImageView::create(); pic->loadTexture(path.c_str()); pic->setAnchorPoint(ccp(0.5f,0.5f)); CCPoint position; getGridPosition(x,y,position); pic->setPosition(position); pic->setTag(getGridTag(x, y)); this->m_gridContentLayer->addChild(pic); } } } m_gridContentLayer->setPositionY(MyGame::CUR_STANDARD_HEIGHT); CCDelayTime *delay = CCDelayTime::create(duration); CCMoveTo *moveTo = CCMoveTo::create(BEGIN_GAME_DROP_DOWN_DURATION, ccp(GRID_BEGIN_X, GRID_BEGIN_Y)); CCAction* action = CCSequence::create(delay, moveTo, NULL); m_gridContentLayer->runAction(action);}
触摸方块:
bool GameScene::ccTouchBegan(CCTouch *touch, CCEvent *pEvent){ m_hitChild = TouchGroup::ccTouchBegan(touch, pEvent); if(GRID_BEGIN_X != m_gridContentLayer->getPositionX() || GRID_BEGIN_Y != m_gridContentLayer->getPositionY()){//格子整体移动的时候不响应点击事件 m_hitChild = true; } if (!m_hitChild) { bool within = getPointGridPos(touch->getLocation(), m_touchGrid); if (!within)//没有击中格子,不处理消除 { m_hitChild = true; } } return true;}
void GameScene::ccTouchEnded(CCTouch *touch, CCEvent *pEvent){ TouchGroup::ccTouchEnded(touch, pEvent); if (!m_hitChild) { CCPoint pos = touch->getLocation(); GridPos gridPos; bool within = getPointGridPos(pos, gridPos); if (within && gridPos.m_x == m_touchGrid.m_x && gridPos.m_y == m_touchGrid.m_y) { vector<GridPos> grids; this->extendPos(gridPos, grids); if (0 == this->eliminateGrids(grids))//消除成功,计算是否可以继续消除 { int score = this->getScore(grids.size()); this->setScore(m_score + score, true, pos, true);//加上所得分改变分数 showEliminatePrompt(grids.size(), score); clearPromptGrids(); } } }}
下面开始介绍最核心的部分:
//检测一个方块周围是否有和它一样颜色的 如果有就把它们放到数组中void GameScene::extendPos(const GridPos &pos, vector<GridPos> &validGrids) const{ validGrids.clear(); validGrids.push_back(pos);//把有方块的左边放入validGrids中 char color = m_gridData[getGridIndex(pos)]; if (GRID_EMPTY_DATA == color) { return; } int checkedGrids[GRID_COUNT_PORTRAIT * GRID_COUNT_LANDSCAPE]; for (int i=0;i<GRID_COUNT_PORTRAIT * GRID_COUNT_LANDSCAPE; i++) { checkedGrids[i] = 0; } unsigned int index = 0; while(index < validGrids.size()){ GridPos checkedPos = validGrids[index];//得到每一个方块坐标 int checkedIndex = getGridIndex(checkedPos); GridPos left(checkedPos.m_x-1, checkedPos.m_y);//检测左边 if (checkSameGrid(left,checkedGrids,color)) { validGrids.push_back(left); checkedGrids[getGridIndex(left)]++; } GridPos right(checkedPos.m_x+1, checkedPos.m_y); if (checkSameGrid(right,checkedGrids,color)) { validGrids.push_back(right); checkedGrids[getGridIndex(right)]++; } GridPos up(checkedPos.m_x, checkedPos.m_y-1); if (checkSameGrid(up,checkedGrids,color)) { validGrids.push_back(up); checkedGrids[getGridIndex(up)]++; } GridPos down(checkedPos.m_x, checkedPos.m_y+1); if (checkSameGrid(down,checkedGrids,color)) { validGrids.push_back(down); checkedGrids[getGridIndex(down)]++; } checkedGrids[checkedIndex]++; index++; }}
检测点击的方块周围是否有相同颜色的方块:
//检测同种颜色的方块bool GameScene::checkSameGrid(GridPos &pos, int *checkedGrids, char color) const{ if (pos.m_x < 0 || pos.m_x >= GRID_COUNT_LANDSCAPE || pos.m_y < 0 || pos.m_y >= GRID_COUNT_PORTRAIT)//out range { return false; } int index = getGridIndex(pos); if (0 != checkedGrids[index])//is checked { return false; } return color == m_gridData[index];//check color}
消除方块:
int GameScene::eliminateGrids(std::vector<GridPos> &eliminateGrids){ if (eliminateGrids.size() <= 1) { return 1; } for (vector<GridPos>::iterator iter = eliminateGrids.begin(); iter != eliminateGrids.end(); iter++)//消除 { GridPos p = *iter; int index = getGridIndex(p); vector<EliminateGrid>::iterator iterPos = m_waitEliminateGrids.end(); for (vector<EliminateGrid>::iterator m_iter = m_waitEliminateGrids.begin(); m_iter != m_waitEliminateGrids.end(); m_iter++) { if ((*m_iter).m_gridPos.m_x > p.m_x || ((*m_iter).m_gridPos.m_x == p.m_x && (*m_iter).m_gridPos.m_y < p.m_y)) { iterPos = m_iter; break; } } EliminateGrid eliminateGrid(p,m_gridData[index]); m_waitEliminateGrids.insert(iterPos, 1, eliminateGrid); m_gridData[index] = GRID_EMPTY_DATA; } if (eliminateGrids.size() >= SHOW_REWARD_AMN_ELIMINATE_GRID_MIN_COUNT)//消除大于等于5个格子的特效 { CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(GameScene::playEliminateRewardEffect), this, eliminateGrids.size()*ELIMINATE_INTERVAL, false); } m_finishEliminate=false; showEliminateAmn();//消除方块时播放的动画 return 0;}
消除之后,移动方块:
void GameScene::eliminateEmptyGrids(float waitTime){ int index = 0; for (int x = 0; x < GRID_COUNT_LANDSCAPE; x++)//落下 { int empty = 0; for (int y = 0; y < GRID_COUNT_PORTRAIT; y++) { if (GRID_EMPTY_DATA == m_gridData[index]) { empty++; }else if (empty > 0) { moveGrid(index, index-empty, 0, -empty * GRID_HEIGHT, DROP_DOWN_DURATION, waitTime); } index++; } } int empty = 0; for (int x = 0; x < GRID_COUNT_LANDSCAPE; x++)//平移 { if (GRID_EMPTY_DATA == m_gridData[this->getGridIndex(x, 0)]) { empty++; }else if (empty > 0) { for (int y = 0; y < GRID_COUNT_PORTRAIT; y++) { int oldIndex = getGridIndex(x, y); if (GRID_EMPTY_DATA != m_gridData[oldIndex]) { moveGrid(oldIndex, oldIndex - empty * GRID_COUNT_PORTRAIT, -empty * GRID_WIDTH, 0, MOVE_TO_LEFT_DURATION, waitTime + DROP_DOWN_DURATION); } } } }}void GameScene::moveGrid(int oldIndex, int newIndex, int disX, int disY, float duration, float waitTime){ m_gridData[newIndex]=m_gridData[oldIndex];//数据移动 m_gridData[oldIndex] = GRID_EMPTY_DATA; int oldTag = oldIndex;//图像移动 CCNode* gridSprite = this->m_gridContentLayer->getChildByTag(oldTag); int newTag = newIndex; gridSprite->setTag(newTag); CCMoveBy *moveBy = CCMoveBy::create(duration, ccp(disX, disY)); CCEaseSineIn *moveAction = CCEaseSineIn::create(moveBy); CCAction* action = 0; if (waitTime > 0) { CCDelayTime *delay = CCDelayTime::create(waitTime); action = CCSequence::create(delay, moveAction, NULL); }else{ action = CCSequence::create(moveAction, NULL); } gridSprite->runAction(action);}
无可消除的方块,结束:
bool GameScene::finish(int remainCount){ int reward = this->getRewardScore(remainCount); this->setScore(m_score + reward, true, ccp(MyGame::CUR_STANDARD_WIDTH/2,MyGame::CUR_STANDARD_HEIGHT/2), true); this->showRemainRewardPrompt(remainCount, reward, SHOW_FINISH_INFO_DELAY_TIME); m_waitEliminateGrids.clear(); for (int x = 0; x < GRID_COUNT_LANDSCAPE; x++) { for (int y = GRID_COUNT_PORTRAIT - 1; y >= 0; y--) { int index = getGridIndex(x,y); if (GRID_EMPTY_DATA != m_gridData[index]) { EliminateGrid eliminateGrid(GridPos(x,y), (int)(m_gridData[index])); m_waitEliminateGrids.push_back(eliminateGrid); m_gridData[index] = GRID_EMPTY_DATA; } } } m_finishEliminate=true; CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(GameScene::showEliminateAmn), this, ELIMINATE_INTERVAL, kCCRepeatForever, SHOW_FINISH_INFO_DELAY_TIME + REMAIN_REWARD_MOVE_DURATION, false); if (m_score < m_levelPassScore)//分数没达到要求,游戏结束 { std::stringstream curLevelSS; curLevelSS << m_level; MyGame::getInstance()->tJSendLogDataBy3k("850", curLevelSS.str().c_str()); return false; }else{ //下一关游戏 }}
我们再加点提示可以消除的方块功能:
计算可以消除的方块:
void GameScene::calculatePromptGrids(){ m_promptGrids.clear(); bool checkedGrids[GRID_COUNT_PORTRAIT * GRID_COUNT_LANDSCAPE]; for (int i=0;i<GRID_COUNT_PORTRAIT * GRID_COUNT_LANDSCAPE; i++) { checkedGrids[i] = false; } vector<GridPos> validGrids; GridPos pos; for (int x = 0; x < GRID_COUNT_LANDSCAPE; x++)//落下 { for (int y = 0; y < GRID_COUNT_PORTRAIT; y++) { int index = getGridIndex(x,y); if (GRID_EMPTY_DATA == m_gridData[index]) { break; }else if (!checkedGrids[index]) { pos.m_x=x; pos.m_y=y; validGrids.clear(); extendPos(pos, validGrids); //检测所有方块,如果有第一个可以消除的放到validGrids,传给m_promptGrids,然后接着检测,最后把消除最多的传给m_promptGrids bool changeGrids = validGrids.size() > 1 && validGrids.size()>m_promptGrids.size(); if (changeGrids) { m_promptGrids.clear(); } for (vector<GridPos>::iterator iter = validGrids.begin(); iter != validGrids.end(); iter++) { checkedGrids[getGridIndex(*iter)]=true; if (changeGrids) { m_promptGrids.push_back(*iter); } } } } }}
//提示消除方块动作void GameScene::showPromptGrids(float interval){ if (m_promptGrids.size()>0) { float scale = m_scaledPromptGrids ? 1.0f : PROMPT_GRIDS_MIN_SCALE; for (vector<GridPos>::iterator iter=m_promptGrids.begin(); iter!=m_promptGrids.end(); iter++) { CCNode *gridNode = m_gridContentLayer->getChildByTag(getGridTag(*iter)); CCScaleTo *scaleTo= CCScaleTo::create(PROMPT_GRIDS_DURATION, scale, scale); CCSequence *action = CCSequence::create(scaleTo, NULL); gridNode->runAction(action); } m_scaledPromptGrids=!m_scaledPromptGrids; }}
如果点击提示的格子就清除提示格子
void GameScene::clearPromptGrids(){ if (m_scaledPromptGrids) { for (vector<GridPos>::iterator iter=m_promptGrids.begin(); iter!=m_promptGrids.end(); iter++) { CCNode *gridNode = m_gridContentLayer->getChildByTag(getGridTag(*iter)); if (gridNode) { CCScaleTo *scaleTo= CCScaleTo::create(PROMPT_GRIDS_DURATION, 1.0f, 1.0f); CCSequence *action = CCSequence::create(scaleTo, NULL); gridNode->runAction(action); } } } m_promptGrids.clear(); m_scaledPromptGrids=false; }
0 0
- 消除类游戏核心算法
- 消除游戏的核心算法
- 消除游戏之消除算法
- 消除类游戏
- CCF 消除类游戏
- 消除类游戏
- CCF 消除类游戏
- ccf 消除类游戏
- CCF 消除类游戏
- 消除类游戏
- ccf 消除类游戏
- 消除类游戏
- CCF消除类游戏
- 消除类游戏
- CCF 消除类游戏
- 消除类游戏
- cocos2d 简单消除游戏算法 (一)
- 简单JS消除类游戏
- Android xml资源文件中@、@android:type、@*、?、@+含义和区别
- linux 内存管理
- 测试
- Android开源项目分类汇总
- Android 自定义RecyclerView (替代ListView的最新组件)实现真正的Gallery效果
- 消除类游戏核心算法
- IOS突破限制--5
- 元素随滚动条滚动特效(广告,标题栏等)
- linux按键驱动程序心得
- mapreduce join
- 总结swift语言常见的20个问题和回答
- 亚马逊Fire TV Stick电视棒让手机变身遥控器
- JavaWeb 服务启动时,在后台启动加载一个线程。
- 用swift开发仪表盘控件(一)