Skip to content

Commit ddcfa1f

Browse files
committed
feat: add camera top when device is mobile
1 parent 3d648ee commit ddcfa1f

3 files changed

Lines changed: 26 additions & 11 deletions

File tree

src/Game.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import { SpaceShuttleComponent } from './components/models/SpaceShuttleComponent
66
import { StarsComponent } from './components/models/StarsComponent';
77
import { TextComponent } from './components/models/TextComponent';
88
import { ShootComponent } from './components/models/ShootComponent';
9-
import { CameraComponent } from './components/models/CameraComponent';
9+
import { CameraComponent, CameraMode } from './components/models/CameraComponent';
10+
import { Device } from './util/Device';
1011

1112
export class Game {
1213

@@ -46,7 +47,8 @@ export class Game {
4647
this.renderer.setClearColor("#191644");
4748
this.renderer.shadowMap.enabled = true;
4849
this.container.appendChild(this.renderer.domElement);
49-
await this.cameraComponent.load(this.scene);
50+
const initialCameraMode: CameraMode = Device.isMobileDevice() ? CameraMode.Top : CameraMode.Default;
51+
await this.cameraComponent.load(this.scene, initialCameraMode);
5052

5153
/* ********* Models *********** */
5254
await this.spaceCraft.load(this.scene);

src/components/models/CameraComponent.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import * as THREE from 'three';
22
import { GameComponentBase } from '../GameComponentBase';
33

4-
type CameraMode = 'default' | 'top';
5-
4+
export enum CameraMode {
5+
Default = 'default',
6+
Top = 'top'
7+
}
68
enum CameraScene {
79
Default = '1',
810
Top = '2',
@@ -13,7 +15,7 @@ export class CameraComponent extends GameComponentBase {
1315
private readonly defaultPosition: THREE.Vector3 = new THREE.Vector3(5, 2, 30);
1416
private readonly topViewOffset: THREE.Vector3 = new THREE.Vector3(0, 35, 20);
1517
private readonly topViewLookOffset: THREE.Vector3 = new THREE.Vector3(0, 0, -15);
16-
private mode: CameraMode = 'default';
18+
private mode: CameraMode = CameraMode.Default;
1719
private targetProvider: () => THREE.Vector3;
1820

1921
constructor(targetProvider: () => THREE.Vector3) {
@@ -26,8 +28,13 @@ export class CameraComponent extends GameComponentBase {
2628
return this.camera;
2729
}
2830

29-
public async load(scene: THREE.Scene): Promise<void> {
30-
this.camera.position.copy(this.defaultPosition);
31+
public async load(scene: THREE.Scene, initialMode: CameraMode = CameraMode.Default): Promise<void> {
32+
this.mode = initialMode;
33+
if (this.mode === CameraMode.Top) {
34+
this.updateCameraTracking(true);
35+
} else {
36+
this.camera.position.copy(this.defaultPosition);
37+
}
3138
scene.add(this.camera);
3239
window.addEventListener('keydown', this.handleCameraChange);
3340
}
@@ -38,22 +45,22 @@ export class CameraComponent extends GameComponentBase {
3845

3946
private handleCameraChange = (event: KeyboardEvent): void => {
4047
if (event.key === CameraScene.Top) {
41-
this.mode = 'top';
48+
this.mode = CameraMode.Top;
4249
this.updateCameraTracking(true);
4350
}
4451
if (event.key === CameraScene.Default) {
45-
this.mode = 'default';
52+
this.mode = CameraMode.Default;
4653
this.camera.position.copy(this.defaultPosition);
4754
this.camera.lookAt(new THREE.Vector3(0, 0, 0));
4855
}
4956
}
5057

5158
private updateCameraTracking(force: boolean = false): void {
52-
if (this.mode !== 'top' && !force) {
59+
if (this.mode !== CameraMode.Top && !force) {
5360
return;
5461
}
5562

56-
if (this.mode === 'top') {
63+
if (this.mode === CameraMode.Top) {
5764
const targetPosition = this.targetProvider();
5865
this.camera.position.set(
5966
targetPosition.x + this.topViewOffset.x,

src/util/Device.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export class Device {
2+
public static isMobileDevice(): boolean {
3+
const mobileRegex = /Mobi|Android|iPhone|iPad|iPod|Tablet/i;
4+
return mobileRegex.test(navigator.userAgent) || window.innerWidth <= 900;
5+
}
6+
}

0 commit comments

Comments
 (0)