Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Clone in Desktop Download ZIP

Loading…

Enhancements #1

Open
wants to merge 9 commits into from
@JoelBesada
Owner

Here are some enhancements I made for the editor. The biggest new thing is that you now get these cool particles when you enter power mode:

citd-particles2

Here's a list of the other changes:

  • The "Current streak" counter is now just called "Combo", and there is a bar below it to indicate how much time is left before it resets.
  • The screen shake intensity now increases for each multiple of 100 you go above the Power Mode threshold.
  • Power Mode now activates when you reach a combo of 200 instead of 250.
@ptz0n

Awesome!

@Takadimi

Amazing... :D

@lmayorga1980

Need play with this now

@timaschew

I checked out your branch, but I don't see any particles, just shaking

@JoelBesada
Owner

@timaschew Which browser + version are you on?

@aspelund

I want this for sublime!

@enrique-ramirez

Same as @timaschew. I'm on Chrome 46.0.2490.86 (64-bit) (OSX) and I see only shaking.

@aspelund

And also I want a class' style definition to be animated into the class with some kind of particle transformation...

@timaschew

I tried on chrome, firefox and safari, same result on all browsers.
I'm using OS X El Capitan

@varemenos

I could watch this forever (sorry for getting pinged for this pointing comment)

@JoelBesada
Owner

@enrique-ramirez @timaschew Alright I'll look into it. Since you're getting the shaking I assume you hit "Power Mode" by getting your combo to 200, which is when the particles should also come into effect.

@timaschew

Yes, shaking starts at 200 points, in power mode.
I tried to continue until 1000, but it was still just shaking.

@eur0pa

Does the screen shake go up to "Vlambeer"?

@MichielDeMey

Dude, that's pretty amazing!

@jonnytobin

Love it!!

@JohanSandstroem

Same issue as previous posters - no particle effects are shown.

Running Chrome 46.0.2490.86m on Windows 10.1

@JoelBesada
Owner

@JohanSandstroem @enrique-ramirez @timaschew Hmm I can't seem to reproduce this in any browser. Can you try out this version http://joelbox.s3.amazonaws.com/citd/index.html? I want to know if there's something weird with your builds.

@enrique-ramirez

@JoelBesada Ah, it does work with that version. Where could our builds go wrong?

@JoelBesada
Owner

@enrique-ramirez No idea :)

This does include the fix from @gernberg that fixes the position of the particles after you've scrolled however, if you've all been scrolled too far down to see the particles. You could try it locally again with the latest commit.

@timaschew

Yeah it works, awesome, thanks!

@tufanbarisyildirim

Awesome :+1: :D

@aldee07

Code with feelings

@kuroware

Literally the best thing i've seen

@salebgmilj2

Awesome man 👍👌

@jleppert

Zomg!!!

@liyaodong

Cool !

@saddamcrr7

awesome

@jhoonb

hahaahaha, awesome!

@moolex

I have lost my eyes .. D _ D

@looooker

awesome

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 25, 2015
  1. @JoelBesada

    Add particle effects

    JoelBesada committed
  2. @JoelBesada
Commits on Nov 26, 2015
  1. @JoelBesada

    Layout tweaks

    JoelBesada committed
  2. @JoelBesada

    Add comment particle color

    JoelBesada committed
  3. @JoelBesada
  4. @JoelBesada

    Lower power mode threshold

    JoelBesada committed
  5. @JoelBesada
Commits on Nov 28, 2015
  1. @gernberg
  2. @JoelBesada

    Merge pull request #2 from gernberg/enhancements

    JoelBesada committed
    Bugfix for particle effects positioning being off due to scrolling
