feat: considerable progress
Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
parent
3a9b5a38af
commit
57f3540834
10 changed files with 204 additions and 9 deletions
7
frontend/package-lock.json
generated
7
frontend/package-lock.json
generated
|
|
@ -13,6 +13,7 @@
|
|||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.511.0",
|
||||
"matter-js": "^0.20.0",
|
||||
"next": "15.3.3",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^18.3.1",
|
||||
|
|
@ -2025,6 +2026,12 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/matter-js": {
|
||||
"version": "0.20.0",
|
||||
"resolved": "https://registry.npmjs.org/matter-js/-/matter-js-0.20.0.tgz",
|
||||
"integrity": "sha512-iC9fYR7zVT3HppNnsFsp9XOoQdQN2tUyfaKg4CHLH8bN+j6GT4Gw7IH2rP0tflAebrHFw730RR3DkVSZRX8hwA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.511.0",
|
||||
"matter-js": "^0.20.0",
|
||||
"next": "15.3.3",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^18.3.1",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export default function Home() {
|
||||
export default function Blog() {
|
||||
return (
|
||||
<main className="flex items-center justify-center h-screen">
|
||||
This is blog list page
|
||||
|
|
|
|||
|
|
@ -127,4 +127,15 @@
|
|||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.text-pill {
|
||||
background: #e53e3e;
|
||||
border-radius: 9999px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,12 +42,11 @@ export default function RootLayout({
|
|||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<div className="min-h-screen">
|
||||
<NavigationMenu />
|
||||
{children}
|
||||
<footer className=""></footer>
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen">
|
||||
<NavigationMenu />
|
||||
{children}
|
||||
<footer className="flex"></footer>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import { NameComponent } from "@/components/NameComponent";
|
||||
import { World } from "@/components/PhysicsSimulation";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className="flex items-center justify-center h-screen">
|
||||
<main className="flex flex-col items-center justify-start pt-15 h-screen">
|
||||
<World />
|
||||
|
||||
<NameComponent />
|
||||
</main>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export default function Home() {
|
||||
export default function Portfolio() {
|
||||
return (
|
||||
<main className="flex items-center justify-center h-screen">
|
||||
This is portfolio
|
||||
|
|
|
|||
7
frontend/src/app/talk/page.tsx
Normal file
7
frontend/src/app/talk/page.tsx
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export default function Talk() {
|
||||
return (
|
||||
<main className="flex items-center justify-center h-screen">
|
||||
This is talk
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
@ -14,6 +14,9 @@ export function NavigationMenu() {
|
|||
<Button variant="ghost">
|
||||
<Link href="/portfolio">Portfolio</Link>
|
||||
</Button>
|
||||
<Button variant="ghost">
|
||||
<Link href="/talk">Talk</Link>
|
||||
</Button>
|
||||
<ModeToggle />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
164
frontend/src/components/PhysicsSimulation.tsx
Normal file
164
frontend/src/components/PhysicsSimulation.tsx
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useTheme } from "next-themes";
|
||||
import Matter from "matter-js";
|
||||
|
||||
export function World() {
|
||||
const containerRef = useRef(null);
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
const getRandomXY = (width: number, height: number, radius: number) => {
|
||||
const randomX = Math.floor(Math.random() * (width - 2 * radius)) + radius;
|
||||
const randomY = Math.floor(Math.random() * (height - 2 * radius)) + radius;
|
||||
return [randomX, randomY];
|
||||
};
|
||||
const getBgColor = () => {
|
||||
if (typeof window !== "undefined") {
|
||||
return (
|
||||
getComputedStyle(document.documentElement)
|
||||
.getPropertyValue("--color-background")
|
||||
.trim() || "#f0f0f0"
|
||||
);
|
||||
}
|
||||
return "#f0f0f0";
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
const width = container.offsetWidth;
|
||||
const height = container.offsetHeight;
|
||||
const bgColor = getBgColor();
|
||||
|
||||
const {
|
||||
Engine,
|
||||
Render,
|
||||
Bodies,
|
||||
Composite,
|
||||
Runner,
|
||||
Mouse,
|
||||
MouseConstraint,
|
||||
} = Matter;
|
||||
const engine = Engine.create();
|
||||
engine.gravity.y = 0.3;
|
||||
engine.enableSleeping = false;
|
||||
|
||||
const render = Render.create({
|
||||
element: container,
|
||||
engine,
|
||||
options: {
|
||||
width,
|
||||
height,
|
||||
wireframes: false,
|
||||
background: bgColor,
|
||||
},
|
||||
});
|
||||
|
||||
// Bottom wall (ground)
|
||||
const ground = Bodies.rectangle(width / 2, height - 10, width, 20, {
|
||||
isStatic: true,
|
||||
render: { fillStyle: bgColor },
|
||||
});
|
||||
|
||||
// Left wall
|
||||
const leftWall = Bodies.rectangle(-10, height / 2, 20, height + 40, {
|
||||
isStatic: true,
|
||||
render: { fillStyle: bgColor },
|
||||
});
|
||||
|
||||
// Right wall
|
||||
const rightWall = Bodies.rectangle(
|
||||
width + 10,
|
||||
height / 2,
|
||||
20,
|
||||
height + 40,
|
||||
{
|
||||
isStatic: true,
|
||||
render: { fillStyle: bgColor },
|
||||
},
|
||||
);
|
||||
|
||||
// Top wall
|
||||
const topWall = Bodies.rectangle(width / 2, -10, width, 20, {
|
||||
isStatic: true,
|
||||
render: { fillStyle: bgColor },
|
||||
});
|
||||
|
||||
// Random ball position
|
||||
const radius = 15;
|
||||
|
||||
let [randomX, randomY] = getRandomXY(width, height, radius);
|
||||
const ballRed = Bodies.circle(randomX, randomY, radius, {
|
||||
restitution: 0.8,
|
||||
render: { fillStyle: "red" },
|
||||
});
|
||||
[randomX, randomY] = getRandomXY(width, height, radius);
|
||||
const ballBlue = Bodies.circle(randomX, randomY, radius, {
|
||||
restitution: 0.8,
|
||||
render: { fillStyle: "blue" },
|
||||
});
|
||||
[randomX, randomY] = getRandomXY(width, height, radius);
|
||||
const ballGreen = Bodies.circle(randomX, randomY, radius, {
|
||||
restitution: 0.8,
|
||||
render: { fillStyle: "green" },
|
||||
});
|
||||
|
||||
const pillHeight = 50;
|
||||
const pill = Matter.Bodies.rectangle(randomX, randomY, 200, pillHeight, {
|
||||
chamfer: { radius: pillHeight / 2 },
|
||||
isStatic: false,
|
||||
density: 0.001,
|
||||
friction: 0.05,
|
||||
frictionAir: 0.01,
|
||||
render: {
|
||||
fillStyle: "rgba(255, 255, 255, 0)", // transparent fill
|
||||
strokeStyle: "#000000", // black border
|
||||
lineWidth: 2,
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
// Mouse interaction
|
||||
const mouse = Mouse.create(render.canvas);
|
||||
const mouseConstraint = MouseConstraint.create(engine, {
|
||||
mouse,
|
||||
constraint: {
|
||||
stiffness: 1,
|
||||
angularStiffness: 0,
|
||||
render: { visible: false },
|
||||
},
|
||||
});
|
||||
|
||||
// Add all elements to the world
|
||||
Composite.add(engine.world, [
|
||||
ground,
|
||||
leftWall,
|
||||
rightWall,
|
||||
topWall,
|
||||
ballGreen,
|
||||
ballBlue,
|
||||
ballRed,
|
||||
pill,
|
||||
mouseConstraint,
|
||||
]);
|
||||
|
||||
Render.run(render);
|
||||
const runner = Runner.create();
|
||||
Runner.run(runner, engine);
|
||||
|
||||
return () => {
|
||||
Render.stop(render);
|
||||
Runner.stop(runner);
|
||||
Composite.clear(engine.world);
|
||||
Engine.clear(engine);
|
||||
render.canvas.remove();
|
||||
};
|
||||
}, [resolvedTheme]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="w-[95vw] h-[40vh] mx-auto relative overflow-hidden"
|
||||
/>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue