- During my dev journey, I had the opportunity to create some cool projects.
+ During my dev journey, I have the opportunity to create some cool projects.
I've collected here those that might pick your interest.
-
+
@@ -37,7 +36,7 @@
I develloped it with Golang for the backend and svelte for the frontend, and it has worked pretty well for me :D
-
+
@@ -71,15 +70,15 @@
-
+
loc_a_la_carte:
- During my dev journey, I had the opportunity to create some cool projects.
- I've collected here those that might pick your interest.
+ À la carte is a game I built for the Numworks, in the context of a TI Planet contest.
+ It's built in python and optimized for it to run smoothly on the target calculator.
@@ -91,10 +90,31 @@
loc_minecraft_mods:
- During my dev journey, I had the opportunity to create some cool projects.
- I've collected here those that might pick your interest.
+ During some of my (too) many Minecraft two weeks phases, I develloped some minecraft mods. Mainly in Fabric,
+ I even did a tutorial to get
+ started and be introduced to the wonderfull world of Mixins xD.
+ No more spire: I did this mod for the server that I was playing back then OriginRealms.
+ Everyone was spamming about the spire update in chat, so I decided to do some cleanup and free the chat from this pollution.
+ Modern chunk detector: This mod was made for the server 9b9t that my friend and I were playing. It highlights the chunk that were
+ generated in modern version of MC. Great to track bases trails ;)
+
+
+
diff --git a/projects/script.js b/projects/script.js
new file mode 100644
index 0000000..3f961f4
--- /dev/null
+++ b/projects/script.js
@@ -0,0 +1,97 @@
+// ─── Configuration ────────────────────────────────────────────
+// Each pair is [sourceId, targetId].
+// Arrows go from the bottom-center of the source
+// to the top-center of the target.
+const CONNECTIONS = [
+ ['n0', 'n1'],
+ ['n1', 'n2'],
+ ['n2', 'n3'],
+];
+
+// ─── Setup ────────────────────────────────────────────────────
+const scene = document.getElementById('body');
+const svg = document.getElementById('arrows');
+
+// Create one SVG per connection
+const pathEls = CONNECTIONS.map(() => {
+ const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
+ p.setAttribute('class', 'arrow-path');
+ p.setAttribute('marker-end', 'url(#head)');
+ svg.appendChild(p);
+ return p;
+});
+
+// ─── Core: Manhattan path between two elements ────────────────
+// r1 = bounding rect of source, r2 = bounding rect of target
+// Both rects are relative to the scene container.
+function manhattanPath(r1, r2) {
+ const x1 = r1.left + r1.width / 2; // bottom-center of source
+ const y1 = r1.top + r1.height + 10;
+ const x2 = r2.left + r2.width / 2; // top-center of target
+ const y2 = r2.top + 5; // stop 8px above target (arrowhead gap)
+
+ const ymid = y1 + (y2 - y1) / 2; // elbow halfway between the two
+
+ // M: move to source bottom
+ // L: go straight down to mid-y
+ // L: go horizontally to target x
+ // L: go straight down to target top
+ return `M ${x1} ${y1}
+ L ${x1} ${ymid}
+ L ${x2} ${ymid}
+ L ${x2} ${y2}`;
+}
+
+// ─── Redraw all arrows ────────────────────────────────────────
+function redraw() {
+ const sceneRect = scene.getBoundingClientRect();
+
+ CONNECTIONS.forEach(([srcId, tgtId], i) => {
+ const src = document.getElementById(srcId).getBoundingClientRect();
+ const tgt = document.getElementById(tgtId).getBoundingClientRect();
+
+ // Convert from viewport coords → scene-local coords
+ const r1 = {
+ left: src.left - sceneRect.left,
+ top: src.top - sceneRect.top,
+ width: src.width,
+ height: src.height,
+ };
+ const r2 = {
+ left: tgt.left - sceneRect.left,
+ top: tgt.top - sceneRect.top,
+ width: tgt.width,
+ height: tgt.height,
+ };
+
+ pathEls[i].setAttribute('d', manhattanPath(r1, r2));
+ });
+}
+
+// ─── Drag logic ───────────────────────────────────────────────
+document.querySelectorAll('.node').forEach(node => {
+ node.addEventListener('mousedown', e => {
+ e.preventDefault();
+ const startX = e.clientX;
+ const startY = e.clientY;
+ const originL = parseInt(node.style.left);
+ const originT = parseInt(node.style.top);
+
+ const onMove = e => {
+ node.style.left = Math.max(0, originL + e.clientX - startX) + 'px';
+ node.style.top = Math.max(0, originT + e.clientY - startY) + 'px';
+ redraw();
+ };
+ const onUp = () => {
+ window.removeEventListener('mousemove', onMove);
+ window.removeEventListener('mouseup', onUp);
+ };
+
+ window.addEventListener('mousemove', onMove);
+ window.addEventListener('mouseup', onUp);
+ });
+});
+
+// ─── Initial draw ─────────────────────────────────────────────
+// Wait two frames so the browser has laid out the divs
+requestAnimationFrame(() => requestAnimationFrame(redraw));
diff --git a/projects/style.css b/projects/style.css
index eb704b3..5e7cba8 100644
--- a/projects/style.css
+++ b/projects/style.css
@@ -51,6 +51,26 @@ a {
margin-bottom: -3px;
}
+/* ─── SVG overlay ────────────────────────────────────────── */
+#arrows {
+ position: absolute;
+ inset: 0; /* fill the scene */
+ width: 100%;
+ height: 100%;
+ pointer-events: none; /* clicks pass through to divs */
+ overflow: visible; /* arrows can leave the box if needed */
+}
+
+
+/* Arrow path style */
+.arrow-path {
+ fill: none;
+ stroke: #aaa9a2;
+ stroke-width: 1.5;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+}
+
/* Win32 classic scrollbar */
::-webkit-scrollbar {
width: 17px;