• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Is there a way to reduce arrow key input delay

Status
Not open for further replies.

Deleted member 219079

D

Deleted member 219079

I would love to make something which uses arrow keys, but there's this horrible delay between keystrokes.

I could make W A S D keys to bind them to abilities and trigger via that, would that be any faster?
 

Deleted member 219079

D

Deleted member 219079

Yes, but then you lose the "while button is held" functionality.
Oh you're right..

I think the sharpcraft guys might be able to do a workaround; they already have mouse position tracking.
I'm a bit doubtful on that one, but hope they do it..
 
Sadly, that isn't possible. Keyboard actions must be sync'd, which is why they take forever to respond.

Abilities might work, but as ruler said, you lose some functionality. Sadly, due to battle.net's dated system, it is difficult to deal with arrow keys. In some games, e.g. WoW, they'll have direct response to keyboard actions, and sync only afterward (so there won't be any delay from the player's perspective, but you'll appear slightly behind where you actually are on other people's screens, until you get sync'd into the proper place ofc). Idk, perhaps it could be possible in Wc3 but I haven't tested it. Either way, it would likely be impossible to prevent desyncs since wc3 is really temperamental about out-of-sync movement.
 

Deleted member 219079

D

Deleted member 219079

*sigh* motivated from pnf's post I was sure call TriggerRegisterPlayerEvent(t, GetLocalPlayer(), EVENT_PLAYER_ARROW_UP_DOWN) would be faster (the get local player)

it made no difference..
 
Level 15
Joined
Oct 29, 2012
Messages
1,474
First you should know that GUI is slower than JASS
BJs are slow alo
So you may use JASS better or just convert it or convert the whole map after using GUI
Second, there is no way to avoid Warcraft Desync, There will be no delay ( Or we can say there is, but very very tiny ), if the host and players have a low ping ( From 1 to 100 ) , Otherwise there will be many bugs ... in addition, There is no way to reduce delays in games but improving the internet ;)

Since I play my own ARROW-KEYS-Platformer map locally with my brother, none of us noticed any delay... SEE ? It's only ping, or maybe GUI triggering which can cause all this

I might have helped

Good luck
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
Sorry but your post wasnt helpful at all. If you know how things work behind the scenes, you know that sync rate is the same as your ping to host(hence no delay in singleplayer maps)

You are also limited by the engine and fact that wc3 uses battle.net 1.0, which is ancient
 

Deleted member 219079

D

Deleted member 219079

(hence no delay in singleplayer maps)
There's still a delay :/ E.g. unit starts to move after I've tapped a key. But I have to tap it fast before the move animation starts. I think it's roughly about tenth of a second.
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
First you should know that GUI is slower than JASS
BJs are slow alo
So you may use JASS better or just convert it or convert the whole map after using GUI
Second, there is no way to avoid Warcraft Desync, There will be no delay ( Or we can say there is, but very very tiny ), if the host and players have a low ping ( From 1 to 100 ) , Otherwise there will be many bugs ... in addition, There is no way to reduce delays in games but improving the internet ;)

Since I play my own ARROW-KEYS-Platformer map locally with my brother, none of us noticed any delay... SEE ? It's only ping, or maybe GUI triggering which can cause all this

I might have helped

Good luck

Nope.

1. GUI code is "slower" because there are more function calls, which a bloated code. It does not affect the actual speed of execution, and has no effect on arrow key input delay.
2. While you don't notice arrow key input delay, many of us do. Even in singleplayer maps. When you compare it to actual platformer games, you should see a noticeable difference. Go launch any platformer game you can find, and tap tap tap left or right a few times to observe the character movement. Now do the same in a Warcraft 3 platformer.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,192
There's still a delay :/ E.g. unit starts to move after I've tapped a key. But I have to tap it fast before the move animation starts. I think it's roughly about tenth of a second.
The command still has to be synchronized as believe it or not, you do run a host server when playing single player. In fact you can even get the "You have been disconnected" error in single player due to your host dropping you (a lot of people did not believe it when the one guy posted about it).

I am not sure but maybe host robots can alter such delays as they could be based on how the server synchronizes them (it could wait X seconds and then ship all press responses at once to all clients).

In any case there would always be at least a delay of the time from client to host plus the time from host to the worst (highest ping) client. Anything above that is added on due to synchronization or just how they decided to implement button presses.
 

Deleted member 219079

D

Deleted member 219079

