HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

GameClock

04-14-2009, 10:07 AM#1
Pyrogasm
I needed a GetElapsedGameTime() function for a system I plan on making in the future, so I decided to make it cool and make a library for this. Thus, I give you the GameClock library:
Collapse GameClock:
library GameClock initializer Init
    //============================================================================================
    // GameClock library (Version 1.02)
    //   by Pyrogasm (4/14/09)
    //
    // - The purpose of this library is to give a standardized platform for tracking
    //   the current duration of a game using a global timer and TimerGetElapsed().
    //
    // - The output can either be a real number (with which you may do whatever you
    //   want), or a string in the format HH:MM:SS.
    //
    // - The boolean "Exact" determines if the output should be the full elapsed time,
    //   or if it should be truncated, showing the time as a clock would.
    //
    // - If you know that you will only ever use exact or truncated values, you can
    //   shorten GetElapsedGameTime into one line to make it inline-friendly and save
    //   yourself a few nanoseconds of code execution.
    //
    // - Version 1.00: Release
    // - Version 1.01: Removed some documentation, removed unnecessary loops, altered
    //                 GAME_LENGTH
    // - Version 1.02: Inlined CreateTimer() call, removed example library
    //============================================================================================

    globals
        private constant real GAME_LENGTH = 36000.00 //10 hours
        private constant real GAME_SPEED = 1.00 //Might be changed if game speed is altered with UI files

        //The point of no return
        private timer Clock = CreateTimer()
    endglobals

    function GetElapsedGameTime takes boolean Exact returns real
        local real E = TimerGetElapsed(Clock)*GAME_SPEED

        if not Exact then
            set E = R2I(E)
        endif

        return E
    endfunction

    function GetElapsedGameTimeString takes boolean Exact returns string
        local real E = TimerGetElapsed(Clock)*GAME_SPEED
        local integer H = 0
        local integer M = 0
        local string S
        
        set H = R2I(E/3600.00)
        set E = E-3600.00*H

        set M = R2I(E/60.00)
        set E = E-60.00*M


        if H < 10 then
            set S = "0" + I2S(H) + ":"
        else
            set S = I2S(H) + ":"
        endif

        if M < 10 then
            set S = S + "0" + I2S(M) + ":"
        else
            set S = I2S(M) + ":"
        endif

        if E < 10 then
            set S = S + "0"
        endif

        if Exact then
            set S = S + R2S(E)
        else
            set S = S + I2S(R2I(E))
        endif


        return S
    endfunction


    private function Init takes nothing returns nothing
        call TimerStart(Clock, GAME_LENGTH, false, null)
    endfunction
endlibrary

In theory this is useful to someone other than me.
04-14-2009, 04:55 PM#2
Rising_Dusk
This is a good idea, but you have some poor implementation for parts.
Collapse JASS:
        loop
            exitwhen E < 3600.00
            set E = E-3600.00
            set H = H+1
        endloop
These sections can be simply replaced by:
Collapse JASS:
set H = R2I(E/3600.)
set E = E - (3600.*H)
Similar for the minutes section.
Collapse JASS:
public timer Clock = null
The GAME_LENGTH parameter should probably be something far bigger than a day just because it does not matter. Maybe like 3 days just for the sake of it.

Also, the clock timer should be private. There is no reason the user would ever have to access it other than to screw it up by destroying/pausing/restarting/etc.
Collapse JASS:
public timer Clock = null
Should be:
Collapse JASS:
private timer Clock = CreateTimer()

Also, could you make your first post use [hiddenjass][/hiddenjass] tags instead? It's kind of long right now. Doesn't really matter either way, though.
04-14-2009, 05:24 PM#3
Anitarf
I see a problem with the GameClockDisplay library: the user will most likely only ever use one of the three display methods provided, so it makes no sesne to have a library providing all three of them, instead each should be it's own library (at least those methods that deserve a library).
04-14-2009, 05:28 PM#4
Rising_Dusk
I think the display library is silly anyways since most users will want to use the string somewhere in a multiboard or in the map of their choosing which may not coincide with your options. I wouldn't even have it there, personally.
04-14-2009, 11:24 PM#5
Pyrogasm
I made the display library more as an example/easy-to-implement visual thing. That's why it's not part of the actual library. If I wanted to make it into a sensible one I'd have used Textmacroes or something weird to only implement what the user wanted.

