@@ -12,24 +12,54 @@ class App
1212 POWER_MODE_ACTIVATION_THRESHOLD : 250
1313 STREAK_TIMEOUT : 10 * 1000
1414
15+ MAX_PARTICLES : 500
16+ PARTICLE_NUM_RANGE : [5 .. 12 ]
17+ PARTICLE_GRAVITY : 0.075
18+ PARTICLE_ALPHA_FADEOUT : 0.96
19+ PARTICLE_VELOCITY_RANGE :
20+ x : [- 1 , 1 ]
21+ y : [- 3.5 , - 1.5 ]
22+
23+ PARTICLE_COLORS :
24+ " text" : [255 , 255 , 255 ]
25+ " text.xml" : [255 , 255 , 255 ]
26+ " keyword" : [0 , 221 , 255 ]
27+ " variable" : [0 , 221 , 255 ]
28+ " meta.tag.tag-name.xml" : [0 , 221 , 255 ]
29+ " keyword.operator.attribute-equals.xml" : [0 , 221 , 255 ]
30+ " constant" : [249 , 255 , 0 ]
31+ " constant.numeric" : [249 , 255 , 0 ]
32+ " support.constant" : [249 , 255 , 0 ]
33+ " string.attribute-value.xml" : [249 , 255 , 0 ]
34+ " string.unquoted.attribute-value.html" : [249 , 255 , 0 ]
35+ " entity.other.attribute-name.xml" : [129 , 148 , 244 ]
36+
1537 EXCLAMATION_EVERY : 10
1638 EXCLAMATIONS : [" Super!" , " Radical!" , " Fantastic!" , " Great!" , " OMG" ,
1739 " Whoah!" , " :O" , " Nice!" , " Splendid!" , " Wild!" , " Grand!" , " Impressive!" ,
1840 " Stupendous!" , " Extreme!" , " Awesome!" ]
1941
2042 currentStreak : 0
2143 powerMode : false
44+ particles : []
45+ particlePointer : 0
46+ lastDraw : 0
2247
2348 constructor : ->
2449 @$streakCounter = $ " .streak-container .counter"
2550 @$exclamations = $ " .streak-container .exclamations"
2651 @$reference = $ " .reference-screenshot-container"
52+ @$editor = $ " #editor"
53+ @canvas = @ setupCanvas ()
54+ @canvasContext = @canvas .getContext " 2d"
2755 @$download = $ " .download-button"
2856
2957 @$body = $ " body"
3058
3159 @debouncedSaveContent = _ .debounce @saveContent , 300
3260 @debouncedEndStreak = _ .debounce @endStreak , @STREAK_TIMEOUT
61+ @throttledShake = _ .throttle @shake , 100 , trailing : false
62+ @throttledSpawnParticles = _ .throttle @spawnParticles , 25 , trailing : false
3363
3464 @editor = @ setupAce ()
3565 @ loadContent ()
@@ -38,10 +68,14 @@ class App
3868 @editor .getSession ().on " change" , @onChange
3969 $ (window ).on " beforeunload" , -> " Hold your horses!"
4070
41- $ (" .instructions-container, .instructions-button" ).on " click" , => $ (" body" ).toggleClass " show-instructions"
71+ $ (" .instructions-container, .instructions-button" ).on " click" , ->
72+ $ (" body" ).toggleClass " show-instructions"
73+
4274 @$reference .on " click" , => @$reference .toggleClass " active"
4375 @$download .on " click" , @onClickDownload
4476
77+ window .requestAnimationFrame ? @onFrame
78+
4579 setupAce : ->
4680 editor = ace .edit " editor"
4781
@@ -51,16 +85,28 @@ class App
5185 editor .getSession ().setMode " ace/mode/html"
5286 editor .session .setOption " useWorker" , false
5387 editor .session .setFoldStyle " manual"
88+ editor .$blockScrolling = Infinity
5489
5590 editor
5691
92+ setupCanvas : ->
93+ canvas = $ (" .canvas-overlay" )[0 ]
94+ canvas .width = window .innerWidth
95+ canvas .height = window .innerHeight
96+ canvas
97+
5798 loadContent : ->
5899 return unless (content = localStorage[" content" ])
59100 @editor .setValue content, - 1
60101
61102 saveContent : =>
62103 localStorage[" content" ] = @editor .getValue ()
63104
105+ onFrame : (time ) =>
106+ @ drawParticles time - @lastDraw
107+ @lastDraw = time
108+ window .requestAnimationFrame ? @onFrame
109+
64110 increaseStreak : ->
65111 @currentStreak ++
66112 @ showExclamation () if @currentStreak > 0 and @currentStreak % @EXCLAMATION_EVERY is 0
@@ -93,21 +139,63 @@ class App
93139 $exclamation .remove ()
94140 , 3000
95141
142+ getCursorPosition : ->
143+ {left , top } = @editor .renderer .$cursorLayer .getPixelPosition ()
144+ left += @editor .renderer .gutterWidth + 4
145+ {x : left, y : top}
146+
147+ spawnParticles : (type ) ->
148+ return unless @powerMode
149+
150+ {x , y } = @ getCursorPosition ()
151+ numParticles = _ (@PARTICLE_NUM_RANGE ).sample ()
152+ color = @ getParticleColor type
153+ _ (numParticles).times =>
154+ @particles [@particlePointer ] = @ createParticle x, y, color
155+ @particlePointer = (@particlePointer + 1 ) % @MAX_PARTICLES
156+
157+ getParticleColor : (type ) ->
158+ @PARTICLE_COLORS [type] or [255 , 255 , 255 ]
159+
160+ createParticle : (x , y , color ) ->
161+ x : x
162+ y : y + 10
163+ alpha : 1
164+ color : color
165+ velocity :
166+ x : @PARTICLE_VELOCITY_RANGE .x [0 ] + Math .random () *
167+ (@PARTICLE_VELOCITY_RANGE .x [1 ] - @PARTICLE_VELOCITY_RANGE .x [0 ])
168+ y : @PARTICLE_VELOCITY_RANGE .y [0 ] + Math .random () *
169+ (@PARTICLE_VELOCITY_RANGE .y [1 ] - @PARTICLE_VELOCITY_RANGE .y [0 ])
170+
171+ drawParticles : (timeDelta ) =>
172+ @canvasContext .clearRect 0 , 0 , @canvas .width , @canvas .height
173+
174+ for particle in @particles
175+ continue if particle .alpha <= 0.1
176+
177+ particle .velocity .y += @PARTICLE_GRAVITY
178+ particle .x += particle .velocity .x
179+ particle .y += particle .velocity .y
180+ particle .alpha *= @PARTICLE_ALPHA_FADEOUT
181+
182+ @canvasContext .fillStyle = " rgba(#{ particle .color .join " , " } , #{ particle .alpha } )"
183+ @canvasContext .fillRect Math .round (particle .x - 1 ), Math .round (particle .y - 1 ), 3 , 3
184+
96185 shake : ->
97- intensity = - (Math .random () * 5 + 5 )
98- x = intensity * (Math .random () > 0.5 ? - 1 : 1 )
99- y = intensity * (Math .random () > 0.5 ? - 1 : 1 )
186+ return unless @powerMode
100187
101- translate = " translate3D(#{ x} px, #{ y} px, 0)"
102- @$body .css
103- " webkit-transform" : translate
104- " transform" : translate
188+ intensity = 1 + 2 * Math .random () * Math .floor (
189+ (@currentStreak - @POWER_MODE_ACTIVATION_THRESHOLD ) / 100
190+ )
191+ x = intensity * (if Math .random () > 0.5 then - 1 else 1 )
192+ y = intensity * (if Math .random () > 0.5 then - 1 else 1 )
193+
194+ @$editor .css " margin" , " #{ y} px #{ x} px"
105195
106196 setTimeout =>
107- @$body .css
108- " webkit-transform" : " none"
109- " transform" : " none"
110- , 50
197+ @$editor .css " margin" , " "
198+ , 75
111199
112200 activatePowerMode : =>
113201 @powerMode = true
@@ -133,6 +221,16 @@ class App
133221 @ increaseStreak ()
134222 @ debouncedEndStreak ()
135223
136- @ shake () if @powerMode
224+ @ throttledShake ()
225+
226+ pos = if e .data .action is " insertText"
227+ e .data .range .end
228+ else
229+ e .data .range .start
230+
231+ token = @editor .session .getTokenAt pos .row , pos .column
232+
233+ _ .defer =>
234+ @ throttledSpawnParticles (token .type ) if token
137235
138236$ -> new App
0 commit comments