📄 fieldplayerstates.cpp
字号:
#include "FieldPlayerStates.h"
#include "Debug/DebugConsole.h"
#include "SoccerPitch.h"
#include "FieldPlayer.h"
#include "SteeringBehaviors.h"
#include "SoccerTeam.h"
#include "Goal.h"
#include "2D/geometry.h"
#include "SoccerBall.h"
#include "ParamLoader.h"
#include "Messaging/Telegram.h"
#include "Messaging/MessageDispatcher.h"
#include "SoccerMessages.h"
#include "time/Regulator.h"
//uncomment below to send state info to the debug window
#define PLAYER_STATE_INFO_ON
//************************************************************************ Global state
GlobalPlayerState* GlobalPlayerState::Instance()
{
static GlobalPlayerState instance;
return &instance;
}
void GlobalPlayerState::Execute(FieldPlayer* player)
{
//if a player is in possession and close to the ball reduce his max speed
if((player->BallWithinReceivingRange()) && (player->isControllingPlayer()))
{
player->SetMaxSpeed(Prm.PlayerMaxSpeedWithBall);
}
else
{
player->SetMaxSpeed(Prm.PlayerMaxSpeedWithoutBall);
}
}
bool GlobalPlayerState::OnMessage(FieldPlayer* player, const Telegram& telegram)
{
switch(telegram.Msg)
{
case Msg_ReceiveBall:
{
//set the target
player->Steering()->SetTarget(*(static_cast<Vector2D*>(telegram.ExtraInfo)));
//change state
player->GetFSM()->ChangeState(ReceiveBall::Instance());
return true;
}
break;
case Msg_SupportAttacker:
{
//if already supporting just return
if (player->GetFSM()->isInState(*SupportAttacker::Instance()))
{
return true;
}
//set the target to be the best supporting position
player->Steering()->SetTarget(player->Team()->GetSupportSpot());
//change the state
player->GetFSM()->ChangeState(SupportAttacker::Instance());
return true;
}
break;
case Msg_Wait:
{
//change the state
player->GetFSM()->ChangeState(Wait::Instance());
return true;
}
break;
case Msg_GoHome:
{
player->SetDefaultHomeRegion();
player->GetFSM()->ChangeState(ReturnToHomeRegion::Instance());
return true;
}
break;
case Msg_PassToMe:
{
//get the position of the player requesting the pass
FieldPlayer* receiver = static_cast<FieldPlayer*>(telegram.ExtraInfo);
#ifdef PLAYER_STATE_INFO_ON
debug_con << "Player " << player->ID() << " received request from " <<
receiver->ID() << " to make pass" << "";
#endif
//if the ball is not within kicking range or their is already a
//receiving player, this player cannot pass the ball to the player
//making the request.
if (player->Team()->Receiver() != NULL ||
!player->BallWithinKickingRange() )
{
#ifdef PLAYER_STATE_INFO_ON
debug_con << "Player " << player->ID() << " cannot make requested pass <cannot kick ball>" << "";
#endif
return true;
}
//make the pass
player->Ball()->Kick(receiver->Pos() - player->Ball()->Pos(),
Prm.MaxPassingForce);
#ifdef PLAYER_STATE_INFO_ON
debug_con << "Player " << player->ID() << " Passed ball to requesting player" << "";
#endif
//let the receiver know a pass is coming
Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY,
player->ID(),
receiver->ID(),
Msg_ReceiveBall,
&receiver->Pos());
//change state
player->GetFSM()->ChangeState(Wait::Instance());
player->FindSupport();
return true;
}
break;
}//end switch
return false;
}
//***************************************************************************** CHASEBALL
ChaseBall* ChaseBall::Instance()
{
static ChaseBall instance;
return &instance;
}
void ChaseBall::Enter(FieldPlayer* player)
{
player->Steering()->SeekOn();
#ifdef PLAYER_STATE_INFO_ON
debug_con << "Player " << player->ID() << " enters chase state" << "";
#endif
}
void ChaseBall::Execute(FieldPlayer* player)
{
//if the ball is within kicking range the player changes state to KickBall.
if (player->BallWithinKickingRange())
{
player->GetFSM()->ChangeState(KickBall::Instance());
return;
}
//if the player is the closest player to the ball then he should keep
//chasing it
if (player->isClosestTeamMemberToBall())
{
player->Steering()->SetTarget(player->Ball()->Pos());
return;
}
//if the player is not closest to the ball anymore, he should return back
//to his home region and wait for another opportunity
player->GetFSM()->ChangeState(ReturnToHomeRegion::Instance());
}
void ChaseBall::Exit(FieldPlayer* player)
{
player->Steering()->SeekOff();
}
//*****************************************************************************SUPPORT ATTACKING PLAYER
SupportAttacker* SupportAttacker::Instance()
{
static SupportAttacker instance;
return &instance;
}
void SupportAttacker::Enter(FieldPlayer* player)
{
player->Steering()->ArriveOn();
player->Steering()->SetTarget(player->Team()->GetSupportSpot());
#ifdef PLAYER_STATE_INFO_ON
debug_con << "Player " << player->ID() << " enters support state" << "";
#endif
}
void SupportAttacker::Execute(FieldPlayer* player)
{
//if his team loses control go back home
if (!player->Team()->InControl())
{
player->GetFSM()->ChangeState(ReturnToHomeRegion::Instance()); return;
}
//if the best supporting spot changes, change the steering target
if (player->Team()->GetSupportSpot() != player->Steering()->Target())
{
player->Steering()->SetTarget(player->Team()->GetSupportSpot());
player->Steering()->ArriveOn();
}
//if this player has a shot at the goal AND the attacker can pass
//the ball to him the attacker should pass the ball to this player
if( player->Team()->CanShoot(player->Pos(),
Prm.MaxShootingForce))
{
player->Team()->RequestPass(player);
}
//if this player is located at the support spot and his team still have
//possession, he should remain still and turn to face the ball
if (player->AtTarget())
{
player->Steering()->ArriveOff();
//the player should keep his eyes on the ball!
player->TrackBall();
player->SetVelocity(Vector2D(0,0));
//if not threatened by another player request a pass
if (!player->isThreatened())
{
player->Team()->RequestPass(player);
}
}
}
void SupportAttacker::Exit(FieldPlayer* player)
{
//set supporting player to null so that the team knows it has to
//determine a new one.
player->Team()->SetSupportingPlayer(NULL);
player->Steering()->ArriveOff();
}
//************************************************************************ RETURN TO HOME REGION
ReturnToHomeRegion* ReturnToHomeRegion::Instance()
{
static ReturnToHomeRegion instance;
return &instance;
}
void ReturnToHomeRegion::Enter(FieldPlayer* player)
{
player->Steering()->ArriveOn();
if (!player->HomeRegion()->Inside(player->Steering()->Target(), Region::halfsize))
{
player->Steering()->SetTarget(player->HomeRegion()->Center());
}
#ifdef PLAYER_STATE_INFO_ON
debug_con << "Player " << player->ID() << " enters ReturnToHome state" << "";
#endif
}
void ReturnToHomeRegion::Execute(FieldPlayer* player)
{
if (player->Pitch()->GameOn())
{
//if the ball is nearer this player than any other team member &&
//there is not an assigned receiver && the goalkeeper does not gave
//the ball, go chase it
if ( player->isClosestTeamMemberToBall() &&
(player->Team()->Receiver() == NULL) &&
!player->Pitch()->GoalKeeperHasBall())
{
player->GetFSM()->ChangeState(ChaseBall::Instance());
return;
}
}
//if game is on and close enough to home, change state to wait and set the
//player target to his current position.(so that if he gets jostled out of
//position he can move back to it)
if (player->Pitch()->GameOn() && player->HomeRegion()->Inside(player->Pos(),
Region::halfsize))
{
player->Steering()->SetTarget(player->Pos());
player->GetFSM()->ChangeState(Wait::Instance());
}
//if game is not on the player must return much closer to the center of his
//home region
else if(!player->Pitch()->GameOn() && player->AtTarget())
{
player->GetFSM()->ChangeState(Wait::Instance());
}
}
void ReturnToHomeRegion::Exit(FieldPlayer* player)
{
player->Steering()->ArriveOff();
}
//***************************************************************************** WAIT
Wait* Wait::Instance()
{
static Wait instance;
return &instance;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -