/*
matterjs -
https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js
tailwind -
https://cdn.tailwindcss.com
*/
const { Engine, Render, Body, Bodies, Composite } = Matter;
const engine = Engine.create();
// particle vars
let particleGraphic, particleBody;
const particleRadius = 15;
const particleHolder = document.querySelector("#particleHolder");
// boundaries
let leftwall, rightwall, floor;
const wallThickness = 100;
// svg variables
const viewportWidth = 400;
const viewportHeight = 400;
const w = 400;
const h = 400;
const namespace = "http://www.w3.org/2000/svg";
// ui
const replayButton = document.querySelector("#button");
function initSVG() {
const svg = document.querySelector("svg");
svg.setAttribute("width", `${viewportWidth}`);
svg.setAttribute("height", `${viewportHeight}`);
svg.setAttribute("viewBox", `0 0 ${w} ${h}`);
const bg = document.querySelector("#bg");
bg.setAttribute("width", w);
bg.setAttribute("height", h);
bg.setAttribute("fill", "#eaeaea");
}
function initRenderer() {
// create renderer
const rendererHolder = document.querySelector("#rendererHolder");
const render = Render.create({
element: rendererHolder,
engine: engine,
options: {
width: w,
height: h,
showAngleIndicator: true
}
});
Render.run(render);
}
function initParticle() {
if (particleGraphic) {
particleHolder.removeChild(particleGraphic);
particleGraphic = null;
Composite.remove(engine.world, particleBody);
}
// dimensions, etc
const xpos = w / 2;
const ypos = -particleRadius;
// randomly decide how many sides the particle will have
const sides = 3 + Math.round(Math.random() * 7);
const radius = particleRadius + Math.random() * particleRadius;
const restitution = 0.9;
const color = getRandomColor();
// body
particleBody = getPolygonBody(0, 0, sides, radius, restitution, 0);
// get all the verticies so we can use them to create the svg polygon
const vertices = particleBody.vertices;
// graphic
particleGraphic = getPolygonGraphic(xpos, ypos, vertices, color);
particleHolder.appendChild(particleGraphic);
// give the body an initial random rotation and position
Body.setAngle(particleBody, Math.random() * 2 * Math.PI);
Body.setPosition(particleBody, { x: xpos, y: ypos });
}
function initWallAndFloor() {
floor = Bodies.rectangle(w / 2, h + wallThickness / 2, w, wallThickness, {
isStatic: true,
id: "floor"
});
leftwall = Bodies.rectangle(-wallThickness / 2, h / 2, wallThickness, h, {
isStatic: true,
id: "leftwall"
});
rightwall = Bodies.rectangle(w + wallThickness / 2, h / 2, wallThickness, h, {
isStatic: true,
id: "righttwall"
});
}
function initUI() {
replayButton.addEventListener("click", () => {
initParticle();
Composite.add(engine.world, [particleBody]);
Body.setPosition(particleBody, {
x: 20 + Math.random() * (w - 40),
y: -particleRadius
});
Body.setSpeed(particleBody, 0);
Body.setVelocity(particleBody, { x: 0, y: 0 });
});
}
function getPolygonBody(
xpos,
ypos,
sides,
radius,
restitution,
index,
isStatic = false
) {
const b = Bodies.polygon(xpos, ypos, sides, radius, {
id: `polygon_${index}`,
friction: 1,
restitution: restitution,
isStatic: isStatic
});
return b;
}
function getPolygonGraphic(xpos, ypos, vertices, color = "black") {
let points = "";
vertices.forEach((vertex) => {
console.log("vertex: ", vertex);
points = `${points} ${vertex.x},${vertex.y}`;
});
const pg = document.createElementNS(namespace, "polygon");
pg.setAttribute("points", points);
pg.setAttribute("fill", color);
pg.setAttribute("stroke", "#212121");
const g = document.createElementNS(namespace, "g");
g.appendChild(pg);
g.setAttribute("transform", `translate(${xpos} ${ypos})`);
return g;
}
function getRandomColor() {
return `hsl(${Math.round(Math.random() * 360)} 70% 50%)`;
}
function initWorld() {
Composite.add(engine.world, [particleBody, leftwall, rightwall, floor]);
}
function update() {
Engine.update(engine);
const pos = particleBody.position;
const radians = particleBody.angle;
const degrees = (radians * 180) / Math.PI;
particleGraphic.setAttribute(
"transform",
`translate(${pos.x} ${pos.y}) rotate(${degrees})`
);
window.requestAnimationFrame(update);
}
initSVG();
initRenderer();
initParticle();
initWallAndFloor();
initWorld();
initUI();
update();