This page is out of date. Refresh to see the latest.
View
7 app/index.html
@@ -6,15 +6,18 @@
<script src="bundle.js" inline></script>
</head>
<body>
+ <div class="background"></div>
+ <canvas class="canvas-overlay"></canvas>
<pre id="editor"></pre>
<div class="streak-container">
- <div class="current">Current Streak</div>
+ <div class="current">Combo</div>
<div class="counter">0</div>
+ <div class="bar"></div>
<div class="exclamations"></div>
</div>
<div class="reference-screenshot-container">
+ <span>Reference</span>
<div class="reference-screenshot" style="background-image:url(assets/page.png);"></div>
- <span>Reference Screenshot</span>
</div>
<div class="power-mode-indicator">
View
144 app/scripts/app.coffee
@@ -9,9 +9,33 @@ require "brace/theme/vibrant_ink"
require "brace/ext/searchbox"
class App
- POWER_MODE_ACTIVATION_THRESHOLD: 250
+ POWER_MODE_ACTIVATION_THRESHOLD: 200
STREAK_TIMEOUT: 10 * 1000
+ MAX_PARTICLES: 500
+ PARTICLE_NUM_RANGE: [5..12]
+ PARTICLE_GRAVITY: 0.075
+ PARTICLE_ALPHA_FADEOUT: 0.96
+ PARTICLE_VELOCITY_RANGE:
+ x: [-1, 1]
+ y: [-3.5, -1.5]
+
+ PARTICLE_COLORS:
+ "text": [255, 255, 255]
+ "text.xml": [255, 255, 255]
+ "keyword": [0, 221, 255]
+ "variable": [0, 221, 255]
+ "meta.tag.tag-name.xml": [0, 221, 255]
+ "keyword.operator.attribute-equals.xml": [0, 221, 255]
+ "constant": [249, 255, 0]
+ "constant.numeric": [249, 255, 0]
+ "support.constant": [249, 255, 0]
+ "string.attribute-value.xml": [249, 255, 0]
+ "string.unquoted.attribute-value.html": [249, 255, 0]
+ "entity.other.attribute-name.xml": [129, 148, 244]
+ "comment": [0, 255, 121]
+ "comment.xml": [0, 255, 121]
+
EXCLAMATION_EVERY: 10
EXCLAMATIONS: ["Super!", "Radical!", "Fantastic!", "Great!", "OMG",
"Whoah!", ":O", "Nice!", "Splendid!", "Wild!", "Grand!", "Impressive!",
@@ -19,17 +43,26 @@ class App
currentStreak: 0
powerMode: false
+ particles: []
+ particlePointer: 0
+ lastDraw: 0
constructor: ->
@$streakCounter = $ ".streak-container .counter"
+ @$streakBar = $ ".streak-container .bar"
@$exclamations = $ ".streak-container .exclamations"
@$reference = $ ".reference-screenshot-container"
+ @$editor = $ "#editor"
+ @canvas = @setupCanvas()
+ @canvasContext = @canvas.getContext "2d"
@$download = $ ".download-button"
@$body = $ "body"
@debouncedSaveContent = _.debounce @saveContent, 300
@debouncedEndStreak = _.debounce @endStreak, @STREAK_TIMEOUT
+ @throttledShake = _.throttle @shake, 100, trailing: false
+ @throttledSpawnParticles = _.throttle @spawnParticles, 25, trailing: false
@editor = @setupAce()
@loadContent()
@@ -38,10 +71,14 @@ class App
@editor.getSession().on "change", @onChange
$(window).on "beforeunload", -> "Hold your horses!"
- $(".instructions-container, .instructions-button").on "click", => $("body").toggleClass "show-instructions"
+ $(".instructions-container, .instructions-button").on "click", ->
+ $("body").toggleClass "show-instructions"
+
@$reference.on "click", => @$reference.toggleClass "active"
@$download.on "click", @onClickDownload
+ window.requestAnimationFrame? @onFrame
+
setupAce: ->
editor = ace.edit "editor"
@@ -51,9 +88,16 @@ class App
editor.getSession().setMode "ace/mode/html"
editor.session.setOption "useWorker", false
editor.session.setFoldStyle "manual"
+ editor.$blockScrolling = Infinity
editor
+ setupCanvas: ->
+ canvas = $(".canvas-overlay")[0]
+ canvas.width = window.innerWidth
+ canvas.height = window.innerHeight
+ canvas
+
loadContent: ->
return unless (content = localStorage["content"])
@editor.setValue content, -1
@@ -61,6 +105,11 @@ class App
saveContent: =>
localStorage["content"] = @editor.getValue()
+ onFrame: (time) =>
+ @drawParticles time - @lastDraw
+ @lastDraw = time
+ window.requestAnimationFrame? @onFrame
+
increaseStreak: ->
@currentStreak++
@showExclamation() if @currentStreak > 0 and @currentStreak % @EXCLAMATION_EVERY is 0
@@ -68,6 +117,8 @@ class App
if @currentStreak >= @POWER_MODE_ACTIVATION_THRESHOLD and not @powerMode
@activatePowerMode()
+ @refreshStreakBar()
+
@renderStreak()
endStreak: ->
@@ -83,6 +134,18 @@ class App
_.defer =>
@$streakCounter.addClass "bump"
+ refreshStreakBar: ->
+ @$streakBar.css
+ "webkit-transform": "scaleX(1)"
+ "transform": "scaleX(1)"
+ "transition": "none"
+
+ _.defer =>
+ @$streakBar.css
+ "webkit-transform": ""
+ "transform": ""
+ "transition": "all #{@STREAK_TIMEOUT}ms linear"
+
showExclamation: ->
$exclamation = $("<span>")
.addClass "exclamation"
@@ -93,21 +156,64 @@ class App
$exclamation.remove()
, 3000
+ getCursorPosition: ->
+ {left, top} = @editor.renderer.$cursorLayer.getPixelPosition()
+ left += @editor.renderer.gutterWidth + 4
+ top -= @editor.renderer.scrollTop
+ {x: left, y: top}
+
+ spawnParticles: (type) ->
+ return unless @powerMode
+
+ {x, y} = @getCursorPosition()
+ numParticles = _(@PARTICLE_NUM_RANGE).sample()
+ color = @getParticleColor type
+ _(numParticles).times =>
+ @particles[@particlePointer] = @createParticle x, y, color
+ @particlePointer = (@particlePointer + 1) % @MAX_PARTICLES
+
+ getParticleColor: (type) ->
+ @PARTICLE_COLORS[type] or [255, 255, 255]
+
+ createParticle: (x, y, color) ->
+ x: x
+ y: y + 10
+ alpha: 1
+ color: color
+ velocity:
+ x: @PARTICLE_VELOCITY_RANGE.x[0] + Math.random() *
+ (@PARTICLE_VELOCITY_RANGE.x[1] - @PARTICLE_VELOCITY_RANGE.x[0])
+ y: @PARTICLE_VELOCITY_RANGE.y[0] + Math.random() *
+ (@PARTICLE_VELOCITY_RANGE.y[1] - @PARTICLE_VELOCITY_RANGE.y[0])
+
+ drawParticles: (timeDelta) =>
+ @canvasContext.clearRect 0, 0, @canvas.width, @canvas.height
+
+ for particle in @particles
+ continue if particle.alpha <= 0.1
+
+ particle.velocity.y += @PARTICLE_GRAVITY
+ particle.x += particle.velocity.x
+ particle.y += particle.velocity.y
+ particle.alpha *= @PARTICLE_ALPHA_FADEOUT
+
+ @canvasContext.fillStyle = "rgba(#{particle.color.join ", "}, #{particle.alpha})"
+ @canvasContext.fillRect Math.round(particle.x - 1), Math.round(particle.y - 1), 3, 3
+
shake: ->
- intensity = -(Math.random() * 5 + 5)
- x = intensity * (Math.random() > 0.5 ? -1 : 1)
- y = intensity * (Math.random() > 0.5 ? -1 : 1)
+ return unless @powerMode
- translate = "translate3D(#{x}px, #{y}px, 0)"
- @$body.css
- "webkit-transform": translate
- "transform": translate
+ intensity = 1 + 2 * Math.random() * Math.floor(
+ (@currentStreak - @POWER_MODE_ACTIVATION_THRESHOLD) / 100
+ )
+ x = intensity * (if Math.random() > 0.5 then -1 else 1)
+ y = intensity * (if Math.random() > 0.5 then -1 else 1)
+
+ @$editor.css "margin", "#{y}px #{x}px"
setTimeout =>
- @$body.css
- "webkit-transform": "none"
- "transform": "none"
- , 50
+ @$editor.css "margin", ""
+ , 75
activatePowerMode: =>
@powerMode = true
@@ -133,6 +239,16 @@ class App
@increaseStreak()
@debouncedEndStreak()
- @shake() if @powerMode
+ @throttledShake()
+
+ pos = if e.data.action is "insertText"
+ e.data.range.end
+ else
+ e.data.range.start
+
+ token = @editor.session.getTokenAt pos.row, pos.column
+
+ _.defer =>
+ @throttledSpawnParticles(token.type) if token
$ -> new App
View
105 app/styles/index.scss
@@ -14,15 +14,8 @@ body, html {
}
body {
- background-image: url(~assets/images/logo.png);
- background-position: 50% 50%;
- background-repeat: no-repeat;
- background-size: 520px 476px;
- position: relative;
- &.power-mode {
- animation: body-power 2s infinite both;
- }
+ position: relative;
}
button {
@@ -68,6 +61,33 @@ body.show-instructions {
}
}
+.background {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ z-index: 0;
+ opacity: 0.5;
+ background-image: url(~assets/images/logo.png);
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ background-size: 520px 476px;
+
+ .power-mode & {
+ background-image: url(~assets/images/logo-power.png);
+ animation: background-power 2s infinite both;
+ }
+}
+
+.canvas-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 10;
+ pointer-events: none;
+}
+
#editor {
position: absolute;
top: 0;
@@ -75,8 +95,9 @@ body.show-instructions {
left: 0;
right: 0;
margin: 0;
- background-color: rgba(0,0,0,0.5);
+ background: transparent;
font-size: 14px;
+ transform: translate3d(0, 0, 0);
.ace_keyword,
.ace_meta,
@@ -137,15 +158,25 @@ body.power-mode #editor {
.streak-container {
position: absolute;
z-index: 10;
- right: 40px;
+ right: 20px;
top: 20px;
- text-align: center;
+ text-align: right;
.current {
color: white;
font-size: 16px;
}
+ .bar {
+ position: relative;
+ opacity: 0.5;
+ margin-top: 23px;
+ height: 8px;
+ background: #4EFFA1;
+ width: 100%;
+ transform: scaleX(0);
+ }
+
.counter {
font-size: 80px;
color: #4EFFA1;
@@ -164,15 +195,14 @@ body.power-mode #editor {
color: #4EFFA1;
opacity: 0.75;
font-size: 20px;
- width: 210px;
+ text-align: right;
.exclamation {
- left: 0;
+ right: 0;
top: 0;
display: block;
position: absolute;
- width: 100%;
- text-align: center;
+ min-width: 200px;
animation: exclamation 1.5s ease-out both;
}
}
@@ -182,7 +212,7 @@ body.power-mode #editor {
position: absolute;
z-index: 10;
bottom: 20px;
- right: 60px;
+ right: 20px;
&:active {
bottom: 19px;
@@ -192,7 +222,7 @@ body.power-mode #editor {
.instructions-button {
position: absolute;
z-index: 20;
- right: 70px;
+ right: 20px;
bottom: 70px;
}
@@ -203,17 +233,14 @@ body.power-mode #editor {
right: 20px;
cursor: pointer;
color: white;
- text-align: center;
+ text-align: right;
font-size: 12px;
- width: 280px;
- padding: 20px;
box-sizing: border-box;
.reference-screenshot {
- display: inline-block;
width: 200px;
height: 160px;
- margin-bottom: 10px;
+ margin-top: 15px;
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
@@ -255,15 +282,19 @@ body.power-mode #editor {
}
body.power-mode {
- background-image: url(~assets/images/logo-power.png);
-
.power-mode-indicator {
opacity: 1;
animation: power-mode-indicator 750ms linear both;
}
- .streak-container .counter {
- color: #00DDFF;
+ .streak-container {
+ .counter {
+ color: #00DDFF;
+ }
+
+ .bar {
+ background: #00DDFF;
+ }
}
button {
@@ -295,16 +326,6 @@ body.power-mode {
}
}
-@keyframes body-power {
- 0% {
- animation-timing-function: ease-out;
- }
- 50% {
- background-size: 650px 595px;
- animation-timing-function: ease-in;
- }
-}
-
@keyframes exclamation {
100% {
opacity: 0;
@@ -312,6 +333,16 @@ body.power-mode {
}
}
+@keyframes background-power {
+ 0% {
+ animation-timing-function: ease-out;
+ }
+ 50% {
+ transform: scale(1.5);
+ animation-timing-function: ease-in;
+ }
+}
+
@keyframes power-mode-indicator {
0% { transform: matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
3.2% { transform: matrix3d(0.673, 0.192, 0, 0, 0.126, 0.673, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
@@ -333,5 +364,3 @@ body.power-mode {
84.68% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
100% { transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }
}
-
-
View
12 gulpfile.coffee
@@ -2,6 +2,7 @@ _ = require "underscore"
$ = require("gulp-load-plugins")()
gulp = require "gulp"
path = require "path"
+merge = require "merge-stream"
deepExtend = require "deep-extend"
runSequence = require "run-sequence"
autoprefixer = require "autoprefixer-core"
@@ -86,10 +87,17 @@ webpackers = _(config.webpackEnvs).mapObject (val) ->
gulp
.task "copy-assets", ->
- gulp
- .src [path.join(config.paths.assets, "**"), path.join(config.paths.app, "index.html")]
+ assets = gulp
+ .src path.join(config.paths.assets, "**")
+ .pipe gulp.dest("#{config.paths.tmp}/assets")
+
+
+ instructions = gulp
+ .src path.join(config.paths.app, "index.html")
.pipe gulp.dest(config.paths.tmp)
+ merge assets, instructions
+
.task "copy-page-files", ->
gulp
.src path.join(config.paths.assets, "{instructions.html,page.png}")
View
1  package.json
@@ -17,6 +17,7 @@
"gulp-load-plugins": "^0.8.0",
"gulp-util": "^3.0.4",
"jquery": "^2.1.3",
+ "merge-stream": "^1.0.0",
"postcss-loader": "^0.3.0",
"run-sequence": "^1.0.2",
"sass-loader": "^0.4.0",
Something went wrong with that request. Please try again.