找回密码
 点一下
查看: 1822|回复: 5

FCS自制弹幕函数+自制HashSystem【高手帮忙测试下效率和检查下】

[复制链接]
发表于 2009-8-11 18:28:36 | 显示全部楼层 |阅读模式
其他论坛都每人回...在这里再发一遍好了,...............


[s:186] 首先说下弹幕函数~这个弹幕函数是咱昨晚通宵写好的...等写完的时候已经早上5点多了...这个弹幕函数的思路就是来自橙子之前跟我说的那个单位组模拟的思路而想到的~~~是利用了Loop的exitwhen的模拟判断+boolean判断当前指针索引是否为空来欺骗电脑的~~~

【但是缺点就是需要用到一个缓存~虽然只有一个integer数据需要传递但是想到以前网上听说GC在Timer下效率比数组慢100倍...】

接下来就是自制的HashSystem系统了~~这个是今天中午突然想到的~~也是因为橙子的模拟单位组思路而想到的一个东西(之前我没用过什么HashSystem和DataSystem...不知道那些都是怎么写的...)~就是利用handle取余后Loop中灰常XE的exitwhen功能...来模拟GC~~

【但是因为这个是为了配合弹幕系统写的HashSystem~所以只写了“单层目录结构”~要完全达到GC的单Handle绑定多数据的话只需要再增加一层目录结构即可~~但是原理和思路还是一样的】


不过因为本人jass技术实在有限...所以虽然测试的时候没问题...但是会出现什么BUG或者效率什么的还是请高手帮忙查看测试以下....................................

FCS_弹幕函数+FCS_HashSystem单层结构函数.w3x

38 KB, 下载次数: 28

夜天新手助推器.rar

354 KB, 下载次数: 8

地图专用UI

 楼主| 发表于 2009-8-11 18:29:45 | 显示全部楼层
  这个就是自制的单层目录结构HashSystem的函数主体...

HashSystem的调用方法

//调用方法
//call HashSystemInteger(H2I(绑定的数据), H2I(绑定的内容))

//读取方法
//set Integer Data = GetHashSystemInteger(H2I(绑定的数据))

//清除方法
//call FlushHashSystemMission(H2I(绑定的数据))


所需变量

[jass]
globals
    //FCS HashSystem变量声明
    integer array udg_HashSystem_Handle //目录
    integer array udg_HashSystem_HandleData //内容
    boolean array udg_HashSystem_HandleFullBoolean //目录是否为空
endglobals
[/jass]

[jass]
//FCS HashSystem函数主体开始
function Mod takes integer X, integer Y returns integer
    local integer modulus = X - (X / Y) * Y
    if (modulus < 0) then
        set modulus = modulus + Y
    endif
    return modulus
endfunction

//清除方法
//call FlushHashSystemMission(H2I(Timer))

function FlushHashSystemMission takes integer DataHandle returns nothing
    local integer Handle = Mod(DataHandle, 9)
    local integer N = 0
     
    loop
        exitwhen udg_HashSystem_Handle[Handle+(N*10)] == DataHandle
        set N = N+1
    endloop
     
    set Handle = Handle+(N*10)
    //call BJDebugMsg("清除取得handle:"+I2S(Handle))
    set udg_HashSystem_HandleFullBoolean[Handle] = false
endfunction

//读取方法
//set Integer Data = GetHashSystemInteger(H2I(Timer))

function GetHashSystemInteger takes integer DataHandle returns integer
    local integer Handle = Mod(DataHandle, 9)
    local integer N = 0
     
    loop
        exitwhen udg_HashSystem_Handle[Handle+(N*10)] == DataHandle
        set N = N+1
    endloop
     
    set Handle = Handle+(N*10)
    //call BJDebugMsg("读取取得handle:"+I2S(Handle))
    return udg_HashSystem_HandleData[Handle]
endfunction

//调用方法
//call HashSystemInteger(H2I(Timer), H2I(Data))

function HashSystemInteger takes integer DataHandle, integer Data returns nothing
    local integer Handle = Mod(DataHandle, 9)
    local integer N = 0
     
    loop
        exitwhen udg_HashSystem_HandleFullBoolean[Handle+(N*10)] == false
        set N = N+1
        if ( N > 800 ) then
            set N = 0
        endif
    endloop
     
    set Handle = Handle+(N*10)
    //call BJDebugMsg("存储取得handle:"+I2S(Handle))
    set udg_HashSystem_HandleFullBoolean[Handle] = true
    set udg_HashSystem_Handle[Handle] = DataHandle
    set udg_HashSystem_HandleData[Handle] = Data
