From c96d034e2652dd44ed979a224094488ac4d119cd Mon Sep 17 00:00:00 2001 From: TidePlus <115383230+TidePlus@users.noreply.github.com> Date: Sun, 8 Oct 2023 09:26:27 +0530 Subject: [PATCH 1/3] Create index.html --- BallColoron/TidePlus/index.html | 105 ++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 BallColoron/TidePlus/index.html diff --git a/BallColoron/TidePlus/index.html b/BallColoron/TidePlus/index.html new file mode 100644 index 000000000..08854f4aa --- /dev/null +++ b/BallColoron/TidePlus/index.html @@ -0,0 +1,105 @@ + +
+
+ +
+ + + +
+ + Play +

hint: red color always comes first

+
+ +
+
+

Bouncing ball
changes color

+
+
+
+
+
+

Tap on the bar to switch the colors
(Red, Yellow, Purple)

+
+
+
+
+
+
+
+

Always match the
ball and bar colors

+
+
+
+
+
+
+ +
+ +
+ +
+ +

Coloron

+ +
+
+ +

Tweet to challenge friends

+ +

+ + Tweet + +

+ +
+ Play Again + Menu +
+ +
+ +
+ +
+ +
+ +
+
+
+
+
+
+
+ +
+
+
+
+ +
+ +
+
Click on the bars to change the color!
+
+
+
+
+ +
+ +
From 3917c42f1840fe181eedb55b3ccac859490afe49 Mon Sep 17 00:00:00 2001 From: TidePlus <115383230+TidePlus@users.noreply.github.com> Date: Sun, 8 Oct 2023 09:26:56 +0530 Subject: [PATCH 2/3] Create style.css --- BallColoron/TidePlus/style.css | 738 +++++++++++++++++++++++++++++++++ 1 file changed, 738 insertions(+) create mode 100644 BallColoron/TidePlus/style.css diff --git a/BallColoron/TidePlus/style.css b/BallColoron/TidePlus/style.css new file mode 100644 index 000000000..54797d44b --- /dev/null +++ b/BallColoron/TidePlus/style.css @@ -0,0 +1,738 @@ +@mixin bubble_shape ($width: 4px) { + border-radius: 50%; + position: absolute; + background-color: rgba(0, 0, 0, 0.12); + border-color: rgba(0, 0, 0, 0.12); + border-width: $width; +} + +@mixin bubble ($size, $top, $left) { + height: $size; + width: $size; + top: $top; + left: $left; +} + +@mixin bubble_hollow ($size, $top, $left) { + @include bubble ($size, $top, $left); + background-color: transparent; + border-style: solid; +} + +@mixin triangle ($height, $width, $top, $left) { + border-left: ($height/2) solid transparent; + border-right: ($height/2) solid transparent; + border-bottom: $width solid rgba(0, 0, 0, 0.12); + background-color: transparent; + left: $left; + top: $top; +} + +@mixin triangle_hollow ($height, $width, $top, $left) { + @include triangle( $height, $width, $top, $left ); + &:after { + content: " "; + display: block; + position: absolute; + border-left: ($height/4-1) solid transparent; + border-right: ($height/4-1) solid transparent; + border-bottom: ($height/2-3) solid transparent; + top: 6px; + left: -($width/4); + transition: border-bottom-color 0.4s ease; + + .red & { + border-bottom-color: #fc5c82; + } + .yellow & { + border-bottom-color: #fcd45c; + } + .purple & { + border-bottom-color: #9174f5; + } + } +} + +@mixin block ($height, $width, $top, $left) { + height: $height; + width: $width; + top: $top; + left: $left; +} + +@mixin block_hollow ($height, $width, $top, $left) { + @include block ($height, $width, $top, $left); + & .inner { + background-color: transparent !important; + border-style: solid; + box-sizing: border-box; + } +} + +.bubble { + @include bubble_shape; +} +.bubble-1 { + @include bubble(15px, 21px, 59px); +} +.bubble-2 { + @include bubble(27px, 36px, 16px); +} +.bubble-3 { + @include bubble(21px, 63px, 49px); +} +.bubble-4 { + @include bubble(15px, 98px, 37px); +} +.bubble-5 { + @include bubble_hollow(5px, 116px, 20px); +} +.bubble-6 { + @include bubble(6px, 128px, 63px); +} +.bubble-7 { + @include bubble(27px, 150px, 52px); +} +.bubble-8 { + @include bubble(19px, 154px, 18px); +} +.bubble-9 { + @include bubble(10px, 189px, 13px); +} +.bubble-10 { + @include bubble_hollow(5px, 199px, 52px); +} +.bubble-11 { + @include bubble(21px, 220px, 29px); +} +.bubble-12 { + @include bubble(21px, 263px, 48px); +} +.bubble-13 { + @include bubble_hollow(5px, 275px, 16px); +} +.bubble-14 { + @include bubble(15px, 296px, 34px); +} +.triangle { + position: absolute; + background-color: rgba(0, 0, 0, 0.12); + border-color: rgba(0, 0, 0, 0.12); +} +.triangle-1 { + @include bubble_shape; + @include bubble(10px, 22px, 55px); +} +.triangle-2 { + @include triangle_hollow(16px, 14px, 27px, 15px); +} +.triangle-3 { + @include triangle_hollow(24px, 19px, 60px, 43px); +} +.triangle-4 { + @include bubble_shape(3px); + @include bubble_hollow(8px, 61px, 17px); +} +.triangle-5 { + @include triangle(10px, 8px, 101px, 25px); + transform: rotate(180deg); +} + +.triangle-6 { + @include triangle(8px, 6px, 103px, 60px); + transform: rotate(-90deg); +} + +.triangle-7 { + @include triangle(25px, 19px, 126px, 17px); + transform: rotate(180deg); +} + +.triangle-8 { + @include triangle(21px, 16px, 149px, 50px); +} + +.triangle-9 { + @include triangle(11px, 8px, 177px, 21px); +} + +.triangle-10 { + @include bubble_shape; + @include bubble(10px, 177px, 60px); +} + +.triangle-11 { + @include triangle(18px, 13px, 213px, 33px); + transform: rotate(180deg); +} + +.triangle-12 { + @include bubble_shape(2px); + @include bubble_hollow(10px, 233px, 65px); +} + +.triangle-13 { + @include bubble_shape; + @include bubble(10px, 250px, 22px); +} + +.triangle-14 { + @include triangle_hollow(16px, 14px, 270px, 45px); + transform: rotate(180deg); +} + +.stick { + .block { + position: absolute; + overflow: hidden; + z-index: 999; + border-radius: 7px; + .inner { + border-radius: 7px; + background-color: rgba(0, 0, 0, 0.12); + border-color: rgba(0, 0, 0, 0.12); + border-width: 3px; + height: 100%; + width: 100%; + position: absolute; + } + &:nth-child(2n+1) .inner-2 { + left: -200%; + } + &:nth-child(2n+2) .inner-2 { + left: 200%; + } + } + .block-1 { + @include block_hollow(16px, 31px, 16px, 30px); + } + .block-2 { + @include block(14px, 42px, 50px, 15px); + } + .block-3 { + @include block(18px, 9px, 73px, 64px); + } + .block-4 { + @include block(9px, 14px, 84px, 26px); + } + .block-5 { + @include block(15px, 15px, 109px, 45px); + .inner { + border-radius: 50%; + } + } + .block-6 { + @include block(9px, 27px, 135px, 19px); + } + .block-7 { + @include block(12px, 12px, 144px, 60px); + .inner { + border-radius: 50%; + border-style: solid; + box-sizing: border-box; + background-color: transparent; + } + } + .block-8 { + @include block(27px, 14px, 164px, 24px); + } + .block-9 { + @include block(8px, 8px, 188px, 64px); + } + .block-10 { + @include block_hollow(12px, 22px, 219px, 11px); + } + .block-11 { + @include block(22px, 22px, 226px, 50px); + .inner { + border-radius: 50%; + } + } + .block-12 { + @include block(18px, 9px, 248px, 26px); + } + .block-13 { + @include block(8px, 8px, 278px, 50px); + .inner { + border-radius: 50%; + } + } + .block-14 { + @include block_hollow(12px, 22px, 297px, 18px); + } + .block-15 { + @include block(9px, 27px, 307px, 48px); + } +} + +body { + background-color: #28DAD4; + margin: 0; + padding: 0; + overflow: hidden; + font-family: 'Roboto', sans-serif; +} +a { + cursor: url(https://greghub.github.io/coloron/public/svg/cursor.svg), pointer; + &:focus, &:active { + cursor: url(https://greghub.github.io/coloron/public/svg/cursor-tap.svg), pointer; + } +} +.container { + position: fixed; + left: 0; + top: 0; + height: 100%; + width: 100%; +} +.waves, .mounts { + position: absolute; + width: 100%; + left: 0; + bottom: 0; +} +.waves div, .mounts div { + position: absolute; + width: 100%; +} +.clouds { + position: absolute; + width: 100%; + left: 0; + top: 77px; + height: 151px; + background: url(https://greghub.github.io/coloron/public/svg/clouds.svg) repeat-x; + background-position-x: 170px; +} +.top_wave { + background: url(https://greghub.github.io/coloron/public/svg/top_wave.png) repeat-x 0 -1px; + height: 35px; + bottom: 0; + z-index: 10001; +} +.wave1 { + background: url(https://greghub.github.io/coloron/public/svg/wave1.svg) repeat-x; + height: 150px; + bottom: 0; + z-index: 23; +} +.wave2 { + background: url(https://greghub.github.io/coloron/public/svg/wave2.svg) repeat-x; + height: 180px; + bottom: 30px; + z-index: 22; +} +.wave3 { + background: url(https://greghub.github.io/coloron/public/svg/wave3.svg) repeat-x; + height: 180px; + bottom: 90px; + z-index: 21; +} +.wave4 { + background: url(https://greghub.github.io/coloron/public/svg/wave4.svg) repeat-x; + height: 180px; + bottom: 120px; + z-index: 20; +} +.mount1 { + background: url(https://greghub.github.io/coloron/public/svg/mount1.svg) repeat-x; + height: 150px; + bottom: 280px; + z-index: 11; +} +.mount2 { + background: url(https://greghub.github.io/coloron/public/svg/mount2.svg) repeat-x; + height: 150px; + bottom: 290px; + z-index: 10; +} +.noise { + position: fixed; + width: 100%; + height: 100%; + left: 0; + top: 0; + z-index: 1010; + background: url(https://greghub.github.io/coloron/public/svg/noise.png); +} +.glow { + position: absolute; + left: -350px; + top: -350px; + width: 800px; + height: 800px; + background-color: rgba(81, 237, 200, 0.34); + border-radius: 50%; + box-shadow: 0 0 100px 100px rgba(81, 237, 200, 0.34); + z-index: 1010; +} +.sun { + position: relative; + left: 50%; + top: 50%; + width: 1px; + height: 1px; + background-color: rgba(255, 227, 69, 1); + border-radius: 50%; + box-shadow: 0 0 32px 32px rgba(255, 227, 69, 1), + 0 0 150px 150px rgba(103, 244, 210, 0.4); +} +.small-glow { + z-index: 99; + width: 12px; + height: 12px; + border-radius: 50%; + position: absolute; + background-color: rgba(255, 255, 255, 0.34); + box-shadow: 0 0 1px 1px rgba(255, 255, 255, 0.34); +} +.small-glow.yellow { + background-color: rgba(255, 227, 69, 0.34); + box-shadow: 0 0 4px 4px rgba(255, 227, 69, 0.34); +} +.sticks { + z-index: 1011; + outline: none; + -webkit-tap-highlight-color: rgba(0,0,0,0); +} +.stick { + height: 362px; + width: 90px; + border-radius: 14px; + background-image: url(https://greghub.github.io/coloron/public/svg/noise.png); + position: relative; + overflow: hidden; + float: left; + margin-right: 90px; + transition: background-color 0.4s ease; + cursor: url(https://greghub.github.io/coloron/public/svg/cursor.svg), pointer; + &:focus, &:active { + cursor: url(https://greghub.github.io/coloron/public/svg/cursor-tap.svg), pointer; + } +} +.stick.red { + background-color: #FF4571; +} +.stick.yellow { + background-color: #FFD145; +} +.stick.purple { + background-color: #8260F6; +} +.stick.inactive { + background-color: #4C4660; +} +.ball, .ball-demo { + background: url(https://greghub.github.io/coloron/public/svg/ball.svg) right bottom; + background-size: 64px 64px; + width: 53px; + height: 53px; + z-index: 1011; + background-color: #FF4571; + border-radius: 50%; +} +.ball { + margin-bottom: 250px; +} +.controls { + z-index: 999999; + position: relative +} +.game-full-flex { + position: fixed; + display: none; // gets updated to flex with JS + flex-direction: column; + justify-content: space-between; + align-items: center; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 9998; +} +.start-game { + .start-game-top { + min-height: 20%; + .play-full-page { + display: none; + border: 3px solid #fff; + border-radius: 100px; + color: #fff; + width: 260px; + height: 50px; + font-size: 28px; + text-align: center; + font-weight: 900; + letter-spacing: -1px; + line-height: 52px; + text-decoration: none; + text-transform: uppercase; + margin-top: 24px; + &:hover { + opacity: 0.7; + } + } + } + .logo-holder { + width: 513px; + height: 162px; + background-color: #4C4660; + border: 4px solid #FF4571; + border-radius: 68px; + text-align: center; + margin-top: -10%; + .logo { + color: #fff; + text-transform: uppercase; + font-weight: 900; + font-size: 100px; + letter-spacing: -0.1em; + margin-top: 10px; + margin-bottom: 4px; + text-align: center; + span { + margin-left: -8px; + margin-right: -8px; + } + } + .play-button { + display: inline-block; + background-color: #FF4571; + border: 4px solid #fff; + border-radius: 100px; + color: #fff; + width: 200px; + height: 56px; + font-size: 42px; + text-align: center; + font-weight: 900; + letter-spacing: -3px; + line-height: 56px; + text-decoration: none; + &:hover { + background-color: lighten(#FF4571, 5%); + } + } + .hint { + color: #fff; + font-size: 20px; + span { + color: #FF4571; + } + } + } + .how-to-play { + display: flex; + justify-content: space-around; + width: 100%; + .section-1, .section-3 { + flex: 1; + .content { + justify-content: center; + } + } + h4 { + color: #fff; + font-weight: 400; + font-size: 22px; + text-align: center; + } + .content { + height: 200px; + position: relative; + display: flex; + justify-content: space-around; + } + .bar { + width: 60px; + border-radius: 7px; + margin-top: auto; + transition: background-color 0.4s ease; + &.bar-1 { + height: 180px; + background: #FF4571; + } + &.bar-2 { + height: 120px; + background: #FFD145; + } + &.bar-3 { + height: 150px; + background: #4C4660; + } + } + .section-2 { + .bar { + cursor: url(https://greghub.github.io/coloron/public/svg/cursor.svg), pointer; + &:focus, &:active { + cursor: url(https://greghub.github.io/coloron/public/svg/cursor-tap.svg), pointer; + } + } + } + .section-3 { + .ball-demo { + background-color: #815FF8; + } + .bar-1 { + height: 120px; + background-color: #815FF8; + } + } + } +} +.stop-game { + justify-content: center; + .score-container { + background-color: #4C4660; + width: 433px; + height: 386px; + border-radius: 38px; + text-align: center; + h1 { + color: #fff; + text-transform: uppercase; + letter-spacing: -0.1em; + margin-top: 20px; + margin-bottom: 4px; + font-size: 64px; + } + .final-score { + color: #FFE345; + font-weight: 900; + font-size: 130px; + letter-spacing: -6px; + line-height: 110px; + } + .result { + color: #FF4571; + text-transform: uppercase; + font-weight: 700; + font-size: 30px; + } + h4 { + color: #fff; + margin-top: 12px; + } + .tweet { + background: #fff; + padding: 8px 20px; + border-radius: 4px; + color: #55ACEE; + text-decoration: none; + font-size: 18px; + line-height: 24px; + display: inline-block; + &:hover { + background-color: #55ACEE; + color: #fff; + } + i { + font-size: 24px; + top: 2px; + right: 2px; + position: relative; + } + } + .play-again { + background-color: #FF4571; + border: 2px solid #fff; + color: #fff; + text-decoration: none; + text-transform: uppercase; + font-weight: 900; + letter-spacing: -1px; + font-size: 26px; + padding: 6px 24px; + border-radius: 22px; + margin: 6px 4px; + display: inline-block; + &:hover { + background-color: lighten(#FF4571, 5%); + } + } + .main-menu { + background-color: #44BFA3; + border: 2px solid #fff; + color: #fff; + text-decoration: none; + text-transform: uppercase; + font-weight: 900; + letter-spacing: -1px; + font-size: 26px; + padding: 6px 24px; + border-radius: 22px; + margin: 6px 4px; + display: inline-block; + &:hover { + background-color: lighten(#44BFA3, 5%); + } + } + } +} +.scene { + display: flex; + flex-direction: column; + justify-content: space-between; + position: fixed; + z-index: 9997; + left: 0; + top: 0; + width: 100%; + height: 100%; + .ball-holder { + flex: 1; + display: flex; + flex-direction: column; + justify-content: flex-end; + padding-left: 558px; + } + .score { + position: fixed; + right: 54px; + top: 20px; + color: #33485F; + font-size: 90px; + font-weight: 900; + letter-spacing: -0.1em; + } + .learn-to-play { + z-index: 9999; + display: inline-block; + text-align: center; + position: relative; + top: 20%; + font-size: 48px; + color: rgba(255,255,255,0.85); + font-weight: 700; + letter-spacing: -2px; + opacity: 0; + } +} + +.splash { + display: none; +} + +@media print { + .splash { + display: block; + position: fixed; + z-index: 99999; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #28DAD4; + background-image: url(https://greghub.github.io/coloron/public/images/coloron-image.png); + background-size: auto 100%; + background-repeat: no-repeat; + background-position: center; + } +} + +.nominee { + position: fixed; + right: 0; + top: 0; + z-index: 9999; +} From c92a0acdf06f976d06e5adad63c7a78c03fe4cac Mon Sep 17 00:00:00 2001 From: TidePlus <115383230+TidePlus@users.noreply.github.com> Date: Sun, 8 Oct 2023 09:28:04 +0530 Subject: [PATCH 3/3] Added Babel Script --- BallColoron/TidePlus/main.js | 588 +++++++++++++++++++++++++++++++++++ 1 file changed, 588 insertions(+) create mode 100644 BallColoron/TidePlus/main.js diff --git a/BallColoron/TidePlus/main.js b/BallColoron/TidePlus/main.js new file mode 100644 index 000000000..d7f9708a5 --- /dev/null +++ b/BallColoron/TidePlus/main.js @@ -0,0 +1,588 @@ +class Game { + + constructor() { + this.score = 0; + this.isRunning = 0; // game is not running + + this.calculateScale(); + + this.timeline = new TimelineMax({smoothChildTiming: true}); + this.time = 1.6; // initial speed + this.colors = ["#FF4571", "#FFD145", "#8260F6"]; // the 3 colors used in the game + this.colorsRGBA = ["rgba(255, 69, 113, 1)", "rgba(255, 69, 113, 1)", "rgba(255, 69, 113, 1)"]; + this.color = this.colors[0]; // the intial color of the ball + this.prevColor = null; // used as a holder to prevent ball colors from repeating + } + + /** + * The game screen is scalable. I took 1200x800px as the initial scale. + * In order to display the game an many screen sizes properly + * I have to compare the player's sreen size to the initial scale, + * then scale the game using CSS Transform to fit the screen properly + * The function is called in the controller and anywhere where I need + * to recalculate the scale on screen resize or device rotation + */ + calculateScale() { + this.screen = $(window).width(); // screen width + this.screenHeight = $(window).height(); + this.scale = (this.screen > this.screenHeight) ? this.screenHeight/800 : this.screen/1200; + this.stickWidth = 180*this.scale; + this.steps = this.screen/this.stickWidth; // how many steps (stick width + margin) it takes from one end to another + } + + /** + * Creating as many sticks we need to fill the screen + * from start to end of the screen. The steps property is used for that + */ + generateSticks() { + let numberOfSticks = Math.ceil(this.steps); + for(let i = 0; i <= numberOfSticks; i++) + new Stick(); + } + + generateBall() { + this.balltween = new TimelineMax({repeat: -1, paused: 1}); + $('.scene .ball-holder').append('
'); + this.bounce(); + } + + generateTweet() { + let top = $(window).height() / 2 - 150; + let left = $(window).width() / 2 - 300; + window.open("https://twitter.com/intent/tweet?url=https://codepen.io/gregh/full/yVLOyO&text=I scored "+ this.score +" points on Coloron! Can you beat my score?&via=greghvns&hashtags=coloron", "TweetWindow", "width=600px,height=300px,top=" + top + ",left=" + left); + } + + /** + * The greeting when the game begins + */ + intro() { + + TweenMax.killAll(); + + //TweenMax.to('.splash', 0.3, { opacity: 0, display: 'none', delay: 1 }) + + $('.stop-game').css('display', 'none'); + $('.start-game').css('display', 'flex'); + + let introTl = new TimelineMax(); + let ball = new TimelineMax({repeat: -1, delay: 3}); + introTl + .fromTo('.start-game .logo-holder', 0.9, { opacity: 0 }, { opacity: 1 }) + .staggerFromTo('.start-game .logo span', 0.5, { opacity: 0 }, { opacity: 1 }, 0.08) + .staggerFromTo('.start-game .bar', 1.6, { y: '+100%' }, { y: '0%', ease: Elastic.easeOut.config(1, 0.3) }, 0.08) + .staggerFromTo('.start-game .ball-demo', 1, { scale: 0 }, { scale: 1, ease: Elastic.easeOut.config(1, 0.3) }, 0.8, 2) + + + ball.fromTo('.start-game .section-1 .ball-demo', 0.5, { y: "0px" }, { y: "100px", scaleY: 1.1, transformOrigin: "bottom", ease: Power2.easeIn}) + .to('.start-game .section-1 .ball-demo', 0.5, { y: "0px", scaleY: 1, transformOrigin: "bottom", ease: Power2.easeOut, + onStart: () => { + while(this.prevColor==this.color) { + this.color = (new Color).getRandomColor(); + } + this.prevColor = this.color; + TweenMax.to('.start-game .section-1 .ball-demo', 0.5, {backgroundColor: this.color}); + } + }); + } + + /** + * Display score + */ + showResult() { + let score = this.score; + $('.stop-game').css('display', 'flex'); + $('.stop-game .final-score').text(score + '!'); + $('.stop-game .result').text(this.showGrade(score)); + $('.nominee').show(); + + let resultTimeline = new TimelineMax(); + resultTimeline + .fromTo('.stop-game .score-container', 0.7, { opacity: 0, scale: 0.3 }, { opacity: 1, scale: 1, ease: Elastic.easeOut.config(1.25, 0.5)}) + .fromTo('.stop-game .final-score', 2, { scale: 0.5 }, { scale: 1, ease: Elastic.easeOut.config(2, 0.5)}, 0) + .fromTo('.stop-game .result', 1, { scale: 0.5 }, { scale: 1, ease: Elastic.easeOut.config(1.5, 0.5)}, 0.3) + ; + + } + + /** + * Takes players score and generates the cheering copy + * @param {int} score + * @return {string} grade + */ + showGrade(score) { + if(score > 30) return "Chuck Norris?"; + else if(score > 25) return "You're da man"; + else if(score > 20) return "Awesome"; + else if(score > 15) return "Great!"; + else if(score > 13) return "Nice!"; + else if(score > 10) return "Good Job!"; + else if(score > 5) return "Really?"; + else return "Poor..."; + } + + start() { + + this.stop(); // stop the game + + $('.start-game, .stop-game').css('display', 'none'); // hide all the popups + $('.nominee').hide(); + + new Game(); + this.score = 0; // reset + + this.isRunning = 1; + + // Clean up the stick and ball holders + // and generate new ones + $('#sticks, .scene .ball-holder').html(''); + $('#score').text(this.score); + this.generateSticks(); + this.generateBall(); + + // disables scene animations for Phones + if( !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent) ) { + Animation.sceneAnimation(); + } + this.moveToStart(); + this.moveScene(); + + // reset timescale to normal as the game speeds up + this.timeline.timeScale(1); + this.balltween.timeScale(1); + } + + stop() { + + this.isRunning = 0; + + $('.start-game, .stop-game').css('display', 'none'); + $('#sticks, .scene .ball-holder, #score').html(''); + TweenMax.killAll(); + + this.showResult(); + } + + scaleScreen() { + + TweenMax.killAll(); // prevent multiple calls on resize + + let height = $(window).height(); + let width = $(window).width(); + + this.calculateScale(); + + $('.container') + .css('transform', 'scale(' + this.scale + ')') + .css('height', height/this.scale) + .css('width', width/this.scale) + .css('transformOrigin', 'left top'); + + $('#sticks').width(this.screen/this.scale + 3 * this.stickWidth/this.scale); + + } + + /** + * Calls the above function + * If the game is running it stops and shows the score + * If the game has stops it takes player to the main menu + */ + scaleScreenAndRun() { + + this.scaleScreen(); + + if(this.isRunning) { + this.stop(); + } else { + this.intro(); + } + + } + + /** + * This is the initial animation + * where the sticks come to the starting position + * and the ball appears and falls down + */ + moveToStart() { + + let tip = new TimelineMax({ delay: 2 }); + + tip + .fromTo('.learn-to-play', 1, { scale: 0 }, { scale: 1, opacity: 1, ease: Elastic.easeOut.config(1.25, 0.5) }) + .to('.learn-to-play', 1, { scale: 0, opacity: 0, ease: Elastic.easeOut.config(1.25, 0.5) }, 3) + + TweenMax.fromTo('#ball', this.time, + { + scale: 0 + }, + { + scale: 1, + delay: this.time * ((this.steps - 3) - 1.5), + onComplete: () => { + this.balltween.play(); + } + }); + + this.timeline.add( + TweenMax.fromTo('#sticks', this.time * this.steps, { x: this.screen / this.scale }, { x: 0, ease: Power0.easeNone}) + ); + } + + /** + * The animation that moves sticks + */ + moveScene() { + + this.timeline.add( + TweenMax.to('#sticks', this.time, { x: '-=180px', ease: Power0.easeNone, repeat: -1, onRepeat: () => { this.rearrange() } }) + ); + + } + + /** + * removes the first stick and adds one the the end + * this gives the sticks an infinite movement + */ + rearrange() { + + let scale = this.speedUp(); + + this.timeline.timeScale(scale); + this.balltween.timeScale(scale); + + $('#sticks .stick').first().remove(); + new Stick(); + + } + + /** + * The game speeds up based on score + * The GSAP timeScale() function is called on the timeline to speed up the game + * This calculates how much shall the game speed up + */ + speedUp() { + if(this.score > 30) { + return 1.8; + } + if(this.score > 20) { + return 1.7; + } + if(this.score > 15) { + return 1.5; + } + else if(this.score > 12) { + return 1.4; + } + else if(this.score > 10) { + return 1.3; + } + else if(this.score > 8) { + return 1.2; + } + else if(this.score > 5) { + return 1.1; + } + return 1; + } + + /** + * Ball bouncing animation + * It checks if the ball and stick colors match + * And changes the ball color + */ + bounce() { + + this.balltween + .to('#ball', this.time/2, {y: '+=250px', scaleY: 0.7, transformOrigin: "bottom", ease: Power2.easeIn, + onComplete: () => { + this.checkColor(); + } + }).to('#ball', this.time/2, {y: '-=250px', scaleY: 1.1, transformOrigin: "bottom", ease: Power2.easeOut, + onStart: () => { + while(this.prevColor==this.color) { + this.color = (new Color).getRandomColor(); + } + this.prevColor = this.color; + TweenMax.to('#ball', 0.5, {backgroundColor: this.color}); + $('#ball').removeClass('red') + .removeClass('yellow') + .removeClass('purple') + .addClass((new Color).colorcodeToName(this.color)); + } + }) + } + + checkColor() { + + let ballPos = $('#ball').offset().left + $('#ball').width()/2; + let stickWidth = $('.stick').width(); + let score = this.score; + + $('#sticks .stick').each(function(){ + if($(this).offset().left < ballPos && $(this).offset().left > (ballPos - stickWidth)) { + + if( Color.getColorFromClass($(this)) == Color.getColorFromClass('#ball') ) { + // if matches increase the score + score++; + $('#score').text(score); + TweenMax.fromTo('#score', 0.5, { scale: 1.5 }, { scale: 1, ease: Elastic.easeOut.config(1.5, 0.5) }); + } else { + + // you loose + game.stop(); + + } + + } + }) + + this.score = score; + } + +} + +class Stick { + + constructor() { + this.stick = this.addStick(); + } + + addStick() { + this.stick = $('#sticks').append('
'); + return this.stick; + } + +} + +class Color { + + constructor() { + this.colors = ["#FF4571", "#FFD145", "#8260F6"]; + this.effects = ["bubble", "triangle", "block"]; + this.prevEffect = null; + } + + getRandomColor() { + let colorIndex = Math.random()*3; + let color = this.colors[Math.floor(colorIndex)]; + return color; + } + + colorcodeToName(color) { + let colors = ["#FF4571", "#FFD145", "#8260F6"]; + let names = ["red", "yellow", "purple"]; + let index = colors.indexOf(color); + if(index == -1) return false; + return names[index]; + } + + /** + * Changes the color of an element + * As we as adds verbal name of the color + */ + changeColor(el) { + let index = el.data("index"); + if(index===undefined) { index = 0; } + else { index += 1; } + if(index==3) index = 0; + el + .css('background-color', this.colors[index]) + .data('index', index); + + el.removeClass('red') + .removeClass('yellow') + .removeClass('purple') + .addClass(this.colorcodeToName(this.colors[index])); + + if(el.hasClass('inactive')) { + this.setEffect(el); + el.addClass('no-effect'); + } + + el.removeClass('inactive'); + } + + getRandomEffect() { + let effectIndex = null; + + effectIndex = Math.floor(Math.random()*3); + while(effectIndex == this.prevEffect) { + effectIndex = Math.floor(Math.random()*3); + } + + this.prevEffect = effectIndex; + return this.effects[effectIndex]; + } + + /** + * Adds the effect specific particles to the stick + */ + setEffect(el) { + let effect = this.getRandomEffect(); + el.addClass(effect + '-stick'); + for(let i = 1; i <= 14; i++) { + if(effect=='block') { + el.append(`
`); + } else { + el.append(`
`); + } + } + } + + /** + * Since the ball and sticks have several classes + * This method searches for the color class + * @param el [DOM element] + * @return {string} class name + */ + static getColorFromClass(el) { + let classes = $(el).attr('class').split(/\s+/); + for (var i = 0, len = classes.length; i < len; i++) { + if(classes[i] == 'red' || classes[i] == 'yellow' || classes[i] == 'purple') { + return classes[i]; + } + } + } +} + +class Animation { + + /** + * Creates and positions the small glow elements on the screen + */ + static generateSmallGlows(number) { + let h = $(window).height(); + let w = $(window).width(); + let scale = (w > h) ? h/800 : w/1200; + + h = h/scale; + w = w/scale; + + for(let i = 0; i < number; i++) { + let left = Math.floor(Math.random()*w); + let top = Math.floor(Math.random()*(h/2)); + let size = Math.floor(Math.random()*8) + 4; + $('.small-glows').prepend('
'); + let noise = $('.small-glows .small-glow').first(); + noise.css({left: left, top: top, height: size, width: size}); + } + } + + /** + * Creates the animations for sticks + * The effects is chosen by random + * And one of the three functions is + * Called accordingly + */ + playBubble(el) { + let bubble = new TimelineMax(); + bubble.staggerFromTo(el.find('.bubble'), 0.3, {scale: 0.1}, {scale: 1}, 0.03) + bubble.staggerTo(el.find('.bubble'), 0.5, {y: '-=60px', yoyo: true, repeat: -1}, 0.03); + } + + playTriangle(el) { + let triangle = new TimelineMax(); + triangle.staggerFromTo(el.find('.triangle'), 0.3, {scale: 0.1}, {scale: 1}, 0.03) + .staggerTo(el.find('.triangle'), 1.5, { + cycle:{ + rotationY: [0, 360], + rotationX: [360, 0], + }, + repeat: -1, + repeatDelay: 0.1 + }, 0.1); + } + + playBlock(el) { + let block = new TimelineMax(); + let block2 = new TimelineMax({delay: 0.69}); + + block.staggerFromTo(el.find('.block'), 0.3, {scale: 0.1}, {scale: 1}, 0.03) + .staggerTo(el.find('.block .inner:not(.inner-2)'), 1, { + cycle: { + x: ["+200%", "-200%"] + }, + repeat: -1, + repeatDelay: 0.6, + }, 0.1); + block2.staggerTo(el.find('.block .inner-2'), 1, { + cycle: { + x: ["+200%", "-200%"] + }, + repeat: -1, + repeatDelay: 0.6, + }, 0.1); + } + + static sceneAnimation() { + + const speed = 15; // uses it's local speed + + // animates the small glows in a circular motion + $('.small-glow').each(function(){ + let speedDelta = Math.floor(Math.random()*8); + let radius = Math.floor(Math.random()*20)+20; + TweenMax.to($(this), speed+speedDelta, {rotation: 360, transformOrigin: "-"+radius+"px -"+radius+"px", repeat: -1, ease: Power0.easeNone}); + }) + + var wavet = TweenMax.to('.top_wave', speed*1.7/42, {backgroundPositionX: '-=54px', repeat: -1, ease: Power0.easeNone}); + var wave1 = TweenMax.to('.wave1', speed*1.9/42, {backgroundPositionX: '-=54px', repeat: -1, ease: Power0.easeNone}); + var wave2 = TweenMax.to('.wave2', speed*2/42, {backgroundPositionX: '-=54px', repeat: -1, ease: Power0.easeNone}); + var wave3 = TweenMax.to('.wave3', speed*2.2/42, {backgroundPositionX: '-=54px', repeat: -1, ease: Power0.easeNone}); + var wave4 = TweenMax.to('.wave4', speed*2.4/42, {backgroundPositionX: '-=54px', repeat: -1, ease: Power0.easeNone}); + + var mount1 = TweenMax.to('.mount1', speed*8, {backgroundPositionX: '-=1760px', repeat: -1, ease: Power0.easeNone}); + var mount2 = TweenMax.to('.mount2', speed*10, {backgroundPositionX: '-=1782px', repeat: -1, ease: Power0.easeNone}); + + var clouds = TweenMax.to('.clouds', speed*3, {backgroundPositionX: '-=1001px', repeat: -1, ease: Power0.easeNone}); + + } + +} + + var game = new Game(); + var animation = new Animation(); + var color = new Color(); + var userAgent = window.navigator.userAgent; + + Animation.generateSmallGlows(20); + + $(document).ready(function(){ + //game.showResult(); + game.scaleScreen(); + game.intro(); + //game.start(); + //game.bounce(); + + if($(window).height() < 480) { + $('.play-full-page').css('display', 'block'); + } + }) + + $(document).on('click', '.stick', function(){ + color.changeColor($(this)); + if($(this).hasClass('no-effect')) { + if($(this).hasClass('bubble-stick')) { + animation.playBubble($(this)); + } else if($(this).hasClass('triangle-stick')) { + animation.playTriangle($(this)); + } else if($(this).hasClass('block-stick')) { + animation.playBlock($(this)); + } + $(this).removeClass('no-effect'); + } + }); + + $(document).on('click', '.section-2 .bar', function(){ + color.changeColor($(this)); + }); + + $(window).resize(function(){ + if (!userAgent.match(/iPad/i) && !userAgent.match(/iPhone/i)) { + game.scaleScreenAndRun(); + } + }); + + $(window).on("orientationchange",function(){ + game.scaleScreenAndRun(); + });