maxm-multiplayercircles.web.val.run
Readme

Multiplayer Circles

Move circles around. State is synced with the server. Open a window in another tab and watch the circles update as you move them .

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { ResultSet, sqlite } from "https://esm.town/v/std/sqlite?v=6";
import { Hono } from "npm:hono@3";
await sqlite.batch([
// `DROP TABLE IF EXISTS draggable_circles`,
`CREATE TABLE IF NOT EXISTS draggable_circles (
idx INTEGER NOT NULL UNIQUE,
x REAL NOT NULL,
y REAL NOT NULL
)`,
]);
// const circles = [
// { "x": 372.1564948287251, "y": 467.31488912659233, "index": 0 },
// { "x": 383.03204910618865, "y": 409.3382384327329, "index": 1 },
// { "x": 276.12943550800577, "y": 206.43967315595253, "index": 2 },
// { "x": 332.11355889496815, "y": 99.81295018896702, "index": 3 },
// { "x": 281.6660037446992, "y": 268.44660700812955, "index": 4 },
// { "x": 478.1371051427014, "y": 155.1225458786182, "index": 5 },
// { "x": 562.1071796055135, "y": 249.0351695539056, "index": 6 },
// { "x": 361.2641058287132, "y": 256.52910153255004, "index": 7 },
// { "x": 421.6175146074128, "y": 424.18276199871326, "index": 8 },
// { "x": 321.24193621279403, "y": 407.59672549522344, "index": 9 },
// { "x": 191.660159711138, "y": 432.14191514382543, "index": 10 },
// { "x": 119.15993815756639, "y": 96.84634939589058, "index": 11 },
// { "x": 121.65490887696441, "y": 564.6775769550197, "index": 12 },
// { "x": 110.8157416379427, "y": 244.36858357746033, "index": 13 },
// { "x": 263.1779853877889, "y": 202.64154214241603, "index": 14 },
// { "x": 135.13227065644418, "y": 336.9982482747027, "index": 15 },
// { "x": 129.77166867674111, "y": 286.4481811355409, "index": 16 },
// { "x": 465.98646535831665, "y": 503.4452648259519, "index": 17 },
// { "x": 201.30560985313258, "y": 300.19885737204976, "index": 18 },
// { "x": 285.49861283238147, "y": 90.07963880167979, "index": 19 },
// ];
// circles.forEach(async (c) => {
// await sqlite.execute({ sql: `INSERT INTO draggable_circles VALUES (?, ?, ?)`, args: [c.index, c.x, c.y] });
// });
function parseResultSet<T>(row: ResultSet): T[] {
return row.rows.map((r) => Object.fromEntries(r.map((c, i) => [row.columns[i], c]))) as T[];
}
type Circle = {
x: number;
y: number;
idx: number;
};
const getCircles = async () => {
return parseResultSet<Circle>(await sqlite.execute("select * from draggable_circles"));
};
function diffCircles(array1: Circle[], array2: Circle[]): Circle[] {
const changes: Circle[] = [];
const map1 = new Map(array1.map(row => [row.idx, row]));
const map2 = new Map(array2.map(row => [row.idx, row]));
for (const [idx, row1] of map1) {
const row2 = map2.get(idx);
if (row2 && (row1.x !== row2.x || row1.y !== row2.y)) {
changes.push(row2);
}
}
return changes;
}
const clientCode = () => {
const height = 600;
const width = 600;
const radius = 32;
const svg = d3.select("svg");
const drag = (() => {
function dragstarted() {
d3.select(this).attr("stroke", "black");
}
function dragged(event, d) {
d3.select(this).raise().attr("cx", d.x = event.x).attr("cy", d.y = event.y);
}
function dragended() {
const x = d3.select(this).attr("cx");
const y = d3.select(this).attr("cy");
fetch(`/update?x=${x}&y=${y}&i=${d3.select(this).attr("idx")}`, { method: "post" });
d3.select(this).attr("stroke", null);
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
})();
window.circleObjects = svg.selectAll("circle")
.data(circles)
.join("circle")
.attr("cx", d => d.x)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
v104
June 12, 2024