Source: ball.js

/*******************************************************************************
*   @file ball.js
*   @brief File containing the Ball class
*
*   @author <a href='mailto:omareq08@gmail.com'> Omar Essilfie-Quaye </a>
*   @version 1.0
*   @date 02-Aug-2018
*
*******************************************************************************/

/**
*	Class representing a Ball
*/
class Ball {
	/**
	*	Create a Ball
	*
	*	@param {number} x  - The initial x location of the Ball.
	*	@param {number} y  - The initial y location of the Ball.
	*	@param {number} vx - The initial x velocity of the Ball.
	*	@param {number} vy - The initial y velocity of the Ball.
	*	@param {number} r  - The radius of the Ball.
	*	@param {number} m  - The mass of the Ball.
	*/
	constructor(x, y, vx, vy, r, m) {
		this.x = x;
		this.y = y;
		this.vx = vx;
		this.vy = vy;
		this.r = r;
		this.m = m;
		this.colour = color(255, 255, 255);
	}

	/**
	 * Sets the x position of the ball.
	 *
	 * @param {number} newX - The new x value of the ball.
	 */
	setX(newX) {
		this.x = newX;
	}

	/**
	 * Sets the y position of the ball.
	 *
	 * @param {number} newY - The new y value of the ball.
	 */
	setY(newY) {
		this.y = newY;
	}

	/**
	 * Sets the x velocity of the ball.
	 *
	 * @param {number} newVelX - The new x velocity of the ball.
	 */
	setVelX(newVelX) {
		this.vx = newVelX;
	}

	/**
	 * Sets the y velocity of the ball.
	 *
	 * @param {number} newVelY - The new y velocity of the ball.
	 */
	setVelY(newVelY) {
		this.vy = newVelY;
	}

	/**
	*	Applies a single force to the Ball.
	*
	*	@param {number} fx  - The x component of the force.
	*	@param {number} fy  - The y component of the force.
	*	@param {number} dt  - The time step.
	*/
	applyForce(fx, fy, dt) {
		let ax = fx/this.m;
		this.vx += ax * dt;
		this.x += this.vx * dt;

		let ay = fy/this.m;
		this.vy += ay * dt;
		this.y += this.vy * dt;
	}

	/**
	*	Checks to see if the Ball has left the boundaries of the canvas. If
	*	they have the ball will bounce back with 90% of it's original speed.
	*/
	checkEdges(ballWallPseudoCOR) {
		const cor = constrain(ballWallPseudoCOR, 0, 1);
		if(this.x + this.r > width) {
			this.x = width - this.r;
			this.vx *= -cor;
			this.colour = color(255, 0, 0);
		}
		if(this.y + this.r > height) {
			this.y = height - this.r;
			this.vy *= -cor;
			this.colour = color(0, 255, 0);
		}
		if(this.x - this.r < 0) {
			this.x = this.r;
			this.vx *= -cor;
			this.colour = color(0, 0, 255);
		}
		if(this.y - this.r < 0) {
			this.y = this.r;
			this.vy *= -cor;
			this.colour = color(255, 255, 255);
		}
	}

	/**
	*	Checks to see if the given ball collides with this ball.
	*
	*	@param {number} ball - The ball to check the collision against.
	*/
	hits(ball) {
		let distSqr = (this.x - ball.x)**2 + (this.y - ball.y)**2;
		if(distSqr <= (this.r + ball.r)**2	) {
			return true;
		}
		return false;
	}

	/**
	*	Applies physics for elastic collision between balls.
	*
	*	@param {number} ball - The ball to do the collision against.
	*/
	collidePhysics(ball) {
		let distSqr = abs(this.x - ball.x)**2 + abs(this.y - ball.y)**2;
		let crossoverLen = this.r - (sqrt(distSqr) - ball.r);
		let normalX = ball.x - this.x;
		let normalY = ball.y - this.y;
		let normalisationConst = 1.0 / sqrt(normalX**2 + normalY**2);
		normalX *= normalisationConst;
		normalY *= normalisationConst;

		// let tangentX = -normalY;
		// let tangentY = normalX;

		this.x -= 0.5 * crossoverLen * normalX;
		this.y -= 0.5 * crossoverLen * normalY;
		ball.setX(ball.x + 0.5 * crossoverLen * normalX);
		ball.setY(ball.y + 0.5 * crossoverLen * normalY);

		// let collisionPointX = this.x + normalX * this.r;
		// let collisionPointY = this.y + normalY * this.r;

		let kebefore = 0.5 * this.m * (this.vx**2 + this.vy**2);
		kebefore += 0.5 + ball.m * (ball.vx**2 + ball.vy**2);


		let m1Reduced = 2.0 * ball.m / (this.m + ball.m);
		let inner12 = (this.vx - ball.vx) * (this.x - ball.x);
		inner12 += (this.vy - ball.vy) * (this.y - ball.y);

		let d12Recip = 1.0 / (this.r + ball.r)**2;
		// let d12Recip = 1.0 / ((this.x - ball.x)**2 + (this.y - ball.y)**2);

		this.vx -= m1Reduced * inner12 * d12Recip * (this.x - ball.x);
		this.vy -= m1Reduced * inner12 * d12Recip * (this.y - ball.y);


		let m2Reduced = 2.0 * ball.m / (this.m + ball.m);
		let inner21 = (ball.vx - this.vx) * (ball.x - this.x);
		inner21 += (ball.vy - this.vy) * (ball.y - this.y);

		let d21Recip = 1.0 / (this.r + ball.r)**2;
		// let d21Recip = 1.0 / ((ball.x - this.x)**2 + (ball.y - this.y)**2);

		ball.setVelX(ball.vx -
			m2Reduced * inner21 * d21Recip * (ball.x - this.x));
		ball.setVelY(ball.vy -
			m2Reduced * inner21 * d21Recip * (ball.y - this.y));

		let keafter = 0.5 * this.m * (this.vx**2 + this.vy**2);
		keafter += 0.5 + ball.m * (ball.vx**2 + ball.vy**2);

		console.log("KE Before: ", kebefore, " KE After: ", keafter);
	}

	/**
	*	Draws a white ellipse at the Balls position on the canvas
	*/
	show() {
		push();
		fill(this.colour);
		ellipse(this.x, height - this.y, 2 * this.r, 2 * this.r);
		pop();
	}
}

Documentation generated by JSDoc 4.0.2 on Sun Feb 04 2024 18:35:38 GMT+0000 (Greenwich Mean Time)