feedback7: merge fb7-dragsnap — a dragged operator stands on the tile under the pointer while that is a legal target, as in the owner's recording of the official deployment (the report in PR #403 by @bubububaoshe; the pick, highlight, wheel and drop stay the pointer's tile); §27.62; golden: unchanged
This commit is contained in:
commit
775d4f8515
11 files changed
+228
-53
No files matched your search
+30
-19
@@ -44,9 +44,10 @@
|
||||
// clicks and hover (battleUnitAt), the pen (penUnitAt) — is render/pick.js over the tile under the pointer (groundTile:
|
||||
// raised tops first); battle enemies, which walk between tiles, by their ground position (flying ones by their drawn
|
||||
// body; a huge boss also anywhere on its hit area — data/enemies.json `hitArea`, user playtest #5). A dragged piece
|
||||
// is held under the pointer — a unit with its drawn feet DRAG_HOLD_TILES below it (the pointer on its body), an item
|
||||
// plate centred on it — and drops on the tile under the pointer (render/drag.js); an item dropped on a unit's tile
|
||||
// equips that unit.
|
||||
// drops on the tile under the pointer (render/drag.js). A dragged unit stands on that tile while it is a legal target
|
||||
// (a board tile or a bench slot: drag.js dragStandTile; the official deploy drag, the owner's recording of 2026-10-09,
|
||||
// PR #403's report) and is held under the pointer elsewhere — its drawn feet DRAG_HOLD_TILES below it, the pointer on
|
||||
// its body; an item plate stays centred on the pointer. An item dropped on a unit's tile equips that unit.
|
||||
// Direction step (ui/facingWheel.js, research 09 §1.2):
|
||||
// view.tileScreen(row, col) → { x, y, s, poly: [[x,y]×4] } (client px: tile-top centre, px per tile, corners) | null
|
||||
// view.holdPiece(uid, {row,col} | null) keep a dropped prep piece standing on a tile while its direction is
|
||||
@@ -119,7 +120,7 @@ import { SnapshotBuffer, frameTime } from './interp.js';
|
||||
import { TileField } from './tiles.js';
|
||||
import { UnitView, ItemView, DeviceView, FORMS, syncView } from './units.js';
|
||||
import { FxSystem, ensureDamageFonts } from './fx.js';
|
||||
import { createDragController, pieceTile } from './drag.js';
|
||||
import { createDragController, pieceTile, dragStandTile } from './drag.js';
|
||||
import { backdropTextures, shadowTexture, refreshTierChips, silhouetteTexture } from './textures.js';
|
||||
import { TILE_H, TIER_COLORS, COLORS } from './style.js';
|
||||
import { loadBoardArt } from './boardArt.js';
|
||||
@@ -1083,23 +1084,33 @@ export async function createFieldView(host, options = {}) {
|
||||
function moveDragVisual(p) {
|
||||
if (!dragState) return;
|
||||
const v = dragState.view;
|
||||
// held under the pointer: a unit with its drawn (lifted) feet DRAG_HOLD_TILES of its own px per tile below it (the
|
||||
// scale at the pointer's ground, refined once at the feet), an item plate centred on it; the drop target
|
||||
// (p.target, highlighted below) is the tile under the pointer
|
||||
const item = v instanceof ItemView;
|
||||
const g = cam.unproject(p.x, p.y, 0);
|
||||
const hold = item ? 0 : DRAG_HOLD_TILES;
|
||||
const s0 = g ? cam.scaleAt(g.x, g.y, 0) : cam.scale;
|
||||
const t = pickTile(cam, p.x, p.y + hold * s0, heightAt, tiles.levels);
|
||||
const z = t ? heightAt(t.row, t.col) : 0;
|
||||
const up = item ? z : z + (v.lift || 0) + (v.hover || 0);
|
||||
let w = cam.unproject(p.x, p.y + hold * s0, up);
|
||||
if (w && hold) w = cam.unproject(p.x, p.y + hold * cam.scaleAt(w.x, w.y, up), up) || w;
|
||||
if (w) {
|
||||
v.x = Math.max(-1, Math.min(21, w.x));
|
||||
v.y = Math.max(-1, Math.min(19, w.y));
|
||||
v.z = z;
|
||||
// a unit over a legal drop target — the tile under the pointer, on the board or the bench (render/drag.js
|
||||
// dragStandTile) — stands on it, lifted, as in the official deploy drag (the owner's recording of 2026-10-09): the
|
||||
// world point the drop tween goes to (boardWorld, the prep field transform applied), set at once, no tween
|
||||
const stand = item ? null : dragStandTile(p);
|
||||
if (stand) {
|
||||
const w = boardWorld(stand.row, stand.col, stand.bench);
|
||||
v.x = w.x; v.y = w.y; v.z = w.z;
|
||||
} else {
|
||||
// otherwise held under the pointer (the player still sees what they carry): a unit with its drawn (lifted) feet
|
||||
// DRAG_HOLD_TILES of its own px per tile below it (the scale at the pointer's ground, refined once at the feet), an
|
||||
// item plate centred on it
|
||||
const g = cam.unproject(p.x, p.y, 0);
|
||||
const hold = item ? 0 : DRAG_HOLD_TILES;
|
||||
const s0 = g ? cam.scaleAt(g.x, g.y, 0) : cam.scale;
|
||||
const t = pickTile(cam, p.x, p.y + hold * s0, heightAt, tiles.levels);
|
||||
const z = t ? heightAt(t.row, t.col) : 0;
|
||||
const up = item ? z : z + (v.lift || 0) + (v.hover || 0);
|
||||
let w = cam.unproject(p.x, p.y + hold * s0, up);
|
||||
if (w && hold) w = cam.unproject(p.x, p.y + hold * cam.scaleAt(w.x, w.y, up), up) || w;
|
||||
if (w) {
|
||||
v.x = Math.max(-1, Math.min(21, w.x));
|
||||
v.y = Math.max(-1, Math.min(19, w.y));
|
||||
v.z = z;
|
||||
}
|
||||
}
|
||||
// the drop target (p.target, highlighted) is the tile under the pointer
|
||||
if (p.target && p.target.area !== 'temp') {
|
||||
const r = p.target.area === 'board' ? p.target.row : GEO.HAND_ROW;
|
||||
const c = p.target.area === 'board' ? p.target.col : p.target.idx;
|
||||
|
||||
@@ -26,8 +26,9 @@ const CHAIN_KINDS = new Set(['chain', 'chainHeal']);
|
||||
const DROP_PENDING_MS = 1300;
|
||||
|
||||
/**
|
||||
* A dragged unit is held with its drawn feet this many tiles below the pointer — the pointer on its body, the model
|
||||
* under the finger / mouse (user playtest #4 item 1: as in v2.1; mouse and touch alike). An item plate is centred on it.
|
||||
* A dragged unit over no legal target is held with its drawn feet this many tiles below the pointer — the pointer on its
|
||||
* body, the model under the finger / mouse (user playtest #4 item 1: as in v2.1; mouse and touch alike); over a legal
|
||||
* target it stands on that tile (render/drag.js dragStandTile). An item plate is centred on the pointer.
|
||||
*/
|
||||
export const DRAG_HOLD_TILES = 0.45;
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@
|
||||
// direction wheel to re-orient it in place (research 09 §1.2 — "drag the unit onto its own tile and swipe").
|
||||
// Everything is judged at the pointer (user playtest #4 item 1: the ground is drawn as tiles): a press / hover is on the
|
||||
// piece standing on the tile under it (`hitPiece`, render/pick.js), and while dragging the target, `tileHover` and the
|
||||
// legality are that tile — an item dropped on a unit's tile goes to that unit; app.js holds the dragged ghost under
|
||||
// the pointer. A release over DOM UI covering the canvas (the shop bar) is 'outside' (mouse and touch alike).
|
||||
// legality are that tile — an item dropped on a unit's tile goes to that unit. app.js draws a dragged unit standing on
|
||||
// that tile while it is a legal target (`dragStandTile`, the official deploy drag) and held under the pointer
|
||||
// otherwise; an item plate stays on the pointer. A release over DOM UI covering the canvas (the shop bar) is 'outside'
|
||||
// (mouse and touch alike).
|
||||
//
|
||||
// Events emitted through `emit(name, payload)`:
|
||||
// pieceHover { uid, piece, clientX, clientY } | { uid: null } (mouse/pen hover changes)
|
||||
@@ -80,6 +82,21 @@ export function resolveDrop(p) {
|
||||
return { kind: 'drop', target: slot };
|
||||
}
|
||||
|
||||
/**
|
||||
* The tile a dragged UNIT is drawn standing on, from a `pieceDragMove` payload: the drop target under the pointer while
|
||||
* it is legal — a board tile, or a bench slot (row HAND_ROW) — as `{ row, col, bench }` in board space; null otherwise
|
||||
* (no target, an illegal tile, a temp slot, the pointer over DOM UI such as the shop bar): the unit is then held under
|
||||
* the pointer. As in the official deploy drag (the owner's recording of 2026-10-09) the model stands on the tile the
|
||||
* finger is on, and moving within that tile leaves it where it is. app.js never snaps an item plate.
|
||||
*/
|
||||
export function dragStandTile(move, geo = GEO) {
|
||||
const t = move && move.legal === true ? move.target : null;
|
||||
if (!t) return null;
|
||||
if (t.area === 'board' && Number.isInteger(t.row) && Number.isInteger(t.col)) return { row: t.row, col: t.col, bench: false };
|
||||
if (t.area === 'hand' && Number.isInteger(t.idx)) return { row: geo.HAND_ROW, col: t.idx, bench: true };
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Legality via the UI callback (board → (piece,row,col); hand → (piece, HAND_ROW, idx)). Throwing ⇒ illegal. */
|
||||
export function isLegal(canPlace, piece, slot) {
|
||||
if (!slot || slot.area === 'temp' || slot.area === 'outside') return false;
|
||||
|
||||
Reference in new issue
Block a user