endfunction
//FCS HashSystem函数主体结束 [/jass]
回复

使用道具 举报

 楼主| 发表于 2009-8-11 18:32:26 | 显示全部楼层
  下面这个就是整个弹幕函数+HashSystem的结构主体~~~

弹幕函数的调用方法

//函数最终会返回一个单位,能用变量记录

//call CreateBullet(玩家,弹幕单位id,X坐标, Y坐标,方向, 速度,距离,伤害数值,伤害检查范围,是否可伤害同伴,是否碰撞可破坏物,碰撞可破坏物范围,是否检查地形可通行)

//最大支持弹幕数量:1000


[jass]
globals
    //FCS HashSystem变量声明
    integer array udg_HashSystem_Handle //目录
    integer array udg_HashSystem_HandleData //内容
    boolean array udg_HashSystem_HandleFullBoolean //目录是否为空
     
    //FCS 弹幕函数变量声明
    boolean udg_Bullet_DestroyRectBoolean
    boolean array udg_Bullet_UnitEmptyBoolean
    boolean array udg_Bullet_DamageBoolean
    boolean array udg_Bullet_DestroyBoolean
    boolean array udg_Bullet_WalkBilityBoolean
    unit array udg_Bullet_Unit
    real array udg_Bullet_Speed
    real array udg_Bullet_Distance
    real array udg_Bullet_DistanceMax
    real array udg_Bullet_Damage
    real array udg_Bullet_DamageArena
    rect array udg_Bullet_Rect
endglobals
function H2I takes handle h returns integer
    return h
    return 0
endfunction
function I2U takes integer i returns unit
    return i
    return null
endfunction
//FCS HashSystem函数主体开始
function Mod takes integer X, integer Y returns integer
    local integer modulus = X - (X / Y) * Y
    if (modulus < 0) then
        set modulus = modulus + Y
    endif
    return modulus
endfunction
//call FlushHashSystemMission(H2I(Timer))
function FlushHashSystemMission takes integer DataHandle returns nothing
    local integer Handle = Mod(DataHandle, 9)
    local integer N = 0
     
    loop
        exitwhen udg_HashSystem_Handle[Handle+(N*10)] == DataHandle
        set N = N+1
    endloop
     
    set Handle = Handle+(N*10)
    //call BJDebugMsg("清除取得handle:"+I2S(Handle))
    set udg_HashSystem_HandleFullBoolean[Handle] = false
endfunction
//set Integer Data = GetHashSystemInteger(H2I(Timer))
function GetHashSystemInteger takes integer DataHandle returns integer
    local integer Handle = Mod(DataHandle, 9)
    local integer N = 0
     
    loop
        exitwhen udg_HashSystem_Handle[Handle+(N*10)] == DataHandle
        set N = N+1
    endloop
     
    set Handle = Handle+(N*10)
    //call BJDebugMsg("读取取得handle:"+I2S(Handle))
    return udg_HashSystem_HandleData[Handle]
endfunction
//call HashSystemInteger(H2I(Timer), H2I(Data))
function HashSystemInteger takes integer DataHandle, integer Data returns nothing
    local integer Handle = Mod(DataHandle, 9)
    local integer N = 0
     
    loop
        exitwhen udg_HashSystem_HandleFullBoolean[Handle+(N*10)] == false
        set N = N+1
        if ( N > 800 ) then
            set N = 0
        endif
    endloop
     
    set Handle = Handle+(N*10)
    //call BJDebugMsg("存储取得handle:"+I2S(Handle))
    set udg_HashSystem_HandleFullBoolean[Handle] = true
    set udg_HashSystem_Handle[Handle] = DataHandle
    set udg_HashSystem_HandleData[Handle] = Data
endfunction
//FCS HashSystem函数主体结束
function Trig_RectArenaBoolean takes nothing returns nothing
    set udg_Bullet_DestroyRectBoolean = false
    //call BJDebugMsg( "存在可破坏物" )