It's always good to post your movement trigger
I used GUI arrow keyed trigger in my 2D Warcraft game, EVEN GUI ran it fast ^^ There might be some desync'ment parts in your trigger

Module which I'll use on any struct using key input:
JASS:
library Keys initializer init
    globals
        constant integer KEY_RIGHT = 0
        constant integer KEY_UP = 1
        constant integer KEY_LEFT = 2
        constant integer KEY_DOWN = 3
        boolean array KEY
        real array KEY_ANGLE
    endglobals
    private function init takes nothing returns nothing
        set KEY_ANGLE[KEY_RIGHT] = 0*bj_DEGTORAD
        set KEY_ANGLE[KEY_UP] = 90*bj_DEGTORAD
        set KEY_ANGLE[KEY_LEFT] = 180*bj_DEGTORAD
        set KEY_ANGLE[KEY_DOWN] = 270*bj_DEGTORAD
    endfunction
    //! textmacro FuncKey takes KEY, FNAME
        private static method $FNAME$Down takes nothing returns boolean
            set KEY[KEY_$KEY$] = true
            call thistype.onKeyHit()
            return false
        endmethod
        private static method $FNAME$Up takes nothing returns boolean
            set KEY[KEY_$KEY$] = false
            call thistype.onKeyHit()
            return false
        endmethod
    //! endtextmacro
    //! textmacro InitKey takes KEY, FNAME
        set t = CreateTrigger()
        call TriggerRegisterPlayerEvent(t, PLAYER, EVENT_PLAYER_ARROW_$KEY$_DOWN)
        call TriggerAddCondition(t, Condition(function thistype.$FNAME$Down))
        set t = CreateTrigger()
        call TriggerRegisterPlayerEvent(t, PLAYER, EVENT_PLAYER_ARROW_$KEY$_UP)
        call TriggerAddCondition(t, Condition(function thistype.$FNAME$Up))
    //! endtextmacro
    module KeyInput
        //! runtextmacro FuncKey("DOWN", "down")
        //! runtextmacro FuncKey("LEFT", "left")
        //! runtextmacro FuncKey("RIGHT", "right")
        //! runtextmacro FuncKey("UP", "up")
        private static method delayedInit takes nothing returns nothing
            local trigger t
            call DestroyTimer(GetExpiredTimer())
            //! runtextmacro InitKey("DOWN", "down")
            //! runtextmacro InitKey("LEFT", "left")
            //! runtextmacro InitKey("RIGHT", "right")
            //! runtextmacro InitKey("UP", "up")
            set t = null
        endmethod
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(), 0, false, function thistype.delayedInit)
        endmethod
    endmodule
endlibrary

