Friday, October 5, 2012

CH8.UnrealScript-State Controll-50

1.State Usage

2.State

 

A.State Usage

在使用State之前先把SimpleEnemy.uc的placeable移除,由Spawner Actor來產生敵人就可以了,增加 State:

state Seeking

{

}

將整個Tick(float DeltaTime) function 放在state Seek裡面:

state Seeking

{

function Tick(float DeltaTime)

{

local CustomTopDownController player;

local vector NewLocation;

if(PCEnemy == none)

{

foreach LocalPlayerControllers(class'CustomTopDownController',player)

{

if(Player.Pawn != none)

{

PCEnemy= Player.Pawn;

`log("Enemy Target is :" @ PCEnemy);

}

}

}

else if(!bFreeze && VSize(Location - PCEnemy.Location) < ChaseDistance)

{

if(VSize(Location-PCEnemy.Location) < AttackDistance)

{

PCEnemy.Bump(self,CollisionComponent,vect(0,0,0));

}

else

{

NewLocation=Location;

NewLocation += normal(PCEnemy.Location - Location) *MovementSpeed* DeltaTime;

SetLocation(NewLocation);

}

}

}

}

接著因為State是Seeking不應該有攻擊的邏輯那應該被放在state Attacking,因此移除攻擊的部分 state Seeking:

state Seeking

{

function Tick(float DeltaTime)

{

local CustomTopDownController player;

local vector NewLocation;

if(PCEnemy == none)

{

foreach LocalPlayerControllers(class'CustomTopDownController',player)

{

if(Player.Pawn != none)

{

PCEnemy= Player.Pawn;

`log("Enemy Target is :" @ PCEnemy);

}

}

}

NewLocation=Location;

NewLocation += normal(PCEnemy.Location - Location) *MovementSpeed* DeltaTime;

SetLocation(NewLocation);

}

}

再來將相關邏輯分開,讓它更具閱讀性:

function GetEnemy()

{

local CustomTopDownController player;

foreach LocalPlayerController(class'CustomTopDownController',player)

{

if(player.Pawn != none)

PCEnemy = player.Pawn;

}

}

state Seeking

{

function Tick(float DeltaTime)

{

local CustomTopDownController player;

local vector NewLocation;

if(PCEnemy == none)

{

GetEnemy()

}

NewLocation=Location;

NewLocation += normal(PCEnemy.Location - Location) *MovementSpeed* DeltaTime;

SetLocation(NewLocation);

}

}

主要讓Seeking State變成是只要尋找玩家在哪裡,邏輯分開可以有效往後改變邏輯時能夠變換成其他演算法且可以其他狀態能夠確保不被影響,接著就是Attacking State:

state Attacking

{

}

增加攻擊程式碼:

state Attacking

{

function Tick(float DeltaTime)

{

if(PCEnemy == none)

{

GetEnemy();

}

if(PCEnemy != none)

{

PCEnemy.Bump(self,CollisionComponent,vect(0,0,0));

}

}

}

判斷是否有敵人,有敵人則攻擊,Attacking State完成後還有freeze state因為在遊戲結束時要停止攻擊:

state Frozen

{

function Tick(float DeltaTime)

{

}

}

移除 freeze() function和變數。

以上已經將狀態和邏輯分開後,再來就是切換狀態與狀態之間的變換,現在有三個狀態Seeking Attacking Frozen,敵人一開始的狀態因該是Seeking,因此在seeking state 加上 auto:

auto state Seeking

在Seeking裡面加上state的切換:

auto state Seeking

{

function Tick(float DeltaTime)

{

local CustomTopDownController player;

local vector NewLocation;

if(PCEnemy == none)

{

GetEnemy();

}

NewLocation=Location;

NewLocation += normal(PCEnemy.Location - Location) *MovementSpeed* DeltaTime;

SetLocation(NewLocation);

if(VSize(Location - PCEnemy.Location) < AttackDistance)

GoToState('Attacking');

}

}

接著就是處理Attacking State:

state Attacking

{

function Tick(float DeltaTime)

{

if(PCEnemy == none)

{

GetEnemy();

}

if(PCEnemy != none)

{

PCEnemy.Bump(self,CollisionComponent,vect(0,0,0));

if(VSize(Location-PCEnemy.Location) > AttackDistance)

GoToState('Seeking');

}

}

}

當離開攻擊範圍則要跑回Seeking state才能夠再次追擊敵人,Compiler後會之前間差不多,只剩下遊戲結束後敵人要有的行為把Frezon State改成Fleeing State做的不同的變化,遊戲結束後敵人會逃跑:

state Fleeing

{

}

增加 RunAway() function:

function RunAway()

{

GoToState('Fleeing');

}

再EnemySpawnPoint.uc增加 MakeEnemyRun() 並移除FreezeEnemy():

function MakeEnemyRun()

{

if(simpleEnemy != none)

simpleEnemy.RunAway();

}

在FunnyGameInfo.uc 變更ScoreObjective():

function ScoreObjective(PlayerReplicationInfo playerScore,int score)

{

local int i;

EnemiesLeft--;

super.ScoreObjective(playerScore,score);

if(EnemiesLeft==0)

{

for(i=0;i<enemySpawnPoint.length;i++)

enemySpawnPoint[i].MakeEnemyRun();

ClearTimer('ActiveSpawner');

}

}

回到Fleeing State在裡面增加Tick() function:

function Tick(float DeltaTime)

{

local vector NewLocation;

if(PCEnemy == none)

GetEnemy();

if(PCEnemy != none)

{

NewLocation = Location;

NewLocation -= normal(PCEnemy.Location - Location) * MovementSpeed * DeltaTime;

SetLocation(NewLocation);

}

}

當完成遊戲時,如果場上有敵人馬上就會逃離。

B.State:

在 State:Seeking、Attacking、Fleeing裡面都有Tick() function,如果再State 外若宣告function Tick(float DeltaTime)則State外的Tick()是不會被執行的,除非有使用GoToState(‘’); 才能脫離State執行外面的Tick(),

No comments:

Post a Comment