文章出處

概述:

本文介紹一種“邏輯持久化技術”。目的是進一步提升代碼復用程度。主要應用場景在游戲中,例如人物角色升級、事物隊列冷卻等。

 

 

前言:

開發游戲中,經常看到一些業務邏輯相似,但是又無法復用的代碼。例如升級。

 

英雄:每100點經驗升級1級。

騎寵:每100點經驗升級1星,每12星升級一級。

 

如果用傳統的設計思路,會得到以下代碼片段:

 

USR_HERO
{
  public int exp;
  public int level;
}
UsrHeroDao
{
  public boolean upgrade( USR_HERO hero, int exp)
  {
    hero.exp += exp;
    if (hero.exp >= MAX_EXP)
    {
      hero.exp = MAX_EXP - hero.exp;
      hero.level += 1;
    }
  }
}

 

 

如果是寵物,就寫一套寵物的升級代碼。這種代碼開發多了,就開始覺得煩,但是不認真看又會出Bug。我們程序員尼瑪怎么能每天都重復的干著這些無聊的事情??

 

于是我開始冥思苦想,如果這些能力是模塊,一個對象安裝了這個模塊,就具備了升級的能力,那我就不用開發了啊。多爽??不斷的冥思苦想,曾經還半夜在家里的大廳摸黑轉來轉去,大腦不斷構造著各種架構,又不斷的被推翻。

 

終于,有一天, 我走在回家的路上的時候,給我想到了!!!

PS: 各位看解決方案的時候,也可以稍微1分鐘思考下上面的問題)

 

核心思路:

首先要分析為什么代碼不能復用。因為升級的經驗值是值類型對象!這個就是一切的根源本質。可以想象下,如果把對象的經驗、等級放入方法內運算,實際上對象的值是沒有受到影響的,因為按值傳遞被拷貝了一份。

 

所以???把值類型轉成對象類型,突然間一切都柳暗花明了。例如:

 

OrmInt
{
  public int value;
}
USR_HERO
{
  public OrmInt exp;
  public OrmInt level;
}

 

 

看到這里,大家是否突然間明白了?突然間覺得高端大氣上檔次了?尼瑪這可是我奮戰幾天的結果。我相信我不說,業界起碼3年內不會有人往這個方向思考(臭美一下,各位大俠手下留情,千萬別噴我。。。。。)

 

現在我把升級的方法修改一下:

 

UsrHeroDao
{
  public boolean upgrade(OrmInt exp, OrmInt level, int exp)
  {
    exp.value += exp;
    If(exp.value >= MAX_EXP)
    {
      exp.value = MAX_EXP - exp;
      level.value += 1; 
    }
  }
}

 

 

怎樣?是不是覺得爽了很多。

案例:

為了進一步說明這個“邏輯持久化”如何的高端,我舉個我實際使用的例子, 使用了簡化代碼:

 

// 為OrmInt增加一個可升級的方法,返回升級對象。
OrmInt
{
  public OrmUpgradable ugprade(OrmInt upgradeValue, OrmUpgradeLimit upgradeLimited)
  {
    OrmUpgradable value = new OrmUpgradable(this, value, ugpradeLimited);
  }
}

// 升級對象,支持鏈式編程,實現升級觸發下一升級的效果
OrmUpgradable
{
  private OrmInt value; // 被升級的對象
  private OrmInt upgradeValue; // 當前升級的值
  private OrmUpgradeLimit upgradeLImited; // 升級的上限對象
  private OrmUpgradable head; // 鏈式升級的頭
  private OrmUpgrade child; // 鏈式升級的尾
  
  // 觸發下一個升級
  public OrmUpgradable upgrade(OrmInt value, OrmInt upgradeValue, OrmUpgradeLimit upgradeLimited)
  {
    OrmUpgradable orm = new OrmUpgradable(value, upgradeValue, upgradeLimited);
    orm.head = this.head;
    this.child = orm;
    return orm;
  }
  
  // 開始升級
  public boolean doWhile()
  {
    // 不斷循環升級
    if(this.value.greatThan(0))
    {
      // 當前的升級上限
      int upgradeLimited = this.upgradeLimited.getUpgradeLimit();
      // 計算可升級的值的部分 并升級
      int incValue = min(upgradeLimited.substract(this.value), upgradeValue);
      this.value.increase(incValue);
  
      //判斷是否升級
      if(this.value.greatEqualThan(upgradeLimit))
      {
        // 鏈式觸發后續的升級
        if(!this.child.doWhile())
          return true;
      }
  
      // 更新剩余可升級部分
      upgradeValue.update(upgradeValue.substract(incValue));
      this.value.update(0);
    }
  
  return true;
  
  }
}

 

 

 

使用方法:

p.value.upgrade(11, 10)

.upgrade(p.value2, 1, 10)

.upgrade(p.value3, 1, 10)

.doWhile()

 

這段代碼用起來簡單,但是原理有點復雜。

  • 首先這是個鏈式升級。當exp值增加到達了最大值,則觸發下個對象level進行增加,一直觸發到最后。然后一個循環。
  • 其次,exp不斷升級,直到可升級的值用完了。感覺就像一個儲水池。
  • 最后,升級上限我用了一個對象OrmUpgradeLimit,原因是實際項目中,當用戶的等級不同的時候,當前等級經驗值上限是不一樣的。所以OrmUpgradeLimit實際上內部包含了level這個對象。而由于level類型對象,因此在升級過程中,升級上限是動態變化的。

 

小結:

本文拋磚引玉,介紹了一種非常強大的“業務邏輯持久化”技術。本質就是值類型轉對象類型;對象類型除了包含數據外,并帶上處理方法。

這樣,這個對象復制給了OrmOrm就具備了對應的能力。所以我命名為“業務邏輯持久化”,因為我把邏輯放在了持久層。

 

擴展閱讀: 

實際上現在的業務邏輯操作,都是圍繞著數據。

邏輯更確切的說,就是圍繞相互有關聯的數據字段進行邏輯操作。 思維發散下,就明白。這個已經不是對某個對象進行操作了。

英雄有經驗等級、坐騎也有經驗等級,但是升級這個操作實際上是針對經驗和等級這2個數據建立關系,而不是英雄和坐騎。

這個技術國外叫做:functional reactive programming
Hudak, Paul (September 1989). "Conception, evolution, and application of functional programming languages" (PDF). ACM Computing Surveys 21 (3): 359–411. doi:10.1145/72551.72554.

 

下期預告:

領先業界3年的游戲開發技術——頂級數據庫持久層的設計。

目前最流行的數據庫持久層是什么?Hibernate?ADO.NET?不,Hibernate從出生開始,我就覺得他實在太落后了。歡迎關注6月份的主題——頂級數據庫持久層設計。

 

關于我們:

我們來自Pixysoft獨立游戲制作人。我們的目標是培養早就游戲行業的獨立制作人,提供一切相關的技術文檔資料,從前端到后端、策劃、數值、美術全方位進行培養。

歡迎加入我們的群:95755843

本群每月1~10日為開放日,不限條件加入。11~30日為閉關日,除了成員邀請外,不對外開放,進行封閉培訓。

本群關注的是思想的交流,其次借助開源平臺共享資源。

歡迎游戲愛好者加入。


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()