Regarding the public timer: I intended it to be public in the first place so that it could be linked with TimerDialogs, but they can only show counting down (not up). I just forgot to make it private.

Fixed everything up (including the loops) and used some HiddenJass tags. I think code posts look so empty if it's all inside HiddenJass tags, so I kept the main library in normal tags.
04-15-2009, 12:21 AM#6
Rising_Dusk
Quote:
Originally Posted by Pyrogasm
I made the display library more as an example/easy-to-implement visual thing. That's why it's not part of the actual library. If I wanted to make it into a sensible one I'd have used Textmacroes or something weird to only implement what the user wanted.
It doesn't really matter, if you want to present it in the first post as a supplementary library, then it must also adhere to the submission requirements.
Quote:
Originally Posted by Pyrogasm
Fixed everything up (including the loops) and used some HiddenJass tags. I think code posts look so empty if it's all inside HiddenJass tags, so I kept the main library in normal tags.
You forgot to inline the CreateTimer() call.

Also, if you think they are empty, it is because you are not putting enough effort into formating your posts. Check out the LastOrder library or something for an idea of how to present a library with content in the first post.
04-15-2009, 12:30 AM#7
Pyrogasm
Bah. Removed GameClockDisplays because I don't want to fix it up and apparently examples have to be perfect.

Cheerio.


