void PluginWindow::init(QString element) { GameElement::ElementType elemType; if (element == "white") { elemType = GameElement::TypeWhite; } else { elemType = GameElement::TypeBlack; } // Инициируем модель доски if (bmodel == NULL) { bmodel = new BoardModel(this); connect(bmodel, SIGNAL(changeGameStatus(GameModel::GameStatus)), this, SLOT(changeGameStatus(GameModel::GameStatus))); connect(bmodel, SIGNAL(setupElement(int, int)), this, SLOT(setupElement(int, int))); connect(bmodel, SIGNAL(lose()), this, SLOT(setLose()), Qt::QueuedConnection); connect(bmodel, SIGNAL(draw()), this, SLOT(setDraw()), Qt::QueuedConnection); connect(bmodel, SIGNAL(switchColor()), this, SIGNAL(switchColor())); connect(bmodel, SIGNAL(doPopup(const QString)), this, SIGNAL(doPopup(const QString))); }
bool RogueScene::init() { // 1. super init first if ( !Layer::init() ) { return false; } // 乱数 srand((unsigned int)time(NULL)); // TouchEvent settings auto listener = EventListenerTouchOneByOne::create(); listener->setSwallowTouches(true); listener->onTouchBegan = CC_CALLBACK_2(RogueScene::onTouchBegan, this); listener->onTouchMoved = CC_CALLBACK_2(RogueScene::onTouchMoved, this); listener->onTouchEnded = CC_CALLBACK_2(RogueScene::onTouchEnded, this); // this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this); this->getEventDispatcher()->addEventListenerWithFixedPriority(listener, 1); auto winSize = Director::getInstance()->getWinSize(); // --------------------- // タイルマップを生成 // --------------------- auto pTiledMap = TMXTiledMap::create("tmx/desert.tmx"); pTiledMap->setPosition(Point::ZERO); this->addChild(pTiledMap, RogueScene::zTiledMapIndex, RogueScene::kTiledMapTag); m_baseMapSize = pTiledMap->getMapSize(); m_baseTileSize = pTiledMap->getTileSize(); m_baseContentSize = pTiledMap->getContentSize(); m_mapManager.init(0, (int)m_baseMapSize.height, 0, (int)m_baseMapSize.width); // 使ってなかった // // フロントレイヤー // auto pFrontLayer = Layer::create(); // pTiledMap->addChild(pFrontLayer, // RogueScene::TiledMapIndex::zTiledMapFrontIndex, // RogueScene::TiledMapTag::kTiledMapFrontTag); // エネミーレイヤー auto pEnemyLayer = Layer::create(); pTiledMap->addChild(pEnemyLayer, RogueScene::TiledMapIndex::zTiledMapEnemyBaseIndex, RogueScene::TiledMapTag::kTiledMapEnemyBaseTag); // ドロップアイテムレイヤー auto pDropItemLayer = Layer::create(); pTiledMap->addChild(pDropItemLayer, RogueScene::TiledMapIndex::zTiledMapDropItemBaseIndex, RogueScene::TiledMapTag::kTiledMapDropItemBaseTag); // 障害物をmapManagerに適応する auto pColisionLayer = pTiledMap->getLayer("colision"); for (int x = 0; x < m_baseMapSize.width; x++) { for (int y = 0; y < m_baseMapSize.height; y++) { if (pColisionLayer->getTileAt(Point(x, y))) { MapIndex mapIndex = {x, y, MoveDirectionType::MOVE_NONE}; auto tileMapIndex = mapIndexToTileIndex(mapIndex); m_mapManager.addObstacle(&tileMapIndex); } } } // --------------------- // グリッド線を生成 // --------------------- auto draw = DrawNode::create(); draw->setPosition(Point::ZERO); // 線の太さと色 float lineSize = 1 * 0.5; Color4F color = Color4F::MAGENTA; // 縦線を引く for (int x = 1; x < m_baseMapSize.width; x++) { float xPoint = x * m_baseTileSize.width; draw->drawSegment(Point(xPoint, 0), Point(xPoint, m_baseContentSize.height), lineSize, color); } // 横線を引く for (int y = 1; y < m_baseMapSize.height; y++) { float yPoint = y * m_baseTileSize.height; draw->drawSegment(Point(0, yPoint), Point(m_baseContentSize.width, yPoint), lineSize, color); } // マップに追加 pTiledMap->addChild(draw, RogueScene::TiledMapIndex::zGridLineIndex, RogueScene::TiledMapTag::kGridLineTag); //------------------------- // ステータスバー? //------------------------- auto statusLayer = LayerColor::create(Color4B::BLACK); statusLayer->setContentSize(Size(winSize.width, m_baseTileSize.height * 0.8)); statusLayer->setPosition(Point(0, winSize.height - statusLayer->getContentSize().height)); // TODO: あとで更新する auto sampleText = LabelTTF::create(" --F Lv-- HP ---/--- 満腹度 ---/--- - G", GAME_FONT(16), 16); sampleText->setPosition(Point(sampleText->getContentSize().width / 2, statusLayer->getContentSize().height / 2)); statusLayer->addChild(sampleText); this->addChild(statusLayer, RogueScene::zStatusBarIndex, RogueScene::kStatusBarTag); // // 下のステータスバー2 // auto pStatusLayer2 = LayerColor::create(Color4B::BLACK); // pStatusLayer2->setContentSize(Size(m_baseTileSize.width, m_baseTileSize.height)); // pStatusLayer2->setPosition(Point(0, 0)); // // // TODO: アイコン表示するかな(ステータスバー2?) // auto pFaceSprite = Sprite::createWithSpriteFrame(SpriteFrame::create("actor_4_f.png", Rect(0, 0, 96, 96))); // float scale = 1.0f / 3.0f; // pFaceSprite->setScale(scale, scale); // // pFaceSprite->setContentSize(pFaceSprite->getContentSize() * scale); // // CCLOG("getContentSize (%f, %f) ", pFaceSprite->getContentSize().width, pFaceSprite->getContentSize().height); // // pFaceSprite->setPosition(Point(pFaceSprite->getContentSize().width / 2, pFaceSprite->getContentSize().height / 2)); // pFaceSprite->setPosition(Point(pFaceSprite->getContentSize().width * pFaceSprite->getScaleX() / 2, pFaceSprite->getContentSize().height * pFaceSprite->getScaleY() / 2)); // pStatusLayer2->addChild(pFaceSprite); // // this->addChild(pStatusLayer2, RogueScene::zStatusBar2Index, RogueScene::kStatusBar2Tag); //------------------------- // ゲームログ表示 //------------------------- // float startWidth = pFaceSprite->getContentSize().width * pFaceSprite->getScaleX(); auto pGameLogLayer = LayerColor::create(Color4B(0, 0, 0, 192)); pGameLogLayer->setContentSize(Size(winSize.width * 0.8, m_baseTileSize.height * 1.5)); pGameLogLayer->setPosition(winSize.width / 2 - pGameLogLayer->getContentSize().width / 2, 0); int baseFontSize = 10; auto pLogTextLabel = LabelTTF::create("", GAME_FONT(baseFontSize), baseFontSize, Size::ZERO, TextHAlignment::LEFT, TextVAlignment::TOP); pLogTextLabel->setPosition(Point(pLogTextLabel->getContentSize().width / 2 + pLogTextLabel->getFontSize() / 4, pGameLogLayer->getContentSize().height - pLogTextLabel->getContentSize().height / 2 - pLogTextLabel->getFontSize() / 4)); pGameLogLayer->addChild(pLogTextLabel); this->addChild(pGameLogLayer, RogueScene::zGameLogIndex, RogueScene::kGameLogTag); // ------------------------ // ミニマップ // ------------------------ // 青で半透明 auto miniMapLayer = LayerColor::create(Color4B(0, 0, 196, 128)); // 1/8サイズ miniMapLayer->setContentSize(Size(m_baseMapSize.width * m_baseTileSize.width / 8, m_baseMapSize.height * m_baseTileSize.height / 8)); // ステータスバーの下くらい miniMapLayer->setPosition(0, miniMapLayer->getPositionY() + winSize.height - miniMapLayer->getContentSize().height - statusLayer->getContentSize().height); this->addChild(miniMapLayer, RogueScene::zMiniMapIndex, RogueScene::kMiniMapTag); // ------------------------ // イベントリ作成 // ------------------------ showItemList(1); hideItemList(); // --------------------- // プレイヤー生成 // --------------------- ActorSprite::ActorDto actorDto; actorDto.name = "ジニー"; actorDto.faceImgId = 0; actorDto.imageResId = 1015; // 基本 actorDto.attackRange = 1; actorDto.movePoint = 5; actorDto.playerId = 4; // 攻守 actorDto.attackPoint = 5; actorDto.defencePoint = 1; // 経験値 actorDto.exp = 0; actorDto.nextExp = 10; // HP actorDto.hitPoint = 15; actorDto.hitPointLimit = 15; actorDto.lv = 1; // 満腹度?精神力? actorDto.magicPoint = 100; actorDto.magicPointLimit = 100; ActorMapItem actorMapItem; actorMapItem.mapDataType = MapDataType::PLAYER; // 画面の中心(固定) actorMapItem.mapIndex = pointToIndex(Point(winSize.width/2, winSize.height/2)); actorMapItem.seqNo = 1; actorMapItem.moveDist = actorDto.movePoint; actorMapItem.attackDist = actorDto.attackRange; actorMapItem.moveDone = false; actorMapItem.attackDone = false; auto actorSprite = ActorSprite::createWithActorDto(actorDto); actorSprite->setPosition(indexToPoint(actorMapItem.mapIndex)); // 画面の中心 actorSprite->setActorMapItem(actorMapItem); actorSprite->runBottomAction(); // プレイヤーは画面中心にくるのでmapLayerに追加しない this->addChild(actorSprite, RogueScene::zActorBaseIndex, (RogueScene::kActorBaseTag + actorMapItem.seqNo)); // マップに追加 m_mapManager.addActor(actorSprite->getActorMapItem()); refreshStatus(); // プレイヤーの位置表示用(同じく1/8サイズ) auto miniMapActorLayer = LayerColor::create(Color4B::YELLOW); // タイルの1/8サイズ miniMapActorLayer->setContentSize(m_baseTileSize / 8); // 現在位置からPositionを取得して1/8にする miniMapActorLayer->setPosition(indexToPointNotTileSize(actorSprite->getActorMapItem()->mapIndex) / 8); // 移動時に更新できるようにplayerIdをtag管理 miniMapActorLayer->setTag(actorSprite->getTag()); // add miniMapLayer->addChild(miniMapActorLayer); // --------------------- // 敵キャラ生成 // --------------------- ActorSprite::ActorDto enemyDto; enemyDto.name = "スライム"; enemyDto.faceImgId = 0; enemyDto.imageResId = 1011; // 基本 enemyDto.attackRange = 1; // TODO: 未使用 enemyDto.movePoint = 10; // 索敵範囲 enemyDto.playerId = 901; // 攻守 enemyDto.attackPoint = 2; enemyDto.defencePoint = 0; // 経験値 enemyDto.exp = 0; enemyDto.nextExp = 10; // HP enemyDto.hitPoint = 10; enemyDto.hitPointLimit = 10; enemyDto.lv = 1; // 満腹度?精神力? enemyDto.magicPoint = 100; enemyDto.magicPointLimit = 100; MapIndex enemyMapIndex1 = {4, 4, MoveDirectionType::MOVE_DOWN}; tileSetEnemyActorMapItem(enemyDto, enemyMapIndex1); ActorSprite::ActorDto enemyDto2 = enemyDto; MapIndex enemyMapIndex2 = {14,12, MoveDirectionType::MOVE_DOWN}; tileSetEnemyActorMapItem(enemyDto2, enemyMapIndex2); ActorSprite::ActorDto enemyDto3 = enemyDto; MapIndex enemyMapIndex3 = {20,4, MoveDirectionType::MOVE_DOWN}; tileSetEnemyActorMapItem(enemyDto3, enemyMapIndex3); //------------------------- // アイテム配置 //------------------------- DropItemSprite::DropItemDto dropItemDto; dropItemDto.itemId = 1; dropItemDto.imageResId = 64; // imageId 10064 dropItemDto.name = "ポーション"; MapIndex mapIndex = {7, 5, MoveDirectionType::MOVE_NONE}; tileSetDropMapItem(dropItemDto, mapIndex); DropItemSprite::DropItemDto dropItemDto2; dropItemDto2.itemId = 2; dropItemDto2.imageResId = 168; // imageId 10168 dropItemDto2.name = "ぶどう"; MapIndex mapIndex2 = {10, 9, MoveDirectionType::MOVE_NONE}; tileSetDropMapItem(dropItemDto2, mapIndex2); // ------------------------------- // メニュー // ------------------------------- auto rect = Rect(0, 0, 300, 30); auto capRect = Rect(0, 0, 300, 30); auto pScale9Sprite1 = extension::Scale9Sprite::create("menu_button.png", rect, capRect); pScale9Sprite1->setContentSize(Size(40, 20)); pScale9Sprite1->setOpacity(192); auto pScale9Sprite2 = extension::Scale9Sprite::create("menu_button.png", rect, capRect); pScale9Sprite2->setContentSize(Size(40, 20)); pScale9Sprite2->setOpacity(128); auto pMenuItem1 = MenuItemSprite::create(pScale9Sprite1, pScale9Sprite2, [this](Object *pSender) { CCLOG("menuItem1が押された!"); showItemList(1); }); pMenuItem1->setColor(Color3B::GREEN); pMenuItem1->setPosition(Point(winSize.width - pMenuItem1->getContentSize().width / 2, pMenuItem1->getContentSize().height / 2)); auto pMenu = Menu::create(pMenuItem1, NULL); pMenu->setPosition(Point::ZERO); this->addChild(pMenu, RogueScene::zMenuIndex, RogueScene::kMenuTag); // --------------------------------- // プレイヤーの先行 changeGameStatus(GameStatus::PLAYER_TURN); return true; }
void RogueScene::touchEventExec(cocos2d::Point touchPoint) { auto pMapLayer = (TMXTiledMap*)getChildByTag(kTiledMapTag); // マップ移動分を考慮 MapIndex touchPointMapIndex = touchPointToIndex(touchPoint - pMapLayer->getPosition()); CCLOG("onTouchBegan touchPointMapIndex x = %d y = %d", touchPointMapIndex.x, touchPointMapIndex.y); // 画面外判定 if (isMapLayerOver(touchPointMapIndex)) { // タッチ判定とみなさない return; } // タッチした位置が有効なIndexか判定 MapIndex addMoveIndex = checkTouchEventIndex(touchPointMapIndex); if (addMoveIndex.x == 0 && addMoveIndex.y == 0) { // タッチ判定とみなさない return; } // キャラの向きを変更 auto pActorSprite = getPlayerActorSprite(1); pActorSprite->runMoveAction(addMoveIndex); // 敵をタッチした auto pEnemyMapItem = m_mapManager.getActorMapItem(&touchPointMapIndex); if (pEnemyMapItem->mapDataType == MapDataType::ENEMY) { auto pPlayerDto = pActorSprite->getActorDto(); auto pEnemyDto = getEnemyActorSprite(pEnemyMapItem->seqNo)->getActorDto(); int damage = BattleLogic::exec(pPlayerDto, pEnemyDto); // 攻撃イベント logMessage("%sの攻撃: %sに%dのダメージ", pPlayerDto->name.c_str(), pEnemyDto->name.c_str(), damage); } else { // 障害物判定 if (isTiledMapColisionLayer(touchPointMapIndex)) { // TODO: ぶつかるSE再生 logMessage("壁ドーン"); } else { changeGameStatus(GameStatus::PLAYER_ACTION); // アイテムに重なったときの拾う処理 auto pTouchPointMapItem = m_mapManager.getMapItem(&touchPointMapIndex); if (pTouchPointMapItem->mapDataType == MapDataType::MAP_ITEM) { // ドロップアイテムを拾う auto pDropMapItem = (DropMapItem*) pTouchPointMapItem; // TODO: 拾うSE再生 // itemを取得 auto pDropItemLayer = getChildByTag(RogueScene::kTiledMapTag)->getChildByTag(RogueScene::TiledMapTag::kTiledMapDropItemBaseTag); auto pDropItemSprite = (DropItemSprite*) pDropItemLayer->getChildByTag(RogueScene::TiledMapTag::kTiledMapDropItemBaseTag + pDropMapItem->seqNo); // メッセージログ auto pDropItemDto = pDropItemSprite->getDropItemDto(); logMessage("%sを拾った。", pDropItemDto->name.c_str()); // イベントリに追加する getItemWindowLayer()->addItemList(pDropItemDto); // mapManagerから消す m_mapManager.removeMapItem(pDropMapItem); // ミニマップを更新 auto pMiniMapLayer = getChildByTag(kMiniMapTag); pMiniMapLayer->removeChildByTag(pDropItemSprite->getTag()); // Map上からremoveする pDropItemLayer->removeChild(pDropItemSprite); } // 移動処理 moveMap(addMoveIndex, pActorSprite->getActorMapItem()->seqNo, pActorSprite->getActorMapItem()->mapDataType, CallFunc::create([this](void) { changeGameStatus(GameStatus::ENEMY_TURN); })); // コールバックまでgameStatusを更新はしない return; } } // TODO: 会話 // 会話イベント // ターン終了 changeGameStatus(GameStatus::ENEMY_TURN); }
void RogueScene::enemyTurn() { // モンスターの数だけ繰り返す std::list<ActorMapItem> enemyList = m_mapManager.findEnemyMapItem(); for (ActorMapItem enemyMapItem : enemyList) { // ランダムでとどまるか移動するかきめる int rand = GetRandom(2, 2); if (rand == 1) { auto pEnemySprite = getEnemyActorSprite(enemyMapItem.seqNo); pEnemySprite->getActorMapItem()->moveDone = true; // とどまる logMessage("様子を見ている seqNo = %d", enemyMapItem.seqNo); } else if (rand == 2) { // プレイヤーに向かって移動 or プレイヤーに攻撃 auto pPlayerActorSprite = getPlayerActorSprite(1); // プレイヤーの周辺で最もコストが低い箇所へ移動 auto playerMapIndex = pPlayerActorSprite->getActorMapItem()->mapIndex; std::list<MapIndex> searchMapIndexList; searchMapIndexList.clear(); // 右 MapIndex searchMapIndex = playerMapIndex; searchMapIndex.x += 1; searchMapIndex.y += 0; searchMapIndex.moveDictType = MoveDirectionType::MOVE_LEFT; searchMapIndexList.push_back(searchMapIndex); // 左 searchMapIndex = playerMapIndex; searchMapIndex.x += -1; searchMapIndex.y += 0; searchMapIndex.moveDictType = MoveDirectionType::MOVE_RIGHT; searchMapIndexList.push_back(searchMapIndex); // 上 searchMapIndex = playerMapIndex; searchMapIndex.x += 0; searchMapIndex.y += 1; searchMapIndex.moveDictType = MoveDirectionType::MOVE_DOWN; searchMapIndexList.push_back(searchMapIndex); // 下 searchMapIndex = playerMapIndex; searchMapIndex.x += 0; searchMapIndex.y += -1; searchMapIndex.moveDictType = MoveDirectionType::MOVE_UP; searchMapIndexList.push_back(searchMapIndex); // そもそもプレイヤーが隣接しているかチェック bool isPlayerAttack = false; { for (MapIndex mapIndex : searchMapIndexList) { if (MAP_INDEX_DIFF(enemyMapItem.mapIndex, mapIndex)) { isPlayerAttack = true; } } } MapIndex moveMapIndex = enemyMapItem.mapIndex; if (isPlayerAttack) { // 攻撃 moveMapIndex =pPlayerActorSprite->getActorMapItem()->mapIndex; } else { // 移動可能な経路情報を設定 m_mapManager.createActorFindDist(enemyMapItem.mapIndex, enemyMapItem.moveDist); // 最も移動コストがかからない場所を抽出 MapItem targetMoveDistMapItem = m_mapManager.searchTargetMapItem(searchMapIndexList); // 移動リスト作成 if (targetMoveDistMapItem.mapDataType == MapDataType::MOVE_DIST) { std::list<MapIndex> moveList = m_mapManager.createMovePointList(&targetMoveDistMapItem.mapIndex, &enemyMapItem); std::list<MapIndex>::iterator it = moveList.begin(); it++; moveMapIndex = *it; // 2件目を取得(1件目は自分なので) it = moveList.end(); } } // 移動有無関係なく向きは変える auto pEnemySprite = getEnemyActorSprite(enemyMapItem.seqNo); MapIndex addMoveIndex = { moveMapIndex.x - pEnemySprite->getActorMapItem()->mapIndex.x, moveMapIndex.y - pEnemySprite->getActorMapItem()->mapIndex.y, m_mapManager.checkMoveDirectionType(moveMapIndex, pEnemySprite->getActorMapItem()->mapIndex) }; pEnemySprite->runMoveAction(addMoveIndex); // 行動前にする pEnemySprite->getActorMapItem()->moveDone = false; pEnemySprite->getActorMapItem()->attackDone = false; if (isMapLayerOver(moveMapIndex)) { CCLOG("移動不可 seqNo = %d (%d, %d)", enemyMapItem.seqNo, moveMapIndex.x, moveMapIndex.y); pEnemySprite->getActorMapItem()->moveDone = true; } else if (isTiledMapColisionLayer(moveMapIndex)) { logMessage("壁ドーン seqNo = %d (%d, %d)", enemyMapItem.seqNo, moveMapIndex.x, moveMapIndex.y); pEnemySprite->getActorMapItem()->moveDone = true; } else if (m_mapManager.getActorMapItem(&moveMapIndex)->mapDataType == MapDataType::ENEMY) { if (MAP_INDEX_DIFF(enemyMapItem.mapIndex, moveMapIndex)) { //logMessage("待機 seqNo = %d (%d, %d)"); } else { logMessage("敵ドーン seqNo = %d (%d, %d)", enemyMapItem.seqNo, moveMapIndex.x, moveMapIndex.y); } pEnemySprite->getActorMapItem()->moveDone = true; } else if (m_mapManager.getActorMapItem(&moveMapIndex)->mapDataType == MapDataType::PLAYER) { auto pPlayerDto = pPlayerActorSprite->getActorDto(); auto pEnemyDto = pEnemySprite->getActorDto(); int damage = BattleLogic::exec(pEnemyDto, pPlayerDto); // 攻撃イベント logMessage("%sの攻撃: %sに%dダメージ", pEnemyDto->name.c_str(), pPlayerDto->name.c_str(), damage); pEnemySprite->getActorMapItem()->attackDone = true; } else { // 移動中のステータスへ changeGameStatus(GameStatus::ENEMY_ACTION); // 移動開始 moveMap(addMoveIndex, enemyMapItem.seqNo, enemyMapItem.mapDataType, CallFuncN::create([this, pEnemySprite](Object* pObj) { // 移動終わり次のモンスターへいきたいところ // listをメンバ変数で持っちゃえばいけるか? auto pEnemySprite = static_cast<ActorSprite*>(pObj); pEnemySprite->getActorMapItem()->moveDone = true; bool isTurnEnd = true; std::list<ActorMapItem> enemyList = m_mapManager.findEnemyMapItem(); for (ActorMapItem enemyMapItem : enemyList) { auto pEnemySprite = getEnemyActorSprite(enemyMapItem.seqNo); auto pEnemyMapItem = pEnemySprite->getActorMapItem(); if (!pEnemyMapItem->moveDone && !pEnemyMapItem->attackDone) { isTurnEnd = false; break; } } if (isTurnEnd) { changeGameStatus(GameStatus::PLAYER_TURN); } else { changeGameStatus(GameStatus::ENEMY_TURN); } })); } } } // 留まった時とかはここでターン終了 if (m_gameStatus != GameStatus::ENEMY_ACTION) { changeGameStatus(GameStatus::PLAYER_TURN); } bool isTurnEnd = true; for (ActorMapItem enemyMapItem : enemyList) { auto pEnemySprite = getEnemyActorSprite(enemyMapItem.seqNo); auto pEnemyMapItem = pEnemySprite->getActorMapItem(); if (!pEnemyMapItem->moveDone && !pEnemyMapItem->attackDone) { isTurnEnd = false; break; } } }