Add non-linear controller input curve and fix auth token error
- Replace linear controller scaling with power curve (exp 2.5) for smoother VR controls - less sensitive at low deflections, full power at 90% stick travel - Fix Missing Refresh Token error by clearing stale auth state automatically instead of leaving users in broken state - Fix build errors: use ScoreEvent type in weaponSystem, remove unused parTime parameter from buildResult 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
749cc18211
commit
6655abeeec
@ -156,6 +156,20 @@ export class AuthService {
|
|||||||
return await this._client.getTokenSilently();
|
return await this._client.getTokenSilently();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error('Error getting access token:', error);
|
log.error('Error getting access token:', error);
|
||||||
|
|
||||||
|
// If refresh token is missing/invalid, clear stale auth state
|
||||||
|
// User will appear logged out and can log in fresh
|
||||||
|
if (error instanceof Error && error.message.includes('Missing Refresh Token')) {
|
||||||
|
log.warn('[AuthService] Clearing stale auth session');
|
||||||
|
this._user = null;
|
||||||
|
// Clear Auth0 local storage cache without redirecting
|
||||||
|
try {
|
||||||
|
await this._client.logout({ openUrl: false });
|
||||||
|
} catch {
|
||||||
|
// Ignore logout errors - just clear local state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,8 +144,7 @@ export class GameResultsService {
|
|||||||
levelName: string,
|
levelName: string,
|
||||||
gameStats: GameStats,
|
gameStats: GameStats,
|
||||||
totalAsteroids: number,
|
totalAsteroids: number,
|
||||||
endReason: 'victory' | 'death' | 'stranded',
|
endReason: 'victory' | 'death' | 'stranded'
|
||||||
parTime: number
|
|
||||||
): GameResult {
|
): GameResult {
|
||||||
// Get player name from auth service
|
// Get player name from auth service
|
||||||
const authService = AuthService.getInstance();
|
const authService = AuthService.getInstance();
|
||||||
|
|||||||
@ -609,14 +609,20 @@ export class Ship {
|
|||||||
rightStick: Vector2.Zero(),
|
rightStick: Vector2.Zero(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Merge inputs with smooth deadzone scaling (controller takes priority if active, keyboard disabled in VR)
|
// Merge inputs with non-linear curve (controller takes priority if active, keyboard disabled in VR)
|
||||||
// Deadzone: 0.1-0.15 range with linear scaling (avoids abrupt cliff effect)
|
// Deadzone: 0.1, Max input: 0.9, Power curve for slow start, fast finish
|
||||||
|
const DEADZONE = 0.1;
|
||||||
|
const MAX_INPUT = 0.9;
|
||||||
|
const CURVE_EXPONENT = 2.5;
|
||||||
|
|
||||||
const leftMagnitude = controllerState.leftStick.length();
|
const leftMagnitude = controllerState.leftStick.length();
|
||||||
const rightMagnitude = controllerState.rightStick.length();
|
const rightMagnitude = controllerState.rightStick.length();
|
||||||
|
|
||||||
// Scale factor: 0% at 0.1, 100% at 0.15, linear interpolation between
|
// Calculate curved scale: slow at low deflection, ramps up toward max at 0.9
|
||||||
const leftScale = Math.max(0, Math.min(1, (leftMagnitude - 0.1) / 0.05));
|
const leftScale = leftMagnitude <= DEADZONE ? 0 :
|
||||||
const rightScale = Math.max(0, Math.min(1, (rightMagnitude - 0.1) / 0.05));
|
Math.pow(Math.min(1, (leftMagnitude - DEADZONE) / (MAX_INPUT - DEADZONE)), CURVE_EXPONENT);
|
||||||
|
const rightScale = rightMagnitude <= DEADZONE ? 0 :
|
||||||
|
Math.pow(Math.min(1, (rightMagnitude - DEADZONE) / (MAX_INPUT - DEADZONE)), CURVE_EXPONENT);
|
||||||
|
|
||||||
const combinedInput = {
|
const combinedInput = {
|
||||||
leftStick:
|
leftStick:
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { GameStats } from "../game/gameStats";
|
|||||||
import { Projectile } from "./projectile";
|
import { Projectile } from "./projectile";
|
||||||
import { RockFactory } from "../environment/asteroids/rockFactory";
|
import { RockFactory } from "../environment/asteroids/rockFactory";
|
||||||
import log from "../core/logger";
|
import log from "../core/logger";
|
||||||
|
import { ScoreEvent } from "../ui/hud/scoreboard";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles weapon firing and projectile lifecycle using shape casting
|
* Handles weapon firing and projectile lifecycle using shape casting
|
||||||
@ -39,7 +40,7 @@ export class WeaponSystem {
|
|||||||
private _havokPlugin: HavokPlugin | null = null;
|
private _havokPlugin: HavokPlugin | null = null;
|
||||||
|
|
||||||
// Observable for score updates when asteroids are destroyed
|
// Observable for score updates when asteroids are destroyed
|
||||||
private _scoreObservable: Observable<{score: number, remaining: number, message: string}> | null = null;
|
private _scoreObservable: Observable<ScoreEvent> | null = null;
|
||||||
|
|
||||||
// Ship body to ignore in shape casts
|
// Ship body to ignore in shape casts
|
||||||
private _shipBody: PhysicsBody | null = null;
|
private _shipBody: PhysicsBody | null = null;
|
||||||
|
|||||||
@ -671,8 +671,7 @@ export class StatusScreen {
|
|||||||
this._currentLevelName,
|
this._currentLevelName,
|
||||||
this._gameStats,
|
this._gameStats,
|
||||||
this._totalAsteroids,
|
this._totalAsteroids,
|
||||||
endReason,
|
endReason
|
||||||
this._parTime
|
|
||||||
);
|
);
|
||||||
|
|
||||||
log.info('[StatusScreen] Built result:', result);
|
log.info('[StatusScreen] Built result:', result);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user