论坛首页 Java企业应用论坛

使用XWorker编写战斗模拟器

浏览 2018 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-02-14  

  还是XWorker的介绍贴,XWorker是免费开源项目,下面是使用XWorker的数据对象技术开发的我们游戏项目的战斗模拟器,希望让大家了解XWorker中开发的方式。另外不建议目前用XWorker开发商业应用,后果自负,因为XWorker还不成熟,所以才希望有人能够加入XWorker的开发。

 

数据对象的使用说明:

    主要是用于编写界面和数据统计,数据对象技术类似于信息化系统那种格式化的CUDI操作,只不过在XWorker数据对象主要用于一般编辑界面,即不限于数据库的操作,主要是对一般的表单、表格的等处理,如示例中的战斗数据的展示和统计等。

 

战斗模拟器的界面:

 

战斗模拟器的详细说明

1. 玩家和怪物界面

XWorker中的代码是:

<Group name="playerGroup" text="玩家">
    <GridData style="FILL_HORIZONTAL" name="playerGroupGridData"/>
    <FillLayout name="FillLayout"/>
    <DataObjectForm formType="edit" name="playerForm" dataObject="tools:dataobjects.PlayerThingDataObject"/>
</Group>
<Group name="monsterGroup" text="怪物">
    <FillLayout name="monsterGroup"/>
    <GridData style="FILL_HORIZONTAL" name="monsterGroupGridData"/>
    <DataObjectForm formType="edit" name="monsterForm" dataObject="tools:dataobjects.Monster"/>
</Group>

以上代码生成了如下界面:

生成以上表单的依据是tools:dataobjects.PlayerThingDataObject和tools:dataobjects.Monster,如Monster的定义是:

<ListDataObject label="Monster" listData="npcList" editCols="4" storeSortDir="ASC" name="Monster" dataClassName="Npc">
    <attribute type="int" propertyPath="id" label="标识" queryEditor="false" viewEditor="false" gridEditor="false" name="id" editEditor="false" createEditor="false"/>
    <attribute propertyPath="name" label="名称" inputtype="label" name="name"/>
    <attribute type="int" propertyPath="level" label="等级" name="level"/>
    <attribute type="int" propertyPath="hpMax" label="气血上限" name="hpMax"/>
    <attribute type="int" propertyPath="mpMax" label="内息上限" name="mpMax"/>
    <attribute type="short" propertyPath="attackMin" label="最小攻击" name="minAttack"/>
    <attribute type="short" propertyPath="attackMax" label="最大攻击" name="maxAttack"/>
    <attribute type="float" propertyPath="hitRateAdd" label="命中率" name="hitRate"/>
    <attribute type="float" propertyPath="hitRateBase" label="基础命中率" name="hitRateBase"/>
    <attribute type="float" propertyPath="hitRateAdd" label="额外命中率" name="hitRateAdd"/>
    <attribute type="float" propertyPath="avoRate" label="躲闪率" name="avoRate"/>
    <attribute type="float" propertyPath="criRate" label="暴击率" name="criRate"/>
    <attribute type="float" propertyPath="destRate" label="破击率" name="destroyRate"/>
    <attribute type="float" propertyPath="harmReduceRate" label="伤害减免率" name="harmReduce"/>
    <attribute type="float" propertyPath="criHarmRate" label="暴击伤害率" name="criHarmRate"/>
    <attribute type="float" propertyPath="desReduceRate" label="破击减免率" name="desReduceRate"/>
    <attribute type="float" propertyPath="hpAbsorbRate" label="气血吸收率" name="hpAbsorbRate"/>
    <attribute type="float" propertyPath="damageReboundRate" label="伤害反弹率" name="damageReboundRate"/>
    <attribute type="int" propertyPath="speed" label="速度" name="speed"/>
    <attribute type="int" propertyPath="skill.id" label="技能" inputattrs="tools:battle.SkillSelector:/@shell" inputtype="openWindow" name="skill"/>
    <attribute type="short" propertyPath="defence" label="防御" name="defence"/>
</ListDataObject>

 

2. 设置和读取表单数据

   表单生成后,填充表单数据和获取表单数据的方法。

   a. 设置表单的数据

   以下是按钮的代码:

<Composite name="buttonComposite">
    <GridData horizontalAlignment="END" style="FILL_HORIZONTAL" name="buttonCompositeGridData"/>
    <RowLayout marginTop="0" name="buttonCompositeRowLayout"/>
    <Button name="selectPlayerBtn" text="选择角色">
        <RowData name="RowData" width="80"/>
        <Listeners>
            <Listener name="selectPlayerBtnSelection">
                <ShellDialog name="selectPlayer" shellPath="tools:battle.PlayerThingSelector:/@shell">
                    <Result condition="_return != null" name="ifOk">
                        <FormSetValues formName="playerForm" name="setPlayer" valueVariable="_return"/>
                    </Result>
                </ShellDialog>
            </Listener>
        </Listeners>
    </Button>
    <Button name="selectMonsterBtn" text="选择怪物">
        <RowData name="RowData" width="80"/>
        <Listeners>
            <Listener name="selectMonsterBtnSelection">
                <ShellDialog name="selectMonster" shellPath="tools:battle.MonsterSelector:/@shell">
                    <Result condition="_return != null" name="ifOk">
                        <FormSetValues formName="monsterForm" name="setMonster" valueVariable="_return"/>
                        <PropertySetter propertyName="monster" dataSource="actionContext.getScope(0)" name="setActionContext" value="_return"/>
                    </Result>
                </ShellDialog>
            </Listener>
        </Listeners>
    </Button>
    <Button name="startBattleBtn" text="开始战斗">
        <RowData name="RowData" width="80"/>
        <Listeners>
            <Listener name="startBattleBtnSelection">
                <GroovyAction code="" name="startBattle"/>
            </Listener>
        </Listeners>
    </Button>
    <Button name="updatePlayerBtn" text="保存角色">
        <RowData name="RowData" width="80"/>
        <Listeners>
            <Listener name="updatePlayerBtnSelection">
                <EventExecutor exceptionMessage="更新角色失败。" name="executeEpdatePlayer" successMessage="更新角色成功。">
                    <actions name="actions">
                        <FormUpdateDataObject name="updatePlayer" formName="playerForm"/>
                    </actions>
                </EventExecutor>
            </Listener>
        </Listeners>
    </Button>
    <Button name="createNewPlayerBtn" text="保存为新角色">
        <RowData name="RowData" width="80"/>
        <Listeners>
            <Listener name="createNewPlayerBtnSelection">
                <EventExecutor exceptionMessage="创建角色失败。" name="eventExecutor" successMessage="创建角色成功。">
                    <actions name="actions">
                        <FormCreateDataObject name="createPlayer" formName="playerForm"/>
                    </actions>
                </EventExecutor>
            </Listener>
        </Listeners>
    </Button>
</Composite>

 

对应的界面是:

 

我们使用选择怪物按钮来解释如何选择怪物并填充怪物表单,选择怪物的按钮的事件处理代码是:

<Listeners>
    <Listener name="selectMonsterBtnSelection">
        <ShellDialog name="selectMonster" shellPath="tools:battle.MonsterSelector:/@shell">
            <Result condition="_return != null" name="ifOk">
                <FormSetValues formName="monsterForm" name="setMonster" valueVariable="_return"/>
                <PropertySetter propertyName="monster" dataSource="actionContext.getScope(0)" name="setActionContext" value="_return"/>
            </Result>
        </ShellDialog>
    </Listener>
</Listeners>

 分解讲解:

<ShellDialog name="selectMonster" shellPath="tools:battle.MonsterSelector:/@shell">

 打开选择怪物的窗口tools:battle.MonsterSelector:/@shell。

<Result condition="_return != null" name="ifOk">

 如果选择的怪物。

<FormSetValues formName="monsterForm" name="setMonster" valueVariable="_return"/>

 把怪物数据填充到怪物表单。

<PropertySetter propertyName="monster" dataSource="actionContext.getScope(0)" name="setActionContext" value="_return"/>

 把怪物数据设置到全局变量中,以备后用。

 

b. 获取表单数据的代码

