improve mouse lock and split up screen rendering into two canvas elements

This commit is contained in:
LabyStudio
2022-02-04 14:28:05 +01:00
parent a6f365225c
commit 039d799bed
5 changed files with 60 additions and 52 deletions
+38 -26
View File
@@ -9,8 +9,17 @@ window.GameWindow = class {
this.mouseMotionY = 0; this.mouseMotionY = 0;
this.mouseLocked = false; this.mouseLocked = false;
// Get canvas wrapper
this.wrapper = document.getElementById(this.canvasWrapperId); this.wrapper = document.getElementById(this.canvasWrapperId);
// Create world renderer
this.canvas = document.createElement('canvas');
this.wrapper.appendChild(this.canvas);
// Create screen renderer
this.canvas2d = document.createElement('canvas');
this.wrapper.appendChild(this.canvas2d);
// Stats // Stats
this.stats = new Stats() this.stats = new Stats()
this.stats.showPanel(0); this.stats.showPanel(0);
@@ -30,7 +39,7 @@ window.GameWindow = class {
document.addEventListener('mousemove', event => this.onMouseMove(event), false); document.addEventListener('mousemove', event => this.onMouseMove(event), false);
// Losing focus event // Losing focus event
window.addEventListener("mouseout", function () { this.canvas.addEventListener("mouseout", function () {
if (minecraft.currentScreen === null) { if (minecraft.currentScreen === null) {
minecraft.displayScreen(new GuiIngameMenu()); minecraft.displayScreen(new GuiIngameMenu());
} }
@@ -76,28 +85,26 @@ window.GameWindow = class {
} }
requestFocus() { requestFocus() {
let scope = this; window.focus();
this.canvas.requestPointerLock();
document.body.style.cursor = 'none';
this.mouseLocked = true;
}
setTimeout(function () { exitFocus() {
window.focus(); document.exitPointerLock();
scope.renderer.canvas.requestPointerLock(); document.body.style.cursor = 'default';
}, 0);
} }
loadRenderer(renderer) { loadRenderer(renderer) {
this.renderer = renderer; this.renderer = renderer;
let canvas = this.renderer.canvas;
// Add web renderer canvas to wrapper
this.wrapper.appendChild(canvas);
// Initialize window size // Initialize window size
this.onResize(); this.onResize();
// Request focus // Request focus
let scope = this; let scope = this;
canvas.onclick = function () { document.onclick = function () {
if (scope.minecraft.currentScreen === null) { if (scope.minecraft.currentScreen === null) {
scope.requestFocus(); scope.requestFocus();
} }
@@ -105,28 +112,33 @@ window.GameWindow = class {
} }
updateWindowSize() { updateWindowSize() {
this.scaleFactor = 1; let wrapperWidth = this.wrapper.offsetWidth;
this.width = this.wrapper.offsetWidth; let wrapperHeight = this.wrapper.offsetHeight;
this.height = this.wrapper.offsetHeight;
for (this.scaleFactor = 1; this.width / (this.scaleFactor + 1) >= 320 && this.height / (this.scaleFactor + 1) >= 240; this.scaleFactor++) { let scale;
for (scale = 1; wrapperWidth / (scale + 1) >= 320 && wrapperHeight / (scale + 1) >= 240; scale++) {
// Empty
} }
this.width = this.width / this.scaleFactor; this.scaleFactor = scale;
this.height = this.height / this.scaleFactor; this.width = wrapperWidth / scale;
this.height = wrapperHeight / scale;
if (!(this.renderer === null)) {
this.renderer.webRenderer.setPixelRatio(/*this.minecraft.currentScreen === null ? 1 :*/ 1 / this.scaleFactor);
}
} }
onResize() { onResize() {
this.updateWindowSize(); this.updateWindowSize();
// Adjust camera let wrapperWidth = this.width * this.scaleFactor;
let wrapperHeight = this.height * this.scaleFactor;
// Update world renderer size and camera
this.renderer.camera.aspect = this.width / this.height; this.renderer.camera.aspect = this.width / this.height;
this.renderer.camera.updateProjectionMatrix(); this.renderer.camera.updateProjectionMatrix();
this.renderer.webRenderer.setSize(this.width * this.scaleFactor, this.height * this.scaleFactor); this.renderer.webRenderer.setSize(wrapperWidth, wrapperHeight);
// Update canvas 2d size
this.canvas2d.style.width = wrapperWidth + "px";
this.canvas2d.style.height = wrapperHeight + "px";
// Reinitialize gui // Reinitialize gui
this.renderer.initializeGui(); this.renderer.initializeGui();
@@ -138,7 +150,7 @@ window.GameWindow = class {
} }
onFocusChanged() { onFocusChanged() {
this.mouseLocked = document.pointerLockElement === this.renderer.canvas; this.mouseLocked = document.pointerLockElement === this.canvas;
} }
onMouseMove(event) { onMouseMove(event) {
@@ -148,7 +160,7 @@ window.GameWindow = class {
this.mouseX = event.clientX / this.scaleFactor; this.mouseX = event.clientX / this.scaleFactor;
this.mouseY = event.clientY / this.scaleFactor; this.mouseY = event.clientY / this.scaleFactor;
if (!this.mouseLocked && this.minecraft.currentScreen === null) { if (document.pointerLockElement !== this.canvas && this.minecraft.currentScreen === null) {
this.requestFocus(); this.requestFocus();
} }
} }
+1
View File
@@ -119,6 +119,7 @@ window.Minecraft = class {
if (screen === null) { if (screen === null) {
this.window.requestFocus(); this.window.requestFocus();
} else { } else {
this.window.exitFocus();
screen.setup(this, this.window.width, this.window.height); screen.setup(this, this.window.width, this.window.height);
} }
} }
@@ -30,7 +30,7 @@ window.IngameOverlay = class extends Gui {
this.textureHotbar, this.textureHotbar,
0, 22, 0, 22,
24, 24, 24, 24,
x + this.minecraft.inventory.selectedSlotIndex * 20, y - 1, x + this.minecraft.inventory.selectedSlotIndex * 20 - 1, y - 1,
24, 24 24, 24
) )
@@ -37,9 +37,8 @@ window.WorldRenderer = class {
this.scene.matrixAutoUpdate = false; this.scene.matrixAutoUpdate = false;
// Create web renderer // Create web renderer
this.canvas = document.createElement('canvas')
this.webRenderer = new THREE.WebGLRenderer({ this.webRenderer = new THREE.WebGLRenderer({
canvas: this.canvas, canvas: this.window.canvas,
antialias: false antialias: false
}); });
@@ -54,47 +53,44 @@ window.WorldRenderer = class {
} }
initializeGui() { initializeGui() {
// We will use 2D canvas element to render our HUD.
this.canvas2d = document.createElement('canvas')
// Update camera size // Update camera size
this.canvas2d.width = this.window.width; this.window.canvas2d.width = this.window.width;
this.canvas2d.height = this.window.height; this.window.canvas2d.height = this.window.height;
// Get context stack of 2d canvas // Get context stack of 2d canvas
this.stack2d = this.canvas2d.getContext('2d'); this.stack2d = this.window.canvas2d.getContext('2d');
this.stack2d.webkitImageSmoothingEnabled = false; this.stack2d.webkitImageSmoothingEnabled = false;
this.stack2d.mozImageSmoothingEnabled = false; this.stack2d.mozImageSmoothingEnabled = false;
this.stack2d.imageSmoothingEnabled = false; this.stack2d.imageSmoothingEnabled = false;
// Create texture from rendered graphics. // Create texture from rendered graphics.
this.frameBuffer = new THREE.Texture(this.canvas2d) //this.frameBuffer = new THREE.Texture(this.canvas2d)
this.frameBuffer.needsUpdate = true; //this.frameBuffer.needsUpdate = true;
this.frameBuffer.minFilter = THREE.LinearFilter; //this.frameBuffer.minFilter = THREE.LinearFilter;
this.frameBuffer.maxFilter = THREE.LinearFilter; //this.frameBuffer.maxFilter = THREE.LinearFilter;
// Create HUD material. // Create HUD material.
let material = new THREE.MeshBasicMaterial({ //let material = new THREE.MeshBasicMaterial({
map: this.frameBuffer, // map: this.frameBuffer,
transparent: true // transparent: true
}); //});
// Create plane to render the HUD. This plane fill the whole screen. // Create plane to render the HUD. This plane fill the whole screen.
let geometry = new THREE.PlaneGeometry(this.canvas2d.width, this.canvas2d.height); //let geometry = new THREE.PlaneGeometry(this.canvas2d.width, this.canvas2d.height);
let plane = new THREE.Mesh(geometry, material); //let plane = new THREE.Mesh(geometry, material);
// Create also a custom scene for HUD. // Create also a custom scene for HUD.
this.scene2d = new THREE.Scene(); //this.scene2d = new THREE.Scene();
this.scene2d.add(plane); //this.scene2d.add(plane);
// Create 2D camera // Create 2D camera
this.camera2d = new THREE.OrthographicCamera(0, 0, 0, 0, 0, 30); /*this.camera2d = new THREE.OrthographicCamera(0, 0, 0, 0, 0, 30);
this.camera2d.aspect = this.window.width / this.window.height; this.camera2d.aspect = this.window.width / this.window.height;
this.camera2d.left = -this.window.width / 2; this.camera2d.left = -this.window.width / 2;
this.camera2d.right = this.window.width / 2; this.camera2d.right = this.window.width / 2;
this.camera2d.top = this.window.height / 2; this.camera2d.top = this.window.height / 2;
this.camera2d.bottom = -this.window.height / 2; this.camera2d.bottom = -this.window.height / 2;
this.camera2d.updateProjectionMatrix(); this.camera2d.updateProjectionMatrix();*/
} }
render(partialTicks) { render(partialTicks) {
@@ -107,9 +103,8 @@ window.WorldRenderer = class {
let cameraChunkZ = Math.floor(player.z >> 4); let cameraChunkZ = Math.floor(player.z >> 4);
this.renderChunks(cameraChunkX, cameraChunkZ); this.renderChunks(cameraChunkX, cameraChunkZ);
// Clear frame buffer for 2d screen // Reset 2d canvas
this.stack2d.clearRect(0, 0, this.window.width, this.window.height); this.stack2d.clearRect(0, 0, this.window.width, this.window.height);
this.frameBuffer.needsUpdate = true;
// Render in-game overlay // Render in-game overlay
let mouseX = this.minecraft.window.mouseX; let mouseX = this.minecraft.window.mouseX;
@@ -123,7 +118,6 @@ window.WorldRenderer = class {
// Render actual scene and hud // Render actual scene and hud
this.webRenderer.render(this.scene, this.camera); this.webRenderer.render(this.scene, this.camera);
this.webRenderer.render(this.scene2d, this.camera2d);
} }
orientCamera(partialTicks) { orientCamera(partialTicks) {
+1
View File
@@ -8,6 +8,7 @@ body {
} }
canvas { canvas {
position: absolute;
image-rendering: -moz-crisp-edges; /* Firefox */ image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -webkit-crisp-edges; /* Webkit (Safari) */ image-rendering: -webkit-crisp-edges; /* Webkit (Safari) */
image-rendering: pixelated; /* Chrome */ image-rendering: pixelated; /* Chrome */