94°

游戏数值系统 - 基础功能实现

前言

游戏的各个子系统中充斥着各种不同的数值,比如:玩家金钱、等级、在线时长等,而这些数值又会跟其他的子系统有一些关联,比如任务、成就、榜单等,因此数值系统是非常重要的模块之一.

数值类型

玩家在体验游戏的过程当中,无非就是对不同的数值进行了修改,比如杀死了某个怪物之后获得了xx点经验、对某个英雄进行升级等,我们将这些数值统称数值类型,比如上面提到的金钱、等级、在线时长、经验等,这些数值集合用一个枚举来表示,代码如下:

menu ValueType {
    Money,
    Level,
    OnlineTime
}

基础数值类型

所谓基础数值类型就是它的使用只会对本身产生影响,比如使用金钱进行的各类操作都只是金钱发生了变化,通过金钱的变化来改变其他的数值.

复杂数值类型

从字面上可以理解到这种数值类型其实是其他数值的集合,比如钱袋(使用之后会获得一定数量的金钱)、礼包(使用之后会获得N种其他的数值类型).

基础数值类型更新

我们先从一个简单的业务场景来讲解,比如1级升级到2级需要10元, 该业务中涉及了2个不同的数值类型的变化,伪代码如下:

user.money -= 10;
user.level += 1;

此时需求变化了,策划要求可以使用所有的钱进行升级,多出来的部分要转化成经验,假设玩家身上有15元,伪代码如下:

user.money -= 15;
user.level += 1;
user.exp += 5;

我们将以上的代码重构一下,将user.moneyuser.leveluser.exp提取到一个集合中,每种数值都是独立的元素,这样可以灵活扩展,将相关业务抽象化到一个通用的方法中,代码如下:

class ValueEntry {
    public valueType: number;
public count: number;

}

class User { private m_ValueTypeOfEntry: { [key: number]: ValueEntry } = {};

public update(...valueEntries: ValueEntry[]): void {
    for (const r of valueEntries) {
        let oldEntry = this.m_ValueTypeOfEntry[r.valueType];
        if (!oldEntry) {
            oldEntry = {
                valueType: r.valueType,
                count: 0,
            };
            this.m_ValueTypeOfEntry[r.valueType] = oldEntry;
        }

        oldEntry.count += r.count;
    }
}

}

此时策划又有了新的需求,如果数值类型小于0的情况下,得报错,那么只需要对User.update扩展一下便可满足需求了,此处就不再给出代码了.

复合数值类型更新

由于复合数值类型的变更会对其他数值类型发生变化,其次就是在整个游戏的开发过程当中,复合类型会不断的增加,如果像上面那样频繁的对User.update进行修改,显然是不符合OCP的,因此我们应该再次对User.update进行扩展来支持复合数值类型的更新.

首先我们分析一下流程,当复合数值类型变化时会产出其他的简单数值类型,然后更新,因此我们应该在原先的代码之前加入拦截器,该拦截器的作用就是在更新m_ValueTypeOfEntry之前先把复合类型产出的简单类型添加到参数集合中,假设需求为使用每个钱包可以获得1000元,相关代码如下:

type InterceptAction = (valueEntry: ValueEntry, reduceValueEntries: ValueEntry[]) => void;

function walletIntercept(valueEntry: ValueEntry, reduceValueEntries: ValueEntry[]): void { if (valueEntry.count >= 0) { return; }

valueEntries.push({
    valueType: ValueType.Money,
    count: Math.abs(valueEntry.count) * 1000,
});

}

class User { public update(...valueEntries: ValueEntry[]): void { let reduceValueEntries: ValueEntry[] = []; for (const r of valueEntries) { const interceptAction = InterceptorFactory.build(r.valueType); if (interceptAction) { interceptAction(r, reduceValueEntries); } } if (reduceValueEntries.length) { this.update(...reduceValueEntries); }

    // 原先代码
}

}

结束语

由于篇幅问题今天就先到这里了,数值系统的基础部分基本已经完成,以上代码均为同步代码仅作为参考并非实际项目中的代码,下周我会在此基础上加入奖励模块,配合奖励模块简化复合类型的更新,或者加入数值对象模块,比如英雄、宠物等对象在数值系统中的设计,如果有任何疑问或者错误欢迎指出,谢谢.

文章原始地址: https://my.oschina.net/ahl5esoft/blog/4301907

本文转载自博客园,原文链接:https://www.cnblogs.com/ahl5esoft/p/13054234.html

全部评论: 0

    我有话说: