import jQuery from 'jquery'; import 'bootstrap'; import 'bootstrap/dist/css/bootstrap.css'; import '../css/main.css'; import '../css/util.css'; // RequestAnimFrame: a browser API for getting smooth animations window.requestAnimFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { return window.setTimeout(callback, 1000 / 60); }; })(); window.cancelRequestAnimFrame = (function () { return window.cancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelRequestAnimationFrame || window.oCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame || clearTimeout })(); (function ($) { "use strict"; var P = (function () { var PP = []; var A = function () { PP.push(null); }; var B = function () { return PP.length; }; var C = function () { PP = []; }; return { A: A, B: B, C: C }; })() var A = P.A, B = P.B, C = P.C; // Initialize canvas and required variables var canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d"), // Create canvas context W = 640, // Window's width H = 480, // Window's height particles = [], // Array containing particles ball = {}, // Ball object paddles = [2], // Array containing two paddles mouse = {}, // Mouse object to store it's current position points = 0, // Varialbe to store points fps = 60, // Max FPS (frames per second) particlesCount = 20, // Number of sparks when ball strikes the paddle flag = 0, // Flag variable which is changed on collision particlePos = {}, // Object to contain the position of collision multipler = 1, // Varialbe to control the direction of sparks startBtn = {}, // Start button object restartBtn = {}, // Restart button object over = 0, // flag varialbe, cahnged when the game is over init, // variable to initialize animation paddleHit; // Add mousemove and mousedown events to the canvas canvas.addEventListener("mousemove", trackPosition, true); canvas.addEventListener("mousedown", btnClick, true); // Initialise the collision sound var collision = document.getElementById("collide"); // Set the canvas's height and width to full screen canvas.width = W; canvas.height = H; // Function to paint canvas function paintCanvas() { ctx.fillStyle = "black"; ctx.fillRect(0, 0, W, H); } // Function for creating paddles function Paddle(pos) { // Height and width this.h = 5; this.w = 150; // Paddle's position this.x = W / 2 - this.w / 2; this.y = (pos == "top") ? 0 : H - this.h; } // Push two new paddles into the paddles[] array paddles.push(new Paddle("bottom")); paddles.push(new Paddle("top")); // Ball object ball = { x: 50, y: 50, r: 5, c: "green", vx: 4, vy: 8, // Function for drawing ball on canvas draw: function () { ctx.beginPath(); ctx.fillStyle = this.c; ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false); ctx.fill(); } }; // Start Button object startBtn = { w: 100, h: 50, x: W / 2 - 50, y: H / 2 - 25, draw: function () { ctx.strokeStyle = "blue"; ctx.lineWidth = "2"; ctx.strokeRect(this.x, this.y, this.w, this.h); ctx.font = "18px Arial, sans-serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillStlye = "Green"; ctx.fillText("Start", W / 2, H / 2); } }; // Restart Button object restartBtn = { w: 100, h: 50, x: W / 2 - 50, y: H / 2 - 50, draw: function () { ctx.strokeStyle = "green"; ctx.lineWidth = "2"; ctx.strokeRect(this.x, this.y, this.w, this.h); ctx.font = "18px Arial, sans-serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillStlye = "white"; ctx.fillText("Restart", W / 2, H / 2 - 25); } }; // Function for creating particles object function createParticles(x, y, m) { this.x = x || 0; this.y = y || 0; this.radius = 1.2; this.vx = -1.5 + Math.random() * 3; this.vy = m * Math.random() * 1.5; } // Draw everything on canvas function draw() { paintCanvas(); for (var i = 0; i < paddles.length; i++) { var p = paddles[i]; ctx.fillStyle = "green"; ctx.fillRect(p.x, p.y, p.w, p.h); } ball.draw(); update(); } // Function to increase speed after every 5 points function increaseSpd() { if (B() % 4 == 0) { if (Math.abs(ball.vx) < 15) { ball.vx += (ball.vx < 0) ? -1 : 1; ball.vy += (ball.vy < 0) ? -2 : 2; } } } // Track the position of mouse cursor function trackPosition(e) { mouse.x = e.offsetX; mouse.y = e.offsetY; } // Function to update positions, score and everything. // Basically, the main game logic is defined here function update() { // Update scores updateScore(); // Move the paddles on mouse move if (mouse.x && mouse.y) { for (var i = 1; i < paddles.length; i++) { var p = paddles[i]; p.x = mouse.x - p.w / 2; } } // Move the ball ball.x += ball.vx; ball.y += ball.vy; // Collision with paddles var p1 = paddles[1]; var p2 = paddles[2]; // If the ball strikes with paddles, // invert the y-velocity vector of ball, // increment the points, play the collision sound, // save collision's position so that sparks can be // emitted from that position, set the flag variable, // and change the multiplier if (collides(ball, p1)) { collideAction(ball, p1); } else if (collides(ball, p2)) { collideAction(ball, p2); } else { // Collide with walls, If the ball hits the top/bottom, // walls, run gameOver() function if (ball.y + ball.r > H) { ball.y = H - ball.r; gameOver(); } else if (ball.y < 0) { ball.y = ball.r; gameOver(); } // If ball strikes the vertical walls, invert the // x-velocity vector of ball if (ball.x + ball.r > W) { ball.vx = -ball.vx; ball.x = W - ball.r; } else if (ball.x - ball.r < 0) { ball.vx = -ball.vx; ball.x = ball.r; } } // If flag is set, push the particles if (flag == 1) { for (var k = 0; k < particlesCount; k++) { particles.push(new createParticles(particlePos.x, particlePos.y, multipler)); } } // Emit particles/sparks emitParticles(); // reset flag flag = 0; } //Function to check collision between ball and one of //the paddles function collides(b, p) { if (b.x + ball.r >= p.x && b.x - ball.r <= p.x + p.w) { if (b.y >= (p.y - p.h) && p.y > 0) { paddleHit = 1; return true; } else if (b.y <= p.h && p.y == 0) { paddleHit = 2; return true; } else return false; } } //Do this when collides == true function collideAction(ball, p) { ball.vy = -ball.vy; if (paddleHit == 1) { ball.y = p.y - p.h; particlePos.y = ball.y + ball.r; multipler = -1; } else if (paddleHit == 2) { ball.y = p.h + ball.r; particlePos.y = ball.y - ball.r; multipler = 1; } A(); increaseSpd(); if (collision) { if (B() > 0) collision.pause(); collision.currentTime = 0; collision.play(); } particlePos.x = ball.x; flag = 1; } // Function for emitting particles function emitParticles() { for (var j = 0; j < particles.length; j++) { var par = particles[j]; ctx.beginPath(); ctx.fillStyle = "white"; if (par.radius > 0) { ctx.arc(par.x, par.y, par.radius, 0, Math.PI * 2, false); } ctx.fill(); par.x += par.vx; par.y += par.vy; // Reduce radius so that the particles die after a few seconds par.radius = Math.max(par.radius - 0.05, 0.0); } } // Function for updating score function updateScore() { ctx.fillStlye = "white"; ctx.font = "16px Arial, sans-serif"; ctx.textAlign = "left"; ctx.textBaseline = "top"; ctx.fillText("Score: " + B(), 20, 20); } // Function for running the whole animation function animloop() { init = requestAnimFrame(animloop); draw(); } // Function to execute at startup function startScreen() { draw(); startBtn.draw(); } // On button click (Restart and start) function btnClick(e) { // Variables for storing mouse position on click var mx = e.offsetX, my = e.offsetY; // Click start button if (mx >= startBtn.x && mx <= startBtn.x + startBtn.w) { animloop(); // Devare the start button after clicking it startBtn = {}; } // If the game is over, and the restart button is clicked if (over == 1) { if (mx >= restartBtn.x && mx <= restartBtn.x + restartBtn.w) { ball.x = 20; ball.y = 20; ball.vx = 4; ball.vy = 8; animloop(); C(); over = 0; } } } window.gameOver = function () { ctx.fillStlye = "white"; ctx.font = "20px Roboto, sans-serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText("Сохраняю результат...", W / 2, H / 2 + 25); var key = sessionStorage.getItem("key"); fetch('/answer/check', { method: 'POST', body: JSON.stringify({ key: key, score: B() }), }) .then(function (data) { return data.json() }) .catch(function () { }) .then(function (approval) { if (!approval) { ctx.fillText("Не удалось сохранить с этим ключом", W / 2, H / 2 + 65); return } var top = approval.top; for (var i = 0; i < top.length; i++) { var score = top[i].Score; var name = top[i].Member.substr(20); ctx.fillText(name + " → " + score, W / 2, H / 2 - 150 + 20 * i); } var msg = approval.msg; for (var i = 0; i < msg.length; i++) { ctx.fillText(msg[i], W / 2, H / 2 + 65 + 20 * i); } }) // Stop the Animation cancelRequestAnimFrame(init); // Set the over flag over = 1; // Show the restart button restartBtn.draw(); } window.playGame = function (_this) { var key = $("#q-form").find("input[name='key']") if (!key.val().trim().length) { key.parent().addClass("alert-validate"); return false; } sessionStorage.setItem("key", key.val().trim()); var q = $("#q"); var a = $("#a"); q.addClass("hidden"); a.removeClass("hidden"); return false; } startScreen(); })(jQuery);