endfunction
function Bullet_Action takes nothing returns nothing
    local timer Timer = GetExpiredTimer()
    //local integer ID = GetStoredInteger(udg_GC, I2S(H2I(Timer)), "ID")
    local integer ID = GetHashSystemInteger(H2I(Timer))
     
    local boolean DamageBoolean
    local boolean DestroyBoolean
    local boolean WalkBilityBoolean
    local boolean FinishBoolean = false
     
    local unit Unit = udg_Bullet_Unit[ID]
    local real Speed
    local real Distance
    local real DistanceMax
    local real Damage
    local real DamageArena
    local real X
    local real Y
    local real Face
     
    local group Group
    local unit GroupUnit
    local rect RectArena
     
    if ( GetUnitState(Unit, UNIT_STATE_LIFE) > 0 ) then //弹幕是否存活
        set Distance = udg_Bullet_Distance[ID]
        set DistanceMax = udg_Bullet_DistanceMax[ID]
        if ( Distance <= DistanceMax ) then //弹幕是否达到最大距离
            set Speed = udg_Bullet_Speed[ID]
            set X = GetUnitX(Unit)
            set Y = GetUnitY(Unit)
            set Face = GetUnitFacing(Unit)
            set X = X+Cos(Face*0.01745)*Speed
            set Y = Y+Sin(Face*0.01745)*Speed
            
            set udg_Bullet_Distance[ID] = Distance+Speed
            set DamageArena = udg_Bullet_DamageArena[ID]
            
            //选取弹幕周围单位
            set Group = CreateGroup()
            call GroupEnumUnitsInRange(Group, X, Y, DamageArena,null)
            
            loop
                set GroupUnit = FirstOfGroup(Group)
                exitwhen GroupUnit == null
                set Damage = udg_Bullet_Damage[ID]
                set DamageBoolean = udg_Bullet_DamageBoolean[ID]
                 
                if ( DamageBoolean == true ) then //是否伤害同伴
                    if ( GetUnitState(GroupUnit, UNIT_STATE_LIFE) > 0 ) then
                        call UnitDamageTarget( Unit, GroupUnit, Damage, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
                        set FinishBoolean = true
                        //call BJDebugMsg( "伤害目标" )
                    endif
                else
                    if ( IsUnitEnemy(GroupUnit, GetOwningPlayer(Unit)) == true ) then
                        if ( GetUnitState(GroupUnit, UNIT_STATE_LIFE) > 0 ) then
                            call UnitDamageTarget( Unit, GroupUnit, Damage, true, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
                            set FinishBoolean = true
                            //call BJDebugMsg( "伤害目标" )
                        endif
                    endif
                endif
                 
                call GroupRemoveUnit(Group, GroupUnit)
            endloop
            call DestroyGroup(Group)
            
            set WalkBilityBoolean = udg_Bullet_WalkBilityBoolean[ID]
            if ( WalkBilityBoolean == true ) then //是否检查可通行
                if ( IsTerrainPathable(X, Y, PATHING_TYPE_WALKABILITY) == true ) then //坐标位置是否可通行
                    set FinishBoolean = true
                    //call BJDebugMsg( "不可通行" )
                endif
            endif
            
            set DestroyBoolean = udg_Bullet_DestroyBoolean[ID]
            if ( DestroyBoolean == true ) then //是否检查碰撞可破坏物
                set RectArena = udg_Bullet_Rect[ID]
                call MoveRectTo(RectArena, X, Y)
                set udg_Bullet_DestroyRectBoolean = true
                call EnumDestructablesInRect( RectArena, null, function Trig_RectArenaBoolean )
                if ( udg_Bullet_DestroyRectBoolean == false ) then //是否存在可破坏物
                    set FinishBoolean = true
                endif
                 
            endif
            
        else
            set FinishBoolean = true
            //call BJDebugMsg( "达到距离" )
        endif
    else
        set FinishBoolean = true
        //call BJDebugMsg( "弹幕消失" )
    endif
     
    if ( FinishBoolean == true ) then
        //call FlushStoredMission(udg_GC, I2S(H2I(Timer)))
        call FlushHashSystemMission(H2I(Timer))
        call PauseTimer(Timer)
        call DestroyTimer(Timer)
        call KillUnit(Unit)
        call RemoveRect(RectArena)
        set udg_Bullet_UnitEmptyBoolean[ID] = false
    else
        call SetUnitX(Unit, X)
        call SetUnitY(Unit, Y)
    endif
     
    set Timer = null
    set Unit = null
    set Group = null
    set GroupUnit = null
    set RectArena = null
endfunction
//函数最终会返回一个单位,能用变量记录
//call CreateBullet(玩家,弹幕单位id,X坐标, Y坐标,方向, 速度,距离,伤害数值,伤害检查范围,是否可伤害同伴,是否碰撞可破坏物,碰撞可破坏物范围,是否检查地形可通行)
//最大支持弹幕数量:1000
function CreateBullet takes player UnitPlayer, integer UnitID, real X, real Y, real Face, real Speed, real DistanceMax, real Damage, real DamageArena, boolean DamageBoolean, boolean DestroyBoolean, real DestroyArena, boolean DestroyArenaBoolean returns unit
    local unit Unit = CreateUnit(UnitPlayer, UnitID, X, Y, Face)
    local timer Timer = CreateTimer()
    local integer N = 0
     
    loop
        //call BJDebugMsg( "进入循环判断" )
        set N = N+1
        exitwhen udg_Bullet_UnitEmptyBoolean[N] == false
        if ( N == 1000 ) then //这里修改最大弹幕支持数(数值越少函数效率越高)
            set N = 0
            //call BJDebugMsg( "循环达到1000次" )
        endif
    endloop
    //call BJDebugMsg( "跳出循环" )
    //call DisplayTimedTextToPlayer(UnitPlayer,0,0,30,"当前指针:"+I2S(N))
     
    set udg_Bullet_UnitEmptyBoolean[N] = true
    set udg_Bullet_Unit[N] = Unit
    set udg_Bullet_Speed[N] = Speed
    set udg_Bullet_Distance[N] = 0
    set udg_Bullet_DistanceMax[N] = DistanceMax
    set udg_Bullet_Damage[N] = Damage
    set udg_Bullet_DamageArena[N] = DamageArena
    set udg_Bullet_DamageBoolean[N] = DamageBoolean
    set udg_Bullet_DestroyBoolean[N] = DestroyBoolean
    set udg_Bullet_WalkBilityBoolean[N] = DestroyArenaBoolean
    if ( DestroyBoolean == true ) then
        set udg_Bullet_Rect[N] = Rect(X-DestroyArena, Y-DestroyArena, X+DestroyArena, Y+DestroyArena)
    endif
    //call BJDebugMsg( "变量赋值完成" )
     
     
    //call StoreInteger(udg_GC, I2S(H2I(Timer)), "ID", N)
    call HashSystemInteger(H2I(Timer), N)
    //call BJDebugMsg( "缓存赋值完成" )
    call TimerStart(Timer, 0.01, true, function Bullet_Action)
    //call BJDebugMsg( "计时器正常开启" )
     
    set Unit = null
    set Timer = null
    return udg_Bullet_Unit[N]
endfunction
[/jass]
回复

使用道具 举报

发表于 2009-8-11 21:58:11 | 显示全部楼层
hash函数太容易产生碰撞,数据一多可能导致长期查表,和直接查8192个数据效率比提高不了多少。

另外储存hashdata的函数,如果同一余数的800个位置都被填满了,会出现死循环。

弹幕函数懒得看了,这里的人都很懒显然……

BTW,这东东和TBA啥关系??
回复

使用道具 举报

发表于 2009-8-12 11:49:14 | 显示全部楼层
既然是用timer为什么不直接用TimerDataSys呢.......

无耻地给lz发个广告:http://bbs.islga.org/read-htm-tid-26015-fpage-6.html

拿TDS就是这样做弹幕的.......
回复

使用道具 举报

发表于 2009-8-12 13:41:57 | 显示全部楼层
引用楼主sakurawarskula于2009-08-11 18:28发表的 FCS自制弹幕函数+自制HashSystem【高手帮忙测试下效率和检查下】 :
但是缺点就是需要用到一个缓存~虽然只有一个integer数据需要传递但是想到以前网上听说GC在Timer下效率比数组慢100倍.

hash也比数组慢100倍
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-5-6 05:38 , Processed in 0.237868 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表