def mvalues = monsterForm.doAction("getValues", actionContext);

 以上是groovy的脚本代码,获取怪物表单中的编辑的数据。

 

3. 统计数据处理


 以上是模拟战斗后的统计结果,实际上战斗过程是由游戏的代码完成的,XWorker负责把每次的战斗结果汇总并显示出来,在这里介绍如何使用数据对象的统计功能。

统计的代码如下:

 

//计算玩家的统计信息
def attackStaticDObj = world.getThing("tools:battle.AttackInfoStatic");
//玩家统计
def playerAttackStatic = attackStaticDObj.doAction("query", actionContext, ["attackDetails": playerAttackDetails]).get(0);
//怪物统计
def monsterAttackStatic = attackStaticDObj.doAction("query", actionContext, ["attackDetails": monsterAttackDetails]).get(0);    

 playerAttackDetails和monsterAttackDetails是一次战斗的详细信息,是由游戏代码算出来的,attackStaticDObj是统计模块,做统计,

  attackStaticDObj.doAction("query", actionContext, ["attackDetails": playerAttackDetails]).get(0);是执行统计并算出结果。

其中统计的定义是tools:battle.AttackInfoStatic,它的代码如下:

<StatisticsQueryDataObject dataObject="ResultDataObject" editCols="4" storeSortDir="ASC" name="ResultStat">
    <attribute type="int" label="战斗次数" size="10" gridWidth="60" inputtype="label" aggregateExpression="*" name="totalCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="胜利次数" size="10" gridWidth="60" inputtype="label" aggregateExpression="result" name="winCount" queryFieldType="aggregate"/>
    <attribute type="float" aggregateFunction="avg" colspan="2" label="胜率" size="10" inputtype="label" aggregateExpression="result" name="winRate" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="总时间" size="10" inputtype="label" aggregateExpression="time" name="time" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="avg" label="平均战斗时间" size="10" inputtype="label" aggregateExpression="time" name="avgTime" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="avg" label="玩家平均攻击次数" size="10" inputtype="label" aggregateExpression="playerAttackCount" name="avgAttackCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="avg" label="怪物平均攻击次数" size="10" inputtype="label" aggregateExpression="monsterAttackCount" name="avgMonsterAttackCount" queryFieldType="aggregate"/>
    <attribute colspan="4" label="玩家统计数据" inputtype="label" name="playerData" queryFieldType="finalExpression" finalExpression="&quot;&quot;"/>
    <attribute type="int" aggregateFunction="sum" label="攻击次数" size="10" inputtype="label" aggregateExpression="playerAttackCount" name="playerAttackCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="总伤害" size="10" inputtype="label" aggregateExpression="playerAttack" name="playerAttack" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="暴击次数" inputtype="label" aggregateExpression="playerCrickedCount" name="playerCrickedCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="破击次数" inputtype="label" aggregateExpression="playerDestroyedCount" name="playerDestroyedCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="命中次数" inputtype="label" aggregateExpression="playerHitCount" name="playerHitCount" queryFieldType="aggregate"/>
    <attribute type="int" label="平均战斗伤害" size="10" inputtype="label" name="avgPlayerBattleAttack" queryFieldType="finalExpression" finalExpression="playerAttack/totalCount"/>
    <attribute type="float" label="暴击率" inputtype="label" name="playerAvgCrickedCount" queryFieldType="finalExpression" finalExpression="playerCrickedCount/playerAttackCount"/>
    <attribute type="int" label="破击率" inputtype="label" name="playerAvgDestroyedCount" queryFieldType="finalExpression" finalExpression="playerDestroyedCount/playerAttackCount"/>
    <attribute type="float" label="命中率" inputtype="label" name="playerAvgHitRate" queryFieldType="finalExpression" finalExpression="playerHitCount/playerAttackCount"/>
    <attribute type="int" label="平均每次伤害" size="10" inputtype="label" name="playerAvgAttackDamage" queryFieldType="finalExpression" finalExpression="playerAttack/playerAttackCount"/>
    <attribute type="int" aggregateFunction="sum" label="内息消耗" size="10" inputtype="label" aggregateExpression="playerAttackerMpUsed" name="playerAttackerMpUsed" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="avg" label="平均战斗内息消耗" size="10" inputtype="label" aggregateExpression="playerAttackerMpUsed" name="avgPlayerAttackerMpUsed" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="气血消耗" size="10" inputtype="label" aggregateExpression="playerAttackerHpUsed" name="playerAttackerHpUsed" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="气血吸收" size="10" inputtype="label" aggregateExpression="playerHpAbsorb" name="playerHpAbsorb" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="内息吸收" size="10" inputtype="label" aggregateExpression="playerMpAbsorb" name="playerMpAbsorb" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="伤害反弹" size="10" inputtype="label" aggregateExpression="playerDamageRebound" name="playerDamageRebound" queryFieldType="aggregate"/>
    <attribute colspan="4" label="怪物统计数据" inputtype="label" name="monsterData" queryFieldType="finalExpression" finalExpression="&quot;&quot;"/>
    <attribute type="int" aggregateFunction="sum" label="攻击次数" size="10" inputtype="label" aggregateExpression="monsterAttackCount" name="monsterAttackCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="总伤害" size="10" inputtype="label" aggregateExpression="monsterAttack" name="monsterAttack" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="暴击次数" inputtype="label" aggregateExpression="monsterCrickedCount" name="monsterCrickedCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="破击次数" inputtype="label" aggregateExpression="monsterDestroyedCount" name="monsterDestroyedCount" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="命中次数" inputtype="label" aggregateExpression="monsterHitCount" name="monsterHitCount" queryFieldType="aggregate"/>
    <attribute type="int" label="平均战斗伤害" size="10" inputtype="label" name="avgmonsterBattleAttack" queryFieldType="finalExpression" finalExpression="monsterAttack/totalCount"/>
    <attribute type="float" label="暴击率" inputtype="label" name="monsterAvgCrickedCount" queryFieldType="finalExpression" finalExpression="monsterCrickedCount/monsterAttackCount"/>
    <attribute type="int" label="破击率" inputtype="label" name="monsterAvgDestroyedCount" queryFieldType="finalExpression" finalExpression="monsterDestroyedCount/monsterAttackCount"/>
    <attribute type="float" label="命中率" inputtype="label" name="monsterAvgHitRate" queryFieldType="finalExpression" finalExpression="monsterHitCount/monsterAttackCount"/>
    <attribute type="int" label="平均每次伤害" size="10" inputtype="label" name="monsterAvgAttackDamage" queryFieldType="finalExpression" finalExpression="monsterAttack/monsterAttackCount"/>
    <attribute type="int" aggregateFunction="sum" label="内息消耗" size="10" inputtype="label" aggregateExpression="monsterAttackerMpUsed" name="monsterAttackerMpUsed" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="avg" label="平均战斗内息消耗" size="10" inputtype="label" aggregateExpression="monsterAttackerMpUsed" name="avgmonsterAttackerMpUsed" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="气血消耗" size="10" inputtype="label" aggregateExpression="monsterAttackerHpUsed" name="monsterAttackerHpUsed" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="气血吸收" size="10" inputtype="label" aggregateExpression="monsterHpAbsorb" name="monsterHpAbsorb" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="内息吸收" size="10" inputtype="label" aggregateExpression="monsterMpAbsorb" name="monsterMpAbsorb" queryFieldType="aggregate"/>
    <attribute type="int" aggregateFunction="sum" label="伤害反弹" size="10" inputtype="label" aggregateExpression="monsterDamageRebound" name="monsterDamageRebound" queryFieldType="aggregate"/>
</StatisticsQueryDataObject>

 StatisticsQueryDataObject是一个分组和汇总模块,可以对List数据或数组等分组和汇总。

  • 大小: 150.6 KB
  • 大小: 83.6 KB
  • 大小: 20.1 KB
  • 大小: 58.9 KB
   发表时间:2012-02-14  
以上是为了介绍XWorker特性,希望能够有人参与,不过基本上本轮的介绍(前面也有帖子)以失败告终了。

目前XWorker还有很多事情要做,主要是想法太多哈,不过今后会有更多的实用功能推出,到时候可能大家会更容易接受一些。
1 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics