Updated Private -> RSA
[samples/web/SensorBall.git] / js / main.js
1 /*
2  *      Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  *      Licensed under the Flora License, Version 1.1 (the "License");
5  *      you may not use this file except in compliance with the License.
6  *      You may obtain a copy of the License at
7  *
8  *              http://floralicense.org/license/
9  *
10  *      Unless required by applicable law or agreed to in writing, software
11  *      distributed under the License is distributed on an "AS IS" BASIS,
12  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *      See the License for the specific language governing permissions and
14  *      limitations under the License.
15  */
16
17 /*global $: false, tizen: false, navigator: false, app: true*/
18
19 var app = {
20         sensor: null,
21         R: 2000.0, // // gravity constant * m * M
22
23         gameWidth: 0,
24         gameHeight: 0,
25         ballWidth: 0,
26         ballHeight: 0,
27         sunWidth: 0,
28         sunHeight: 0,
29         ballX: 0,
30         ballY: 0,
31         dX: 0,
32         dY: 0,
33         sunX: 0,
34         sunY: 0,
35
36         backgroundWidth: 0,
37         backgroundHeight: 0,
38         backgroundTop: 0,
39         backgroundLeft: 0,
40
41         resistance: 0.98, // air
42         friction: 0.90, // bounce
43         sideFriction: 0.95,
44         frictionC: 0.002,
45         repulse: 0.6,
46         cdd: -0.3,
47
48         current: 'ball',
49         event: null,
50         animationInterval: 40,
51
52         /**
53          * Draw earth background position
54          * @param {int} x current x earth position
55          * @param {int} y current y earth position
56          */
57         earthUpdateBackgroundPosition: function earthUpdateBackgroundPosition(x, y) {
58                 "use strict";
59                 var rX, rY,
60                         cX, cY,
61                         tX, tY,
62                         bdX, bdY,
63                         br;
64
65                 rX = -30.0;
66                 rY = -30.0;
67
68                 cX = (this.gameWidth - this.backgroundWidth) / 2;
69                 cY = (this.gameHeight - this.backgroundHeight) / 2;
70
71                 tX = cX + (-x * rX);
72                 tY = cY + (y * rY);
73
74                 bdX = tX - this.backgroundLeft;
75                 bdY = tY - this.backgroundTop;
76
77                 br = 0.2;
78
79                 this.backgroundLeft += bdX * br;
80                 this.backgroundTop += bdY * br;
81
82                 $('.background').css('background-position', (this.backgroundLeft - 330) + 'px ' + (this.backgroundTop - 330) + 'px');
83         },
84
85         /**
86          * Draw sun position
87          * @param {int} x current x earth position
88          * @param {int} y current y earth position
89          */
90         earthUpdateSunPosition: function earthUpdateSunPosition(x, y) {
91                 "use strict";
92                 var rX, rY,
93                         cX, cY,
94                         tX, tY,
95                         bdX, bdY,
96                         br;
97
98                 rX = -8.0;
99                 rY = -8.0;
100
101                 cX = (this.gameWidth - this.sunWidth) / 2;
102                 cY = (this.gameHeight - this.sunHeight) / 2;
103
104                 tX = cX + (-x * rX);
105                 tY = cY + (y * rY);
106
107                 bdX = tX - this.sunX;
108                 bdY = tY - this.sunY;
109
110                 br = 0.2;
111
112                 this.sunX += bdX * br;
113                 this.sunY += bdY * br;
114
115                 $('#sun').css('left', this.sunX + 'px');
116                 $('#sun').css('top', this.sunY + 'px');
117                 $('#sun').show();
118         },
119
120         /**
121          * Deceleration - used when the earth leaves the Sun's gravitation
122          */
123         deceleration: function deceleration() {
124                 "use strict";
125                 this.dX *= 0.6;
126                 this.dY *= 0.6;
127         },
128
129         /**
130          * Draw the next animation frame for the 'earth' tab
131          */
132         earthEvents: function earthEvents() {
133                 "use strict";
134
135                 var event, borderTolerance,
136                         x, y,
137                         dXl, dYl,
138                         d,
139                         d2,
140                         ddx, ddy,
141                         ratio;
142
143                 event = this.event;
144                 borderTolerance = 30;   // when Earth reach a border, then Earth is "moving"
145
146                 x = -event.accelerationIncludingGravity.x;
147                 y = -event.accelerationIncludingGravity.y;
148
149                 // calculate X and Y distances between the Sun and Earth
150                 dXl = (this.sunX + this.sunWidth / 2 - (this.ballX + (this.ballWidth / 2))); // x distance
151                 dYl = (this.sunY + this.sunHeight / 2 - (this.ballY + (this.ballHeight / 2))); // y distance
152
153                 if (Math.abs(dXl) < 1) {
154                         dXl = dXl < 0 ? -1 : 1; // round to 1 * sign
155                 }
156                 if (Math.abs(dYl) < 1) {
157                         dYl = dYl < 0 ? -1 : 1; // round to 1 * sign
158                 }
159
160                 // distance squared
161                 d2 = Math.pow(dXl, 2) + Math.pow(dYl, 2);
162                 // distance
163                 d = Math.sqrt(d2);
164
165                 // acceleration is proportional to 1/d2 [a=GM/r^2]
166                 // X component is also proportional to dXl / d
167                 ddx = (this.R * dXl) / (d2 * d);
168                 ddy = (this.R * dYl) / (d2 * d);
169
170                 // apply acceleration to speed
171                 this.dX += ddx;
172                 this.dY += ddy;
173
174                 ratio = Math.sqrt(Math.pow(this.dX, 2) + Math.pow(this.dY, 2)) / 25; // max speed
175                 if (ratio > 1) { // speed limit achieved
176                         this.dX /= ratio;
177                         this.dY /= ratio;
178                 }
179
180                 // apply speed to Earth position
181                 this.ballX += this.dX;
182                 this.ballY += this.dY;
183
184                 // What do it when the earth leaves gravitation of the Sun?;
185                 if (this.ballX > (this.gameWidth + borderTolerance)) {
186                         this.ballX = -borderTolerance; this.deceleration();
187                 }
188                 if (this.ballY > (this.gameHeight + borderTolerance)) {
189                         this.ballY = -borderTolerance; this.deceleration();
190                 }
191                 if (this.ballX < -borderTolerance) {
192                         this.ballX = this.gameWidth + borderTolerance; this.deceleration();
193                 }
194                 if (this.ballY < -borderTolerance) {
195                         this.ballY = this.gameHeight + borderTolerance; this.deceleration();
196                 }
197
198                 // update Earth position
199                 $('.ball').css('left', this.ballX + 'px');
200                 $('.ball').css('top', this.ballY + 'px');
201
202                 // relative depth Sun / Earth
203                 if (this.dY > 0) {
204                         $('.ball').css('z-index', 100);
205                 } else {
206                         $('.ball').css('z-index', 20);
207                 }
208
209                 this.earthUpdateBackgroundPosition(x, y);
210                 this.earthUpdateSunPosition(x, y);
211         },
212
213         /**
214          *  Checks if the ball already was on the edge in the previous step
215          *
216          *  If so, this is not a 'real' bounce - the ball is just laying on the edge
217          *  Uses globals: ballX, ballY, ballWidth, ballHeight, gameWidth, gameHeight
218          *
219          *  @return {Object}
220          */
221         shouldVibrateIfHitsEdge: function shouldVibrateIfHitsEdge() {
222                 "use strict";
223                 var ret = {
224                         x: true,
225                         y: true
226                 };
227
228                 if (this.ballX <= 0) {
229                         ret.x = false;
230                 } else if ((this.ballX + this.ballWidth) >= this.gameWidth) {
231                         ret.x = false;
232                 }
233                 if (this.ballY <= 0) {
234                         ret.y = false;
235                 } else if ((this.ballY + this.ballHeight) >= this.gameHeight) {
236                         ret.y = false;
237                 }
238
239                 return ret;
240         },
241
242         /**
243          * Draw the next animation frame for the 'ball' tab
244          */
245         ballEvents: function ballEvents() {
246                 "use strict";
247                 var event,
248                         x,
249                         y,
250                         stickTop = 0,
251                         stickLeft = 0,
252                         stickBottom = 0,
253                         stickRight = 0,
254                         rX,
255                         rY,
256                         ddx,
257                         ddy,
258                         shouldVibrate = null,
259                         isHittingEdge = null;
260
261                 event = this.event;
262
263                 x = -event.accelerationIncludingGravity.x;
264                 y = -event.accelerationIncludingGravity.y;
265
266                 stickTop = 0;
267                 stickLeft = 0;
268                 stickBottom = 0;
269                 stickRight = 0;
270
271                 rX = this.ballX;
272                 rY = this.ballY;
273                 ddx = x * -this.cdd;
274                 ddy = y * this.cdd;
275                 this.dX += ddx;
276                 this.dY += ddy;
277                 this.dX *= this.resistance;
278                 this.dY *= this.resistance;
279
280                 shouldVibrate = this.shouldVibrateIfHitsEdge();
281
282                 this.ballX += this.dX;
283                 this.ballY += this.dY;
284
285                 if (this.ballX < 0) {
286                         this.ballX = 0;
287                         this.dX = Math.abs(this.dX) * this.friction - this.frictionC;
288                         this.dY *= this.sideFriction;
289                         stickLeft = 1;
290                 } else if ((this.ballX + this.ballWidth) > this.gameWidth) {
291                         this.ballX = this.gameWidth - this.ballWidth;
292                         this.dX = -Math.abs(this.dX) * this.friction + this.frictionC;
293                         this.dY *= this.sideFriction;
294                         stickRight = 1;
295                         if (this.ballX < 0) {
296                                 this.ballX = 0;
297                         }
298                 }
299
300                 if (this.ballY < 0) {
301                         this.ballY = 0;
302                         this.dY = Math.abs(this.dY) * this.friction - this.frictionC;
303                         this.dX *= this.sideFriction;
304                         stickTop = 1;
305                 } else if ((this.ballY + this.ballHeight) > this.gameHeight) {
306                         this.ballY = this.gameHeight - this.ballHeight;
307                         this.dY = -Math.abs(this.dY) * this.friction + this.frictionC;
308                         this.dX *= this.sideFriction;
309                         stickBottom = 1;
310                         if (this.ballY < 0) {
311                                 this.ballY = 0;
312                         }
313                 }
314
315                 isHittingEdge = {
316                         x: (stickLeft || stickRight) && Math.abs(this.dX) > 1,
317                         y: (stickTop || stickBottom) && Math.abs(this.dY) > 1
318                 };
319
320                 // if on the edge and the hitting speed is high enough
321                 if ((shouldVibrate.x && isHittingEdge.x) || (shouldVibrate.y && isHittingEdge.y)) {
322                         if (typeof navigator.webkitVibrate === 'function') {
323                                 navigator.webkitVibrate(100);
324                         } else {
325                                 navigator.vibrate(100);
326                         }
327                 }
328
329                 $('.ball').css('left', this.ballX + 'px');
330                 $('.ball').css('top', this.ballY + 'px');
331
332                 rX = this.ballX - rX;
333                 rY = this.ballY - rY;
334
335         },
336
337         /**
338          * Draw the next animation frame
339          */
340         fun: function fun() {
341                 "use strict";
342                 if (this.event) {
343                         switch (this.current) {
344                         case 'ball':
345                                 this.ballEvents();
346                                 break;
347                         case 'earth':
348                                 this.earthEvents();
349                                 break;
350                         case 'baloon':
351                                 this.ballEvents();
352                                 break;
353                         default:
354                                 console.warn("Incorrect current mode");
355                                 this.ballEvents();
356                         }
357                 }
358
359                 // animation - go to next step;
360                 setTimeout(this.fun.bind(this), this.animationInterval);
361         },
362
363         /**
364          * Switch to the 'ball' tab
365          */
366         startBall: function startBall() {
367                 "use strict";
368
369                 $('.ui-content').removeClass('background1 background2 background3').addClass('background1');
370                 $(':jqmData(role="controlbar")').find('.ui-btn').removeClass('ui-btn-hover-s ui-btn-down-s');
371                 this.gameHeight = $('.background').outerHeight();
372
373                 this.cdd = -0.3;
374                 this.resistance = 0.98;
375                 this.friction = 0.90;
376                 this.sideFriction = 0.95;
377                 this.frictionC = 0.002;
378
379                 this.current = 'ball';
380
381                 $('#sun').remove();
382                 $('.ball').attr('src', './images/ball1.png');
383                 $('.ball').css('width', '86px');
384                 $('.ball').css('height', '86px');
385
386                 $('.background').css('background-position', '0px -90px');
387
388                 this.ballWidth = parseInt($('.ball').css('width'), 10);
389                 this.ballHeight = parseInt($('.ball').css('height'), 10);
390         },
391
392         /**
393          * Switch to the 'sky' tab
394          */
395         startSky: function startSky() {
396                 "use strict";
397                 $('.ui-content').removeClass('background1 background2 background3').addClass('background2');
398                 $(':jqmData(role="controlbar")').find('.ui-btn').removeClass('ui-btn-hover-s ui-btn-down-s');
399                 this.gameHeight = $('.background').outerHeight();
400
401                 this.cdd = 0.05;
402                 this.resistance = 0.90;
403                 this.friction = 0.98;
404                 this.sideFriction = 0.95;
405                 this.frictionC = 0.002;
406
407                 this.current = 'baloon';
408
409                 $('#sun').remove();
410                 $('.ball').attr('src', './images/balloon.png');
411                 $('.ball').css('width', '100px');
412                 $('.ball').css('height', '100px');
413
414                 $('.background').css('background-position', '0px -90px');
415
416                 this.ballWidth = parseInt($('.ball').css('width'), 10);
417                 this.ballHeight = parseInt($('.ball').css('height'), 10);
418         },
419
420         /**
421          * Switch to the 'space' tab
422          */
423         startSpace: function startSpace() {
424                 "use strict";
425                 var backgroundPosition, arrayPos;
426
427                 $('.ui-content').removeClass('background1 background2 background3').addClass('background3');
428                 $(':jqmData(role="controlbar")').find('.ui-btn').removeClass('ui-btn-hover-s ui-btn-down-s');
429
430                 this.gameHeight = $('.background').outerHeight();
431
432                 this.friction = 0.60; // bounce
433                 this.sideFriction = 0.95;
434                 this.frictionC = 0.0;
435
436                 this.current = 'earth';
437
438                 $('.ball').attr('src', './images/earth.png');
439                 $('#main').append('<img id="sun" class="sun" src="./images/sun.png" style="display: none;"></img>');
440
441                 this.sunX = (this.gameWidth - parseInt($('#sun').css('width'), 10)) / 2;
442                 this.sunY = (this.gameHeight - parseInt($('#sun').css('height'), 10)) / 2;
443                 $('.ball').css('width', '50px');
444                 $('.ball').css('height', '50px');
445
446                 $('.background').css('background-position', '0px 0px');
447
448                 this.ballWidth = parseInt($('.ball').css('width'), 10);
449                 this.ballHeight = parseInt($('.ball').css('height'), 10);
450                 this.sunWidth = parseInt($('#sun').css('width'), 10);
451                 this.sunHeight = parseInt($('#sun').css('height'), 10);
452
453                 backgroundPosition = $('.background').css('background-position');
454
455                 arrayPos = backgroundPosition.split(' ');
456                 this.backgroundTop = parseInt(arrayPos[0], 10);
457                 this.backgroundLeft = parseInt(arrayPos[1], 10);
458                 this.backgroundWidth = parseInt($('.background').css('width'), 10);
459                 this.backgroundHeight = parseInt($('.background').css('height'), 10);
460         },
461
462         saveSensorData: function saveSensorData(event) {
463                 "use strict";
464                 this.event = event;
465         }
466 };
467
468 $(document).ready(function () {
469         "use strict";
470         var img,
471                 contentHeight = screen.availHeight - $('div[data-role="header"]').outerHeight() - $('div[data-role="footer"]').outerHeight();
472
473         $('div[data-role="content"]').css('height', contentHeight - 33);
474         app.gameWidth = screen.availWidth;
475         app.ballWidth = parseInt($('.ball').css('width'), 10);
476         app.ballHeight = parseInt($('.ball').css('height'), 10);
477
478         window.addEventListener('devicemotion', app.saveSensorData.bind(app), false);
479
480         app.fun();
481
482         document.addEventListener('tizenhwkey', function(e) {
483                 if (e.keyName == "back") {
484                         tizen.application.getCurrentApplication().exit();
485                 }
486         });
487
488         $('.ui-btn-back').bind('touchstart', function (event) {
489                 tizen.application.getCurrentApplication().exit();
490         });
491
492         $('#btnBall').bind('tap', function (event) {
493                 $('#sun').remove();
494                 app.startBall();
495         });
496
497         $('#btnSky').bind('tap', function (event) {
498                 $('#sun').remove();
499                 app.startSky();
500         });
501
502         $('#btnSpace').bind('tap', function (event) {
503                 $('#sun').remove();
504                 app.startSpace();
505         });
506
507         $('#mainPage').on('pageshow', function () {
508                 app.startBall();
509
510                 // fix for hidden back batton
511                 if ($('a.ui-btn-back').is(':hidden')) {
512                         $('#footerControls').removeClass('ui-tabbar-margin-back');
513                 }
514         });
515
516         // Preload backgrounds;
517         img = $('<img>').hide();
518         img.attr('src', 'images/background1.png');
519 });
520
521 $(window).resize(function () {
522         'use strict';
523         app.gameWidth = screen.availWidth;
524         app.gameHeight = $('.background').outerHeight();
525 });