Chicken的代码解剖 :1 ChickenAchievementManager

Posted on 2012-11-07 17:26  neocsl  阅读(492)  评论(0)    收藏  举报

  既然在0篇章中谈过了解锁成就系统,就按着每个类的顺序来研究。如果在某个类中涉及到后续的类内容,我会简单解释,然后在后边的内容中解决这一问题。

  ChickenAchievementManager继承自Object。

 

  关于这个类中要涉及的成就用Enum来罗列。

enum EAchievement
{
 EA_HIGH_SCORE_200,
 EA_CHAIN_5,
 EA_CHAIN_10,
 EA_5_MINUTES,
 EA_2_MINUTES,
 EA_CHICKEN_LIFE_30,
 EA_CHICKEN_LIFE_70,
 EA_FOX_PICKUP_60,
 EA_MAX
};

  这一部分交代了成就,分别有高分。链条的长度,坚持的时间,小鸡的生命,抓住的狐狸数目。以及最后抓住的总和。

enum EAchievementCheckSet
{
 EAC_CHAIN_LENGTH,
 EAC_HIGH_SCORE,
 EAC_TOTAL_PLAYTIME,
 EAC_CHICKEN_LIFE,
 EAC_FOX_PICKUP
};

   上面是一个枚举检测器,可能后便需要这个检测条件来解锁某些成就。、

struct EAchievementEntry
{
 var string AchievementTitle;
 var bool hasUnlocked;
};

   字符串来表述成就的标题和成就是否被解除。当然每个成就都有这个表述,是否被解锁,解锁的名字是什么?因此我们需要一个成就数组。

var array<EAchievementEntry> EAchievementEntries;

  当然解锁一项成就可能会标注颜色

var color AchievementUnlockedColor,AchievementColor;

  接下来我进入了一个神秘的系统OnlineSubSystem,偶尔编译运行的时候我都会被提示OnlineSubSystem错误,这种错误多发生在UDK打开的时候还在编译程序。于是我查了一下API手册,里面阐述到这个类和平台和网络有些关系,有些底层。毕竟是在Object类里面继承的(尽管我认为Actor类也可以写计分系统,但是可能无法存储到对应的设备上,但愿我的人是没有错误)

     我继续挖掘了一下该类,里面有一个结构

struct AchievementDetails
{
var const string AchievementName;
var const bool bIsSecret;
var const bool bWasAchievedOffline;
var const bool bWasAchievedOnline;
var const string Description;
var const int GamerPoints;
var const string HowTo;
var const int Id;
var Surface Image;
}; 

  这个结构记录了一些成就名,id积分之类的东西。看来OnlineSubSystem先天就是和这些内容打交道的类,并且牵扯到设备。

  在这里有一个局部的OnlineSubsystem.PlayerInterface。文档中对PlayerInterface的解释是访问online玩家的途径。预备功课做足了,我们上代码

 function Initialize()
 {
  local OnlineSubSystem OnlineSub;
  local array<AchievementDetails>theDetails;               //AchievementDetails是一个结构
  local int iter;
  
  OnlineSub=class'GameEngine'.Static.GetOnlineSubsystem();
  
  if(OnlineSub!=none&&OnlineSub.PlayerInterface!=none)
  {
   OnlineSub.PlayerInterface.GetAchievements(0,theDetails);     //GetAchievements是一个方法,可能是获取一些数组中的内容
   
   for(iter=0;iter<theDetails.length;iter++)
   {
    if(theDetails[iter].bWasAchievedOnline||theDetails[iter].bWasAchievedOnlien)
    {
     AchievementEntries[theDetails[iter].id].hasUnlocked=true;
    }
   }
  }
  
 }

  对这个类才接触有许多让人犯糊涂的地方,不过我相信多回头看最终就能掌握这部分的意义。  

  这个类相对比较底层,我们将会发现即使GameInfo也可以在这个类中定义变量被使用,因为他将保存游戏中的一些数据。

function UnlockAchievement(EAchievement achievementToUnlock)
 {
  local OnlineSubsystem OnlineSub;
  local ChickenGame theGame;
  
  OnlineSub=class'GameEngine'.Static.GetOnlineSubsystem();
  
  if(!AchievementEntries[achievementToUnlock].hasUnlock)               //achievementToUnlock是参数,看准啦
  {
   if(Onlinesub!=none&&OnlineSub.PlayerInterface=none)
   {
    theGame=ChickenGame(class'WorldInfo'.static.GetWorldInfo().Game);
    theGame.AddFloatingTextEntry(theGame.gameSpawnManager.NotificationTextPos,"Achievement Unlocked!!!",AchievementUnlockedColor,1.6,3.4,0,70);
    theGame.AddFloatingTextEntry(theGame.gameSpawnManager.NotificationTextPos,AchievementEntries[achievementToUnlock].AchievementTitle,AchievementColor,1.6,3.5,60,70);
    AchievementEntries[achievementToUnlock].hasUnlocked=true;
    class'WorldInfo'.static.GetWorldInfo().PlaySound(AchievementUnlockedSound,true);
    OnlineSub.PlayerInterface.UnlockAchievement(0,int(achievementToUnlock));
   }
  }
 }

还是新建了OnlineSubsystem子类,theGame获取游戏类,然后堆起执行操作至于游戏类中定义的gameSpawnManager和blabla的东西等回头遇上了在分析。

UnlockAchievement也是新类。

function CheckToUnlockAchievement(EAchievementCheckSet achievementSetCheck,int valueToCheck)
{
 switch(achievementSetCheck)
 {
  case EAC_FOX_PICKUP:
  if(valueToCheck>=120)
  {
   UnLockAchievement(EA_FOX_PICKUP_60);
  }
  break;
  
  case EAC_CHICKEN_LIFE:
  if(EAC_CHICKEN_LIFE>=210)
  {
   UnlockAchievement(EA_CHICKEN_LITE_120);
  }
  if (valueToCheck >= 120)
  {
   UnlockAchievement(EA_CHICKEN_LIFE_70);
  }
  if (valueToCheck >= 30)
  {
   UnlockAchievement(EA_CHICKEN_LIFE_30);
   }
   break;
    case EAC_TOTAL_PLAYTIME:
        if (valueToCheck >= 240)
        {
            UnlockAchievement(EA_5_MINUTES);
        }
        if (valueToCheck >= 120)
        {
            UnlockAchievement(EA_2_MINUTES);
        }
        break;
    case EAC_CHAIN_LENGTH:
        if (valueToCheck >= 15)
        {
            UnlockAchievement(EA_CHAIN_10);
        }
        else if (valueToCheck >= 10)
        {
            UnlockAchievement(EA_CHAIN_5);
        }
        break;
    case EAC_HIGH_SCORE:
        if (valueToCheck >= 10000)
        {
            UnlockAchievement(EA_HIGH_SCORE_200);
        }  
 };
}

  注意看参数等内容。

  最后学习一下怎么给前面的struct命名。

AchievementEntries(EA_HIGH_SCORE_200)=(AchievementTitle="Top of the Pecking Order")