openvibers/openvibe.games Commits

Surf maps go straight onto the ramp: no character select or customize screen, no hands, tool, vitals or hotbar; the run's clock sits top centre (compact on touch, no key hints) and the view starts looking at the drop (#193)

OP OpenVibers committed 16 days ago · 8f83a20d0f · 2 files, +48 −5

Changes

ddiff --git a/apps/client/src/main.ts b/apps/client/src/main.ts
iindex a520ce1..df7e8c7 100644
---- a/apps/client/src/main.ts
++++ b/apps/client/src/main.ts
@@@ -20,7 +20,7 @@ import { MapLightLayer, mapDiff, staticWork, terrainWork } from './render/mapRun
import { createRapierWorld, loadRapier } from '@openvibe/physics/rapier'
import { FixedTimestep } from '@openvibe/shared'
import { Vector3 } from '@babylonjs/core/Maths/math.vector.js'
--import type { Appearance } from '@openvibe/protocol'
++import { defaultAppearance, type Appearance } from '@openvibe/protocol'
import { Color3 } from '@babylonjs/core/Maths/math.color.js'
import { Scene } from '@babylonjs/core/scene.js'
import { WATER_LEVEL, getMapOverride, terrainHeight } from '@openvibe/content'
@@@ -241,7 +241,12 @@ async function start(): Promise<void> {
} catch {
characters = []
}
-- const choice = await characterSelect(uiRoot, characters, Boolean(sso))
++ // A surf map (OpenVibe.Surf's Ride) goes straight onto the ramp: your first character if you have one, else a surfer
++ // with the default look under your saved name. Character select and the customize screen belong to the islands.
++ const firstOwn = [...characters].sort((a, b) => a.slot - b.slot)[0] ?? null
++ const choice = surfInfo
++ ? { slot: firstOwn ? firstOwn.slot : 0, existing: firstOwn }
++ : await characterSelect(uiRoot, characters, Boolean(sso))
let name: string
let appearance: Appearance
let releaseCamera: () => void
@@@ -249,6 +254,10 @@ async function start(): Promise<void> {
name = choice.existing.name
appearance = { ...choice.existing.appearance, height: 1, build: 1 }
releaseCamera = () => {}
++ } else if (surfInfo) {
++ name = identity.name ?? 'Surfer'
++ appearance = defaultAppearance()
++ releaseCamera = () => {}
} else {
const created = await customizeScreen(scene, content, uiRoot, identity.name, !sso)
name = created.name
@@@ -269,6 +278,8 @@ async function start(): Promise<void> {
const state = new ClientState()
const connection = new Connection()
const input = new InputTracker(canvas)
++ // A surf map starts on a pad above its first ramp: look a little down, so the pad's edge (the drop) is in front.
++ if (surfInfo) input.pitch = -0.2
const view = new EntityView(scene, physics, content, state)
const icons = new IconFactory(scene, content)
const weaponSettings = new WeaponSettings()
@@@ -455,6 +466,12 @@ async function start(): Promise<void> {
environment.hazeFog = false
hud.setCrosshair(false)
}
++ // A surf run is the ramps and the clock: no hands or held tool, and no survival bars or hotbar (surfHud.css hides
++ // those under .ovg-surf).
++ if (surfInfo) {
++ viewmodel.setEnabled(false)
++ uiRoot.classList.add('ovg-surf')
++ }
// From above, a ring under each player (yours blue) shows who is where and which way each one faces.
const markers = topDown ? new TopDownMarkers(scene, state, view, player) : null
const beams = new BeamRenderer(scene)
ddiff --git a/apps/client/src/ui/surfHud.css b/apps/client/src/ui/surfHud.css
iindex b97723d..5a9c5b5 100644
---- a/apps/client/src/ui/surfHud.css
++++ b/apps/client/src/ui/surfHud.css
@@@ -1,9 +1,13 @@
++/* The run's clock sits top centre, as in CS surf: clear of the OpenVibe menu pill (top left) and the phone's Restart
++ button (top right). */
.surf-hud {
position: fixed;
z-index: 12;
-- top: max(1rem, env(safe-area-inset-top));
-- left: max(1rem, env(safe-area-inset-left));
-- width: min(18rem, calc(100vw - 2rem));
++ top: max(0.75rem, env(safe-area-inset-top));
++ left: 50%;
++ translate: -50% 0;
++ width: min(19rem, calc(100vw - 13rem));
++ min-width: 13.5rem;
padding: 0.8rem 0.95rem 0.9rem;
border: 1px solid var(--border, #2a3340);
border-left: 3px solid var(--g-accent, #f0b040);
@@@ -116,3 +120,25 @@
}
.surf-watch { background: transparent !important; color: var(--text-primary, #e6e6e6) !important; }
.surf-finish-actions button:disabled { opacity: 0.45; cursor: default; }
++
++/* A surf place has no survival: the vitals, the hotbar and the first-steps card are the islands'. */
++.ovg-surf .vitals,
++.ovg-surf .hotbar,
++.ovg-surf .first-steps { display: none !important; }
++
++/* Touch: the keys mean nothing, the screen is small. A compact clock, the last two splits. */
++@media (pointer: coarse), (max-width: 640px) {
++ .surf-hud {
++ width: auto;
++ min-width: 0;
++ max-width: calc(100vw - 11.5rem);
++ padding: 0.5rem 0.7rem 0.55rem;
++ border-radius: 0.7rem;
++ font-size: 0.78rem;
++ }
++ .surf-title { display: none; }
++ .surf-timer { font-size: 1.55rem; margin: 0; }
++ .surf-hint { display: none; }
++ .surf-meta { font-size: 0.68rem; }
++ .surf-split:not(:nth-last-child(-n + 2)) { display: none; }
++}