マインスイーパー その4
前回はコンソールで作りましたが今回はGUI版を作りました!
・概要
GUIで遊べるようにCocos2d-x(v2.2.5)を使用.
cocos2d-xでプロジェクトを作成した後に
GameScene.hとGameScene.cppと画像データ1~8.pngとbackground.pngを用意するのみ.
ミニドット絵メーカー
・感想
大体2〜3日で作りました.合計時間は10時間ほど.
コンソールバージョンを作っていたので作りやすかったです.
なので作成のほとんどはCocos2d-xの使い方を調べてたような気がします.
今回のゲームにフラグとかリトライとかゲームオーバーの画面とか難易度とか細かい点を改良できます.
が,それは気が向いたときに行うとして!すこし違うジャンルでゲームを作りたいと思います.
・ソースコード
余り褒められたソースではないですがどうぞ.
GameScene.h
#ifndef __Minesweeper__GameScene__ #define __Minesweeper__GameScene__ #include "cocos2d.h" class GameScene : public cocos2d::CCLayer{ public: // 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(); // a selector callback void menuCloseCallback(CCObject* pSender); // implement the "static node()" method manually CREATE_FUNC(GameScene); /********************************** my define *********************************/ private: const int DEBUG = 1; void makeBackground(const char* path); void initPanels(int width, int height); void makePanels(); //パネルをオープンする cocos2d::CCSprite* openPanel(cocos2d::CCSprite* target); //縦横に爆弾がなければ自動でオープンにする. void openPanelAuto(cocos2d::CCSprite* target); //隣接するにいくつの爆弾があるかを数える int searchBomb(cocos2d::CCSprite* target); //数字をパネルに追加する void setNumber(cocos2d::CCSprite* target); //ボムであるのか調べる bool isBomb(cocos2d::CCSprite* target); //ゲームオーバーを表示する void makeGameOver(cocos2d::CCSprite* target); cocos2d::CCArray* m_panels; cocos2d::CCLabelTTF* pLabel; int m_width = 30, m_height = 20; const int maxBomb = 200; enum{ kTagText, kTagClose, kTagOpen, kTagBomb, }; public: virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent); virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent); }; #endif /* defined(__Minesweeper__GameScene__) */
GameScene.cpp
#include "GameScene.h" #include "time.h" USING_NS_CC; CCScene* GameScene::scene() { // 'scene' is an autorelease object CCScene *scene = CCScene::create(); // 'layer' is an autorelease object GameScene *layer = GameScene::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool GameScene::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(GameScene::menuCloseCallback)); pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 , origin.y + pCloseItem->getContentSize().height/2)); // create menu, it's an autorelease object CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu, 1); ///////////////////////////// // 3. add your codes below... // add a label shows "Hello World" // create and initialize a label pLabel = CCLabelTTF::create("ゲームスタート!!", "Arial", 24); // position the label on the center of the screen pLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height)); pLabel->setTag(kTagText); // add the label as a child to this layer this->addChild(pLabel, 1); // add "HelloWorld" splash screen" // CCSprite* pSprite = CCSprite::create("background.png"); // position the sprite on the center of the screen // pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); // add the sprite as a child to this layer // this->addChild(pSprite, 0); srand((unsigned)time(NULL)); m_panels = new CCArray; // 背景を表示する makeBackground("background.png"); CCLOG("initPanels"); // パネルを初期化する initPanels(m_width, m_height); // パネルを表示する makePanels(); setTouchEnabled(true); setTouchMode(kCCTouchesOneByOne); return true; } void GameScene::menuCloseCallback(CCObject* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); #else CCDirector::sharedDirector()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif #endif } void GameScene::makeBackground(const char* path) { CCSize winSize = CCDirector::sharedDirector()->getWinSize(); CCSprite* bg = CCSprite::create(path); CCSize bgSize = bg->getContentSize(); bg->setScale(winSize.width / bgSize.width); bg->setPosition(ccp(winSize.width * 0.5, winSize.height * 0.5)); this->addChild(bg); } void GameScene::makePanels() { CCObject* it = NULL; CCARRAY_FOREACH(m_panels, it) { CCSprite* target = (CCSprite*)it; this->addChild(target); } } bool GameScene::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent){ return true; } void GameScene:: ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent) { CCDirector* pDirector = CCDirector::sharedDirector(); CCPoint touchPoint = pDirector->convertToGL(pTouch->getLocationInView()); // タッチしたパネルを調べて,オープンにする CCObject* it = NULL; CCARRAY_FOREACH(m_panels, it) { CCSprite* target = dynamic_cast<CCSprite*>(it); CCRect panelRect = CCRectMake( target->getPosition().x - (target->getContentSize().width / 2), target->getPosition().y - (target->getContentSize().height / 2), target->getContentSize().width , target->getContentSize().height ); //パネルをめくる if (panelRect.containsPoint(touchPoint)) { //爆弾だった場合はゲームオーバーを表示 if(isBomb(target)) makeGameOver(target); else{ openPanel(target); openPanelAuto(target); } } } } bool GameScene::isBomb(cocos2d::CCSprite *target) { return (target->getTag() == kTagBomb) ? true : false; } void GameScene::makeGameOver(cocos2d::CCSprite* target) { //ゲームオーバー pLabel->setString("GameOver"); //bombパネルを作成 CCSprite* panel = CCSprite::create("bomb.png"); CCSize panelSize = target->getContentSize(); CCPoint panelPoint = target->getPosition(); panel->setPosition(ccp(panelSize.width / 2, panelSize.height / 2)); (openPanel(target))->addChild(panel); } cocos2d::CCSprite* GameScene::openPanel(cocos2d::CCSprite* target){ CCSprite* frontPanel = CCSprite::create("front_panel.png"); frontPanel->setPosition(target->getPosition()); this->addChild(frontPanel); // 八方向のボムの個数を調べて画像を用意する int bNum = searchBomb(target); if (bNum > 0 && bNum < 9){ CCString* fileName = CCString::createWithFormat("%d.png", bNum); CCSprite* bNumber = CCSprite::create(fileName->getCString()); bNumber->setPosition(ccp(frontPanel->getContentSize().width / 2, frontPanel->getContentSize().height / 2)); frontPanel->addChild(bNumber); } return frontPanel; } void GameScene::initPanels(int width, int height) { m_width = width; m_height = height; CCDirector* pDirector = CCDirector::sharedDirector(); CCSize winSize = pDirector->getWinSize(); // width x heightパネルを作って表示する. for (int y = 0; y < m_height; y++) { for (int x = 0; x < m_width; x++) { CCSprite* panel = CCSprite::create("back_panel.png"); CCSize conSize = panel->getContentSize(); panel->setPosition(ccp((winSize.width / 2) + (conSize.width * (x - (m_width / 2))) , (winSize.height/ 2) + (conSize.height * (y - (m_height) / 2)))); panel->setTag(kTagClose); m_panels->addObject(panel); } } // 爆弾をセットする. for (int n = 0; n < maxBomb; n++) { CCSprite* object = (CCSprite*)m_panels->randomObject(); if( object->getTag() == kTagClose) object->setTag(kTagBomb); else n--; } } void GameScene::openPanelAuto(cocos2d::CCSprite *target) { CCPoint targetPoint = target->getPosition(); CCSize targetSize = target->getContentSize(); targetPoint.setPoint(targetPoint.x , targetPoint.y ); CCObject* it = NULL; //targetの上のパネルをオープン CCRect targetRect = CCRectMake( targetPoint.x - (targetSize.width / 2), targetPoint.y - (targetSize.height / 2) + targetSize.height, targetSize.width , targetSize.height ); CCARRAY_FOREACH(m_panels, it) { CCSprite* nTarget = dynamic_cast<CCSprite*>(it); CCPoint nTargetPoint = nTarget->getPosition(); nTargetPoint.setPoint(nTargetPoint.x , nTargetPoint.y); if (nTarget->getTag() == kTagClose){ if (targetRect.containsPoint(nTargetPoint)) { nTarget->setTag(kTagOpen); openPanel(nTarget); openPanelAuto(nTarget); } } } //targetの左のパネルをオープン targetRect = CCRectMake( targetPoint.x - (targetSize.width / 2) - targetSize.width, targetPoint.y - (targetSize.height / 2), targetSize.width , targetSize.height ); CCARRAY_FOREACH(m_panels, it) { CCSprite* nTarget = dynamic_cast<CCSprite*>(it); CCPoint nTargetPoint = nTarget->getPosition(); nTargetPoint.setPoint(nTargetPoint.x , nTargetPoint.y); if (nTarget->getTag() == kTagClose){ if (targetRect.containsPoint(nTargetPoint)) { nTarget->setTag(kTagOpen); openPanel(nTarget); openPanelAuto(nTarget); } } } //targetの右のパネルをオープン targetRect = CCRectMake( targetPoint.x - (targetSize.width / 2) + targetSize.width, targetPoint.y - (targetSize.height / 2), targetSize.width , targetSize.height ); CCARRAY_FOREACH(m_panels, it) { CCSprite* nTarget = dynamic_cast<CCSprite*>(it); CCPoint nTargetPoint = nTarget->getPosition(); nTargetPoint.setPoint(nTargetPoint.x , nTargetPoint.y); if (nTarget->getTag() == kTagClose){ if (targetRect.containsPoint(nTargetPoint)) { nTarget->setTag(kTagOpen); openPanel(nTarget); openPanelAuto(nTarget); } } } //targetの下のパネルをオープン targetRect = CCRectMake( targetPoint.x - (targetSize.width / 2) , targetPoint.y - (targetSize.height / 2) - targetSize.height, targetSize.width , targetSize.height ); CCARRAY_FOREACH(m_panels, it) { CCSprite* nTarget = dynamic_cast<CCSprite*>(it); CCPoint nTargetPoint = nTarget->getPosition(); nTargetPoint.setPoint(nTargetPoint.x , nTargetPoint.y); if (nTarget->getTag() == kTagClose){ if (targetRect.containsPoint(nTargetPoint)) { nTarget->setTag(kTagOpen); openPanel(nTarget); openPanelAuto(nTarget); } } } } int GameScene::searchBomb(cocos2d::CCSprite *target) { CCPoint targetPoint = target->getPosition(); CCSize targetSize = target->getContentSize(); CCObject* it = NULL; //targetの周りにいくつの爆弾があるのか調べる int num = 0; for (int y = -1; y <= 1; y++) { for (int x = -1; x <= 1; x++) { CCPoint nTargetPoint = target->getPosition(); nTargetPoint.setPoint(nTargetPoint.x + (targetSize.width * x), nTargetPoint.y + (targetSize.height * y)); CCARRAY_FOREACH(m_panels, it){ CCSprite* lTarget = dynamic_cast<CCSprite*>(it); CCRect rec = CCRectMake(lTarget->getPosition().x - (targetSize.width / 2), lTarget->getPosition().y - (targetSize.height / 2), targetSize.width, targetSize.height); if (rec.containsPoint(nTargetPoint)) { if(isBomb(lTarget)) num++; } } } } return num; }