My movement trigger:
JASS:
library Movement requires Keys, MovingSystem, IsDestructableTree
    globals
        private boolean B
        private rect R = Rect(0,0,0,0)
    endglobals
    private function NoTreesEnum takes nothing returns nothing
        set B = false
    endfunction
    private function NoTreesFilter takes nothing returns boolean
        return IsTreeAlive(GetFilterDestructable())
    endfunction
    private function NoTrees takes real x, real y, real radius returns boolean
        call SetRect(R, x-radius, y-radius, x+radius, y+radius)
        set B = true
        call EnumDestructablesInRect(R, Filter(function NoTreesFilter), function NoTreesEnum)
        return B
    endfunction
    private struct MoveQueue extends array
        real angle
        static integer max = -1
        method destroy takes nothing returns nothing
            local integer index = this
            loop
                exitwhen index+1 >= max
                set thistype[index].angle = thistype[index+1].angle
                set index = index + 1
            endloop
            set max = max - 1
        endmethod
    endstruct
    private struct Movement
        private static real angle = 270
        private static integer keys = 0
        private static integer maxQueue = 0
        private static real speed = 128
        private static real uSpeed = 350
        private static real walkTime = speed/(uSpeed+5)
        private static integer standIndex = 0
        private static integer moveIndex = 10
        private static real halfway = 180*bj_DEGTORAD
        private static real full = 360*bj_DEGTORAD
        private static boolean stopped = true
        private static unit u
        private static method onStop takes nothing returns nothing
            local real x
            local real y
            set stopped = MoveQueue.max == -1
            if stopped then
                call SetUnitAnimationByIndex(u, standIndex)
                call DestroyTimer(GetExpiredTimer())
            else
                set x = GetUnitX(u)
                set y = GetUnitY(u)
                if NoTrees(x+speed*Cos(MoveQueue[0].angle),y+speed*Sin(MoveQueue[0].angle),speed) then
                    call MoveUnit(u, x, y, MoveQueue[0].angle, uSpeed, speed)
                    call TimerStart(GetExpiredTimer(), walkTime, false, function thistype.onStop)
                else
                    set stopped = true
                    call SetUnitAnimationByIndex(u, standIndex)
                    call DestroyTimer(GetExpiredTimer())
                endif
                call MoveQueue[0].destroy()
            endif
            if keys > 0 then
                call onKeyHit.evaluate()
            endif
        endmethod
        private static method onKeyHit takes nothing returns nothing
            local integer index = KEY_UP
            local real x
            local real y
            set keys = 0
            set angle = 0
            loop
                if KEY[index] then
                    set angle = angle + KEY_ANGLE[index]
                    set keys = keys + 1
                endif
                exitwhen index == 3
                set index = index + 1
            endloop
            if KEY[KEY_RIGHT] then
                if keys > 0 then
                    if angle / keys <= halfway then
                        set angle = angle + 0
                    else
                        set angle = angle + full
                    endif
                else
                    set angle = KEY_ANGLE[KEY_RIGHT]
                endif
                set keys = keys + 1
            endif
            if keys == 0 then
                return
            endif
            set angle = angle / keys
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            if NoTrees(x+speed*Cos(angle),y+speed*Sin(angle),speed) then
                if stopped then
                    call SetUnitAnimationByIndex(u, moveIndex)
                    call MoveUnit(u, x, y, angle, uSpeed, speed)
                    set stopped = false
                    call TimerStart(CreateTimer(), walkTime, false, function thistype.onStop)
                elseif MoveQueue.max < maxQueue then
                    set MoveQueue.max = MoveQueue.max + 1
                    set MoveQueue[MoveQueue.max].angle = angle
                endif
            endif
        endmethod
        implement KeyInput
        private static method delayedInit takes nothing returns nothing
            call DestroyTimer(GetExpiredTimer())
            set u = ADVENTURER
            call SetCameraTargetController(u, 0, 0, false)
        endmethod
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(), 0, false, function thistype.delayedInit)
        endmethod
    endstruct
endlibrary
 
Level 14
Joined
Jun 27, 2008
Messages
1,325
It's always good to post your movement trigger
I used GUI arrow keyed trigger in my 2D Warcraft game, EVEN GUI ran it fast ^^ There might be some desync'ment parts in your trigger

Dude, this has NOTHING to do with GUI/Jass. Keyevents have delay in multiplayer because they have to get synced, meaning that clients wait till the packages are sent over the network. Obviously this delay is larger in Battlenet than when you play singleplayer games (as syncing isnt required in singleplayer).

First you should know that GUI is slower than JASS
BJs are slow alo
So you may use JASS better or just convert it or convert the whole map after using GUI
It seems that you just repeat what you read somewhere, but dont actually understand it. Converting GUI to Jass has zero effect. Wc3 automatically does that when you save the map in the worldeditor, you just dont see it because it keeps a copy of the GUI triggers.
The fact that GUI and BJs are a bit slower than Jass natives is correct, but completely irrelevant for most purposes because they are only a very very very tiny little bit slower. The design of your code is much more important for the performance, for example if you use clever indexing instead of looping through arrays all the time, etc.
 

Deleted member 219079

D

Deleted member 219079

But is there a way to make the system I posted here respond to arrow key event faster?
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,192
(as syncing isnt required in singleplayer).
Depends on how the game is programmed. It may still try and sync them since even single player runs via a host. However the delay is as good as 0 and might not even involve kernel level routing. However I do know it is possible to get the "You have been disconnected" error while playing single player. Syncing in single player would certainly explain why it performs so badly even then.

But is there a way to make the system I posted here respond to arrow key event faster?
Short of a Tardis, no.

You can try and take some corrective action. For example if you know the release key has X latency and stops a unit from moving, you can let the unit move until the key release event fires and then move it back to the position it was at current time - X. This will produce kind of ugly results but might allow players to more accurately control stuff.

Like wise if you know pressing a key has X latency, then when it is pressed you can carry out actions such that it seems it has been pressed for X seconds already despite only just being pressed. Again in a movement system this would result in a very ugly jump forward however it will produce average results that seem to have less latency.
 
Status
Not open for further replies.
Top