mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-19 15:18:33 +02:00
feat(3d): real player-follow camera (not fit-to-view)
3D is a paid rung and should behave like the other modes. Rework the THREE camera to FOLLOW the player instead of framing the whole level: canvas now sizes to the host (setSize updateStyle), the ortho frustum is a fixed player-centered zoom (span 8) with host aspect, and _animate re-targets the camera to the player world position every frame (keeps the iso (8,9,8) offset; glides smoothly since the player mesh lerps). SP._applyCamera no longer CSS-transforms the 3D canvas (it fills the host and THREE owns the camera). Handles host resize via _fitToHost.
This commit is contained in:
@@ -102,15 +102,12 @@
|
||||
var r = SP._renderer;
|
||||
var host = doc() && doc().getElementById('rk-game-host');
|
||||
if (!r || !r.canvas || !host) return;
|
||||
// The 3D renderer drives its OWN THREE camera and sizes its canvas to the level, so a
|
||||
// player-follow CSS transform would zoom/crop it wrongly. Instead scale-to-FIT the whole
|
||||
// canvas into the host and centre it (no player follow) — a sane, non-broken view.
|
||||
// The 3D renderer fills the host itself (setSize) and its OWN THREE camera follows the
|
||||
// player — so DON'T apply a CSS transform (it would double-transform the WebGL view).
|
||||
if (r.name === '3d') {
|
||||
var cw = r.canvas.width || 1, ch = r.canvas.height || 1;
|
||||
var hw3 = host.clientWidth || host.offsetWidth || 640, hh3 = host.clientHeight || host.offsetHeight || 400;
|
||||
var fit = Math.min(hw3 / cw, hh3 / ch);
|
||||
r.canvas.style.transformOrigin = '0 0';
|
||||
r.canvas.style.transform = 'translate(' + ((hw3 - cw * fit) / 2) + 'px,' + ((hh3 - ch * fit) / 2) + 'px) scale(' + fit + ')';
|
||||
r.canvas.style.transform = 'none';
|
||||
r.canvas.style.left = '0';
|
||||
r.canvas.style.top = '0';
|
||||
return;
|
||||
}
|
||||
var scale = SP._zoom || 1.7;
|
||||
|
||||
@@ -50,11 +50,17 @@
|
||||
this._raf = requestAnimationFrame(function tick() { self._animate(); self._raf = requestAnimationFrame(tick); });
|
||||
};
|
||||
|
||||
ThreeRenderer.prototype._resize = function (scene) {
|
||||
var w = Math.max(420, scene.cols * 32);
|
||||
var h = Math.max(360, scene.rows * 28 + 120);
|
||||
this.renderer.setSize(w, h, false);
|
||||
var aspect = w / h, span = Math.max(scene.cols, scene.rows) * 0.78 + 2.5;
|
||||
// Fill the host and frame a fixed "screenful" around the player. The camera FOLLOWS the player
|
||||
// (see _animate) instead of framing the whole level, so 3D behaves like the other modes. Only
|
||||
// does work when the host size actually changed (cheap to call every frame).
|
||||
ThreeRenderer.prototype._fitToHost = function () {
|
||||
var host = this.host;
|
||||
var w = (host && (host.clientWidth || host.offsetWidth)) || 640;
|
||||
var h = (host && (host.clientHeight || host.offsetHeight)) || 400;
|
||||
if (w === this._cw && h === this._ch) return;
|
||||
this._cw = w; this._ch = h;
|
||||
this.renderer.setSize(w, h, true); // updateStyle:true → the canvas CSS-fills the host
|
||||
var aspect = w / h, span = 8; // fixed zoom = a screenful around the player
|
||||
this.camera.left = -span * aspect;
|
||||
this.camera.right = span * aspect;
|
||||
this.camera.top = span;
|
||||
@@ -219,7 +225,7 @@
|
||||
|
||||
ThreeRenderer.prototype.render = function (scene) {
|
||||
if (!scene || !this.renderer) return;
|
||||
this._resize(scene);
|
||||
this._fitToHost();
|
||||
var key = scene.cols + 'x' + scene.rows + ':' + scene.grid.map(function (r) { return r.join(''); }).join('/');
|
||||
if (key !== this._sizeKey) {
|
||||
this._buildTiles(scene);
|
||||
@@ -273,6 +279,19 @@
|
||||
o.rotation.y += (r - o.rotation.y) * 0.18;
|
||||
}
|
||||
}
|
||||
|
||||
// Player-follow camera: keep the fixed iso offset (8,9,8) but re-target the player's world
|
||||
// position each frame. The player mesh itself lerps, so the camera glides smoothly with it.
|
||||
this._fitToHost(); // pick up any host resize
|
||||
var pcam = null;
|
||||
for (var pid in this.entities) {
|
||||
var pen = this.entities[pid];
|
||||
if (pen.e && (pen.e.you || pen.e.kind === 'player')) { pcam = pen.obj; break; }
|
||||
}
|
||||
if (pcam) {
|
||||
this.camera.position.set(pcam.position.x + 8, 9, pcam.position.z + 8);
|
||||
this.camera.lookAt(pcam.position.x, 0, pcam.position.z);
|
||||
}
|
||||
this.renderer.render(this.scene, this.camera);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user