• 🏆 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!

timers in structs?

Status
Not open for further replies.
Level 17
Joined
Mar 21, 2011
Messages
1,597
hey,
i created a struct to control a cursor in a 2-dimensional grid. this is my first attempt.
I use TimerUtils and ArrowKeyEvent by Bribe.
I wonder if i can get rid of the loop inside of the periodic function by putting it into the struct and have direct access to the instance? Also, i couldnt manage to implement ArrowKey into the Cursor struct because of having 2 method operators? at least thats what i think. is there a way around that too?


JASS:
library PlayerLib initializer Init uses TimerUtils

    globals
        constant string IMG_PATH = "war3mapImported\\betacursor.tga"
    endglobals
   
    function periodic takes nothing returns nothing
        local Cursor c
        local integer i = 0
       
        loop
            set c = Cursor[i]
           
            set c.cursor_timer = c.cursor_timer + 0.05
            if c.cursor_timer >= 0.5 then
                if c.RIGHT == true then
                    call c.SetPos(c.cursor_x + 1, c.cursor_y)
                elseif c.LEFT == true then
                    call c.SetPos(c.cursor_x - 1, c.cursor_y)
                elseif c.UP == true then
                    call c.SetPos(c.cursor_x, c.cursor_y + 1)
                elseif c.DOWN == true then
                    call c.SetPos(c.cursor_x, c.cursor_y - 1)
                endif
            endif
           
            set i = i + 1
            exitwhen i == 8 // MAXPLAYERSLOTS
        endloop
    endfunction
   
    struct ArrowKeyMovement
   
        method onArrowKeyEvent takes integer arrow, boolean pressed returns nothing
            local Cursor c = Cursor[GetEventArrowKeyPlayerId()]
            local integer arrowkey = GetEventArrowKey()
            set c.cursor_timer = 0
            if arrowkey == ARROW_KEY_RIGHT then
                if pressed then
                    set c.RIGHT = true
                    call c.SetPos(c.cursor_x + 1, c.cursor_y)
                else
                    set c.RIGHT = false
                endif
            elseif arrowkey == ARROW_KEY_LEFT then
                if pressed then
                    set c.LEFT = true
                    call c.SetPos(c.cursor_x - 1, c.cursor_y)
                else
                    set c.LEFT = false
                endif
            elseif arrowkey == ARROW_KEY_UP then
                if pressed then
                    set c.UP = true
                    call c.SetPos(c.cursor_x, c.cursor_y + 1)
                else
                    set c.UP = false
                endif
            elseif arrowkey == ARROW_KEY_DOWN then
                if pressed then
                    set c.DOWN = true
                    call c.SetPos(c.cursor_x, c.cursor_y - 1)
                else
                    set c.DOWN = false
                endif
            endif
        endmethod
       
        implement ArrowKey
   
    endstruct

    struct Cursor
        image cursor
        integer cursor_x
        integer cursor_y
        real cursor_timer
        boolean UP = false
        boolean DOWN = false
        boolean LEFT = false
        boolean RIGHT = false
        static integer array instance
        readonly player owner
       
        /*method onArrowKeyEvent takes integer arrow, boolean pressed returns nothing
            if pressed then
                if GetEventArrowKey() == ARROW_KEY_RIGHT then
                    call this.SetPos(this.cursor_x + 1, this.cursor_y)
                endif
            endif
        endmethod*/
       
        static method operator [] takes integer playerid returns thistype
            return instance[playerid]
        endmethod
       
        method SetPos takes integer x, integer y returns nothing
            set this.cursor_x = x
            set this.cursor_y = y
            call SetImagePosition(this.cursor, x*16, y*16, 0)
        endmethod
       
        static method create takes player p returns thistype
            local thistype this = thistype.allocate()
            local string showcursor = ""
            set this.owner = p
            set instance[GetPlayerId(p)] = this
            if GetLocalPlayer() == p then
                set showcursor = IMG_PATH
            endif
            set this.cursor = CreateImage(showcursor, 32, 32, 0, 0, 0, 0, 0, 0, 0, 2)
            call SetImageRenderAlways(this.cursor, true)
            return this
        endmethod
       
        method destroy takes nothing returns nothing
            call this.deallocate()
        endmethod
       
        //implement ArrowKey
   
    endstruct

    private function Init takes nothing returns nothing
        call TimerStart(NewTimer(), 0.05, true, function periodic)
    endfunction

endlibrary
 

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Usually when you want to use timers with structs, you create a static function for the timer callback.
You can attach one integer to the timer with timerUtils. This integer refers to the instance of the struct.
When the static function is called by the expiring timer, you read the data and cast it into the struct type. Then you call the actual non-static timer function for this specific instance.

So the idea is:
JASS:
timer_function
      do stuff

static static_timer_function
      this = GetData(GetExpiredTimer)
      call this.timer_function

start_timer
     timer t = NewTimer()
     startTimer(t, function static_timer_function)
     SetData(t, this)

The syntax of my code is totally wrong, but I hope it gives you an idea how it works.
 
Status
Not open for further replies.
Top