From 2552c8a408367ecca101bdc6812b515bb17df993 Mon Sep 17 00:00:00 2001 From: L3P3 Date: Wed, 24 Jul 2024 18:25:00 +0200 Subject: [PATCH] #46 improve esc camera jump in chromium --- package.json | 2 +- src/app.js | 6 ++--- src/etc/helpers.js | 5 ++++- src/etc/state.js | 3 ++- src/etc/storage.js | 3 ++- src/game/c_game.js | 48 ++++++++++++++++++++++++++++------------ src/game/c_menu_start.js | 3 ++- src/game/m_game.js | 41 ++++++++++++++++++++-------------- 8 files changed, 72 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index 9ff3015..e2a626c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "minicraft", - "version": "0.10.5", + "version": "0.10.6", "description": "voxel-based 3d game, written in javascript", "homepage": "https://l3p3.de/minicraft", "repository": { diff --git a/src/app.js b/src/app.js index 3ba0f82..744f1b1 100755 --- a/src/app.js +++ b/src/app.js @@ -19,7 +19,7 @@ import { addEventListener_, BroadcastChannel_, clearTimeout_, - Date_, + Date_now, handler_noop, localStorage_, localStorage_getItem, @@ -75,7 +75,7 @@ function Root() { }; setInterval(() => ( actions.config_save(), - !BroadcastChannel_ && localStorage_setItem('minicraft.lock', Date_.now()) + !BroadcastChannel_ && localStorage_setItem('minicraft.lock', Date_now()) ), 500); addEventListener_('touchend', event => { @@ -170,7 +170,7 @@ else if (BroadcastChannel_) { else { // first make sure lock has expired const lock_found = Number_(localStorage_getItem('minicraft.lock')); - const lock_limit = Date_.now() - 1000; + const lock_limit = Date_now() - 1000; // if already expired if (lock_found < lock_limit) init(Root); // if not, wait and check again diff --git a/src/etc/helpers.js b/src/etc/helpers.js index d030797..792f2a4 100644 --- a/src/etc/helpers.js +++ b/src/etc/helpers.js @@ -4,6 +4,7 @@ import { export const window_ = window; export const document_ = document; +export const navigator_ = navigator; const Math_ = Math; export const Math_PI = Math_.PI; export const Math_PI_h = Math_PI * .5; @@ -21,7 +22,8 @@ export const Math_log2 = Math_.log2; export const String_fromCharCode = String.fromCharCode; export const BroadcastChannel_ = BroadcastChannel; -export const Date_ = Date; +const Date_ = Date; +export const Date_now = () => Date_.now(); const JSON_ = JSON; export const Promise_ = Promise; export const JSON_stringify = JSON_.stringify; @@ -44,6 +46,7 @@ export const clearTimeout_ = clearTimeout; export const clearInterval_ = clearInterval; export const addEventListener_ = addEventListener; export const removeEventListener_ = removeEventListener; +export const flag_chromium = navigator_.userAgent.includes('WebKit'); /** @param {number} num diff --git a/src/etc/state.js b/src/etc/state.js index 0703513..aa617f6 100644 --- a/src/etc/state.js +++ b/src/etc/state.js @@ -2,6 +2,7 @@ import { VERSION, } from './env.js'; import { + Date_now, JSON_parse, JSON_stringify, Object_keys, @@ -88,7 +89,7 @@ export const reducers = { label: ( prompt(locale_unknown_world_found, '') || locale_unknown_world ).substring(0, 16), - mod_l: Date.now(), + mod_l: Date_now(), mod_r: 0, }; needs_save = true; diff --git a/src/etc/storage.js b/src/etc/storage.js index 2e16bb1..2bf5037 100644 --- a/src/etc/storage.js +++ b/src/etc/storage.js @@ -8,6 +8,7 @@ import { localStorage_getItem, localStorage_removeItem, localStorage_setItem, + navigator_, } from './helpers.js'; // to assert chunk deletion fix is done before this @@ -15,7 +16,7 @@ import './state.js'; let chunks_db = null; if (indexedDB_) { - navigator.storage?.persist?.(); + navigator_.storage?.persist?.(); const request = indexedDB_.open('minicraft', 1); request.onupgradeneeded = event => { // migrate from localStorage to indexedDB diff --git a/src/game/c_game.js b/src/game/c_game.js index 3368275..ee81df7 100644 --- a/src/game/c_game.js +++ b/src/game/c_game.js @@ -19,21 +19,27 @@ import { } from '../etc/constants.js'; import { document_, + flag_chromium, Math_max, window_, } from '../etc/helpers.js'; import { game_create, + game_destroy, game_key, + game_message_print, game_mouse_catch, - game_mouse_move, + game_mouse_move_menu, + game_mouse_move_player, game_render, game_renderer_init, game_resolution_update, game_view_distance_update, - game_destroy, } from './m_game.js'; +import { + player_rotate, +} from './m_player.js'; import Bar from './c_bar.js'; import Inventory from './c_inventory.js'; @@ -74,14 +80,11 @@ export default function Game({ return false; }; - const handler_mousemove = event => { - if ( - model.menu !== MENU_NONE || - document_.pointerLockElement === frame - ) { - game_mouse_move(model, event); - } - }; + const handler_mousemove = event => ( + document_.pointerLockElement === frame + ? game_mouse_move_player(model, event) + : game_mouse_move_menu(model, event) + ); const handler_mousewheel = event => { actions.config_touch_set(false); @@ -100,16 +103,18 @@ export default function Game({ } }; + const passive_true = {passive: true}; + frame.addEventListener('mousedown', handler_mousebutton); frame.addEventListener('mouseup', handler_mousebutton); - frame.addEventListener('mousemove', handler_mousemove); - frame.addEventListener('wheel', handler_mousewheel); + frame.addEventListener('mousemove', handler_mousemove, passive_true); + frame.addEventListener('wheel', handler_mousewheel, passive_true); return () => { frame.removeEventListener('mousedown', handler_mousebutton); frame.removeEventListener('mouseup', handler_mousebutton); - frame.removeEventListener('mousemove', handler_mousemove); - frame.removeEventListener('wheel', handler_mousewheel); + frame.removeEventListener('mousemove', handler_mousemove, passive_true); + frame.removeEventListener('wheel', handler_mousewheel, passive_true); game_destroy(model); ref.game = null; }; @@ -144,6 +149,21 @@ export default function Game({ model.menu === MENU_NONE ) { model.menu = MENU_SETTINGS; + // #46 move camera back after accidental jump + if ( + flag_chromium && + (model.rotate_last_h | model.rotate_last_v) && + model.rotate_last_time > time_now - 100 + ) { + game_message_print(model, `move back ${Math.round(model.rotate_last_h*100)}% ${Math.round(model.rotate_last_v*100)}%`); + player_rotate( + model.player, + -model.rotate_last_h, + -model.rotate_last_v + ); + model.rotate_last_h = model.rotate_last_v = 0; + model.renderer.flag_dirty = true; + } } model.world.flag_paused = !ingame; diff --git a/src/game/c_menu_start.js b/src/game/c_menu_start.js index a3ba81a..524ca6c 100644 --- a/src/game/c_menu_start.js +++ b/src/game/c_menu_start.js @@ -20,6 +20,7 @@ import { VERSION, } from '../etc/env.js'; import { + Date_now, JSON_stringify, Math_max, Math_min, @@ -513,7 +514,7 @@ export default function MenuStart({ actions.world_add({ id: Math_min(0, ...config.worlds.map(world => world.id)) - 1, label: name, - mod_l: Date.now(), + mod_l: Date_now(), mod_r: 0, }); } diff --git a/src/game/m_game.js b/src/game/m_game.js index 7bc2a1f..1008466 100644 --- a/src/game/m_game.js +++ b/src/game/m_game.js @@ -57,6 +57,8 @@ import { import { clearInterval_, clearTimeout_, + Date_now, + flag_chromium, JSON_stringify, Math_ceil, Math_floor, @@ -157,6 +159,9 @@ export const game_create = (actions, frame_element, config, account) => { resolution_raw_y: 1, resolution_x: 0, resolution_y: 0, + rotate_last_h: 0, + rotate_last_time: 0, + rotate_last_v: 0, tick_interval: setInterval_(() => ( world_tick(world, player) ), 50), @@ -185,7 +190,7 @@ export const game_renderer_init = (model, canvas_element) => { export const game_save = model => { world_save(model.world, model.player); model.actions.world_prop(model.world.id, { - mod_l: Date.now(), + mod_l: Date_now(), }); } @@ -243,22 +248,24 @@ export const game_mouse_catch = async model => { catch (error) {} } -export const game_mouse_move = (model, event) => { - if (!model.world.flag_paused) { - const factor = model.config.mouse_sensitivity * Math_PI / (Math_max( - model.resolution_raw_x, - model.resolution_raw_y - ) * model.resolution_css_ratio); - player_rotate( - model.player, - event.movementX * factor, - -event.movementY * factor - ); - } - else { - model.cursor_x = event.clientX; - model.cursor_y = event.clientY; +export const game_mouse_move_player = (model, event) => { + const factor = model.config.mouse_sensitivity * Math_PI / (Math_max( + model.resolution_raw_x, + model.resolution_raw_y + ) * model.resolution_css_ratio); + if (flag_chromium) { + model.rotate_last_time = event.timeStamp; } + player_rotate( + model.player, + model.rotate_last_h = event.movementX * factor, + model.rotate_last_v = -event.movementY * factor + ); +} + +export const game_mouse_move_menu = (model, event) => { + model.cursor_x = event.clientX; + model.cursor_y = event.clientY; } /** @@ -825,7 +832,7 @@ export const game_message_send = (model, value) => { } } -const game_message_print = (model, value, minor = false) => { +export const game_message_print = (model, value, minor = false) => { const id = ++message_id_counter; ( model.messages = model.messages.slice(-49)