Skip to content

Commit f1cb1e2

Browse files
author
DavidQ
committed
Fix Sample 1610 mini map orientation and clarify hybrid 2D vs 3D visualization
1 parent 1de6bd3 commit f1cb1e2

7 files changed

Lines changed: 91 additions & 18 deletions

docs/dev/CODEX_COMMANDS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
MODEL: GPT-5.3-codex
22
REASONING: high
3-
COMMAND: Implement samples 1615-1617, integrate into index, package to <project folder>/tmp/BUILD_PR_LEVEL_17_27_ADVANCED_3D_SAMPLES_BATCH_3.zip
3+
COMMAND: Fix Sample 1610 hybrid demo by correcting mini map Y-axis inversion and adding clear visual distinction between 2D overlay and 3D world. Package results to <project folder>/tmp/BUILD_PR_LEVEL_17_29_SAMPLE_1610_HYBRID_FIX.zip

docs/dev/COMMIT_COMMENT.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Add Advanced 3D Samples batch 3 (1615-1617)
1+
Fix Sample 1610 mini map orientation and clarify hybrid 2D vs 3D visualization
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
- [ ] samples load
2-
- [ ] no errors
1+
2+
- [ ] mini map orientation correct (forward = up)
3+
- [ ] no inversion artifacts
4+
- [ ] 2D vs 3D clearly labeled or visually distinct
5+
- [ ] sample remains simple and functional
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# BUILD_PR_LEVEL_17_29_SAMPLE_1610_HYBRID_FIX
2+
3+
Implement:
4+
5+
1. Mini Map Fix
6+
- invert Y-axis mapping so world forward aligns with upward direction on mini map
7+
- ensure consistent coordinate transform between world and mini map
8+
9+
2. Hybrid Clarity
10+
Add explicit differentiation:
11+
- 2D layer:
12+
- top-down mini map or UI overlay
13+
- clearly labeled "2D Layer"
14+
- 3D layer:
15+
- main camera world
16+
- clearly labeled "3D World"
17+
18+
3. Visual Indicators
19+
- add label overlays or color coding
20+
- optional toggle to highlight layers
21+
22+
Constraints:
23+
- minimal changes
24+
- no engine refactor
25+
- sample must remain simple and educational
26+
27+
Validation:
28+
- moving forward = moves up on mini map
29+
- user can clearly identify what is 2D vs 3D
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# PLAN_PR_LEVEL_17_29_SAMPLE_1610_HYBRID_FIX
2+
3+
Purpose:
4+
Fix clarity and correctness issues in Sample 1610 (Hybrid 2D/3D World).
5+
6+
Problems Identified:
7+
- Mini map is vertically inverted (upside down)
8+
- Hybrid concept is not visually clear (2D vs 3D not distinguishable)
9+
10+
Scope:
11+
- correct mini map coordinate orientation
12+
- make 2D vs 3D distinction explicit and visible
13+
14+
Out of Scope:
15+
- engine changes
16+
- new features beyond clarity and correctness

samples/phase-16/1610/Hybrid2D3DWorldScene.js

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -101,37 +101,49 @@ export default class Hybrid2D3DWorldScene extends Scene {
101101
const zRatio = (point.z - this.worldBounds.minZ) / Math.max(0.0001, this.worldBounds.maxZ - this.worldBounds.minZ);
102102
return {
103103
x: viewport.x + xRatio * viewport.width,
104-
y: viewport.y + zRatio * viewport.height,
104+
y: viewport.y + (1 - zRatio) * viewport.height,
105105
};
106106
}
107107

