@mpgd/cli 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +349 -22
- package/package.json +14 -2
- package/templates/phaser-game/README.md +130 -6
- package/templates/phaser-game/agent/acceptance.md +7 -2
- package/templates/phaser-game/agent/brief.md +1 -1
- package/templates/phaser-game/agent/game-manifest.json +5 -1
- package/templates/phaser-game/apps/target-cloudflare-pages/package.json +28 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/src/worker.ts +12 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/tsconfig.json +8 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/vite.config.ts +28 -0
- package/templates/phaser-game/apps/target-cloudflare-pages/wrangler.jsonc +28 -0
- package/templates/phaser-game/apps/target-devvit/README.md +1 -1
- package/templates/phaser-game/apps/target-devvit/package.json +1 -1
- package/templates/phaser-game/apps/target-devvit/src/server/index.ts +4 -4
- package/templates/phaser-game/index.html +2 -0
- package/templates/phaser-game/legal/privacy.html +78 -0
- package/templates/phaser-game/legal/support.html +66 -0
- package/templates/phaser-game/legal/terms.html +70 -0
- package/templates/phaser-game/mpgd.targets.json +6 -0
- package/templates/phaser-game/package.json +42 -12
- package/templates/phaser-game/pnpm-workspace.yaml +7 -0
- package/templates/phaser-game/public/icon.svg +12 -0
- package/templates/phaser-game/public/manifest.webmanifest +20 -0
- package/templates/phaser-game/src/assets/manifest.ts +15 -0
- package/templates/phaser-game/src/assets/marker.svg +12 -0
- package/templates/phaser-game/src/env.d.ts +1 -0
- package/templates/phaser-game/src/i18n/messages.ts +3 -0
- package/templates/phaser-game/src/main.ts +49 -0
- package/templates/phaser-game/src/platform/installPlatform.ts +1 -1
- package/templates/phaser-game/src/platform/runtimeDetector.ts +9 -1
- package/templates/phaser-game/src/runtime/gameContext.ts +6 -1
- package/templates/phaser-game/src/scenes/BootScene.ts +8 -0
- package/templates/phaser-game/src/scenes/LobbyScene.ts +18 -2
- package/templates/phaser-game/src/scenes/PlayScene.ts +3 -2
- package/templates/phaser-game/src/styles.css +25 -2
- package/templates/phaser-game/vite.config.ts +2 -0
|
@@ -6,7 +6,24 @@
|
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"dev": "__WORKSPACE_I18N_BUILD_PREFIX__vite --host 0.0.0.0",
|
|
9
|
+
"dev:ait": "APP_TARGET=ait APP_VERSION=0.0.0-dev BUILD_ID=ait-sandbox sh -c '__WORKSPACE_I18N_BUILD_PREFIX__vite --host 0.0.0.0'",
|
|
9
10
|
"build": "__WORKSPACE_I18N_BUILD_PREFIX__vite build",
|
|
11
|
+
"build:ait": "pnpm exec mpgd target build ait production --variant wrapper --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
12
|
+
"build:ait:package": "pnpm exec mpgd target build ait production --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
13
|
+
"smoke:ait": "pnpm exec mpgd target smoke ait --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
14
|
+
"ait:wrapper:dev": "pnpm --dir ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}/apps/target-ait run dev",
|
|
15
|
+
"ait:wrapper:dev:plain": "pnpm --dir ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}/apps/target-ait run dev:plain",
|
|
16
|
+
"ait:wrapper:dev:phone": "pnpm --dir ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}/apps/target-ait run dev:phone",
|
|
17
|
+
"ait:devtools:mcp": "pnpm --dir ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}/apps/target-ait run devtools:mcp",
|
|
18
|
+
"ait:devtools:mcp:mobile": "pnpm --dir ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}/apps/target-ait run devtools:mcp:mobile",
|
|
19
|
+
"ait:console:login": "aitcc login",
|
|
20
|
+
"ait:console:whoami": "aitcc whoami",
|
|
21
|
+
"ait:console:init": "aitcc app init",
|
|
22
|
+
"ait:console:register": "aitcc app register",
|
|
23
|
+
"ait:console:status": "aitcc app status",
|
|
24
|
+
"ait:console:deploy": "aitcc app deploy",
|
|
25
|
+
"build:microsoft-store": "pnpm exec mpgd target build microsoft-store production --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
26
|
+
"smoke:microsoft-store": "pnpm exec mpgd target smoke microsoft-store --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
10
27
|
"build:devvit": "pnpm exec mpgd target build reddit production --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
11
28
|
"build:devvit:staging": "pnpm exec mpgd target build reddit staging --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
12
29
|
"smoke:devvit": "pnpm exec mpgd target smoke reddit --targets-file ./mpgd.targets.json --kit-path ${MPGD_KIT_PATH:-__DEFAULT_KIT_PATH__}",
|
|
@@ -18,30 +35,43 @@
|
|
|
18
35
|
"devvit:upload": "pnpm --dir apps/target-devvit run upload",
|
|
19
36
|
"devvit:playtest": "pnpm --dir apps/target-devvit run dev",
|
|
20
37
|
"devvit:publish": "pnpm --dir apps/target-devvit run publish",
|
|
38
|
+
"legal:build": "pnpm exec mpgd legal build",
|
|
39
|
+
"legal:check": "pnpm exec mpgd legal check",
|
|
40
|
+
"pages:build": "pnpm legal:build && pnpm --dir apps/target-cloudflare-pages run build",
|
|
41
|
+
"pages:dev": "pnpm legal:build && pnpm --dir apps/target-cloudflare-pages run dev",
|
|
42
|
+
"pages:preview": "pnpm legal:build && pnpm --dir apps/target-cloudflare-pages run preview",
|
|
43
|
+
"pages:types": "pnpm --dir apps/target-cloudflare-pages run types",
|
|
21
44
|
"check": "ttsc --noEmit -p tsconfig.json",
|
|
22
45
|
"lint": "ttsc --noEmit -p tsconfig.json",
|
|
23
46
|
"format": "ttsc format",
|
|
24
47
|
"fix": "ttsc fix"
|
|
25
48
|
},
|
|
26
49
|
"dependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"@
|
|
29
|
-
"@mpgd/adapter-
|
|
30
|
-
"@mpgd/adapter-
|
|
31
|
-
"@mpgd/
|
|
32
|
-
"@mpgd/
|
|
33
|
-
"@mpgd/
|
|
34
|
-
"@mpgd/
|
|
35
|
-
"@mpgd/
|
|
36
|
-
"@mpgd/
|
|
50
|
+
"@ait-co/polyfill": "^0.1.17",
|
|
51
|
+
"@apps-in-toss/web-framework": "^2.10.4",
|
|
52
|
+
"@mpgd/adapter-ait": "__MPGD_DEPENDENCY_VERSION_ADAPTER_AIT__",
|
|
53
|
+
"@mpgd/adapter-browser": "__MPGD_DEPENDENCY_VERSION_ADAPTER_BROWSER__",
|
|
54
|
+
"@mpgd/adapter-capacitor": "__MPGD_DEPENDENCY_VERSION_ADAPTER_CAPACITOR__",
|
|
55
|
+
"@mpgd/adapter-devvit": "__MPGD_DEPENDENCY_VERSION_ADAPTER_DEVVIT__",
|
|
56
|
+
"@mpgd/analytics": "__MPGD_DEPENDENCY_VERSION_ANALYTICS__",
|
|
57
|
+
"@mpgd/bridge": "__MPGD_DEPENDENCY_VERSION_BRIDGE__",
|
|
58
|
+
"@mpgd/catalog": "__MPGD_DEPENDENCY_VERSION_CATALOG__",
|
|
59
|
+
"@mpgd/game-services": "__MPGD_DEPENDENCY_VERSION_GAME_SERVICES__",
|
|
60
|
+
"@mpgd/i18n": "__MPGD_DEPENDENCY_VERSION_I18N__",
|
|
61
|
+
"@mpgd/platform": "__MPGD_DEPENDENCY_VERSION_PLATFORM__",
|
|
62
|
+
"@mpgd/phaser-assets": "__MPGD_DEPENDENCY_VERSION_PHASER_ASSETS__",
|
|
63
|
+
"@mpgd/target-config": "__MPGD_DEPENDENCY_VERSION_TARGET_CONFIG__",
|
|
37
64
|
"phaser": "4.2.0"
|
|
38
65
|
},
|
|
39
66
|
"devDependencies": {
|
|
40
|
-
"@
|
|
67
|
+
"@ait-co/console-cli": "^0.1.45",
|
|
68
|
+
"@cloudflare/workers-types": "^5.20260707.1",
|
|
69
|
+
"@mpgd/cli": "__MPGD_DEPENDENCY_VERSION_CLI__",
|
|
41
70
|
"@ttsc/unplugin": "0.16.9",
|
|
42
71
|
"@types/node": "^24.0.0",
|
|
43
72
|
"ttsc": "0.16.9",
|
|
44
73
|
"typescript": "7.0.1-rc",
|
|
45
|
-
"vite": "^8.1.3"
|
|
74
|
+
"vite": "^8.1.3",
|
|
75
|
+
"wrangler": "^4.107.0"
|
|
46
76
|
}
|
|
47
77
|
}
|
|
@@ -3,5 +3,12 @@ packages:
|
|
|
3
3
|
- 'apps/*'
|
|
4
4
|
__PNPM_WORKSPACE_KIT_PACKAGES__
|
|
5
5
|
allowBuilds:
|
|
6
|
+
'@sentry/cli': true
|
|
7
|
+
'@swc/core': true
|
|
8
|
+
# @ait-co/devtools lazily installs cloudflared when the phone tunnel starts;
|
|
9
|
+
# keep default workspace installs free of external binary downloads.
|
|
10
|
+
cloudflared: false
|
|
6
11
|
esbuild: true
|
|
7
12
|
protobufjs: true
|
|
13
|
+
sharp: true
|
|
14
|
+
workerd: true
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="starter-icon" cx="42%" cy="32%" r="68%">
|
|
4
|
+
<stop offset="0%" stop-color="#f8fafc" />
|
|
5
|
+
<stop offset="45%" stop-color="#38bdf8" />
|
|
6
|
+
<stop offset="100%" stop-color="#0f766e" />
|
|
7
|
+
</radialGradient>
|
|
8
|
+
</defs>
|
|
9
|
+
<rect width="128" height="128" rx="28" fill="#0f172a" />
|
|
10
|
+
<circle cx="64" cy="62" r="42" fill="url(#starter-icon)" />
|
|
11
|
+
<path d="M42 72 58 40l14 24 14-16 12 24H42Z" fill="#ecfeff" opacity="0.92" />
|
|
12
|
+
</svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lang": "en-US",
|
|
3
|
+
"name": "__GAME_TITLE__",
|
|
4
|
+
"short_name": "__GAME_NAME__",
|
|
5
|
+
"description": "__GAME_TITLE__ built with mpgd-kit.",
|
|
6
|
+
"start_url": "./",
|
|
7
|
+
"scope": "./",
|
|
8
|
+
"display": "standalone",
|
|
9
|
+
"orientation": "landscape",
|
|
10
|
+
"background_color": "#0f172a",
|
|
11
|
+
"theme_color": "#0f172a",
|
|
12
|
+
"icons": [
|
|
13
|
+
{
|
|
14
|
+
"src": "./icon.svg",
|
|
15
|
+
"sizes": "any",
|
|
16
|
+
"type": "image/svg+xml",
|
|
17
|
+
"purpose": "any maskable"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { definePhaserAssetManifest, type PhaserAssetManifest } from '@mpgd/phaser-assets';
|
|
2
|
+
|
|
3
|
+
import markerUrl from './marker.svg?url';
|
|
4
|
+
|
|
5
|
+
export const starterAssetKeys = {
|
|
6
|
+
marker: '__GAME_NAME__.marker',
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
export const starterAssets = definePhaserAssetManifest([
|
|
10
|
+
{
|
|
11
|
+
kind: 'image',
|
|
12
|
+
key: starterAssetKeys.marker,
|
|
13
|
+
url: markerUrl,
|
|
14
|
+
},
|
|
15
|
+
] as const satisfies PhaserAssetManifest);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" role="img" aria-label="Starter marker">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="marker-glow" cx="50%" cy="45%" r="58%">
|
|
4
|
+
<stop offset="0%" stop-color="#99f6e4" />
|
|
5
|
+
<stop offset="55%" stop-color="#2dd4bf" />
|
|
6
|
+
<stop offset="100%" stop-color="#0f766e" />
|
|
7
|
+
</radialGradient>
|
|
8
|
+
</defs>
|
|
9
|
+
<circle cx="48" cy="48" r="42" fill="url(#marker-glow)" />
|
|
10
|
+
<circle cx="48" cy="48" r="32" fill="none" stroke="#ecfeff" stroke-width="5" opacity="0.86" />
|
|
11
|
+
<circle cx="48" cy="48" r="8" fill="#ecfeff" />
|
|
12
|
+
</svg>
|
|
@@ -3,6 +3,7 @@ import type { Locale } from '@mpgd/i18n';
|
|
|
3
3
|
export type GameMessageKey =
|
|
4
4
|
| 'title'
|
|
5
5
|
| 'target'
|
|
6
|
+
| 'viewport'
|
|
6
7
|
| 'backend'
|
|
7
8
|
| 'features'
|
|
8
9
|
| 'featuresNone'
|
|
@@ -19,6 +20,7 @@ const messages = {
|
|
|
19
20
|
en: {
|
|
20
21
|
title: '__GAME_TITLE__',
|
|
21
22
|
target: 'Target: {target}',
|
|
23
|
+
viewport: 'Viewport: {sizeClass} {orientation} - controls {controls}',
|
|
22
24
|
backend: 'Game Services: {mode}',
|
|
23
25
|
features: 'Features: {features}',
|
|
24
26
|
featuresNone: 'none',
|
|
@@ -34,6 +36,7 @@ const messages = {
|
|
|
34
36
|
ko: {
|
|
35
37
|
title: '__GAME_TITLE__',
|
|
36
38
|
target: '타깃: {target}',
|
|
39
|
+
viewport: '뷰포트: {sizeClass} {orientation} - 컨트롤 {controls}',
|
|
37
40
|
backend: 'Game Services: {mode}',
|
|
38
41
|
features: '기능: {features}',
|
|
39
42
|
featuresNone: '없음',
|
|
@@ -2,6 +2,7 @@ import './styles.css';
|
|
|
2
2
|
|
|
3
3
|
import { createAnalyticsReporter, createBufferedAnalyticsSink } from '@mpgd/analytics';
|
|
4
4
|
import { resolveMpgdLocale, type Locale } from '@mpgd/i18n';
|
|
5
|
+
import { resolveTargetViewportPlan } from '@mpgd/target-config';
|
|
5
6
|
|
|
6
7
|
import { t } from './i18n/messages';
|
|
7
8
|
import { createClientId } from './runtime/id';
|
|
@@ -16,9 +17,18 @@ async function bootstrap(): Promise<void> {
|
|
|
16
17
|
let locale: Locale = 'en';
|
|
17
18
|
|
|
18
19
|
try {
|
|
20
|
+
if (__APP_TARGET__ === 'ait') {
|
|
21
|
+
const { install } = await import('@ait-co/polyfill');
|
|
22
|
+
await install();
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
const runtimeConfig = detectRuntime();
|
|
20
26
|
const platform = await installPlatform(runtimeConfig);
|
|
21
27
|
const runtime = await platform.getTargetRuntime();
|
|
28
|
+
const viewport = resolveTargetViewportPlan({
|
|
29
|
+
...measureGameViewport(),
|
|
30
|
+
runtime: runtime.config.runtime,
|
|
31
|
+
});
|
|
22
32
|
const player =
|
|
23
33
|
(await platform.identity.getPlayer()) ?? {
|
|
24
34
|
playerId: 'local-player',
|
|
@@ -49,6 +59,7 @@ async function bootstrap(): Promise<void> {
|
|
|
49
59
|
context: {
|
|
50
60
|
platform,
|
|
51
61
|
runtime,
|
|
62
|
+
viewport,
|
|
52
63
|
player,
|
|
53
64
|
locale,
|
|
54
65
|
gameServices,
|
|
@@ -76,3 +87,41 @@ function renderBootstrapError(error: unknown, locale: Locale): void {
|
|
|
76
87
|
panel.textContent = `${t(locale, 'bootError')}: ${message}`;
|
|
77
88
|
root.append(panel);
|
|
78
89
|
}
|
|
90
|
+
|
|
91
|
+
function measureGameViewport(): {
|
|
92
|
+
readonly width: number;
|
|
93
|
+
readonly height: number;
|
|
94
|
+
readonly source: 'container' | 'visual-viewport' | 'window';
|
|
95
|
+
} {
|
|
96
|
+
const container = document.querySelector<HTMLElement>('#game');
|
|
97
|
+
const rect = container?.getBoundingClientRect();
|
|
98
|
+
|
|
99
|
+
if (rect !== undefined && rect.width > 0 && rect.height > 0) {
|
|
100
|
+
return {
|
|
101
|
+
width: rect.width,
|
|
102
|
+
height: rect.height,
|
|
103
|
+
source: 'container',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const visualViewport = window.visualViewport;
|
|
108
|
+
|
|
109
|
+
if (
|
|
110
|
+
visualViewport !== undefined &&
|
|
111
|
+
visualViewport !== null &&
|
|
112
|
+
visualViewport.width > 0 &&
|
|
113
|
+
visualViewport.height > 0
|
|
114
|
+
) {
|
|
115
|
+
return {
|
|
116
|
+
width: visualViewport.width,
|
|
117
|
+
height: visualViewport.height,
|
|
118
|
+
source: 'visual-viewport',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
width: window.innerWidth,
|
|
124
|
+
height: window.innerHeight,
|
|
125
|
+
source: 'window',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
@@ -71,7 +71,7 @@ export async function installPlatform(runtime: RuntimeConfig): Promise<TargetCon
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
const configTarget = targetConfigKeyForPlatform(runtime.target);
|
|
74
|
+
const configTarget = runtime.configTarget || targetConfigKeyForPlatform(runtime.target);
|
|
75
75
|
const targetConfig = getTargetConfig(targetConfigMatrix, configTarget);
|
|
76
76
|
const effectiveConfig = createEffectiveTargetConfig({
|
|
77
77
|
target: configTarget,
|
|
@@ -11,14 +11,18 @@ const validTargets = new Set<string>([
|
|
|
11
11
|
|
|
12
12
|
export interface RuntimeConfig {
|
|
13
13
|
readonly target: PlatformTarget;
|
|
14
|
+
readonly configTarget: string;
|
|
14
15
|
readonly appVersion: string;
|
|
15
16
|
readonly buildId: string;
|
|
16
17
|
readonly debug: boolean;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export function detectRuntime(): RuntimeConfig {
|
|
21
|
+
const target = normalizeTarget(__APP_TARGET__);
|
|
22
|
+
|
|
20
23
|
return {
|
|
21
|
-
target
|
|
24
|
+
target,
|
|
25
|
+
configTarget: normalizeConfigTarget(__MPGD_CONFIG_TARGET__, target),
|
|
22
26
|
appVersion: __APP_VERSION__,
|
|
23
27
|
buildId: __BUILD_ID__,
|
|
24
28
|
debug: __DEBUG_BUILD__,
|
|
@@ -28,3 +32,7 @@ export function detectRuntime(): RuntimeConfig {
|
|
|
28
32
|
export function normalizeTarget(value: string): PlatformTarget {
|
|
29
33
|
return validTargets.has(value) ? (value as PlatformTarget) : 'browser';
|
|
30
34
|
}
|
|
35
|
+
|
|
36
|
+
export function normalizeConfigTarget(value: string, target: PlatformTarget): string {
|
|
37
|
+
return value.length > 0 ? value : target === 'browser' ? 'web-preview' : target;
|
|
38
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { AnalyticsReporter, BufferedAnalyticsSink } from '@mpgd/analytics';
|
|
2
2
|
import type { Locale } from '@mpgd/i18n';
|
|
3
3
|
import type { PlayerIdentity } from '@mpgd/platform';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
TargetConfiguredGateway,
|
|
6
|
+
TargetRuntimeSnapshot,
|
|
7
|
+
TargetViewportPlan,
|
|
8
|
+
} from '@mpgd/target-config';
|
|
5
9
|
|
|
6
10
|
import type { StarterGameServices } from '../platform/gameServices';
|
|
7
11
|
|
|
@@ -10,6 +14,7 @@ export const starterContextKey = 'starterContext';
|
|
|
10
14
|
export interface StarterContext {
|
|
11
15
|
readonly platform: TargetConfiguredGateway;
|
|
12
16
|
readonly runtime: TargetRuntimeSnapshot;
|
|
17
|
+
readonly viewport: TargetViewportPlan;
|
|
13
18
|
readonly player: PlayerIdentity;
|
|
14
19
|
readonly locale: Locale;
|
|
15
20
|
readonly gameServices: StarterGameServices;
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import Phaser from 'phaser';
|
|
2
2
|
|
|
3
|
+
import { loadPhaserAssets } from '@mpgd/phaser-assets';
|
|
4
|
+
|
|
5
|
+
import { starterAssets } from '../assets/manifest';
|
|
6
|
+
|
|
3
7
|
export class BootScene extends Phaser.Scene {
|
|
4
8
|
constructor() {
|
|
5
9
|
super('BootScene');
|
|
6
10
|
}
|
|
7
11
|
|
|
12
|
+
preload(): void {
|
|
13
|
+
loadPhaserAssets(this, starterAssets);
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
create(): void {
|
|
9
17
|
this.scene.start('LobbyScene');
|
|
10
18
|
}
|
|
@@ -45,14 +45,30 @@ export class LobbyScene extends Phaser.Scene {
|
|
|
45
45
|
})
|
|
46
46
|
.setOrigin(0.5);
|
|
47
47
|
this.add
|
|
48
|
-
.text(
|
|
48
|
+
.text(
|
|
49
|
+
480,
|
|
50
|
+
258,
|
|
51
|
+
t(locale, 'viewport', {
|
|
52
|
+
sizeClass: context.viewport.layout.sizeClass,
|
|
53
|
+
orientation: context.viewport.layout.orientation,
|
|
54
|
+
controls: context.viewport.recommendation.primaryControls,
|
|
55
|
+
}),
|
|
56
|
+
{
|
|
57
|
+
color: '#d6dee8',
|
|
58
|
+
fontFamily: 'Arial, sans-serif',
|
|
59
|
+
fontSize: '18px',
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
.setOrigin(0.5);
|
|
63
|
+
this.add
|
|
64
|
+
.text(480, 300, t(locale, 'backend', { mode: context.gameServices.mode }), {
|
|
49
65
|
color: context.gameServices.mode === 'disabled' ? '#f59e0b' : '#2dd4bf',
|
|
50
66
|
fontFamily: 'Arial, sans-serif',
|
|
51
67
|
fontSize: '18px',
|
|
52
68
|
})
|
|
53
69
|
.setOrigin(0.5);
|
|
54
70
|
this.add
|
|
55
|
-
.text(480,
|
|
71
|
+
.text(480, 342, t(locale, 'tapToStart'), {
|
|
56
72
|
color: '#ffffff',
|
|
57
73
|
fontFamily: 'Arial, sans-serif',
|
|
58
74
|
fontSize: '22px',
|
|
@@ -2,6 +2,7 @@ import Phaser from 'phaser';
|
|
|
2
2
|
|
|
3
3
|
import type { LogicalAdPlacementId } from '@mpgd/platform';
|
|
4
4
|
|
|
5
|
+
import { starterAssetKeys } from '../assets/manifest';
|
|
5
6
|
import { createStarterRunState, stepStarterRunState, type StarterRunState } from '../game/state';
|
|
6
7
|
import { t } from '../i18n/messages';
|
|
7
8
|
import { starterContextKey, type StarterContext } from '../runtime/gameContext';
|
|
@@ -11,7 +12,7 @@ const rewardedPlacementId = 'CONTINUE_AFTER_FAIL' satisfies LogicalAdPlacementId
|
|
|
11
12
|
|
|
12
13
|
export class PlayScene extends Phaser.Scene {
|
|
13
14
|
private state: StarterRunState = createStarterRunState();
|
|
14
|
-
private marker!: Phaser.GameObjects.
|
|
15
|
+
private marker!: Phaser.GameObjects.Image;
|
|
15
16
|
private scoreText!: Phaser.GameObjects.Text;
|
|
16
17
|
private rewardText!: Phaser.GameObjects.Text;
|
|
17
18
|
private analyticsText!: Phaser.GameObjects.Text;
|
|
@@ -26,7 +27,7 @@ export class PlayScene extends Phaser.Scene {
|
|
|
26
27
|
create(): void {
|
|
27
28
|
this.context = this.registry.get(starterContextKey) as StarterContext;
|
|
28
29
|
|
|
29
|
-
this.marker = this.add.
|
|
30
|
+
this.marker = this.add.image(480, 250, starterAssetKeys.marker).setDisplaySize(72, 72);
|
|
30
31
|
this.scoreText = this.add
|
|
31
32
|
.text(480, 86, '', {
|
|
32
33
|
color: '#ffffff',
|
|
@@ -1,20 +1,43 @@
|
|
|
1
1
|
html,
|
|
2
|
-
body
|
|
3
|
-
#game {
|
|
2
|
+
body {
|
|
4
3
|
width: 100%;
|
|
5
4
|
height: 100%;
|
|
6
5
|
margin: 0;
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
body {
|
|
9
|
+
display: grid;
|
|
10
|
+
place-items: center;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
min-width: 0;
|
|
13
|
+
min-height: 100dvh;
|
|
10
14
|
overflow: hidden;
|
|
15
|
+
padding:
|
|
16
|
+
env(safe-area-inset-top)
|
|
17
|
+
env(safe-area-inset-right)
|
|
18
|
+
env(safe-area-inset-bottom)
|
|
19
|
+
env(safe-area-inset-left);
|
|
11
20
|
background: #07111f;
|
|
12
21
|
color: #ffffff;
|
|
13
22
|
font-family: Arial, sans-serif;
|
|
14
23
|
}
|
|
15
24
|
|
|
25
|
+
#game {
|
|
26
|
+
--mpgd-game-max-height: calc(
|
|
27
|
+
100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
width: min(100%, 960px, calc(var(--mpgd-game-max-height) * 16 / 9));
|
|
32
|
+
aspect-ratio: 16 / 9;
|
|
33
|
+
min-width: 0;
|
|
34
|
+
min-height: 0;
|
|
35
|
+
touch-action: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
16
38
|
canvas {
|
|
17
39
|
display: block;
|
|
40
|
+
touch-action: none;
|
|
18
41
|
}
|
|
19
42
|
|
|
20
43
|
.boot-error {
|
|
@@ -5,6 +5,7 @@ export default defineConfig(({ mode }) => {
|
|
|
5
5
|
const isProduction = mode === 'production';
|
|
6
6
|
|
|
7
7
|
return {
|
|
8
|
+
base: './',
|
|
8
9
|
plugins: [
|
|
9
10
|
ttsc({
|
|
10
11
|
project: 'tsconfig.json',
|
|
@@ -13,6 +14,7 @@ export default defineConfig(({ mode }) => {
|
|
|
13
14
|
],
|
|
14
15
|
define: {
|
|
15
16
|
__APP_TARGET__: JSON.stringify(process.env.APP_TARGET ?? 'browser'),
|
|
17
|
+
__MPGD_CONFIG_TARGET__: JSON.stringify(process.env.MPGD_CONFIG_TARGET ?? ''),
|
|
16
18
|
__APP_VERSION__: JSON.stringify(process.env.APP_VERSION ?? '0.0.0-dev'),
|
|
17
19
|
__BUILD_ID__: JSON.stringify(process.env.BUILD_ID ?? 'local'),
|
|
18
20
|
__DEBUG_BUILD__: JSON.stringify(!isProduction),
|