From dccdb02f738967d9613ae0f822ad135438823767 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Sun, 19 Jul 2026 17:28:56 +0300 Subject: [PATCH] =?UTF-8?q?refactor:=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D1=8F=20pro?= =?UTF-8?q?cessBall=20=D0=B4=D0=BB=D1=8F=20=D0=B8=D0=BD=D0=BA=D0=B0=D0=BF?= =?UTF-8?q?=D1=81=D1=83=D0=BB=D1=8F=D1=86=D0=B8=D0=B8=20=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?=D0=B8=D0=BA=D0=B8=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B8=20=D1=81=D1=82=D0=BE=D0=BB=D0=BA=D0=BD=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BC=D1=8F=D1=87=D0=B0=20=D1=81=D0=BE=20?= =?UTF-8?q?=D1=81=D1=82=D0=B5=D0=BD=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/processBall/processBall.js | 54 +++++++++++++++++++++++++ src/lib/processBall/processBall.test.js | 45 +++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/lib/processBall/processBall.js create mode 100644 src/lib/processBall/processBall.test.js diff --git a/src/lib/processBall/processBall.js b/src/lib/processBall/processBall.js new file mode 100644 index 0000000..568a212 --- /dev/null +++ b/src/lib/processBall/processBall.js @@ -0,0 +1,54 @@ +import { Ball } from '../../entities/ball/ball'; + +/** + * Двигает мяч и обрабатывает отскок от стен. Возвращает true, если мяч уже отскочил или вышел за нижнюю границу + * @param {Ball} ball мяч + * @param {number} containerWidth ширина игрового контейнера в пикселях + * @param {number} containerHeight высота игрового контейнера в пикселях + * @returns {boolean} + */ +export function processBall(ball, containerWidth, containerHeight) { + try { + if (!(ball instanceof Ball)) { + throw new Error('Аргумент ball должен быть экземпляром класса мяча'); + } + + if (typeof containerWidth !== 'number' || typeof containerHeight !== 'number') { + throw new Error('Значения размеров игрового контейнера должены являться числами'); + } + + if (containerWidth <= 0 || containerHeight <= 0) { + throw new Error('Размеры игрового контейнера должены быть положительными числами'); + } + + const leftBoundary = ball.radius; + const rightBoundary = containerWidth - ball.radius; + const topBoundary = ball.radius; + const bottomBoundary = containerHeight - ball.radius; + + // Не даем мячу выйти за границы стен слева / справав и меняем направление + if (ball.x <= leftBoundary || ball.x >= rightBoundary) { + ball.x = ball.x <= leftBoundary ? leftBoundary : rightBoundary; + ball.horizontalSpeed *= -1; + return true; + } + + // Не даем мячу выйти за границу стены сверху и меняем направление + if (ball.y <= topBoundary) { + ball.y = topBoundary; + ball.verticalSpeed *= -1; + return true; + } + + // Проверяем выход за границу стены снизу + if (ball.y >= bottomBoundary) { + ball.status = 'out'; + return true; + } + + return false; + } catch (err) { + console.error(err); + return null; + } +} diff --git a/src/lib/processBall/processBall.test.js b/src/lib/processBall/processBall.test.js new file mode 100644 index 0000000..b34fd80 --- /dev/null +++ b/src/lib/processBall/processBall.test.js @@ -0,0 +1,45 @@ +import { Ball } from '../../entities/ball/ball'; +import { processBall } from './processBall'; + +describe('processBall', () => { + it('Возвращает null при неверных типах аргументов', () => { + const ball = new Ball(100, 100, 10, 3); + + expect(processBall(null, 800, 600)).toBeNull(); + expect(processBall(ball, '800', 600)).toBeNull(); + expect(processBall(ball, -1, 600)).toBeNull(); + expect(processBall(ball, 800, -1)).toBeNull(); + }); + + it('Возвращает false, если мяч не касается стен', () => { + const ball = new Ball(400, 300, 10, 3); + + expect(processBall(ball, 800, 600)).toBe(false); + }); + + it('Отражает мяч от боковой стены и возвращает true', () => { + const ball = new Ball(10, 300, 10, 3); + ball.horizontalSpeed = -10; + + expect(processBall(ball, 800, 600)).toBe(true); + expect(ball.x).toBe(ball.radius); + expect(ball.horizontalSpeed).toBe(10); + }); + + it('Отражает мяч от верхней стены и возвращает true', () => { + const ball = new Ball(400, 10, 10, 3); + ball.horizontalSpeed = 0; + ball.verticalSpeed = -10; + + expect(processBall(ball, 800, 600)).toBe(true); + expect(ball.y).toBe(ball.radius); + expect(ball.verticalSpeed).toBe(10); + }); + + it('Помечает мяч вышедшим за нижнюю границу', () => { + const ball = new Ball(400, 595, 10, 3); + + expect(processBall(ball, 800, 600)).toBe(true); + expect(ball.status).toBe('out'); + }); +});