HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

[script] ScrollingText

02-17-2013, 10:38 PM#1
Deaod
A library for scrolling text upwards.

Uses vJass.

Changelog:

12/27/2012 - Version 2.2.1
- optimizations (building the text to display only when needed)
- refactoring for better readability

12/27/2012 - Version 2.2.0
- removed tokenization and method addEx
- renamed struct from ScrollText to ScrollingText to match the library name
- removed counting calls to DisplayTimedTextToPlayer (debug-only before)
- added comments to the main logic

08/12/2012 - Version 2.1.0
- now automatically delays destroying until after finishing displaying the text

08/12/2012 - Version 2.0.0
- major refactoring for code cleanliness, descriptive names, better interface
- fixed the major caveat of lag after too many calls to DisplayTimedTextToPlayer by reducing calls to that function by a factor of at best 15

03/26/2009 - Version 1.0.0
- initial release



Collapse JASS:
// *************************************************************
// *             Scrolling Text -- Version 2.2.1
// *                        by Deaod
// *************************************************************
// *
// *    CREDITS:
// *        - Anitarf (valuable research about in-game messages)
// *        - UnMi, overcold_ice (inspiration)
// *        - Vexorian (JassHelper)
// *        - PitzerMike (JassNewGenPack)
// *        - Pipedream (Grimoire)
// *        - SFilip (TESH)
// *
// *    HOW TO USE:
// *        * declare a variable of type ScrollingText
// *
// *        * use ScrollingText.create() to create a new instance
// *
// *        * add text to display using YourScrollingTextInstance.add(string toAdd)
// *            - toAdd is the actual text that should be displayed as credits.
// *            - make sure toAdd is not longer than a single line in-game.
// *
// *        * to display the ScrollingText, use YourScrollingTextInstance.display(real xOffset, real yOffset, real speed)
// *            - xOffset and yOffset move the point where the Credits are being spawned around
// *            - speed is the scrolling speed of the credits in lines per second
// *
// *************************************************************
library ScrollingText
    
    globals
        private constant    real    LINE_HEIGHT             = 1./15 // 1./15 seems to be the optimal value
        private constant    integer MAX_DISP_LINES          = 15    // 15 is suggested upper limit
        private constant    integer MAX_LINES_PER_INSTANCE  = 1023  // 
        private constant    real    TICK                    = 1./40 // in seconds
    endglobals
    
    struct ScrollingText
        private real speed
        private real scrollDistance
        private real xOff
        private real yOff
        private string linesDisplaying
        private string array linesToDisplay[MAX_LINES_PER_INSTANCE]
        private integer linesCount = 0
        
        private boolean running = false
        private boolean destroyWhenDone = false
        
        private static thistype array structs
        private static integer structsCount = 0
        private static timer structsTimer = CreateTimer()
        
        method add takes string toAdd returns nothing
            if linesCount >= MAX_LINES_PER_INSTANCE then
                debug call BJDebugMsg("ScrollingText.add(): MAX_LINES_PER_INSTANCE exceeded. Discarding following text.")
                return
            endif
            set linesToDisplay[linesCount] = toAdd
            if linesToDisplay[linesCount] == "" or linesToDisplay[linesCount] == null then // avoid displaying (null)
                set linesToDisplay[linesCount] = " "
            endif
            set linesCount = linesCount + 1
        endmethod
        
        private method regenerateLinesDisplaying takes integer currentLine returns nothing
        local integer index
            set index = IMinBJ(currentLine, MAX_DISP_LINES) // number of lines to display
            // lets gather the last 'index2' lines in 'linesDisplaying'
            set linesDisplaying = ""
            loop
                exitwhen index <= 0
                if currentLine - index < linesCount then // do we need to add more lines for padding?
                    set linesDisplaying = linesDisplaying + linesToDisplay[currentLine - index] // apparently not, so just take whats there.
                else
                    set linesDisplaying = linesDisplaying + " " // we do, so add a single whitespace
                endif
                if index > 1 then
                    set linesDisplaying = linesDisplaying + "\n" // add a newline character, unless were at the end
                endif
                set index = index - 1
            endloop
        endmethod
        
        private static method callback takes nothing returns nothing
        local integer index = structsCount - 1
        local integer lastLine
        local integer currentLine
        local thistype this
            loop
                exitwhen index < 0
                set this = structs[index]
                
                set lastLine = R2I(scrollDistance / LINE_HEIGHT) + 1
                set scrollDistance = scrollDistance + speed // scroll further
                set currentLine = R2I(scrollDistance / LINE_HEIGHT) + 1 // generate the line were currently on, offset by +1
                if lastLine < currentLine then // check whether we need to display a new line
                    call regenerateLinesDisplaying(currentLine)
                endif
                
                call ClearTextMessages()
                call DisplayTimedTextToPlayer(GetLocalPlayer(), xOff, yOff + (scrollDistance - R2I(scrollDistance / LINE_HEIGHT) * LINE_HEIGHT), 16*TICK, linesDisplaying)
                
                if currentLine > linesCount + MAX_DISP_LINES then
                    set running = false
                    set structsCount = structsCount - 1
                    set structs[index] = structs[structsCount]
                    if structsCount == 0 then
                        call PauseTimer(structsTimer)
                    endif
                    if destroyWhenDone then
                        call destroy()
                    endif
                endif
                
                set index = index - 1
            endloop
        endmethod
        
        method display takes real xOffset, real yOffset, real speed returns nothing
            if running == true then
                debug call BJDebugMsg("ScrollingText.display(): Can not display the same instance twice at the same time.")
                return
            endif
            set this.speed = speed * LINE_HEIGHT * TICK
            set scrollDistance = 0
            set xOff = xOffset
            set yOff = yOffset
            set running = true
            call regenerateLinesDisplaying(1)
            
            set structs[structsCount] = this
            if structsCount == 0 then
                call TimerStart(structsTimer, TICK, true, function thistype.callback)
            endif
            set structsCount = structsCount + 1
        endmethod
        
        method destroy takes nothing returns nothing
            if running then
                set destroyWhenDone = true
                return
            endif
            call deallocate()
        endmethod
    endstruct
    
endlibrary
Attached Images
File type: gifclear.gif (43 bytes)
02-19-2013, 01:45 PM#2
Anitarf
Hmm, not sure why you need support for multiple simultaneously running scrolling texts since only one can be on the screen at once anyway.