Some little squres to drag around.
Try this example in two browser windows at once!
This example has a write conflict bug in it which is fixed in different ways in the drag_fix_1, drag_fix_2, drag_fix_3.
In this example all of the square data is stored in one shared object. Moving two squares at the same time will cause a write conflict.
As described in Avoiding Write Conflicts, conflict happens when multiple clients write to the same shared object at nearly the same time.
Since dragging involves very frequent writes, when two people drag at the same time, it is inevitable that those writes will happen at nearly the same time.
One way to avoid the write conflict is to allow only one square to be dragged at time. drag_fix_1 takes this approach
A second way to avoid the write conflict is store each square's data in a separate shared object. drag_fix_2 takes this approach.
A third to avoid the write conflict is to make sure only one guest (the host) writes to the shared object. drag_fix_3 takes this approach.
import { Point, pointInRect, Rect } from "./shape.js";
const my_id = Math.random();
let shared;
window.preload = () => {
partyConnect("wss://demoserver.p5party.org", "drag_conflict");
shared = partyLoadShared("shared");
};
window.setup = () => {
createCanvas(400, 400);
noStroke();
if (partyIsHost()) {
shared.sprites = [];
shared.sprites.push(initSprite(new Rect(10, 10, 100, 100), "#ffff66"));
shared.sprites.push(initSprite(new Rect(30, 30, 100, 100), "#ff66ff"));
shared.sprites.push(initSprite(new Rect(50, 50, 100, 100), "#66ffff"));
}
};
window.draw = () => {
background("#cc6666");
shared.sprites.forEach(stepSprite);
shared.sprites.forEach(drawSprite);
};
window.mousePressed = () => {
for (const s of shared.sprites.slice().reverse()) {
if (mousePressedSprite(s)) break;
}
};
window.mouseReleased = () => {
for (const s of shared.sprites.slice().reverse()) {
if (mouseReleasedSprite(s)) break;
}
};
function initSprite(rect = new Rect(), color = "red") {
const s = {};
s.rect = rect;
s.color = color;
return s;
}
function stepSprite(s) {
if (s.inDrag && s.owner === my_id) {
s.rect.l = mouseX + s.dragOffset.x;
s.rect.t = mouseY + s.dragOffset.y;
}
}
function drawSprite(s) {
push();
fill(s.color);
noStroke();
if (s.inDrag) {
strokeWeight(3);
stroke("black");
}
rect(s.rect.l, s.rect.t, s.rect.w, s.rect.h);
pop();
}
function mousePressedSprite(s) {
if (!s.inDrag && pointInRect(new Point(mouseX, mouseY), s.rect)) {
// begin drag
s.inDrag = true;
s.owner = my_id;
s.dragOffset = new Point(s.rect.l - mouseX, s.rect.t - mouseY);
// move to top
const i = shared.sprites.indexOf(s);
shared.sprites.splice(i, 1);
shared.sprites.push(s);
return true;
}
return false;
}
function mouseReleasedSprite(s) {
if (s.owner === my_id) {
s.inDrag = false;
s.owner = null;
}
return false;
}
<!DOCTYPE html>
<html>
<head> </head>
<body>
<main></main>
<div id="readme"></div>
<h2>index.js</h2>
<div id="source-javascript"></div>
<h2>index.html</h2>
<div id="source-html"></div>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.js"></script>
<script src="/dist/p5.party.js"></script>
<script src="index.js" type="module"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.3/highlight.min.js"></script>
<link rel="stylesheet" href="/examples.css" />
<script src="/examples.js" type="module"></script>
</body>
</html>