Playerの作成
行動の遷移処理(Action)の実装
行動の遷移処理(Action)の実装を行います。
CppPlayerController.cppの修正
まずは全文
/**
* @file CppPlayerController.cpp
* @brief プレイヤーコントローラー
* @author inuvatico
* @date 2020/10/17
* @version 1.0
* @copyright 2020 inuvatico
* Released under the MIT license.
* see https://opensource.org/licenses/MIT
* @par (new/Add/Change : 2020/10/17)
*
*/
#include "CppPlayerController.h"
#include "CppPlyBase.h"
#include "../../../uty/ArmCamera.h"
#include "../../../uty/AnmStateComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
//----------------------------------------------------------------
/// コンストラクタ
//----------------------------------------------------------------
ACppPlayerController::ACppPlayerController() {
PrimaryActorTick.bCanEverTick = true; //Tickを呼ばれるようにする
}
//----------------------------------------------------------------
/// BeginPlay()
//----------------------------------------------------------------
void ACppPlayerController::BeginPlay() {
Super::BeginPlay();
MyActor = dynamic_cast <ACppPlyBase*> (GetCharacter());
if (!MyActor) return;
// カメラをセットアップする
ArmCamera = UArmCamera::Create(MyActor);
FVector ofs(0, 0, 100);//注視点を1m高くする
ArmCamera->SetRelativeLocation(ofs);
//移動方向を向かせる
{
MyActor->bUseControllerRotationPitch = false;
MyActor->bUseControllerRotationYaw = false;
MyActor->bUseControllerRotationRoll = false;
auto cmove = MyActor->GetCharacterMovement();
cmove->bOrientRotationToMovement = true;
cmove->RotationRate = FRotator(0.0f, 360*2, 0.0f);
}
SetAction(ActType::Init);
}
//----------------------------------------------------------------
///Tick
//----------------------------------------------------------------
void ACppPlayerController::Tick(float DeltaTime) {
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 1.0f / 560.f, FColor::Orange, FString::Printf(TEXT("Tick")));
PadInput.update(this); //Key入力の更新
//カメラ の更新
if (PadInput.JoyRdist) {
ArmCamera->AddRotation(PadInput.JoyR_X, PadInput.JoyR_Y);
}
if (CurrentAction) {
(this->*CurrentAction)(CallType::ACT);
}
}
//----------------------------------------------------------------
///PAD入力による移動
//----------------------------------------------------------------
void ACppPlayerController::PadMove(void) {
float speedRate = PadInput.JoyLdist;
if (PadInput.JoyLdist) {
// カメラアームの 方向 を取得
FRotator Rotation = ArmCamera->GetRelativeRotation();
FRotator YawRotation(0, Rotation.Yaw, 0);
// PADの 方向 を取得
float angl = atan2(PadInput.JoyL_Y, -PadInput.JoyL_X);
// 移動方向を計算
angl += FMath::DegreesToRadians(-90 + Rotation.Yaw);
UPawnMovementComponent* MovementComponent = MyActor->GetMovementComponent();
if (MovementComponent->Velocity.Z != 0) {
angl = atan2(MovementComponent->Velocity.Y, MovementComponent->Velocity.X);
}
FVector vec(0, 0, 0);
vec.X = cos(angl);
vec.Y = sin(angl);
MyActor->AddMovementInput(vec, speedRate);
}
}
//-------------------------------------------------------------------------------
// アクション関係
//-------------------------------------------------------------------------------
void ACppPlayerController::ActInit(CallType type) {
if (type == CallType::ACT) {
SetAction(ActType::IdleRun);
}
}
void ACppPlayerController::ActIdleRun(CallType type) {
if (CallType::INIT == type) {
MyActor->AnmStateComponent->SetAnmIndex(UAnmIndex::ANMID_IDLE_RUN);
}if (CallType::ACT == type) {
//移動
PadMove();
MyActor->AnmStateComponent->BPAnmState.Speed = PadInput.JoyLdist;
if (PadInput.BtnOn&BTN_R_L) {
SetAction(ActType::Attack1);
}
}
}
//-------------------------------------------------
//! 攻撃(SHOOT)
//-------------------------------------------------
void ACppPlayerController::ActAttack1(CallType type)
{
if (CallType::INIT == type) {
MyActor->AnmStateComponent->SetAnmIndex(UAnmIndex::ANMID_ATTACK1);
}if (CallType::ACT == type) {
if (MyActor->AnmStateComponent->AnmEventBit& (1 << static_cast<int>(UAnmEvent::ST_SHOOT1))) {
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Orange, FString::Printf(TEXT("SHOOT1")));
}
if (MyActor->AnmStateComponent->AnmEventBit& (1 << static_cast<int>(UAnmEvent::ST_SHOOT2))) {
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Orange, FString::Printf(TEXT("SHOOT2")));
}
if (MyActor->AnmStateComponent->AnmEventBit& (1 << static_cast<int>(UAnmEvent::ST_END))) {
SetAction(ActType::IdleRun);
return;
}
}
}
処理の概要
- 処理が開始さるとBeginPlay()でActType::Init指定されます
- ActInit()はすぐにActIdleRun()に遷移します
- ActIdleRun()は移動/カメラ制御と攻撃(ActAttack1)への遷移を行います
- ActAttack1()は攻撃が終了するとActIdleRun()に遷移します
各メソッドについて
BeginPlay()
BeginPlay() では最初のActionSetAction(ActType::Init)
を
を呼び出します。
void ACppPlayerController::BeginPlay() {
---
---
SetAction(ActType::Init);
}
Tick()
現在有効なActionを呼び出します。
void ACppPlayerController::Tick(float DeltaTime) {
---
---
if (CurrentAction) {
(this->*CurrentAction)(CallType::ACT);
}
}
ActInit()
いまは、ActType::IdleRun
に切り替えるだけです。
ActIdleRun()
・開示時(CallType::INIT
)にSetAnmIndexを使って待機&移動アニメーション(ANMID_IDLE_RUN
)を設定します。
・BPAnmState.Speedにジョイスティックのdistを入れることで待機/移動のアニメーション遷移を行います。
・攻撃ボタン(BTN_R_L
)が押下されるとActionが攻撃(Attack1
)に遷移します。
void ACppPlayerController::ActInit(CallType type) {
if (type == CallType::ACT) {
SetAction(ActType::IdleRun);
}
}
void ACppPlayerController::ActIdleRun(CallType type) {
if (CallType::INIT == type) {
MyActor->AnmStateComponent->SetAnmIndex(UAnmIndex::ANMID_IDLE_RUN);
}if (CallType::ACT == type) {
//移動
PadMove();
MyActor->AnmStateComponent->BPAnmState.Speed = PadInput.JoyLdist;
if (PadInput.BtnOn&BTN_R_L) {
SetAction(ActType::Attack1);
}
}
}
ActAttack1()
銃を撃つ処理です。
初期処理(CallType::INIT
)でアニメーションを指定します。
アニメーション通知のST_SHOOT1/ST_SHOOT2
で弾丸を発射します。(予定)
アニメーション通知の終了(ST_END
)を受け取ると待機状態(SetAction(ActType::IdleRun)
)に戻ります。
//-------------------------------------------------
//! 攻撃(SHOOT)
//-------------------------------------------------
void ACppPlayerController::ActAttack1(CallType type)
{
if (CallType::INIT == type) {
MyActor->AnmStateComponent->SetAnmIndex(UAnmIndex::ANMID_ATTACK1);
}if (CallType::ACT == type) {
if (MyActor->AnmStateComponent->AnmEventBit& (1 << static_cast<int>(UAnmEvent::ST_SHOOT1))) {
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Orange, FString::Printf(TEXT("SHOOT1")));
}
if (MyActor->AnmStateComponent->AnmEventBit& (1 << static_cast<int>(UAnmEvent::ST_SHOOT2))) {
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Orange, FString::Printf(TEXT("SHOOT2")));
}
if (MyActor->AnmStateComponent->AnmEventBit& (1 << static_cast<int>(UAnmEvent::ST_END))) {
SetAction(ActType::IdleRun);
return;
}
}
}