TEST_F(TestBufferQueue, testStateTransitionEmptyQueue) { static const SLuint32 newStates[] = { SL_PLAYSTATE_PAUSED, // paused -> paused SL_PLAYSTATE_STOPPED, // paused -> stopped SL_PLAYSTATE_PAUSED, // stopped -> paused SL_PLAYSTATE_PLAYING, // paused -> playing SL_PLAYSTATE_PLAYING, // playing -> playing SL_PLAYSTATE_STOPPED, // playing -> stopped SL_PLAYSTATE_STOPPED, // stopped -> stopped SL_PLAYSTATE_PLAYING, // stopped -> playing SL_PLAYSTATE_PAUSED // playing -> paused }; for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { SLuint32 numBuffers = validNumBuffers[i]; SLuint32 j; PrepareValidBuffer(numBuffers); /* Set initial state to paused*/ SetPlayerState(SL_PLAYSTATE_PAUSED); for (j = 0; j < sizeof(newStates) / sizeof(newStates[0]); ++j) { SetPlayerState(newStates[j]); CheckBufferCount((SLuint32) 0, (SLuint32) 0); } DestroyPlayer(); } }
void CShop::OnPlayerSellMsg( CMessage *pMsg, const CGUID &npcID ) { CPlayer *pPlayer = pMsg->GetPlayer(); if( pPlayer == NULL ) { return ; } CCachedSellData::SellGoodsListT goods_list; long lCount = pMsg->GetLong(); bool bPriceChanged = false; if( lCount <= 0 ) { // invalid operation PutoutLog( LOG_FILE, LT_WARNING, "Player [%s] No goods to sell, ignore this operation.", pPlayer->GetName() ); return ; } // 取出出售物品信息,判断收购价格是否变动 for( long i = 0; i < lCount; ++ i ) { // 取出物品 CCachedSellData::GoodsInfo info; info.index = pMsg->GetLong(); info.amount = pMsg->GetLong(); info.price = pMsg->GetLong(); goods_list.push_back( info ); // 价格是否变动 if( !bPriceChanged ) { bPriceChanged = IsPriceChanged( info.index, info.price ); } } // 价格已经变化,缓存出售数据,等待玩家确认 if( bPriceChanged ) { CCachedSellData::SellGoodsListT *cachedSellList = m_CachedSellData.New( pPlayer->GetExID() ); for( size_t i = 0; i < goods_list.size(); ++ i ) { CCachedSellData::GoodsInfo info = goods_list[i]; info.price = GetBuyPrice( info.index ); cachedSellList->push_back( info ); } SetPlayerState( pPlayer, false ); CMessage msg( MSG_S2C_FBUSINESS_OPER ); msg.Add( (BYTE) S2C_PRICE_CHANGED ); msg.Add( npcID ); msg.Add( m_lID ); msg.SendToPlayer( pPlayer->GetExID(), false ); return ; } DoPlayerSell( pPlayer, goods_list ); }
/* ================================================ */ void GamePlayer::EventUpdate( Common::CMN_EVENT &eventId ) { switch( eventId.m_event ){ case Common::EVENT_HIT_ENEMY_SLIME: case Common::EVENT_HIT_ENEMY_SLIME_ANOTHER: case Common::EVENT_HIT_ENEMY_AHRIMAN: case Common::EVENT_HIT_ENEMY_COW: case Common::EVENT_HIT_ENEMY_BOSS: case Common::EVENT_HIT_ENEMY_SLIME_KING: case Common::EVENT_HIT_ENEMY_WIZARD: case Common::EVENT_HIT_WIZARD_CRYSTAL: case Common::EVENT_HIT_DRAGON: case Common::EVENT_HIT_BULLET_ENEMY: case Common::EVENT_HIT_BLADE_ENEMY: case Common::EVENT_HIT_EXPLOSION_ENEMY: case Common::EVENT_HIT_FIRE_BALL: case Common::EVENT_HIT_FIRE: case Common::EVENT_HIT_BOSS: case Common::EVENT_HIT_BOSS_LEFT: case Common::EVENT_HIT_BOSS_RIGHT: EventDamage( eventId ); break; case Common::EVENT_GET_ITEM_BULLET: PlayerGetItem( Common::ITEM_KIND_RAPID_BULLET ); break; case Common::EVENT_HIT_POISON: if( m_poisonTime >= 0 ){ // 毒ダメージ m_poisonTime = 60 * 5; if( !IsPlayerState( ABNORMAL_STATE_POISON ) ){ // ステータス変更とSEを鳴らす SetPlayerState( ABNORMAL_STATE_POISON, true ); SoundManager::GetInstance()->PlaySE("Poison"); } } break; case Common::EVENT_GET_ITEM_LIFE: PlayerGetItem( Common::ITEM_KIND_LIFE_UP ); break; case Common::EVENT_GET_ITEM_DAMAGE: PlayerGetItem( Common::ITEM_KIND_DAMAGE_UP ); break; case Common::EVENT_GET_ITEM_ANTIDOTE: PlayerGetItem( Common::ITEM_KIND_ANTIDOTE ); break; case Common::EVENT_ADD_FORCE_MOVE: // 必要な情報を取り出す m_forceMoveInfo = eventId.GetExInfoForceMove(); m_invalidCtrlTime = 10; m_invisibleTime = DAMAGE_INVISIBLE_TIME; break; default: break; } }
TEST_F(TestBufferQueue, testEnqueueAtPaused) { for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { SLuint32 numBuffers = validNumBuffers[i]; PrepareValidBuffer(numBuffers); SetPlayerState(SL_PLAYSTATE_PAUSED); EnqueueMaxBuffer(numBuffers); CheckBufferCount(numBuffers, (SLuint32) 0); DestroyPlayer(); } }
TEST_F(TestBufferQueue, testStateTransitionNonEmptyQueue) { static const SLuint32 newStates[] = { SL_PLAYSTATE_PAUSED, // paused -> paused SL_PLAYSTATE_STOPPED, // paused -> stopped SL_PLAYSTATE_STOPPED, // stopped -> stopped SL_PLAYSTATE_PAUSED // stopped -> paused }; for (unsigned i = 0; i < sizeof(validNumBuffers) / sizeof(validNumBuffers[0]); ++i) { SLuint32 numBuffers = validNumBuffers[i]; SLuint32 j; /* Prepare the player */ PrepareValidBuffer(numBuffers); EnqueueMaxBuffer(numBuffers); SetPlayerState(SL_PLAYSTATE_PAUSED); for (j = 0; j < sizeof(newStates) / sizeof(newStates[0]); ++j) { SetPlayerState(newStates[j]); CheckBufferCount(numBuffers, (SLuint32) 0); } DestroyPlayer(); } }
static int IsValidOper( CShopManager *pShopMgr, CMessage *pMsg, const CGUID &npcID, long lShopID ) { CPlayer *pPlayer = pMsg->GetPlayer(); CServerRegion *pRegion = pMsg->GetRegion(); if( pPlayer == NULL || pRegion == NULL ) { return -2; } if( pPlayer->IsDied() ) { return -1; } if( pPlayer->GetCurrentProgress() != CPlayer::PROGRESS_FBUSINESS ) { PutoutLog( LOG_FILE, LT_WARNING, "The Player [%s] is not in PROGRESS_FBUSINESS state.", pPlayer->GetName() ); return -1; } SetPlayerState( pPlayer, true ); CMonster *pNPC = (CMonster*) pRegion->FindAroundObject( pPlayer, TYPE_MONSTER, npcID ); if( pNPC == NULL ) { return -1; } CShop *pShop = pShopMgr->GetShop( lShopID ); if( pShop == NULL ) { return -1; } // NPC是否与商店对应 if( strcmp( pNPC->GetOriginName(), pShop->GetNpcOrigName() ) != 0 ) { return -1; } if( pNPC->Distance( pPlayer ) > 10 ) { return -1; } return 0; }
void CPlayer::OnKill(UINT32 curTime) { m_KillTime = curTime; SetPlayerState(PLAYER_ST_NONE); m_mapRoomTime.clear(); }
// アイテム取得 void GamePlayer::PlayerGetItem( const Common::ITEM_KIND &itemKind, bool isCountUp ) { // アイテムレベル描画クラスに取得を知らせるかどうか bool reflectDisp = true; switch( itemKind ){ default: case Common::ITEM_KIND_RAPID_BULLET: { // 銃の発射間隔を狭める AttackGun::GunState &gunState = m_attackGun->UpdateGunState(); if( gunState.m_shootInterval > BULLET_INTERBAL_MIN ){ gunState.m_shootInterval -= 1; } else{ reflectDisp = false; } if( isCountUp ){ // 取得アイテム数をカウント GameRecorder::GetInstance()->AddItem( Common::ITEM_KIND_RAPID_BULLET ); // アイテム取得音を鳴らす SoundManager::GetInstance()->PlaySE("GetItem"); } } break; case Common::ITEM_KIND_LIFE_UP: { // ライフ回復 m_playerLife += ITEM_HEAL_VALUE; if( m_playerLife > m_playerLifeMax ){ m_playerLife = m_playerLifeMax; } // 回復エフェクト GameEffect::CreateEffect( GameEffect::EFFECT_HEALING, WINDOW_CENTER ); if( isCountUp ){ // 取得アイテム数をカウント GameRecorder::GetInstance()->AddItem( Common::ITEM_KIND_LIFE_UP ); // アイテム取得音を鳴らす SoundManager::GetInstance()->PlaySE("GetItemHeal"); } } break; case Common::ITEM_KIND_DAMAGE_UP: { // ダメージ量UP AttackGun::GunState &gunState = m_attackGun->UpdateGunState(); if( gunState.m_damage < BULLET_DAMAGE_MAX ){ gunState.m_damage += 5; } else{ reflectDisp = false; } if( gunState.m_damage % 4 == 0 ){// 20の倍数になるごとに斬撃の攻撃力もUP AttackBlade::BladeState &bladeState = m_attackBlade->UpdateBladeState(); bladeState.m_damage += 5; } if( isCountUp ){ // 取得アイテム数をカウント GameRecorder::GetInstance()->AddItem( Common::ITEM_KIND_DAMAGE_UP ); // アイテム取得音を鳴らす SoundManager::GetInstance()->PlaySE("GetItem"); } } break; case Common::ITEM_KIND_ANTIDOTE: { // ライフ微回復 m_playerLife += ITEM_ANTIDOTE_HEAL_VALUE; if( m_playerLife > m_playerLifeMax ){ m_playerLife = m_playerLifeMax; } // 毒終了(すぐには毒にならない) m_poisonTime = -60; SetPlayerState( ABNORMAL_STATE_POISON, false ); if( isCountUp ){ // 取得アイテム数をカウント GameRecorder::GetInstance()->AddItem( Common::ITEM_KIND_ANTIDOTE ); // アイテム取得音を鳴らす SoundManager::GetInstance()->PlaySE("GetItemHeal"); // 回復エフェクト GameEffect::CreateEffect( GameEffect::EFFECT_HEALING, WINDOW_CENTER ); } } break; } // 表示部分に伝える if( m_pStatusMenu && reflectDisp ){ m_pStatusMenu->AddItemLevel( itemKind ); } }
/* ================================================ */ void GamePlayer::EventDamage( Common::CMN_EVENT &eventId ) { Common::EVENT_MESSAGE eventKind = eventId.m_event; uint32_t damageValue = eventId.m_eventValue; // 無敵時間中なので処理なし if( m_invisibleTime != 0 && eventKind != Common::EVENT_HIT_FIRE ){ return; } // 既にゲーム終了か const GameManager *pGameMan = GameRegister::GetInstance()->GetManagerGame(); if( pGameMan->IsGameOver() ){ return; } // ダメージ音 switch( eventKind ){ case Common::EVENT_HIT_BULLET_ENEMY: SoundManager::GetInstance()->PlaySE("DamageBullet"); break; case Common::EVENT_HIT_FIRE: // SEなし break; default: SoundManager::GetInstance()->PlaySE("DamageDirect"); break; } // 各ダメージ種類による特殊処理 switch( eventKind ){ default: // ダメージを受けたら一定時間ダメージを受けない m_invisibleTime = DAMAGE_INVISIBLE_TIME; break; case Common::EVENT_HIT_ENEMY_SLIME_KING: { if( !IsPlayerState( ABNORMAL_STATE_MOVE_LOCK ) ){ // 三秒ほど動けずとりこまれる、その後はじき出される Common::CMN_EVENT forceEvent; forceEvent.Init(); forceEvent.m_event = Common::EVENT_ADD_FORCE_MOVE; forceEvent.m_delayTime = 120; Common::EX_FORCE_MOVE moveInfo; math::Vector2 vec = math::Vector2( Utility::GetRandamValueFloat( 100, -100 ) / 100.0f, Utility::GetRandamValueFloat( 100, -100 ) / 100.0f ); vec.Normalize(); moveInfo.m_posX = vec.x; moveInfo.m_posY = vec.y; moveInfo.m_forcePower = 20.0f; forceEvent.SetExInfoForceMove( moveInfo ); AddEvent( forceEvent ); // 動けないステータスにセット SetPlayerState( ABNORMAL_STATE_MOVE_LOCK, true ); } else{ // 既にロック状態なのでなにもしない(ダメージ処理だけ) } // ダメージを受けたら一定時間ダメージを受けない m_invisibleTime = DAMAGE_INVISIBLE_TIME; } break; case Common::EVENT_HIT_ENEMY_SLIME: case Common::EVENT_HIT_ENEMY_SLIME_ANOTHER: case Common::EVENT_HIT_ENEMY_AHRIMAN: case Common::EVENT_HIT_ENEMY_COW: case Common::EVENT_HIT_ENEMY_BOSS: case Common::EVENT_HIT_ENEMY_WIZARD: case Common::EVENT_HIT_WIZARD_CRYSTAL: case Common::EVENT_HIT_DRAGON: case Common::EVENT_HIT_BOSS: case Common::EVENT_HIT_BOSS_LEFT: case Common::EVENT_HIT_BOSS_RIGHT: { // 吹き飛ぶ方向を設定してイベントとしてセットしておく math::Vector2 plPos = Utility::GetPlayerPos(); math::Vector2 enemyPos = math::Vector2( eventId.GetExInfoCmn().m_posX, eventId.GetExInfoCmn().m_posY ); math::Vector2 forceAngle = plPos - enemyPos; forceAngle.Normalize(); Common::CMN_EVENT forceEvent; forceEvent.Init(); forceEvent.m_event = Common::EVENT_ADD_FORCE_MOVE; Common::EX_FORCE_MOVE moveInfo; moveInfo.m_posX = forceAngle.x; moveInfo.m_posY = forceAngle.y; moveInfo.m_forcePower = ( eventKind == Common::EVENT_HIT_ENEMY_COW ) ? 25.0f : 10.0f ; forceEvent.SetExInfoForceMove( moveInfo ); AddEvent( forceEvent ); // ダメージを受けたら一定時間ダメージを受けない m_invisibleTime = DAMAGE_INVISIBLE_TIME; } break; case Common::EVENT_HIT_FIRE: // 炎ダメージアイコン if( !IsPlayerState( ABNORMAL_STATE_FIRE ) ){ SetPlayerState( ABNORMAL_STATE_FIRE, true ); } m_fireTime = 5; // 一定時間ごとにダメージ if( FpsManager::GetUpdateCounter() % 15 == 0 ){ damageValue = 10; } else{ return; } break; } // 特定の攻撃を受けたら一定時間操作不能 switch( eventKind ){ case Common::EVENT_HIT_BLADE_ENEMY: m_invalidCtrlTime = 10; break; case Common::EVENT_HIT_ENEMY_SLIME_KING: m_invalidCtrlTime = 200; break; default: break; } // 防御力に応じてダメージを減らす uint32_t totalDamage = static_cast<uint32_t>( damageValue * m_deffenceLate ); DEBUG_PRINT("ダメージ確定 イベントNo:%d\n", eventKind ); // ダメージ処理実行 ReflectDamage( totalDamage ); }
/* ================================================ */ void GamePlayer::Update() { if( m_playerLife == 0 ){ return; } { // 毎フレーム値が変わるような項目はここで // ダッシュ関連 m_speedMove = m_speedMoveBase * static_cast<uint32_t>(m_speedMultiply + 0.5f); if( m_speedMultiply > 1.0f ){ m_speedMultiply *= 0.94f; // 3フレームに一回残像エフェクト描画 if( FpsManager::GetUpdateCounter() % 3 == 0 && m_speedLv >= 3 ){ GameEffect::CreateEffect( GameEffect::EFFECT_DASH_SMOKE, Utility::GetPlayerPos() ); } } // 一定数になったら切り捨て(終了) if( m_speedMultiply < 1.2f || m_speedLv == Common::STATUS_LEVEL_MAX ){ m_speedMultiply = 1.0f; } // 早すぎる場合は切り捨て if( m_speedMove > DASH_SPEED_MAX ){ m_speedMove = DASH_SPEED_MAX; } // 毒状態ならデクリメント if( m_poisonTime > 0 ){ --m_poisonTime; if( FpsManager::GetUpdateCounter() % 40 == 0 ){ // 一定時間ごとにダメージ ReflectDamage( 3 ); } if( m_poisonTime == 0 ){ // 毒状態終了 SetPlayerState( ABNORMAL_STATE_POISON, false ); } } // 毒にならない時間帯(毒から回復した直後)ならインクリメント else if( m_poisonTime < 0 ){ ++m_poisonTime; } // 無敵時間中ならデクリメント if( m_invisibleTime > 0 ){ --m_invisibleTime; } // 操作不能時間中ならデクリメント if( m_invalidCtrlTime > 0 ){ --m_invalidCtrlTime; if( m_invalidCtrlTime == 0 ){ // 操作不能時間終了 SetPlayerState( ABNORMAL_STATE_MOVE_LOCK, false ); } } // 炎ダメージアイコン if( m_fireTime >= 0 ){ --m_fireTime; if( m_fireTime == 0 ){ SetPlayerState( ABNORMAL_STATE_FIRE, false ); } } } // 現在のライフセット if( m_pStatusMenu ){ m_pStatusMenu->SetPlayerHP( m_playerLife, m_playerLifeMax ); } // 操作不能中でないならパッドイベントをコール if( m_invalidCtrlTime == 0 ){ // パッドに対応した挙動を設定 CallPadEvent(); // 攻撃判定 if( GetStickInfoRight().m_vec != DEFAULT_VECTOR2 ){ const TEX_DRAW_INFO &drawInfo = m_drawTexture.m_pTex2D->GetDrawInfo(); math::Vector2 pos = math::Vector2( drawInfo.m_posOrigin.x, drawInfo.m_posOrigin.y ) + GameAccesser::GetInstance()->GetPlayerOffSet(); math::Vector2 vec = GetStickInfoRight().m_vec; vec.Normalize(); m_attackGun->ShootBullet( pos, vec ); } } // 外からのダメージ等での強制移動 if( m_forceMoveInfo.m_posX != 0.0f && m_forceMoveInfo.m_posY != 0.0f ){ if( m_forceMoveInfo.m_forcePower <= 1.0f ){ m_forceMoveInfo.Init(); } else{ math::Vector2 forceVec = math::Vector2( m_forceMoveInfo.m_posX, m_forceMoveInfo.m_posY ); UpdateMove( forceVec*m_forceMoveInfo.m_forcePower, /*bool isForce=*/true ); m_forceMoveInfo.m_forcePower *= 0.9f; } } // 再生アニメタグセット m_drawTexture.m_pTex2D->SetAnim(GetAnimTag()); }