【独立游戏制作人】领先业界3年的游戏开发技术——业务逻辑持久化

概述:

本文介绍一种“逻辑持久化技术”。目的是进一步提升代码复用程度。主要应用场景在游戏中,例如人物角色升级、事物队列冷却等。

 

 

前言:

开发游戏中,经常看到一些业务逻辑相似,但是又无法复用的代码。例如升级。

 

英雄:每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日为闭关日,除了成员邀请外,不对外开放,进行封闭培训。

本群关注的是思想的交流,其次借助开源平台共享资源。

欢迎游戏爱好者加入。

posted @ 2014-05-04 15:07    阅读(3343)  评论(18编辑  收藏  举报
IT民工