Because I still think it's useful, here's the example library I wrote to show 3 different ways to display the elapsed game time:
Collapse JASS:
library GameClockDisplays initializer Init uses GameClock
    //============================================================================================
    // GameClockDisplays (Version 1.00)
    //   by Pyrogasm (4/13/09)
    //
    // - The purpose of this library is to provide a few standard ways in which the
    //   elapsed game time can be displayed: using a multiboard, player resources,
    //   and/or a texttag
    //
    // - The multiboard will always be able to be maximized, though it starts with a
    //   MultiboardMinimize() call. The multiboard's title window will also
    //   periodically slightly change size, which is also unavoidable; the width of
    //   the multiboard is only applied if it is maximized.
    //
    // - Using Player Resources to display the elapsed time requires you to alter the
    //   GamePlay constants/game interface to change the mouseover text and icons to
    //   whatever you see fit.
    //
    // - When using the texttag, its size and text ought not be altered outside of this
    //   system, as they will always be reset upon the expiring of UpdateTimer
    //
    // - ClockMB (multiboard) and ClockTT (texttag) are public globals so that you may
    //   alter them as you see fit (placement, additional rows/columns, etc.)
    //
    // - Feel free to screw with any part of this library to suit your needs; just
    //   don't re-release it under your own name.
    //============================================================================================

    globals
        //All
        private constant real START_DELAY = 0.01 //Never 0.00!
        private constant real UPDATE_INTERVAL = 1.00 //Why would this ever be otherwise?
        private constant boolean EXACT_TIME = false

        //Multiboard
        private constant boolean USE_MULTIBOARD = true
        private constant string DISPLAY_TITLE = "Elapsed Game Time: " //Include any spaces

        //Resources
        private constant boolean USE_RESOURCES = true
        private constant integer LAST_PLAYER_SLOT = 11 //Last slot you need to show the time for

        //TextTag
        private constant boolean USE_TEXTTAG = true
        private constant string DISPLAY_TEXT = "Elapsed Game Time:  " //Include any spaces
        private constant real DISPLAY_HEIGHT = 0.023 //Refer to TextTagSize2Height
        private constant real CREATE_HEIGHT_OFFSET = 0.00
        private constant real CREATE_X = 0.00
        private constant real CREATE_Y = 0.00


        //The point of no return
        public multiboard ClockMB = null
        public texttag ClockTT = null
        private timer UpdateTimer = null
    endglobals


    private function Update takes nothing returns nothing
        local integer J
        local string T

        if USE_MULTIBOARD then
            call MultiboardSetTitleText(ClockMB, DISPLAY_TITLE+GetElapsedGameTimeString(EXACT_TIME))
        endif

        if USE_RESOURCES then
            set T = GetElapsedGameTimeString(EXACT_TIME)
            set J = 0
            loop
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_GOLD, S2I(SubString(T, 0, 2)))
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_LUMBER, S2I(SubString(T, 3, 5)))
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_FOOD_USED, S2I(SubString(T, 6, 8)))
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_FOOD_CAP, 0)

                set J = J+1
                exitwhen J > LAST_PLAYER_SLOT
            endloop
        endif

        if USE_TEXTTAG then
            call SetTextTagText(ClockTT, DISPLAY_TEXT+GetElapsedGameTimeString(EXACT_TIME), DISPLAY_HEIGHT)
        endif
    endfunction

    private function DelayedInit takes nothing returns nothing
        local integer J
        local string T

        if USE_MULTIBOARD then
            set ClockMB = CreateMultiboard()
            call MultiboardSetTitleText(ClockMB, DISPLAY_TITLE+GetElapsedGameTimeString(EXACT_TIME))
            call MultiboardDisplay(ClockMB, true)
            call MultiboardMinimize(ClockMB, true)
        endif

        if USE_RESOURCES then
            set T = GetElapsedGameTimeString(EXACT_TIME)
            set J = 0
            loop
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_GOLD, S2I(SubString(T, 0, 2)))
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_LUMBER, S2I(SubString(T, 3, 5)))
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_FOOD_USED, S2I(SubString(T, 6, 8)))
                call SetPlayerState(Player(J), PLAYER_STATE_RESOURCE_FOOD_CAP, 0)

                set J = J+1
                exitwhen J > LAST_PLAYER_SLOT
            endloop
        endif

        if USE_TEXTTAG then
            set ClockTT = CreateTextTag()
            call SetTextTagText(ClockTT, DISPLAY_TEXT+GetElapsedGameTimeString(EXACT_TIME), DISPLAY_HEIGHT)
            call SetTextTagPos(ClockTT, CREATE_X, CREATE_Y, CREATE_HEIGHT_OFFSET)
            call SetTextTagVisibility(ClockTT, true)
        endif

        if USE_MULTIBOARD or USE_TEXTTAG or USE_RESOURCES then
            set UpdateTimer = CreateTimer()
            call TimerStart(UpdateTimer, UPDATE_INTERVAL, true, function Update)
        endif
    endfunction

    private function Init takes nothing returns nothing
        call TimerStart(CreateTimer(), START_DELAY, false, function DelayedInit)
    endfunction
endlibrary
04-15-2009, 12:44 AM#8
Rising_Dusk
Rawr, approved.
04-15-2009, 01:19 PM#9
Anachron
What about an converter that converts the elapsed gametime to the ingametimeofday?^^ :P
04-15-2009, 02:45 PM#10
Anitarf
Quote:
Originally Posted by Anachron
What about an converter that converts the elapsed gametime to the ingametimeofday?^^ :P
You mean like GetTimeOfDay?
04-15-2009, 06:20 PM#11
Anachron
But that gets the current time, not the time after the mapstart at 3 seconds later for example.
04-15-2009, 06:33 PM#12
Rising_Dusk
The time of day is independent from the elapsed game time. If you wanted to correlate the two, you'd need to start them at the same time and monitor any manual changes to time of day.

I mean, I see what you're getting at, you want to count how many 'game' days have passed since the beginning of the map, and to do that you'd likely need another library dedicated to that requiring this one.
04-15-2009, 06:52 PM#13
Alevice
Yeah, actually one that may detect when time of the day becomes 0.0 or soemthing like that again.
04-15-2009, 07:25 PM#14
Anachron
Hmm I thought this would be additionally in this package, but I see its another libraby which actually can be use his one as basic.
04-16-2009, 04:41 AM#15
Pyrogasm
Mindworx suggested a similar thing in IRC a few days ago, and I think I might just do that soon. It may or may not need to be based on this library, though. If GetFloatGameState(GAME_STATE_TIME_OF_DAY) does what it should, then that might not even require this library at all.