void BallMap::actionEndCallback(CCNode *node) { BallSprite *ball = (BallSprite *)node; ball->set_isMoving(false); m_matrix[ball->getRow() * (int)m_size.width + ball->getCol()] = NULL; ball->removeFromParent(); }
void BallMap::removeBall() { // make sequence remove m_isAnimationing = true; std::list<BallSprite *>::iterator itList; for (itList = m_readyRemoveList.begin(); itList != m_readyRemoveList.end(); itList++) { BallSprite *ball = dynamic_cast<BallSprite*>(*itList); if (!ball) { continue; } if (ball->getIsNeedRemove()) { m_isNeedFillVacancies = true;//需要掉落 m_isNeedCheckSelf = true; explodeBall(ball); } } m_readyRemoveList.clear(); }
void GameScene_Box2D::delTouchedBalls() { std::vector<BallSprite*>::iterator tempIterator; std::vector<BallSprite*> tmpbollArray; std::vector<std::vector<BallSprite*>::iterator> deleteIteratorArray; for( tempIterator = _bollArray.begin(); tempIterator != _bollArray.end(); tempIterator++ ) { BallSprite *ball = (BallSprite *)*tempIterator; if (ball->getDeleteState()==BallSprite::deleteState::kDelete) { _delballPos.push_back(ball->getPosition()); // _world->DestroyBody(ball->getB2Body()); ball->deleteParticle(_particleSystem,_particleGroup); ball->removeFromParent(); } else { tmpbollArray.push_back(ball); } } _bollArray.clear(); for (auto nodelball = tmpbollArray.begin(); nodelball != tmpbollArray.end(); nodelball++) { BallSprite *ball = (BallSprite *)*nodelball; _bollArray.push_back(ball); } }
BallSprite *BallSprite::createBallSprite(Node *parent ,b2World *world, const std::string& filename) { BallSprite* pInstance = BallSprite::create(); //Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename); pInstance->setTexture(filename); // shape.m_radius = sptite->getContentSize().width / PTM_RATIO; // 形状の大きさ /** * 剛体は次の手順で作成する。剛体とは物理エンジンの影響をうけることが出来る物質のこと 1. 位置・減衰率などで剛体を定義する。 2. 剛体を作成するためにワールドを使用する。 3. 図形・摩擦・密度などから装備を定義する。 4. 剛体から装備を作成する。 */ b2Body* body; // 剛体。rigid body。 b2BodyDef bodyDef; // 剛体の定義 b2CircleShape shape; // 装備の形状 float radius = getBallRadius(); shape.m_radius = radius/ PTM_RATIO;; b2FixtureDef fixtureDef; // 装備の形状定義 // 1. 位置・減衰率などで剛体を定義する。 bodyDef.type = b2_dynamicBody; //bodyDef.position.Set((winSize.width / 2) / PTM_RATIO, (winSize.height) / PTM_RATIO); bodyDef.userData = pInstance; // 画像をこの剛体に紐付ける // 2. 剛体を作成するためにワールドを使用する。 body = world->CreateBody(&bodyDef); fixtureDef.shape = &shape; // 形状を紐付ける fixtureDef.density = 1; // 密度 fixtureDef.friction = 0.9; // 摩擦 // 4. 剛体から装備を作成する。 body->CreateFixture(&fixtureDef); /** PhysicsSpriteに各種情報をセットする */ //parent->addChild(pInstance); pInstance->setB2Body(body); pInstance->setPTMRatio(PTM_RATIO); parent->addChild(pInstance); return pInstance; }
void GameScene::updateBall() { if (!isTouched) { return; } for (int i = 0; i < m_activeballs->count(); i++) { BallSprite* ball = dynamic_cast<BallSprite*>(m_activeballs->objectAtIndex(i)); if (!ball) return; CCPoint ballPoint = ball->getPosition(); float vx = ball->getVelocityX(); float vy = ball->getVelocityY(); // ボールの移動 // CCLOG("# updateBall1 #ball position X: %f, Y: %f", // ball->getPositionX(), ball->getPositionY()); ball->setPosition(ccp(ball->getPositionX() + vx, ball->getPositionY() + vy)); // CCLOG("# updateBall2 #ball position X: %f, Y: %f", // ball->getPositionX(), ball->getPositionY()); if (ballPoint.y < 0) { //ユーザーがボールを奈落に落とした onBallLost(ball); return; } //壁との衝突判定 ball->bounceBall(g_visibleSize); } }
//インスタンス生成 BallSprite* BallSprite::create(BallType type, bool visible) { BallSprite *pRet = new BallSprite(); if (pRet && pRet->init(type, visible)) { pRet->autorelease(); return pRet; } else { delete pRet; pRet = nullptr; return nullptr; } }
BallSprite* BallSprite::create(GameLayer * game, int type, CCPoint position) { /* Create sprite with image file name. Args: pszFileName: char *, string of file name Returns: BallSprite * */ BallSprite *sprite = new BallSprite(game, type, position); if (sprite) { sprite->initBall(); sprite->autorelease(); return sprite; } CC_SAFE_DELETE(sprite); return NULL; }
void GameScene::updateBlocks() { for (int i = 0; i < m_activeballs->count(); i++) { BallSprite* ball = dynamic_cast<BallSprite*>(m_activeballs->objectAtIndex(i)); if (!ball) return; CCRect ballRect = ball->boundingBox(); CCObject* jt = NULL; CCArray* blocksToDelete = new CCArray; CCARRAY_FOREACH(m_blocks, jt) { CCSprite* block = dynamic_cast<CCSprite*>(jt); // CCLOG("updateGame target.x: %f, target.y: %f, tag: %d",target->getContentSize().width, target->getContentSize().height, target->getTag()); CCRect blockRect = block->boundingBox(); //衝突判定 if (ballRect.intersectsRect(blockRect)) { // ボールは跳ね返す ball->bounceBall(blockRect, kTagBlock); blocksToDelete->addObject(block); //スコア加算 m_score += 100; showScore(); //確率に従ってボーナスアイテムを生成する makeItem(block); } } // 当たったブロックを消す CCARRAY_FOREACH(blocksToDelete, jt) { CCSprite *block = dynamic_cast<CCSprite*>(jt); m_blocks->removeObject(block); this->removeChild(block, true); m_blocksDestroyed++; }
BallSprite *GameScene_Box2D::createSprite(Vec2 &pos, Vec2 &velocity){ std::random_device rd; std::mt19937 mt(rd()); std::uniform_real_distribution<double> intval(0,3); int val = (int)intval(mt); __String *filename; BallSprite::ballType type; switch (val) { case 0: filename = String::create("ball.png"); type = BallSprite::ballType::kRed; break; case 1: filename = String::create("pur_ball.png"); type = BallSprite::ballType::kPurple; break; case 2: filename = String::create("blue_ball.png"); type = BallSprite::ballType::kBrue; break; case 3: filename = String::create("yellow_ball.png"); type = BallSprite::ballType::kYellow; break; default: filename = String::create("ball.png"); type = BallSprite::ballType::kBrue; break; } //BallSprite *ball = BallSprite::createBallSprite(this, _world, filename->getCString()); BallSprite *ball = BallSprite::createParticleSprite(this, _world, _particleSystem, _particleGroup, filename->getCString()); //ball->setPosition(pos); ball->setParticlePpos(_particleSystem, _particleGroup, pos.x, pos.y, velocity.x, velocity.y); ball->setTag(spriteType::kBall); ball->setBallType(type); _bollArray.push_back(ball); return ball; }
void GameScene::setBall() { //ボールをバー上に配置する if (m_balls->count() <= 0) { return; } BallSprite* ball = dynamic_cast<BallSprite*>(m_balls->objectAtIndex(0)); CCNode *bar = this->getChildByTag(kTagBar); // CCRect rect = bar->boundingBox(); ball->setPosition( ccp(bar->getPositionX(), bar->getPositionY() + bar->getContentSize().height + 10)); // CCLOG("# setBall #bar.width: %f, height: %f", // bar->getContentSize().width, bar->getContentSize().height); // CCLOG("# setBall #bar position X: %f, Y: %f", // bar->getPositionX(), bar->getPositionY()); // ball->setPosition( // ccp(bar->getPositionX() + bar->getContentSize().width / 2, bar->getPositionY() + bar->getContentSize().height)); this->addChild(ball); m_balls->removeObjectAtIndex(0); m_activeballs->addObject(ball); }
void BallMap::createAndDropBall(int row, int col) { CCSize size = CCDirector::sharedDirector()->getWinSize(); BallSprite *ball = BallSprite::create(row, col); // create animation CCPoint endPosition = positionOfItem(ball); CCPoint startPosition = CCPoint(endPosition.x, endPosition.y + size.height / 2); ball->setPosition(startPosition); float speed = startPosition.y / (2.0 * size.height); ball->runAction(CCSequence::create( CCMoveTo::create(speed, endPosition), CCCallFuncN::create(this, callfuncN_selector(BallMap::setBallNoMoving)), NULL)); // add to BatchNode m_joyPad->get_spriteNode()->addChild(ball); m_matrix[row * (int)m_size.width + col] = ball; }
BallSprite *GameScene_Chipmunk::createSprite(Vec2 &pos){ std::random_device rd; std::mt19937 mt(rd()); std::uniform_real_distribution<double> intval(0,3); int val = (int)intval(mt); __String *filename; BallSprite::ballType type; switch (val) { case 0: filename = String::create("ball.png"); type = BallSprite::ballType::kRed; break; case 1: filename = String::create("pur_ball.png"); type = BallSprite::ballType::kPurple; break; case 2: filename = String::create("blue_ball.png"); type = BallSprite::ballType::kBrue; break; case 3: filename = String::create("yellow_ball.png"); type = BallSprite::ballType::kYellow; break; default: filename = String::create("ball.png"); type = BallSprite::ballType::kBrue; break; } BallSprite *ball = BallSprite::createBallSprite(this, filename->getCString()); ball->setCenter(pos); ball->setTag(spriteType::kBall); ball->setBallType(type); _bollArray.push_back(ball); return ball; }
BallSprite *BallMap::BallOfPoint(CCPoint *point) { BallSprite *Ball = NULL; CCRect rect = CCRect(0, 0, 0, 0); for (int i = 0; i < m_size.height * m_size.width; i++) { Ball = m_matrix[i]; if (Ball) { rect.origin.x = Ball->getPositionX() - (Ball->getContentSize().width / 2); rect.origin.y = Ball->getPositionY() - (Ball->getContentSize().height / 2); rect.size = Ball->getContentSize(); if (rect.containsPoint(*point)) { return Ball; } } } return NULL; }
void BallMap::update(float dt) { // check if animationing if (m_isAnimationing) { // init with false m_isAnimationing = false; for (int i = 0; i < m_size.height * m_size.width; i++) { BallSprite *ball = m_matrix[i]; if (ball && ball->get_isMoving()) { m_isAnimationing = true; break; } } } // if Ball is moving, ignore use touch event m_isTouchEnable = !m_isAnimationing; if (!m_isAnimationing) { if (m_isNeedFillVacancies) { //爆炸效果结束后才掉落新寿司,增强打击感 fillVacancies(); m_isNeedFillVacancies = false; } else { if (m_isNeedCheckSelf) { checkAndRemoveChain(); } } } }
void GameScene_Chipmunk::delTouchedBalls() { std::vector<BallSprite*>::iterator tempIterator; std::vector<BallSprite*> tmpbollArray; std::vector<std::vector<BallSprite*>::iterator> deleteIteratorArray; for( tempIterator = _bollArray.begin(); tempIterator != _bollArray.end(); tempIterator++ ) { BallSprite *ball = (BallSprite *)*tempIterator; if (ball->getDeleteState()==BallSprite::deleteState::kDelete) { _delballPos.push_back(ball->getPosition()); ball->removeFromParent(); } else { tmpbollArray.push_back(ball); } } _bollArray.clear(); for (auto nodelball = tmpbollArray.begin(); nodelball != tmpbollArray.end(); nodelball++) { BallSprite *ball = (BallSprite *)*nodelball; _bollArray.push_back(ball); } }
//指定方向のボールと同じ色かチェックする bool GameLayer::isSameBallType(BallSprite::PositionIndex current, Direction direction) { //全てのボールのBallTypeを取得 auto allBalls = getAllBalls(); if (direction == Direction::x) { if (current.x + 1 > BALL_NUM_X) //列が存在しない場合は抜ける return false; } else { if (current.y + 1 > BALL_NUM_Y) //行が存在しない場合は抜ける return false; } //現在のボールを取得 int currentTag = BallSprite::generateTag(BallSprite::PositionIndex(current.x, current.y)); BallSprite* currentBall = allBalls.at(currentTag); //次のボールを取得 int nextTag; if (direction == Direction::x) nextTag = BallSprite::generateTag(BallSprite::PositionIndex(current.x + 1, current.y)); else nextTag = BallSprite::generateTag(BallSprite::PositionIndex(current.x, current.y + 1)); auto nextBall = allBalls.at(nextTag); if (currentBall->getBallType() == nextBall->getBallType()) //次のボールが同じBallTypeである return true; return false; }
void GameScene::onBallLost(CCNode* sender) { if (UserSettings::getSESetting()) SimpleAudioEngine::sharedEngine()->playEffect(MP3_BALLLOST); BallSprite *ball = dynamic_cast<BallSprite*>(sender); if (ball->getIsItem3()) { this->removeChild(ball, true); m_activeballs->removeObject(ball); if (m_activeballs->count() == 0) { isTouched = false; } return; } cancelTimers(); //奈落に落ちたボールを削除 this->removeChild(ball, true); m_activeballs->removeObject(ball); int remain = this->getBallRemain() - 1; this->setBallRemain(remain); showBallRemain(); if (m_activeballs->count() == 0) { isTouched = false; } //ゲームオーバー判定 if (remain <= 0) { this->gameOver(); return; } setBall(); }
void GameScene_Box2D::onContactPostSolve(PhysicsContact& contact, const PhysicsContactPostSolve& solve) { auto node1 = contact.getShapeA()->getBody()->getNode(); auto node2 = contact.getShapeB()->getBody()->getNode(); if (node1->getTag()== spriteType::kFloor && node2->getTag()== spriteType::kBall) { BallSprite *ball = (BallSprite *)node2; bool ball_state_none = (ball->getBallContState() == BallSprite::ballContactState::kNone); if (ball_state_none) { ball->setBallContState(BallSprite::ballContactState::kFloorContact); } } else if (node2->getTag()== spriteType::kFloor && node1->getTag()== spriteType::kBall) { BallSprite *ball = (BallSprite *)node1; bool ball_state_none = (ball->getBallContState() == BallSprite::ballContactState::kNone); ball->setBallContState(BallSprite::ballContactState::kFloorContact); if (ball_state_none) { ball->setBallContState(BallSprite::ballContactState::kFloorContact); } } else if (node2->getTag()== spriteType::kBall && node1->getTag()== spriteType::kBall) { BallSprite *ball1 = (BallSprite *)node1; BallSprite *ball2 = (BallSprite *)node2; bool ball1_state_floor = (ball1->getBallContState() == BallSprite::ballContactState::kFloorContact); bool ball2_state_floor = (ball2->getBallContState() == BallSprite::ballContactState::kFloorContact); bool ball1_state_none = (ball1->getBallContState() == BallSprite::ballContactState::kNone); bool ball2_state_none = (ball2->getBallContState() == BallSprite::ballContactState::kNone); bool ball1_state_second = (ball1->getBallContState() == BallSprite::ballContactState::kSecondContact); bool ball2_state_second = (ball2->getBallContState() == BallSprite::ballContactState::kSecondContact); if (ball1_state_none || ball2_state_floor) { ball1->setBallContState(BallSprite::ballContactState::kSecondContact); } else if (ball1_state_floor || ball2_state_none) { ball2->setBallContState(BallSprite::ballContactState::kSecondContact); } else if (ball1_state_none || ball2_state_second) { ball1->setBallContState(BallSprite::ballContactState::kSecondContact); } else if (ball2_state_none || ball1_state_second) { ball2->setBallContState(BallSprite::ballContactState::kSecondContact); } } }
void BallMap::getRowChain(BallSprite *ball, std::list<BallSprite *> &chainList) { chainList.push_back(ball);// add first Ball int neighborRow = ball->getRow() - 1; while (neighborRow >= 0) { BallSprite *neighborBall = m_matrix[neighborRow * (int)m_size.width + ball->getCol()]; if (neighborBall && (neighborBall->getImgIndex() == ball->getImgIndex()) && (!neighborBall->getIsNeedRemove() || !ball->getIsNeedRemove()) && !neighborBall->getIgnoreCheck()) { chainList.push_back(neighborBall); neighborRow--; } else { break; } } neighborRow = ball->getRow() + 1; while (neighborRow < m_size.height) { BallSprite *neighborBall = m_matrix[neighborRow * (int)m_size.width + ball->getCol()]; if (neighborBall && (neighborBall->getImgIndex() == ball->getImgIndex()) && (!neighborBall->getIsNeedRemove() || !ball->getIsNeedRemove()) && !neighborBall->getIgnoreCheck()) { chainList.push_back(neighborBall); neighborRow++; } else { break; } } }
BallSprite *BallSprite::createParticleSprite(Node *parent ,b2World *world, b2ParticleSystem *particleSystem, b2ParticleGroup *particleGroup,const std::string& filename) { BallSprite* pInstance = (BallSprite *)Sprite::create(); //BallSprite* pInstance = BallSprite::createBallSprite(parent,world,filename); pInstance->setTexture(filename); parent->addChild(pInstance); // 描画用ノードの作成 DrawNode* draw = DrawNode::create(); draw->setPosition(Vec2(0, 0)); pInstance->addChild(draw); /* 円の描画 */ draw->drawDot(Vec2(pInstance->getBallRadius()/2, pInstance->getBallRadius()/2), // 中心 pInstance->getBallRadius(), // 半径 Color4F(1, 0.5f, 0, 200) // 色 ); particleSystem->SetRadius(getBallRadius()*1.2/PTM_RATIO); b2ParticleDef particleDef; //パーティクルの寿命 //particleDef.lifetime = 2.0f; //particleDef.flags = b2_dynamicBody; particleDef.flags = b2_waterParticle; particleDef.flags |= b2_destructionListenerParticle; particleDef.color = b2ParticleColor(100,150,255,255); //particleDef.velocity.y = -100; //グループへのポインタを渡しておく事でそのグループ内で管理する事ができる。 particleDef.group = particleGroup; particleDef.flags = b2_waterParticle; //void** userdata = particleSystem->GetUserDataBuffer(); particleDef.userData = pInstance; particleSystem->CreateParticle(particleDef); return pInstance; }
BallSprite* BallSprite::createWithNumber(kBallNumber number) { BallSprite *ballSprite = new BallSprite(); ballSprite->setNumber(number); if(ballSprite && ballSprite->initWithFile(PNG_BALL)) { //ボールの数字をラベルとして付ける const char* numberString = CCString::createWithFormat("%d", number)->getCString(); LabelBMFont* numberLabel = CCLabelBMFont::create(numberString, FONT_NUMBER); numberLabel->setPosition(Point(ballSprite->getContentSize().width / 2,ballSprite->getContentSize().height / 2)); numberLabel->setScale(1.8); ballSprite->addChild(numberLabel, kZOrderNumber, kTagNumber); //ボールのメモリを自動消去 ballSprite->autorelease(); //作ったSpriteを返す return ballSprite; } else { CC_SAFE_DELETE(ballSprite); return nullptr; } }
/* bool BallMap::ccTouchBegan(CCTouch *touch, CCEvent *unused) { m_srcBall = NULL; m_destBall = NULL; if (m_isTouchEnable) { auto location = touch->getLocation(); m_srcBall = BallOfPoint(&location); } return m_isTouchEnable; } void BallMap::ccTouchMoved(CCTouch *touch, CCEvent *unused) { if (!m_srcBall || !m_isTouchEnable) { return; } int row = m_srcBall->getRow(); int col = m_srcBall->getCol(); auto location = touch->getLocation(); auto halfBallWidth = m_srcBall->getContentSize().width / 2; auto halfBallHeight = m_srcBall->getContentSize().height / 2; auto upRect = CCRect(m_srcBall->getPositionX() - halfBallWidth, m_srcBall->getPositionY() + halfBallHeight, m_srcBall->getContentSize().width, m_srcBall->getContentSize().height); if (upRect.containsPoint(location)) { row++; if (row < m_height) { m_destBall = m_matrix[row * m_width + col]; } m_movingVertical = true; swapBallAndCheck(); return; } auto downRect = CCRect(m_srcBall->getPositionX() - halfBallWidth, m_srcBall->getPositionY() - (halfBallHeight * 3), m_srcBall->getContentSize().width, m_srcBall->getContentSize().height); if (downRect.containsPoint(location)) { row--; if (row >= 0) { m_destBall = m_matrix[row * m_width + col]; } m_movingVertical = true; swapBallAndCheck(); return; } auto leftRect = CCRect(m_srcBall->getPositionX() - (halfBallWidth * 3), m_srcBall->getPositionY() - halfBallHeight, m_srcBall->getContentSize().width, m_srcBall->getContentSize().height); if (leftRect.containsPoint(location)) { col--; if (col >= 0) { m_destBall = m_matrix[row * m_width + col]; } m_movingVertical = false; swapBallAndCheck(); return; } auto rightRect = CCRect(m_srcBall->getPositionX() + halfBallWidth, m_srcBall->getPositionY() - halfBallHeight, m_srcBall->getContentSize().width, m_srcBall->getContentSize().height); if (rightRect.containsPoint(location)) { col++; if (col < m_width) { m_destBall = m_matrix[row * m_width + col]; } m_movingVertical = false; swapBallAndCheck(); return; } // not a useful movement } void BallMap::swapBallAndCheck() { m_isAnimationing = true; m_isTouchEnable = false; if (!m_srcBall || !m_destBall) { m_movingVertical = true; return; } CCPoint posOfSrc = m_srcBall->getPosition(); CCPoint posOfDest = m_destBall->getPosition(); float time = 0.2; // 1.swap in matrix this->swapBall(m_srcBall, m_destBall); // 2.check for remove able std::list<BallSprite *> colChainListOfFirst; getColChain(m_srcBall, colChainListOfFirst); std::list<BallSprite *> rowChainListOfFirst; getRowChain(m_srcBall, rowChainListOfFirst); std::list<BallSprite *> colChainListOfSecond; getColChain(m_destBall, colChainListOfSecond); std::list<BallSprite *> rowChainListOfSecond; getRowChain(m_destBall, rowChainListOfSecond); if (colChainListOfFirst.size() >= 3 || rowChainListOfFirst.size() >= 3 || colChainListOfSecond.size() >= 3 || rowChainListOfSecond.size() >= 3) { // just swap m_srcBall->runAction(CCMoveTo::create(time, posOfDest)); m_destBall->runAction(CCMoveTo::create(time, posOfSrc)); return; } // 3.no chain, swap back this->swapBall(m_srcBall, m_destBall); m_srcBall->runAction(CCSequence::create( CCMoveTo::create(time, posOfDest), CCMoveTo::create(time, posOfSrc), NULL)); m_destBall->runAction(CCSequence::create( CCMoveTo::create(time, posOfSrc), CCMoveTo::create(time, posOfDest), NULL)); } */ bool BallMap::swapBall(BallSprite* src, BallSprite* dest) { m_srcBall = src; m_destBall = dest; m_matrix[m_srcBall->getRow() * (int)m_size.width + m_srcBall->getCol()] = m_destBall; m_matrix[m_destBall->getRow() * (int)m_size.width + m_destBall->getCol()] = m_srcBall; int tmpRow = m_srcBall->getRow(); int tmpCol = m_srcBall->getCol(); m_srcBall->setRow(m_destBall->getRow()); m_srcBall->setCol(m_destBall->getCol()); m_destBall->setRow(tmpRow); m_destBall->setCol(tmpCol); // 2.check for remove able std::list<BallSprite *> colChainListOfFirst; this->getColChain(m_srcBall, colChainListOfFirst); std::list<BallSprite *> rowChainListOfFirst; this->getRowChain(m_srcBall, rowChainListOfFirst); std::list<BallSprite *> colChainListOfSecond; this->getColChain(m_destBall, colChainListOfSecond); std::list<BallSprite *> rowChainListOfSecond; this->getRowChain(m_destBall, rowChainListOfSecond); if (colChainListOfFirst.size() >= 3 || rowChainListOfFirst.size() >= 3 || colChainListOfSecond.size() >= 3 || rowChainListOfSecond.size() >= 3) { // just swap BallSprite* ball = NULL; std::list<BallSprite*> longerList; std::list<BallSprite*> newList; if (colChainListOfFirst.size()>=3) { longerList.merge(colChainListOfFirst); } if (rowChainListOfFirst.size()>=3) { longerList.merge(rowChainListOfFirst); } // 4消产生特殊元素 if (longerList.size() > 3) { m_srcBall->setIgnoreCheck(true); m_srcBall->setIsNeedRemove(false); m_srcBall->setDisplayMode(DISPLAY_MODE_FOUR); } if (colChainListOfSecond.size()>=3) { longerList.merge(colChainListOfSecond); newList.merge(colChainListOfSecond); } if (rowChainListOfSecond.size()>=3) { longerList.merge(rowChainListOfSecond); newList.merge(rowChainListOfSecond); } // 4消产生特殊元素 if (newList.size() > 3) { m_destBall->setIgnoreCheck(true); m_destBall->setIsNeedRemove(false); m_destBall->setDisplayMode(DISPLAY_MODE_FOUR); } for (std::list<BallSprite *>::iterator itList = longerList.begin(); itList != longerList.end(); itList++) { ball = dynamic_cast<BallSprite*>(*itList); if (!ball) { continue; } markRemove(ball); } // 3.消除标记了的寿司 if (longerList.size() >=3 ) { m_readyRemoveList = longerList; } ball->runAction(CCSequence::create(CCDelayTime::create(0.2f), CCCallFunc::create(this, callfunc_selector(BallMap::removeBall)), NULL)); return true; } m_matrix[m_srcBall->getRow() * (int)m_size.width + m_srcBall->getCol()] = m_destBall; m_matrix[m_destBall->getRow() * (int)m_size.width + m_destBall->getCol()] = m_srcBall; tmpRow = m_srcBall->getRow(); tmpCol = m_srcBall->getCol(); m_srcBall->setRow(m_destBall->getRow()); m_srcBall->setCol(m_destBall->getCol()); m_destBall->setRow(tmpRow); m_destBall->setCol(tmpCol); return false; }
//全ボールに対してボールの並びをチェックする void GameLayer::checkedBall(BallSprite::PositionIndex current, Direction direction) { //全てのボールのBallTypeを取得 auto allBalls = getAllBalls(); //検索するタグの生成 int tag = BallSprite::generateTag(BallSprite::PositionIndex(current.x, current.y)); BallSprite* ball = allBalls.at(tag); //指定方向のチェック済みフラグを取得 bool checked; if (direction == Direction::x) checked = ball->getCheckedX(); else checked = ball->getCheckedY(); if (!checked) { int num = 0; while (true) { //検索位置を取得 BallSprite::PositionIndex searchPosition; if (direction == Direction::x) searchPosition = BallSprite::PositionIndex(current.x + num, current.y); else searchPosition = BallSprite::PositionIndex(current.x, current.y + num); //次のボールと同じballTypeかチェックする if (isSameBallType(searchPosition, direction)) { //次のボールと同じballType int nextTag = BallSprite::generateTag(searchPosition); auto nextBall = allBalls.at(nextTag); //チェックしたボールのチェック済みフラグを立てる if (direction == Direction::x) nextBall->setCheckedX(true); else nextBall->setCheckedY(true); num++; } else { //次のボールが異なるballType if (num >= 2) { int removedNo = 0; //消去するボールのカウント if (_removeNumbers.size() <= _chainNumber) { //配列が存在しない場合は追加する std::map<BallSprite::BallType, int> removeNumber; _removeNumbers.push_back(removeNumber); } _removeNumbers[_chainNumber][ball->getBallType()] += num + 1; //すでにRemovedNoがあるものが存在するかチェック for (int i = 0; i <= num; i++) { BallSprite::PositionIndex linedPosition; if (direction == Direction::x) linedPosition = BallSprite::PositionIndex(current.x + i, current.y); else linedPosition = BallSprite::PositionIndex(current.x, current.y + i); int linedBallTag = BallSprite::generateTag(linedPosition); auto linedBall = allBalls.at(linedBallTag); if (linedBall->getRemovedNo() > 0) { //すでにRemovedNoがあるものが存在するので、removedNoを取得し次の処理を行う removedNo = linedBall->getRemovedNo(); break; } } //消去する順番のカウントアップ if (removedNo == 0) removedNo = ++_maxRemovedNo; //3個以上並んでいた場合は、reomvedNoをセットする for (int i = 0; i <= num; i++) { BallSprite::PositionIndex linedPosition; if (direction == Direction::x) linedPosition = BallSprite::PositionIndex(current.x + i, current.y); else linedPosition = BallSprite::PositionIndex(current.x, current.y + i); int linedBallTag = BallSprite::generateTag(linedPosition); auto linedBall = allBalls.at(linedBallTag); linedBall->setRemovedNo(removedNo); } } break; } }; //指定方向をチェック済みとする if (direction == Direction::x) ball->setCheckedX(true); else ball->setCheckedY(true); } }
void BallMap::checkAndRemoveChain() { BallSprite *ball; // 1. reset ingnore flag for (int i = 0; i < m_size.height * m_size.width; i++) { ball = m_matrix[i]; if (!ball) { continue; } ball->setIgnoreCheck(false); } // 2. check chain std::list<BallSprite *> longerList; for (int i = 0; i < m_size.height * m_size.width; i++) { ball = m_matrix[i]; if (!ball) { continue; } if (ball->getIsNeedRemove()) { continue;// 已标记过的跳过检查 } if (ball->getIgnoreCheck()) { // continue;// 新变化的特殊寿司,不消除 } // start count chain std::list<BallSprite *> colChainList; getColChain(ball, colChainList); if (colChainList.size() >= 3) { longerList.merge(colChainList); } std::list<BallSprite *> rowChainList; getRowChain(ball, rowChainList); if (rowChainList.size() >= 3) { longerList.merge(rowChainList); } if (longerList.size() < 3) { m_isNeedCheckSelf = false; TwoBallPos towBall = this->selfCheckHaveMore(); if (isPointEqual(towBall.srcPos, towBall.destPos)) { this->removeAllBall(true); } continue;// 小于3个不消除 } std::list<BallSprite *>::iterator itList; // longerList.sort(); //sort the list // longerList.erase( unique( longerList.begin(), longerList.end() ), longerList.end());//Remove duplicate list values for (itList = longerList.begin(); itList != longerList.end(); itList++) { ball = dynamic_cast<BallSprite*>(*itList); if (!ball) { continue; } markRemove(ball); } // 如何是自由掉落产生的4消, 取最后一个变化为特殊寿司 if (longerList.size() > 3) { ball->setIgnoreCheck(true); ball->setIsNeedRemove(false); ball->setDisplayMode(DISPLAY_MODE_FOUR); } } if (longerList.size() >= 3) { m_readyRemoveList = longerList; } // 3.消除标记了的寿司 removeBall(); }
void BallMap::fillVacancies() { // reset moving direction flag // m_movingVertical = true; m_isAnimationing = true; CCSize size = CCDirector::sharedDirector()->getWinSize(); int *colEmptyInfo = (int *)malloc(sizeof(int) * m_size.width); memset((void *)colEmptyInfo, 0, sizeof(int) * m_size.width); // 1. drop exist Ball BallSprite *ball = NULL; for (int col = 0; col < m_size.width; col++) { int removedBallOfCol = 0; // from buttom to top for (int row = 0; row < m_size.height; row++) { ball = m_matrix[row * (int)m_size.width + col]; if (NULL == ball) { removedBallOfCol++; } else { if (removedBallOfCol > 0) { // evey item have its own drop distance int newRow = row - removedBallOfCol; // switch in matrix m_matrix[newRow * (int)m_size.width + col] = ball; m_matrix[row * (int)m_size.width + col] = NULL; // set the new row to item ball->setRow(newRow); // move to new position CCPoint startPosition = ball->getPosition(); CCPoint endPosition = positionOfItem(ball); float speed = (startPosition.y - endPosition.y) / size.height; ball->set_isMoving(true); // ball->stopAllActions();// must stop pre drop action ball->runAction(CCSequence::create( CCMoveTo::create(speed, endPosition), CCCallFuncN::create(this, callfuncN_selector(BallMap::setBallNoMoving)), NULL)); } } } // record empty info colEmptyInfo[col] = removedBallOfCol; } // 2. create new item and drop down. for (int col = 0; col < m_size.width; col++) { for (int row = m_size.height - colEmptyInfo[col]; row < m_size.height; row++) { createAndDropBall(row, col); } } free(colEmptyInfo); colEmptyInfo = NULL; }
TwoBallPos BallMap::selfCheckHaveMore() { TwoBallPos point_ab; point_ab.srcPos = CCPointZero; point_ab.destPos = CCPointZero; // bool flag = false; for (int row = 0; row != m_size.height; ++row) { for (int col = 0; col != m_size.width; ++col) { BallSprite* aSprite = BallOfRC(col, row); if ( aSprite && (aSprite->getDisplayMode() == DISPLAY_MODE_FIVE || aSprite->getDisplayMode() == DISPLAY_MODE_SKILL)) { point_ab.srcPos = ccp(aSprite->getCol(), aSprite->getRow()); } //竖向是否有1 2情况的可移动消除 v 1 2 if (aSprite->getRow() - 1 >= 0) { BallSprite* bSprite = BallOfRC(col, row - 1); if ( bSprite && aSprite->getImgIndex() == bSprite->getImgIndex()) { /* (x, y-2) (x-1, y-1) (x, y-1) (x+1, y-1) (x-1, y ) (x, y ) (x+1, y ) (x-1, y+1) (x, y+1) (x+1, y+1) (x, y+2) */ { BallSprite* cSprite = BallOfRC(col, row + 2); if (cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row+1); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col-1, row+1); if (cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row+1); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+1, row+1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row+1); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col, row-3); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row-2); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col-1, row-2); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row-2); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+1, row-2); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row-2); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } } } //v 1 3 if (aSprite->getRow()-2 >= 0) { BallSprite* bSprite = BallOfRC(col, row-2); if ( bSprite && aSprite->getImgIndex() == bSprite->getImgIndex()) { { BallSprite* cSprite = BallOfRC(col, row+1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row-1); point_ab.srcPos = ccp(bSprite->getCol(), bSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col, row-3); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row-1); point_ab.srcPos = ccp(aSprite->getCol(), aSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col-1, row-1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row-1); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+1, row-1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col, row-1); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } } } // h 1 2 if (aSprite->getCol()+1 < m_size.width) { BallSprite* bSprite = BallOfRC(col+1, row); if ( bSprite && aSprite->getImgIndex() == bSprite->getImgIndex()) { { BallSprite* cSprite = BallOfRC(col-2, row); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col -1, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col-1, row-1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col -1, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col-1, row+1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col -1, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+3, row); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col + 2, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+2, row-1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col + 2, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+2, row+1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col + 2, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } } } //h 13 if (aSprite->getCol()+2 < m_size.width) { BallSprite* bSprite = BallOfRC(col+2, row); if ( bSprite && aSprite->getImgIndex() == bSprite->getImgIndex()) { { BallSprite* cSprite = BallOfRC(col+3, row); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col + 1, row); point_ab.srcPos = ccp(aSprite->getCol(), aSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col-1, row); if (cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col + 1, row); point_ab.srcPos = ccp(bSprite->getCol(), bSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+1, row-1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col + 1, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } { BallSprite* cSprite = BallOfRC(col+1, row+1); if ( cSprite && cSprite->getImgIndex() == aSprite->getImgIndex()) { BallSprite* temp = BallOfRC(col + 1, row); point_ab.srcPos = ccp(cSprite->getCol(), cSprite->getRow()); point_ab.destPos = ccp(temp->getCol(), temp->getRow()); return point_ab; } } } } } } return point_ab; }