Split overworldscene.js's player/plane/camera into their own classes
Extracts Player (extends Entity), TestPlane, and PlayerCamera into their own files; the camera now tracks the player's live position at a fixed offset instead of orbiting the world origin over time. Updates test_overworldscene.c to match the new entity order and to build an in-memory zip fixture, since overworldscene.js now require()s these sibling files and require() always resolves through ASSET.zip.
This commit is contained in:
@@ -3,23 +3,21 @@
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
// Player: dynamic capsule body, moved relative to the camera by PLAYER's
|
||||
// own update callback (see entityplayer.c).
|
||||
class Player {
|
||||
class Player extends Entity {
|
||||
constructor() {
|
||||
this.entity = new Entity();
|
||||
super();
|
||||
|
||||
this.position = this.entity.add(POSITION);
|
||||
this.position = this.add(POSITION);
|
||||
this.position.setLocalPosition(0.0, 2.0, 0.0);
|
||||
|
||||
this.physics = this.entity.add(PHYSICS);
|
||||
this.physics = this.add(PHYSICS);
|
||||
this.physics.setShape(PHYSICS_SHAPE_CAPSULE, 0.5, 0.5);
|
||||
|
||||
this.renderable = this.entity.add(RENDERABLE);
|
||||
this.renderable = this.add(RENDERABLE);
|
||||
this.renderable.setMesh(0, MESH_CAPSULE);
|
||||
this.renderable.setColor(0, 0, 255, 255);
|
||||
|
||||
this.entity.add(PLAYER);
|
||||
this.add(PLAYER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2026 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
var CAMERA_OFFSET_ANGLE = 0.0;
|
||||
var CAMERA_OFFSET_RADIUS = 18.0;
|
||||
var CAMERA_OFFSET_HEIGHT = 10.0;
|
||||
|
||||
class PlayerCamera {
|
||||
constructor(target) {
|
||||
this.target = target;
|
||||
|
||||
this.entity = new Entity();
|
||||
this.position = this.entity.add(POSITION);
|
||||
this.entity.add(CAMERA);
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
update() {
|
||||
var targetPosition = this.target.position.getLocalPosition();
|
||||
|
||||
var eyeX = targetPosition.x + Math.cos(CAMERA_OFFSET_ANGLE) *
|
||||
CAMERA_OFFSET_RADIUS;
|
||||
var eyeY = targetPosition.y + CAMERA_OFFSET_HEIGHT;
|
||||
var eyeZ = targetPosition.z + Math.sin(CAMERA_OFFSET_ANGLE) *
|
||||
CAMERA_OFFSET_RADIUS;
|
||||
|
||||
this.position.lookAt(
|
||||
eyeX, eyeY, eyeZ,
|
||||
targetPosition.x, targetPosition.y, targetPosition.z,
|
||||
0.0, 1.0, 0.0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PlayerCamera;
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2026 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
class TestPlane {
|
||||
constructor() {
|
||||
this.entity = new Entity();
|
||||
|
||||
this.position = this.entity.add(POSITION);
|
||||
this.position.setLocalPosition(-10.0, 0.0, -10.0);
|
||||
this.position.setLocalScale(20.0, 1.0, 20.0);
|
||||
|
||||
this.physics = this.entity.add(PHYSICS);
|
||||
this.physics.setBodyType(PHYSICS_BODY_STATIC);
|
||||
this.physics.setShape(PHYSICS_SHAPE_PLANE, 0.0, 1.0, 0.0, 0.0);
|
||||
|
||||
this.renderable = this.entity.add(RENDERABLE);
|
||||
this.renderable.setMesh(0, MESH_PLANE);
|
||||
this.renderable.setColor(128, 128, 128, 255);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TestPlane;
|
||||
@@ -3,72 +3,24 @@
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
// Radius must stay well outside the floor's footprint (a 20x20 plane has a
|
||||
// corner-to-center distance of 10*sqrt(2) =~ 14.1) -- orbiting inside that
|
||||
// puts parts of the floor's own geometry near/behind the camera's view
|
||||
// direction, which the PSP's legacy GU pipeline can't clip properly and
|
||||
// drops the whole triangle instead of clipping it.
|
||||
var CAMERA_ORBIT_RADIUS = 18.0;
|
||||
var CAMERA_ORBIT_HEIGHT = 10.0;
|
||||
var CAMERA_ORBIT_SPEED = 0.5;
|
||||
|
||||
var Player = require('./Player.js');
|
||||
var PlayerCamera = require('./PlayerCamera.js');
|
||||
var TestPlane = require('./TestPlane.js');
|
||||
|
||||
var cameraOrbitAngle = 0.0;
|
||||
var cameraPosition = null;
|
||||
|
||||
// Orbits the camera around the world origin at a fixed radius/height/
|
||||
// speed, always looking back at the origin. Called once up front (so the
|
||||
// very first rendered frame is already positioned correctly) and then
|
||||
// once per frame via update() below.
|
||||
function updateCameraOrbit() {
|
||||
cameraOrbitAngle += Time.delta * CAMERA_ORBIT_SPEED;
|
||||
|
||||
var eyeX = Math.cos(cameraOrbitAngle) * CAMERA_ORBIT_RADIUS;
|
||||
var eyeY = CAMERA_ORBIT_HEIGHT;
|
||||
var eyeZ = Math.sin(cameraOrbitAngle) * CAMERA_ORBIT_RADIUS;
|
||||
|
||||
cameraPosition.lookAt(eyeX, eyeY, eyeZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
|
||||
}
|
||||
var camera = null;
|
||||
|
||||
module.exports = {
|
||||
// Called once by Scene.set(), right after it creates and activates the
|
||||
// scene this module owns.
|
||||
init: function() {
|
||||
// Camera, orbiting the origin (see updateCameraOrbit above).
|
||||
var camera = new Entity();
|
||||
cameraPosition = camera.add(POSITION);
|
||||
camera.add(CAMERA);
|
||||
updateCameraOrbit();
|
||||
|
||||
// Static ground plane. Physics ignores the entity's position
|
||||
// component -- the shape's own normal/distance fully define the
|
||||
// plane in world space.
|
||||
var plane = new Entity();
|
||||
var planePosition = plane.add(POSITION);
|
||||
planePosition.setLocalPosition(-10.0, 0.0, -10.0);
|
||||
planePosition.setLocalScale(20.0, 1.0, 20.0);
|
||||
|
||||
var planePhysics = plane.add(PHYSICS);
|
||||
planePhysics.setBodyType(PHYSICS_BODY_STATIC);
|
||||
planePhysics.setShape(PHYSICS_SHAPE_PLANE, 0.0, 1.0, 0.0, 0.0);
|
||||
|
||||
var planeRenderable = plane.add(RENDERABLE);
|
||||
planeRenderable.setMesh(0, MESH_PLANE);
|
||||
planeRenderable.setColor(128, 128, 128, 255);
|
||||
|
||||
new Player();
|
||||
var player = new Player();
|
||||
new TestPlane();
|
||||
camera = new PlayerCamera(player);
|
||||
},
|
||||
|
||||
// Called once per engine frame while this module is the active scene
|
||||
// (see Scene.set(), engineUpdate() -> moduleSceneUpdateCurrent()).
|
||||
update: function() {
|
||||
if(cameraPosition) updateCameraOrbit();
|
||||
if(camera) camera.update();
|
||||
},
|
||||
|
||||
// Called once by Scene.set() when this module is replaced by another,
|
||||
// right before the scene it owns is destroyed.
|
||||
dispose: function() {
|
||||
cameraPosition = null;
|
||||
camera = null;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user