Animated Number Ticker

Posted by bryan.vaccaro, Posted on December 13, 2011

2 votes

I wrote this snippet as a proof of concept for a score/time keeper in a game I'm currently working on.

The createTicker() function takes two parameters: a number, and the number of digits you want the display to be. It then generates a 'card' for each digit, based on the width and height of the number font + padding.

The increment() function will increase the value of the number, and you can set a timer to increment the value every second to act as a game timer display. A decrement() function would behave pretty much the same way but in reverse, and a jumpToNumber() function would act similar as well.

You can change fontsize, paddingwidth, paddingheight, and space to almost anything and it'll render properly. I didn't include any real error checking in this code snippet, so if you have a 2 digit display increment past 99, it's going to break. It's very easy to check for that sort of stuff if you wish to include this in your project, though.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
--CUT HERE
getmetatable('').__index = function(str,i) return string.sub(str,i,i) end
 
 
local createTicker = function(number,digits)
 
        local localGroup = display.newGroup()
 
        --format the number with leading zeroes equivilent to the 'digits' parameter
        --i.e. displaying the number 123 on a 6 digit display results in: 000123
        str = string.format("%0"..digits.."d", number)
        
        
        
        --get the width of a digit then remove it from display/memory   
        local fontsize = 78
        
        local temp = display.newText(str[1],10, 10, native.systemFont, fontsize)
        numwidth = temp.contentWidth
        numheight = temp.contentHeight
        temp:removeSelf()               
        
        --padding on digits
        paddingwidth=8
        paddingheight=8
        
        --space between cards
        space=8 
        
        --height of digit card
        width=numwidth+(paddingwidth*2)
        height=numheight+(paddingheight*2)
        
        
        --loop through and create a card for each digit
        for i=1,digits do
                local numgrp = display.newGroup()
                
                numgrp:setReferencePoint(display.TopLeftReferencePoint)
                
                --create the background
                local bg = display.newRect(0,0,width,height)
                bg:setFillColor(255,255,255)
                
                bg.x = (width*i)+(space*i)
                bg.y = 0
                
                numgrp:insert(bg)
 
                --create the digit and center it on the bg
                local num = display.newText(str[i],(width*i)+(space*i)-numwidth/2, -(height/2)+paddingheight, native.systemFont, fontsize)
                                
                --set the color of the digit
                num:setTextColor(255,0,0)
        
                numgrp:insert(num)
                
                --insert the card into the localGroup
                localGroup:insert(numgrp)
        end
 
        --set the position of the ticker
        localGroup.y = 200
 
 
        localGroup.increment = function()
                --increment number
                local newnum = tonumber(str) + 1
                --print("Incrementing to:                   " .. newnum)
                
                --create a string from the new number
                local newstr = string.format("%0"..digits.."d",newnum)
 
                for index=1,#str do
                        
                        --only flip cards that are changing number
                        if str[index] ~= newstr[index] then
                                --set the new card to slide into the position of the current card
                                destination = localGroup[index].y
                                
                                local numgrp = display.newGroup()
                                
                                numgrp:setReferencePoint(display.TopLeftReferencePoint)
                
                                local bg = display.newRect(0,0,width,height)
                                bg:setFillColor(255,255,255)
                                
                                bg.x = (width*index)+(space*index)
                                bg.y = 0
                                
                                numgrp:insert(bg)
                                
                                --create the new digit  
                                local num = display.newText(newstr[index],(width*index)+(space*index)-numwidth/2, -(height/2)+paddingheight, native.systemFont, fontsize)
                                
                                --set number to a random color. useful to see what's going on
                                --num:setTextColor(math.random(1,255),math.random(1,255),math.random(1,255))    
                                
                                --set it to black
                                num:setTextColor(0,0,0) 
                                
                                numgrp:insert(num)
                                
                                --set the new card above the current number
                                numgrp.y = localGroup[index].y - localGroup[index].contentHeight
                                
                                --start the card out invisible
                                numgrp.alpha = 0
                                
                                localGroup:insert(numgrp)
                        
                                --when the transition is complete, remove the old number from the localGroup and insert the new number into it
                                --then update the number string
                                local transitionHandler = function()
                                        localGroup:remove(index)
                                        localGroup:insert(index,numgrp)
                                        str = newstr                                    
                                end
                                
                                --speed of the transition should be lower than the timer interval 
                                local speed = 500
                                
                                --transition the two cards
                                local from = transition.to(localGroup[index],{y=localGroup[index].y+localGroup[index].contentHeight,alpha=0,time=speed, onComplete=transitionHandler})
                                local to = transition.to(numgrp,{y=destination,alpha=1,time=speed})
                        end
                end
        end
        
        --return the localGroup so you can call methods on it
        return localGroup
end
 
 
--create a new ticker
--parameters: number to start from, number of digits
--it doesn't do any error checking, so number must fit into the digits specified
local ticker = createTicker(10,4)
 
--increment the ticker one time
--ticker.increment()
 
--start incrementing indefinitely
--there's no error checking, so once it runs out of digits to change it will break
timer.performWithDelay(1000,ticker.increment,0)
 
--END CUT HERE


Replies

quadworks
User offline. Last seen 21 hours 59 min ago. Offline
Joined: 25 Oct 2010

Nice one.

You could change line 124 to something like this:

1
local from = transition.to(localGroup[index],{y=localGroup[index].y+localGroup[index].contentHeight*.75,alpha=0,time=speed, onComplete=transitionHandler,height=localGroup[index].contentHeight*.75})

To have the digit moving down bend a bit. Looks funny though :-)

Best J.

fava's picture
fava
User offline. Last seen 9 hours 52 min ago. Offline
Joined: 21 Feb 2011

Cool! Thanks for sharing!