108108
drawTopdown(renderer) {
109109
const map = this.topdownViewport;
110-
renderer.drawRect(map.x, map.y, map.width, map.height, 'rgba(15, 23, 42, 0.86)');
111-
renderer.strokeRect(map.x, map.y, map.width, map.height, '#60a5fa', 1.5);
110+
renderer.drawRect(map.x - 6, map.y - 28, map.width + 12, map.height + 34, 'rgba(8, 42, 64, 0.54)');
111+
renderer.drawRect(map.x, map.y, map.width, map.height, 'rgba(15, 23, 42, 0.92)');
112+
renderer.strokeRect(map.x, map.y, map.width, map.height, '#22d3ee', 2);
113+
renderer.drawRect(map.x + 8, map.y + 8, 94, 18, 'rgba(8, 145, 178, 0.35)');
114+
renderer.drawText('2D Layer', map.x + 15, map.y + 21, { color: '#67e8f9', font: '12px monospace' });
112115

113116
this.props.forEach((prop) => {
114117
const topLeft = this.worldToMap({ x: prop.transform3D.x, z: prop.transform3D.z }, map);
115118
const bottomRight = this.worldToMap({ x: prop.transform3D.x + prop.size3D.width, z: prop.transform3D.z + prop.size3D.depth }, map);
119+
const left = Math.min(topLeft.x, bottomRight.x);
120+
const top = Math.min(topLeft.y, bottomRight.y);
121+
const width = Math.max(2, Math.abs(bottomRight.x - topLeft.x));
122+
const height = Math.max(2, Math.abs(bottomRight.y - topLeft.y));
116123
renderer.drawRect(
117-
topLeft.x,
118-
topLeft.y,
119-
Math.max(2, bottomRight.x - topLeft.x),
120-
Math.max(2, bottomRight.y - topLeft.y),
124+
left,
125+
top,
126+
width,
127+
height,
121128
prop.color
122129
);
123130
});
124131

125132
const playerTopLeft = this.worldToMap({ x: this.player.x, z: this.player.z }, map);
126133
const playerBottomRight = this.worldToMap({ x: this.player.x + this.player.width, z: this.player.z + this.player.depth }, map);
134+
const playerLeft = Math.min(playerTopLeft.x, playerBottomRight.x);
135+
const playerTop = Math.min(playerTopLeft.y, playerBottomRight.y);
136+
const playerWidth = Math.max(3, Math.abs(playerBottomRight.x - playerTopLeft.x));
137+
const playerHeight = Math.max(3, Math.abs(playerBottomRight.y - playerTopLeft.y));
127138
renderer.drawRect(
128-
playerTopLeft.x,
129-
playerTopLeft.y,
130-
Math.max(3, playerBottomRight.x - playerTopLeft.x),
131-
Math.max(3, playerBottomRight.y - playerTopLeft.y),
132-
'#f8fafc'
139+
playerLeft,
140+
playerTop,
141+
playerWidth,
142+
playerHeight,
143+
'#22d3ee'
133144
);
134-
renderer.drawText('2D Tactical View', map.x + 10, map.y + 18, { color: '#cbd5e1', font: '12px monospace' });
145+
renderer.strokeRect(playerLeft - 1, playerTop - 1, playerWidth + 2, playerHeight + 2, '#ecfeff', 1);
146+
renderer.drawText('Forward ^', map.x + map.width - 74, map.y + 18, { color: '#a5f3fc', font: '12px monospace' });
135147
}
136148

137149
render(renderer) {
@@ -144,7 +156,10 @@ export default class Hybrid2D3DWorldScene extends Scene {
144156
this.drawTopdown(renderer);
145157

146158
const viewport = this.viewport3d;
159+
renderer.drawRect(viewport.x - 6, viewport.y - 28, viewport.width + 12, viewport.height + 34, 'rgba(56, 29, 92, 0.34)');
147160
renderer.strokeRect(viewport.x, viewport.y, viewport.width, viewport.height, '#d8d5ff', 2);
161+
renderer.drawRect(viewport.x + 10, viewport.y + 8, 94, 18, 'rgba(109, 40, 217, 0.35)');
162+
renderer.drawText('3D World', viewport.x + 17, viewport.y + 21, { color: '#ddd6fe', font: '12px monospace' });
148163
drawDepthBackdrop(renderer, viewport);
149164

150165
const cameraState = this.camera3D?.getState?.() ?? {

tests/runtime/Phase16AdvancedBatch1Sanity.test.mjs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,18 @@ function makeInput(keys = []) {
4242

4343
function createRendererProbe(width = 960, height = 540) {
4444
const lines = [];
45+
const texts = [];
4546
return {
4647
lines,
48+
texts,
4749
getCanvasSize() {
4850
return { width, height };
4951
},
5052
clear() {},
5153
strokeRect() {},
52-
drawText() {},
54+
drawText(text) {
55+
texts.push(String(text));
56+
},
5357
drawRect() {},
5458
drawLine(x1, y1, x2, y2, color) {
5559
lines.push({ x1, y1, x2, y2, color });
@@ -104,10 +108,16 @@ function assertHybridDemo() {
104108
scene.step3DPhysics(1 / 60, { input: makeInput(['KeyD']) });
105109
assert.equal(scene.player.x > startX, true, 'Hybrid demo should move player in shared world state.');
106110

111+
const mapNear = scene.worldToMap({ x: scene.player.x, z: scene.worldBounds.minZ + 1 }, scene.topdownViewport);
112+
const mapFar = scene.worldToMap({ x: scene.player.x, z: scene.worldBounds.maxZ - 1 }, scene.topdownViewport);
113+
assert.equal(mapFar.y < mapNear.y, true, 'Hybrid mini map should map forward world depth toward upward screen direction.');
114+
107115
const renderer = createRendererProbe();
108116
scene.render(renderer);
109117
const visibleLines = countVisibleLinesInViewport(renderer.lines, scene.viewport3d);
110118
assert.equal(visibleLines > 0, true, 'Hybrid demo should render visible 3D wireframe output.');
119+
assert.equal(renderer.texts.includes('2D Layer'), true, 'Hybrid demo should clearly label the 2D layer.');
120+
assert.equal(renderer.texts.includes('3D World'), true, 'Hybrid demo should clearly label the 3D world layer.');
111121
}
112122

113123
function assertMultiplayerDemo() {

0 commit comments

Comments
 (0)