summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2024-08-19 22:20:46 -0400
committerpommicket <pommicket@gmail.com>2024-08-19 22:20:46 -0400
commitb6743568630ed182a3791344b3c042c79cc3b559 (patch)
tree811b496f8036f8078a2a9fd93b3673e269b90c9b
parent2deeda6f7c219522218a722bee17b646bd2b7ba6 (diff)
piece position validation, only update on mouseup, etc.
-rw-r--r--TODO.txt2
-rw-r--r--game.html2
-rw-r--r--game.js12
-rw-r--r--index.html2
-rw-r--r--index.js8
-rw-r--r--server/src/main.rs22
6 files changed, 31 insertions, 17 deletions
diff --git a/TODO.txt b/TODO.txt
index 86d3972..9ef13bd 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -2,3 +2,5 @@
- congratualations
- handle server errors on the client side
- let user select piece size
+- change piece.x,y to relative (% of play-area)
+- webgl? maybe?
diff --git a/game.html b/game.html
index 08c0b23..2784661 100644
--- a/game.html
+++ b/game.html
@@ -7,7 +7,7 @@
<meta content="width=device-width,initial-scale=1" name="viewport">
<link rel="icon" href="favicon.png">
<link rel="stylesheet" href="style.css">
- <script src="game.js?v=3" async></script>
+ <script src="game.js?v=4" async></script>
</head>
<body>
<div id="header">
diff --git a/game.js b/game.js
index e558cd2..8cbcd5a 100644
--- a/game.js
+++ b/game.js
@@ -212,7 +212,7 @@ window.addEventListener('load', function () {
element;
nibTypes;
connectedComponent;
- upToDateWithServer;
+ needsServerUpdate;
getClipPath() {
const nibTypes = this.nibTypes;
let shoulderWidth = (pieceWidth - nibSize) / 2;
@@ -247,7 +247,7 @@ window.addEventListener('load', function () {
this.y = y;
this.u = u;
this.v = v;
- this.upToDateWithServer = true;
+ this.needsServerUpdate = false;
this.connectedComponent = [this];
const element = this.element = document.createElement('div');
element.classList.add('piece');
@@ -300,6 +300,7 @@ window.addEventListener('load', function () {
piece.element.classList.remove('no-animation');
piece.element.style.zIndex = pieceZIndexCounter;
if (solved) break;
+ piece.needsServerUpdate = true;
const col = piece.col();
const row = piece.row();
const bbox = piece.boundingBox();
@@ -341,7 +342,6 @@ window.addEventListener('load', function () {
piece.x += dx;
piece.y += dy;
piece.updatePosition();
- piece.upToDateWithServer = false;
}
draggingPieceLastPos.x = e.clientX;
draggingPieceLastPos.y = e.clientY;
@@ -445,7 +445,7 @@ window.addEventListener('load', function () {
// only receive the position of one piece per equivalence class mod is-connected-to
if (connectivity[i] !== i) continue;
const piece = pieces[i];
- if (!piece.upToDateWithServer) continue;
+ if (piece.needsServerUpdate) continue;
if (draggingPiece && draggingPiece.connectedComponent === piece.connectedComponent) continue;
const newPos = canonicalToScreenPos({x: piecePositions[2*i], y: piecePositions[2*i+1]});
const diff = [newPos.x - piece.x, newPos.y - piece.y];
@@ -468,7 +468,7 @@ window.addEventListener('load', function () {
if (!receivedAck) return; // last update hasn't been acknowledged yet
const motions = [];
for (const piece of pieces) {
- if (piece.upToDateWithServer) continue;
+ if (!piece.needsServerUpdate) continue;
const canonicalPos = screenPosToCanonical({
x: piece.x,
y: piece.y,
@@ -530,7 +530,7 @@ window.addEventListener('load', function () {
setJoinLink(puzzleID);
} else if (e.data === 'ack') {
for (const piece of pieces) {
- piece.upToDateWithServer = true;
+ piece.needsServerUpdate = false;
}
receivedAck = true;
} else if (waitingForServerToGiveUsImageUrl && e.data.startsWith('useImage ')) {
diff --git a/index.html b/index.html
index 1a0af50..d34cdbc 100644
--- a/index.html
+++ b/index.html
@@ -19,7 +19,7 @@
<body class="margined">
<h3>jigsaw</h3>
<form id="host-form" method="dialog" action="#">
- <div class="form-line"><label><input type="number" min="10" max="1000" name="pieces" value="100"> 🧩 Number of pieces</label></div>
+ <div class="form-line"><label><input type="number" min="10" max="1000" name="pieces" value="100" id="piece-count"> 🧩 Number of pieces</label></div>
<div class="form-line">
<fieldset>
<legend>Choose your image…</legend>
diff --git a/index.js b/index.js
index 7ad57f0..f9a21dd 100644
--- a/index.js
+++ b/index.js
@@ -1,7 +1,12 @@
-window.addEventListener('load', function () {
+window.addEventListener('load', function () {
const getById = (id) => document.getElementById(id);
const customImageRadio = getById("custom-image");
const customImageURL = getById("image-url");
+ const pieceCountInput = getById("piece-count");
+ const lastPieceCount = parseInt(localStorage.getItem('jigsaw.index.pieceCount'));
+ if (isFinite(lastPieceCount) && lastPieceCount >= parseInt(pieceCountInput.min) && lastPieceCount <= parseInt(pieceCountInput.max)) {
+ getById("piece-count").value = lastPieceCount;
+ }
function onImageTypeChange() {
customImageURL.disabled = customImageRadio.checked ? '' : 'disabled';
}
@@ -13,6 +18,7 @@ window.addEventListener('load', function () {
hostForm.addEventListener("submit", function () {
const formData = new FormData(hostForm);
const pieceCount = formData.get('pieces');
+ localStorage.setItem('jigsaw.index.pieceCount', pieceCount);
const image = formData.get('image') === 'custom' ? formData.get('image-url') : formData.get('image');
const search = new URLSearchParams();
search.set('image', image);
diff --git a/server/src/main.rs b/server/src/main.rs
index afc87eb..d5c33be 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -1,4 +1,5 @@
#![allow(clippy::too_many_arguments)]
+#![allow(clippy::manual_range_contains)]
use futures_util::{SinkExt, StreamExt};
use rand::seq::SliceRandom;
@@ -318,8 +319,8 @@ async fn handle_websocket(
if usize::from(width) * usize::from(height) > MAX_PIECES {
return Err(Error::TooManyPieces);
}
- let nib_count =
- 2 * (width as usize) * (height as usize) - (width as usize) - (height as usize);
+ let nib_count = 2 * usize::from(width) * usize::from(height)
+ - usize::from(width) - usize::from(height);
let mut nib_types: Vec<u16> = Vec::with_capacity(nib_count);
let mut piece_positions: Vec<[f32; 2]> =
Vec::with_capacity((width as usize) * (height as usize));
@@ -330,21 +331,21 @@ async fn handle_websocket(
nib_types.push(rng.gen());
}
// pick piece positions
- for y in 0..(height as u16) {
- for x in 0..(width as u16) {
+ for y in 0..u16::from(height) {
+ for x in 0..u16::from(width) {
let dx: f32 = rng.gen_range(0.0..0.3);
let dy: f32 = rng.gen_range(0.0..0.3);
piece_positions.push([
- (x as f32 + dx) / ((width + 1) as f32),
- (y as f32 + dy) / ((height + 1) as f32),
+ (f32::from(x) + dx) / (f32::from(width) + 1.0),
+ (f32::from(y) + dy) / (f32::from(height) + 1.0),
]);
}
}
piece_positions.shuffle(&mut rng);
}
let mut connectivity_data: Vec<u16> =
- Vec::with_capacity((width as usize) * (height as usize));
- for i in 0..(width as u16) * (height as u16) {
+ Vec::with_capacity(usize::from(width) * usize::from(height));
+ for i in 0..u16::from(width) * u16::from(height) {
connectivity_data.push(i);
}
let mut id;
@@ -403,6 +404,11 @@ async fn handle_websocket(
.ok_or(Error::BadSyntax)?
.parse()
.map_err(|_| Error::BadSyntax)?;
+ for coord in [x, y] {
+ if !coord.is_finite() || coord < -1.0 || coord > 2.0 {
+ return Err(Error::BadSyntax);
+ }
+ }
server.move_piece(puzzle_id, piece, x, y).await?;
}
ws.send(Message::Text("ack".to_string())).await?;