create-playcanvas 0.5.0 → 0.6.0

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.
Files changed (109) hide show
  1. package/README.md +20 -27
  2. package/dist/index.mjs +44 -42
  3. package/package.json +1 -1
  4. package/templates/_features/physics/assets/public/ammo/LICENSE +21 -0
  5. package/templates/_features/physics/assets/public/ammo/SOURCE.md +16 -0
  6. package/templates/_features/physics/assets/public/ammo/ammo.js +973 -0
  7. package/templates/_features/physics/assets/public/ammo/ammo.wasm.js +937 -0
  8. package/templates/_features/physics/assets/public/ammo/ammo.wasm.wasm +0 -0
  9. package/templates/_features/physics/react/package.json +5 -0
  10. package/templates/_features/physics/react/src/sync-ammo.d.ts +4 -0
  11. package/templates/_shared/ar-placement/README.md +7 -0
  12. package/templates/_shared/ar-placement/src/ar-placement.ts +123 -0
  13. package/templates/_shared/first-person-controller/README.md +7 -0
  14. package/templates/_shared/first-person-controller/src/controller.ts +18 -0
  15. package/templates/_shared/first-person-controller/src/scripts.d.ts +5 -0
  16. package/templates/_shared/interactive-sphere/README.md +7 -0
  17. package/templates/_shared/model-viewer/README.md +7 -0
  18. package/templates/_shared/physics-playground/README.md +7 -0
  19. package/templates/_shared/product-configurator/ASSET_LICENSES.md +3 -0
  20. package/templates/_shared/product-configurator/README.md +7 -0
  21. package/templates/_shared/product-configurator/src/product.css +14 -0
  22. package/templates/_shared/scene-editor/README.md +7 -0
  23. package/templates/_shared/scene-editor/src/scene-editor.ts +57 -0
  24. package/templates/_shared/spinning-cube/README.md +7 -0
  25. package/templates/_shared/splat-viewer/README.md +7 -0
  26. package/templates/_shared/sprite-game/README.md +7 -0
  27. package/templates/_shared/sprite-game/src/sprite-game.ts +197 -0
  28. package/templates/_shared/third-person-controller/README.md +7 -0
  29. package/templates/_shared/third-person-controller/src/controller.ts +53 -0
  30. package/templates/_shared/third-person-controller/src/scripts.d.ts +5 -0
  31. package/templates/_shared/vr-starter/README.md +7 -0
  32. package/templates/_shared/vr-starter/src/vr.ts +40 -0
  33. package/templates/_shared/vr-starter/src/xr.d.ts +11 -0
  34. package/templates/engine/ar-placement/src/main.ts +77 -0
  35. package/templates/engine/base/.prettierignore +1 -0
  36. package/templates/engine/base/README.md +1 -1
  37. package/templates/engine/base/_npmrc +1 -0
  38. package/templates/engine/base/eslint.config.mjs +1 -1
  39. package/templates/engine/base/index.html +13 -0
  40. package/templates/engine/base/package.json +2 -2
  41. package/templates/engine/base/src/starter.css +104 -0
  42. package/templates/engine/first-person-controller/src/main.ts +139 -0
  43. package/templates/engine/interactive-sphere/src/App.ts +9 -7
  44. package/templates/engine/interactive-sphere/src/main.ts +2 -29
  45. package/templates/engine/interactive-sphere/src/style.css +18 -97
  46. package/templates/engine/model-viewer/src/main.ts +3 -2
  47. package/templates/engine/physics-playground/src/main.ts +132 -0
  48. package/templates/engine/product-configurator/src/main.ts +156 -0
  49. package/templates/engine/scene-editor/src/main.ts +90 -0
  50. package/templates/engine/splat-viewer/src/main.ts +4 -3
  51. package/templates/engine/sprite-game/src/main.ts +72 -0
  52. package/templates/engine/third-person-controller/src/main.ts +216 -0
  53. package/templates/engine/vr-starter/src/main.ts +101 -0
  54. package/templates/index.ts +66 -5
  55. package/templates/react/ar-placement/src/App.tsx +58 -0
  56. package/templates/react/base/.prettierignore +1 -0
  57. package/templates/react/base/README.md +1 -1
  58. package/templates/react/base/_npmrc +1 -0
  59. package/templates/react/base/eslint.config.mjs +1 -1
  60. package/templates/react/base/index.html +13 -0
  61. package/templates/react/base/package.json +2 -2
  62. package/templates/react/base/src/main.tsx +10 -0
  63. package/templates/react/base/src/starter.css +104 -0
  64. package/templates/react/first-person-controller/src/App.tsx +115 -0
  65. package/templates/react/interactive-sphere/src/App.css +18 -68
  66. package/templates/react/interactive-sphere/src/App.tsx +1 -22
  67. package/templates/react/interactive-sphere/src/Scene.tsx +7 -6
  68. package/templates/react/interactive-sphere/src/index.css +1 -48
  69. package/templates/react/model-viewer/src/App.tsx +2 -2
  70. package/templates/react/physics-playground/src/App.tsx +85 -0
  71. package/templates/react/product-configurator/src/App.tsx +157 -0
  72. package/templates/react/scene-editor/src/App.tsx +84 -0
  73. package/templates/react/splat-viewer/src/App.tsx +3 -3
  74. package/templates/react/sprite-game/src/App.tsx +38 -0
  75. package/templates/react/third-person-controller/src/App.tsx +193 -0
  76. package/templates/react/vr-starter/src/App.tsx +99 -0
  77. package/templates/web-components/ar-placement/index.html +44 -0
  78. package/templates/web-components/ar-placement/src/main.ts +13 -0
  79. package/templates/web-components/base/.prettierignore +1 -0
  80. package/templates/web-components/base/README.md +1 -1
  81. package/templates/web-components/base/_npmrc +1 -0
  82. package/templates/web-components/base/eslint.config.mjs +1 -1
  83. package/templates/web-components/base/package.json +3 -3
  84. package/templates/web-components/base/src/starter.css +104 -0
  85. package/templates/web-components/first-person-controller/index.html +168 -0
  86. package/templates/web-components/first-person-controller/src/main.ts +15 -0
  87. package/templates/web-components/interactive-sphere/index.html +5 -22
  88. package/templates/web-components/interactive-sphere/src/main.ts +5 -4
  89. package/templates/web-components/interactive-sphere/src/style.css +18 -76
  90. package/templates/web-components/model-viewer/index.html +1 -1
  91. package/templates/web-components/model-viewer/src/main.ts +2 -1
  92. package/templates/web-components/physics-playground/index.html +51 -0
  93. package/templates/web-components/physics-playground/src/main.ts +32 -0
  94. package/templates/web-components/product-configurator/index.html +51 -0
  95. package/templates/web-components/product-configurator/src/main.ts +93 -0
  96. package/templates/web-components/scene-editor/index.html +51 -0
  97. package/templates/web-components/scene-editor/src/main.ts +26 -0
  98. package/templates/web-components/spinning-cube/src/main.ts +1 -0
  99. package/templates/web-components/splat-viewer/index.html +2 -2
  100. package/templates/web-components/splat-viewer/src/main.ts +2 -1
  101. package/templates/web-components/sprite-game/index.html +34 -0
  102. package/templates/web-components/sprite-game/src/main.ts +9 -0
  103. package/templates/web-components/third-person-controller/index.html +183 -0
  104. package/templates/web-components/third-person-controller/src/main.ts +16 -0
  105. package/templates/web-components/vr-starter/index.html +80 -0
  106. package/templates/web-components/vr-starter/src/main.ts +12 -0
  107. package/templates/engine/interactive-sphere/src/assets/typescript.svg +0 -1
  108. package/templates/react/interactive-sphere/src/assets/react.svg +0 -1
  109. package/templates/web-components/interactive-sphere/src/assets/typescript.svg +0 -1
@@ -0,0 +1,77 @@
1
+ import {
2
+ AppBase,
3
+ AppOptions,
4
+ CameraComponentSystem,
5
+ Color,
6
+ Entity,
7
+ FILLMODE_FILL_WINDOW,
8
+ LightComponentSystem,
9
+ RenderComponentSystem,
10
+ RESOLUTION_AUTO,
11
+ ScriptComponentSystem,
12
+ StandardMaterial,
13
+ XrManager,
14
+ createGraphicsDevice
15
+ } from 'playcanvas';
16
+
17
+ import { ArPlacement } from './ar-placement';
18
+ import './starter.css';
19
+
20
+ document.body.insertAdjacentHTML(
21
+ 'beforeend',
22
+ '<div class="hud"><section class="panel"><h1>AR Placement</h1><p id="xr-status">Checking AR support…</p><div class="controls"><button id="xr-button" disabled>Start AR</button></div></section></div>'
23
+ );
24
+
25
+ const canvas = document.getElementById('application-canvas') as HTMLCanvasElement;
26
+ const device = await createGraphicsDevice(canvas);
27
+ const options = new AppOptions();
28
+ options.graphicsDevice = device;
29
+ options.componentSystems = [RenderComponentSystem, CameraComponentSystem, LightComponentSystem, ScriptComponentSystem];
30
+ options.xr = XrManager;
31
+
32
+ const app = new AppBase(canvas);
33
+ app.init(options);
34
+ app.start();
35
+ app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
36
+ app.setCanvasResolution(RESOLUTION_AUTO);
37
+
38
+ const camera = new Entity('camera');
39
+ camera.addComponent('camera', { clearColor: new Color(0.05, 0.08, 0.12, 1) });
40
+ camera.setPosition(3, 2.4, 4);
41
+ camera.lookAt(0, 0.5, 0);
42
+ app.root.addChild(camera);
43
+
44
+ const light = new Entity('light');
45
+ light.addComponent('light', { type: 'directional', intensity: 2 });
46
+ light.setEulerAngles(45, 30, 0);
47
+ app.root.addChild(light);
48
+
49
+ const material = (color: Color) => {
50
+ const value = new StandardMaterial();
51
+ value.diffuse = color;
52
+ value.update();
53
+ return value;
54
+ };
55
+ const surface = material(new Color(0.28, 0.3, 0.34));
56
+ const cyan = material(new Color(0.1, 0.7, 0.9));
57
+ const coral = material(new Color(1, 0.35, 0.15));
58
+ const preview = new Entity('preview');
59
+ for (const [name, type, position, scale, value] of [
60
+ ['surface', 'cylinder', [0, 0, 0], [4, 0.15, 4], surface],
61
+ ['box', 'box', [0, 0.65, 0], [1, 1, 1], cyan],
62
+ ['reticle', 'cylinder', [0, 0.12, 0], [1.5, 0.03, 1.5], coral]
63
+ ] as const) {
64
+ const entity = new Entity(name);
65
+ entity.addComponent('render', { type, material: value });
66
+ entity.setLocalPosition(position[0], position[1], position[2]);
67
+ entity.setLocalScale(scale[0], scale[1], scale[2]);
68
+ preview.addChild(entity);
69
+ }
70
+ app.root.addChild(preview);
71
+
72
+ const placement = new Entity('placement');
73
+ placement.addComponent('script');
74
+ placement.script!.create(ArPlacement, { properties: { camera, preview } });
75
+ app.root.addChild(placement);
76
+
77
+ window.addEventListener('resize', () => app.resizeCanvas());
@@ -1,2 +1,3 @@
1
1
  .claude
2
2
  .agents
3
+ public/ammo
@@ -9,7 +9,7 @@ Node.js 22.23.2 or later.
9
9
  ## Getting started
10
10
 
11
11
  ```bash
12
- npm create playcanvas@latest playcanvas-project -- --template engine
12
+ npm create playcanvas@latest playcanvas-project -- --format engine
13
13
  cd playcanvas-project
14
14
  npm install
15
15
  npm run dev
@@ -0,0 +1 @@
1
+ registry=https://registry.npmjs.org/
@@ -1,3 +1,3 @@
1
1
  import typescriptConfig from '@playcanvas/eslint-config/typescript';
2
2
 
3
- export default [{ ignores: ['.claude', '.agents'] }, ...typescriptConfig];
3
+ export default [{ ignores: ['.claude', '.agents', 'public/ammo'] }, ...typescriptConfig];
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>PlayCanvas Starter</title>
8
+ </head>
9
+ <body>
10
+ <canvas id="application-canvas"></canvas>
11
+ <script type="module" src="/src/main.ts"></script>
12
+ </body>
13
+ </html>
@@ -15,14 +15,14 @@
15
15
  "typecheck": "tsc --noEmit"
16
16
  },
17
17
  "dependencies": {
18
- "playcanvas": "^2.21.3"
18
+ "playcanvas": "^2.21.4"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@playcanvas/eslint-config": "3.0.0-beta.8",
22
22
  "eslint": "^9.39.5",
23
23
  "prettier": "^3.9.6",
24
24
  "typescript": "~6.0.3",
25
- "vite": "^8.2.0"
25
+ "vite": "^8.2.1"
26
26
  },
27
27
  "engines": {
28
28
  "node": ">=22.23.2"
@@ -0,0 +1,104 @@
1
+ * {
2
+ box-sizing: border-box;
3
+ }
4
+
5
+ html,
6
+ body,
7
+ #root,
8
+ #application,
9
+ pc-app,
10
+ canvas {
11
+ width: 100%;
12
+ height: 100%;
13
+ margin: 0;
14
+ overflow: hidden;
15
+ }
16
+
17
+ body {
18
+ background: #11151c;
19
+ color: #f8fafc;
20
+ font-family: Inter, ui-sans-serif, system-ui, sans-serif;
21
+ }
22
+
23
+ canvas,
24
+ pc-app {
25
+ display: block;
26
+ }
27
+
28
+ .hud {
29
+ position: fixed;
30
+ inset: 0;
31
+ z-index: 10;
32
+ padding: 20px;
33
+ pointer-events: none;
34
+ }
35
+
36
+ .panel {
37
+ width: min(360px, calc(100vw - 40px));
38
+ padding: 16px;
39
+ border: 1px solid #ffffff24;
40
+ border-radius: 14px;
41
+ background: #0b1019d9;
42
+ box-shadow: 0 12px 40px #0008;
43
+ backdrop-filter: blur(12px);
44
+ pointer-events: auto;
45
+ }
46
+
47
+ h1 {
48
+ margin: 0 0 6px;
49
+ font-size: 18px;
50
+ }
51
+
52
+ p {
53
+ margin: 6px 0 0;
54
+ color: #aeb8c8;
55
+ font-size: 13px;
56
+ line-height: 1.45;
57
+ }
58
+
59
+ .controls {
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: 8px;
63
+ margin-top: 14px;
64
+ }
65
+
66
+ button {
67
+ padding: 8px 11px;
68
+ border: 1px solid #ffffff24;
69
+ border-radius: 9px;
70
+ background: #263247;
71
+ color: inherit;
72
+ cursor: pointer;
73
+ }
74
+
75
+ button:hover,
76
+ button[aria-pressed='true'] {
77
+ border-color: #41b6e6;
78
+ background: #334867;
79
+ }
80
+
81
+ button:disabled {
82
+ cursor: not-allowed;
83
+ opacity: 0.5;
84
+ }
85
+
86
+ .swatch {
87
+ width: 32px;
88
+ height: 32px;
89
+ padding: 0;
90
+ border-radius: 50%;
91
+ background: var(--color);
92
+ }
93
+
94
+ .crosshair {
95
+ position: fixed;
96
+ top: 50%;
97
+ left: 50%;
98
+ width: 16px;
99
+ height: 16px;
100
+ border: 2px solid #fff;
101
+ border-radius: 50%;
102
+ translate: -50% -50%;
103
+ box-shadow: 0 0 4px #000;
104
+ }
@@ -0,0 +1,139 @@
1
+ import {
2
+ AppBase,
3
+ AppOptions,
4
+ CameraComponentSystem,
5
+ CollisionComponentSystem,
6
+ Color,
7
+ Entity,
8
+ FILLMODE_FILL_WINDOW,
9
+ LightComponentSystem,
10
+ RenderComponentSystem,
11
+ RESOLUTION_AUTO,
12
+ RigidBodyComponentSystem,
13
+ ScriptComponentSystem,
14
+ StandardMaterial,
15
+ Vec3,
16
+ WasmModule,
17
+ createGraphicsDevice
18
+ } from 'playcanvas';
19
+
20
+ import { addFirstPersonController } from './controller';
21
+ import './starter.css';
22
+
23
+ WasmModule.setConfig('Ammo', {
24
+ glueUrl: '/ammo/ammo.wasm.js',
25
+ wasmUrl: '/ammo/ammo.wasm.wasm',
26
+ fallbackUrl: '/ammo/ammo.js'
27
+ });
28
+ await new Promise<void>((resolve) => {
29
+ WasmModule.getInstance('Ammo', () => resolve());
30
+ });
31
+
32
+ document.body.insertAdjacentHTML(
33
+ 'beforeend',
34
+ '<div class="hud"><section class="panel"><h1>First-Person Controller</h1><p>Click the scene, then use WASD, mouse look and Space to jump.</p></section></div>'
35
+ );
36
+
37
+ const canvas = document.getElementById('application-canvas') as HTMLCanvasElement;
38
+ const device = await createGraphicsDevice(canvas);
39
+ const options = new AppOptions();
40
+ options.graphicsDevice = device;
41
+ options.componentSystems = [
42
+ RenderComponentSystem,
43
+ CameraComponentSystem,
44
+ LightComponentSystem,
45
+ ScriptComponentSystem,
46
+ CollisionComponentSystem,
47
+ RigidBodyComponentSystem
48
+ ];
49
+
50
+ const app = new AppBase(canvas);
51
+ app.init(options);
52
+ app.start();
53
+ app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
54
+ app.setCanvasResolution(RESOLUTION_AUTO);
55
+
56
+ const material = (color: Color) => {
57
+ const result = new StandardMaterial();
58
+ result.diffuse = color;
59
+ result.emissive = new Color(color.r * 0.2, color.g * 0.2, color.b * 0.2);
60
+ result.update();
61
+ return result;
62
+ };
63
+
64
+ const floor = material(new Color(0.28, 0.3, 0.32));
65
+ const wall = material(new Color(0.42, 0.45, 0.48));
66
+ const blue = material(new Color(0.08, 0.29, 0.48));
67
+ const green = material(new Color(0.18, 0.4, 0.22));
68
+ const wood = material(new Color(0.48, 0.27, 0.1));
69
+ const metal = material(new Color(0.28, 0.33, 0.38));
70
+
71
+ const block = (
72
+ name: string,
73
+ position: [number, number, number],
74
+ scale: [number, number, number],
75
+ blockMaterial: StandardMaterial
76
+ ) => {
77
+ const entity = new Entity(name);
78
+ entity.setPosition(...position);
79
+ entity.setLocalScale(...scale);
80
+ entity.addComponent('render', { type: 'box', material: blockMaterial });
81
+ entity.addComponent('collision', {
82
+ type: 'box',
83
+ halfExtents: new Vec3(scale[0] / 2, scale[1] / 2, scale[2] / 2)
84
+ });
85
+ entity.addComponent('rigidbody', { type: 'static' });
86
+ app.root.addChild(entity);
87
+ };
88
+
89
+ block('floor', [0, -0.1, 0], [18, 0.2, 18], floor);
90
+ block('back-wall', [0, 1.5, -9], [18, 3, 0.3], wall);
91
+ block('front-wall', [0, 1.5, 9], [18, 3, 0.3], wall);
92
+ block('left-wall', [-9, 1.5, 0], [0.3, 3, 18], wall);
93
+ block('right-wall', [9, 1.5, 0], [0.3, 3, 18], wall);
94
+ block('blue-crate', [-2, 0.75, -3], [1.5, 1.5, 1.5], blue);
95
+ block('green-crate', [3, 0.5, 1], [2.5, 1, 1], green);
96
+ block('cargo-left-0', [-5.5, 0.75, -5.5], [2, 1.5, 2], wood);
97
+ block('cargo-left-1', [-5.5, 2, -5.5], [1.5, 1, 1.5], blue);
98
+ block('cargo-right-0', [5.3, 0.6, -4.8], [2.4, 1.2, 2], green);
99
+ block('cargo-right-1', [5.3, 1.7, -4.8], [1.5, 1, 1.5], wood);
100
+ block('cargo-center', [0, 0.6, -6.5], [2.2, 1.2, 1.8], blue);
101
+ for (const [i, z] of [-3.5, 0, 3.5].entries()) {
102
+ block(`shelf-left-post-${i}`, [-6.8, 1.4, z], [0.25, 2.8, 0.25], metal);
103
+ block(`shelf-right-post-${i}`, [6.8, 1.4, z], [0.25, 2.8, 0.25], metal);
104
+ }
105
+ block('shelf-left-low', [-6.8, 0.65, 0], [1.1, 0.18, 7.5], metal);
106
+ block('shelf-left-high', [-6.8, 2.1, 0], [1.1, 0.18, 7.5], metal);
107
+ block('shelf-right-low', [6.8, 0.65, 0], [1.1, 0.18, 7.5], metal);
108
+ block('shelf-right-high', [6.8, 2.1, 0], [1.1, 0.18, 7.5], metal);
109
+ block('pallet', [-2.5, 0.15, 2.5], [3, 0.3, 2], wood);
110
+
111
+ const player = new Entity('player');
112
+ player.setPosition(0, 1, 5);
113
+ player.addComponent('collision', { type: 'capsule', radius: 0.45, height: 1.8 });
114
+ player.addComponent('rigidbody', { type: 'dynamic', mass: 80, angularFactor: Vec3.ZERO });
115
+ app.root.addChild(player);
116
+
117
+ const camera = new Entity('camera');
118
+ camera.addComponent('camera', { clearColor: new Color(0.38, 0.64, 0.86), fov: 80 });
119
+ camera.setLocalPosition(0, 0.65, 0);
120
+ player.addChild(camera);
121
+ addFirstPersonController(player, camera);
122
+
123
+ const light = new Entity('light');
124
+ light.addComponent('light', {
125
+ type: 'directional',
126
+ intensity: 2.5,
127
+ castShadows: true,
128
+ shadowBias: 0.2,
129
+ normalOffsetBias: 0.05
130
+ });
131
+ light.setEulerAngles(50, 30, 0);
132
+ app.root.addChild(light);
133
+
134
+ const fill = new Entity('fill');
135
+ fill.addComponent('light', { type: 'directional', intensity: 0.8 });
136
+ fill.setEulerAngles(-25, -140, 0);
137
+ app.root.addChild(fill);
138
+
139
+ window.addEventListener('resize', () => app.resizeCanvas());
@@ -28,8 +28,8 @@ import { Grid } from 'playcanvas/scripts/esm/grid.mjs';
28
28
 
29
29
  import { throttle } from './utils';
30
30
 
31
- const HOVER_COLOR = new Color(1, 0.647, 0);
32
- const DEFAULT_COLOR = new Color(0.827, 0.827, 0.827);
31
+ const HOVER_COLOR = new Color(0.25, 0.8, 1);
32
+ const DEFAULT_COLOR = new Color(0.9, 0.93, 0.98);
33
33
 
34
34
  // Assets to load
35
35
  const assets = {
@@ -97,7 +97,8 @@ const setupApp = async (canvas: HTMLCanvasElement, onClick: () => void) => {
97
97
 
98
98
  // Create sphere entity
99
99
  const sphere = new Entity('sphere');
100
- sphere.setPosition(new Vec3(0, 0.5, 0));
100
+ sphere.setPosition(new Vec3(0, 0.7, 0));
101
+ sphere.setLocalScale(1.25, 1.25, 1.25);
101
102
 
102
103
  // Create a new material
103
104
  const material = new StandardMaterial();
@@ -113,20 +114,21 @@ const setupApp = async (canvas: HTMLCanvasElement, onClick: () => void) => {
113
114
  // Create camera entity
114
115
  const camera = new Entity('camera');
115
116
  camera.addComponent('camera', {
116
- clearColor: new Color(0.09, 0.09, 0.09)
117
+ clearColor: new Color(0.025, 0.04, 0.065)
117
118
  });
118
- camera.setPosition(new Vec3(4, 1, 4));
119
+ camera.setPosition(new Vec3(3.2, 1.5, 3.2));
120
+ camera.lookAt(0, 0.7, 0);
119
121
  app.root.addChild(camera);
120
122
 
121
123
  // Create camera controls
122
124
  camera.addComponent('script');
123
- camera.script?.create(CameraControls);
125
+ camera.script?.create(CameraControls, { properties: { sceneSize: 3 } });
124
126
 
125
127
  // Create grid entity
126
128
  const grid = new Entity('grid');
127
129
  grid.addComponent('script');
128
130
  grid.script?.create(Grid);
129
- grid.setLocalScale(1000, 1000, 1000);
131
+ grid.setLocalScale(12, 12, 12);
130
132
  app.root.addChild(grid);
131
133
 
132
134
  // Create a picker for mouse interaction
@@ -1,45 +1,18 @@
1
1
  import './style.css';
2
2
  import { setupApp } from './App';
3
- import playcanvasLogo from './assets/playcanvas.png';
4
- import typescriptLogo from './assets/typescript.svg';
5
3
 
6
4
  let count = 0;
7
5
 
8
6
  document.querySelector<HTMLDivElement>('#root')!.innerHTML = `
9
- <div>
10
7
  <canvas id="application-canvas"></canvas>
11
- <div class="absolute overlay">
12
- <div class="grow">
13
- <header>
14
- <h1>PlayCanvas + TypeScript</h1>
15
- <a href="https://developer.playcanvas.com" target="_blank">
16
- <img src="${playcanvasLogo}" class="playcanvas-logo logo" alt="PlayCanvas logo" />
17
- </a>
18
- <a href="https://www.typescriptlang.org/" target="_blank">
19
- <img src="${typescriptLogo}" class="logo typescript" alt="TypeScript logo" />
20
- </a>
21
- </header>
22
- </div>
23
- <div>
24
- <span id="counter" class="pill">
25
- Click Count: ${count}
26
- </span>
27
- <p>
28
- Edit <code>src/App.ts</code> and save to test HMR
29
- </p>
30
- </div>
31
- <p class="read-the-docs">
32
- Click on the PlayCanvas and TypeScript logos to learn more
33
- </p>
34
- </div>
35
- </div>
8
+ <p id="counter" class="counter">Click count: ${count}</p>
36
9
  `;
37
10
 
38
11
  const counterElement = document.getElementById('counter')!;
39
12
 
40
13
  const increment = () => {
41
14
  count++;
42
- counterElement.textContent = `Click Count: ${count}`;
15
+ counterElement.textContent = `Click count: ${count}`;
43
16
  };
44
17
 
45
18
  setupApp(document.getElementById('application-canvas') as HTMLCanvasElement, increment);
@@ -1,107 +1,28 @@
1
- :root {
2
- font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
3
- line-height: 1.5;
4
- font-weight: 400;
5
-
6
- color-scheme: light dark;
7
- color: rgba(255, 255, 255, 0.87);
8
- background-color: #242424;
9
-
10
- font-synthesis: none;
11
- text-rendering: optimizeLegibility;
12
- -webkit-font-smoothing: antialiased;
13
- -moz-osx-font-smoothing: grayscale;
14
- }
15
-
16
- header {
17
- display: flex;
18
- flex-direction: row;
19
- align-items: center;
20
- padding: 2rem;
21
- }
22
-
23
- a {
24
- font-weight: 500;
25
- color: #646cff;
26
- pointer-events: auto;
27
- text-decoration: inherit;
28
- }
29
- a:hover {
30
- color: #535bf2;
31
- }
32
-
33
1
  body {
34
- width: 100%;
35
- height: 100%;
36
- padding: 0;
37
2
  margin: 0;
38
3
  overflow: hidden;
4
+ font-family: Inter, ui-sans-serif, system-ui, sans-serif;
39
5
  }
40
6
 
41
- h1 {
42
- font-size: 2.4em;
43
- line-height: 1.1;
44
- opacity: 0.85;
45
- }
46
-
47
- .logo {
48
- height: 2em;
49
- padding: 0.5em;
50
- will-change: filter;
51
- transition: filter 300ms;
52
- }
53
-
54
- .playcanvas-logo {
55
- border-radius: 100%;
56
- }
57
-
58
- .logo:hover {
59
- filter: drop-shadow(0 0 2em #646cffaa);
60
- }
61
-
62
- .logo.typescript:hover {
63
- filter: drop-shadow(0 0 2em #3178c6aa);
64
- }
65
-
66
- .read-the-docs {
67
- color: #888;
68
- }
69
-
70
- @media (prefers-color-scheme: light) {
71
- :root {
72
- color: #213547;
73
- background-color: #ffffff;
74
- }
75
- a:hover {
76
- color: #747bff;
77
- }
78
- }
79
-
80
- .overlay {
81
- margin: 0 auto;
82
- text-align: center;
83
- display: flex;
84
- flex-direction: column;
85
- align-items: center;
86
- justify-content: stretch;
7
+ canvas {
8
+ display: block;
87
9
  width: 100vw;
88
10
  height: 100vh;
89
- pointer-events: none;
90
- }
91
-
92
- .overlay > .grow {
93
- flex-grow: 1;
94
11
  }
95
12
 
96
- .absolute {
97
- position: absolute;
98
- top: 0;
99
- left: 0;
100
- }
101
-
102
- .pill {
103
- background-color: #000;
104
- color: #fff;
105
- padding: 0.5rem 1rem;
106
- border-radius: 0.5rem;
13
+ .counter {
14
+ position: fixed;
15
+ bottom: 22px;
16
+ left: 50%;
17
+ z-index: 2;
18
+ margin: 0;
19
+ padding: 9px 13px;
20
+ border: 1px solid #ffffff24;
21
+ border-radius: 999px;
22
+ background: #07101bd9;
23
+ color: #f8fafc;
24
+ font-size: 12px;
25
+ font-weight: 650;
26
+ translate: -50% 0;
27
+ backdrop-filter: blur(10px);
107
28
  }
@@ -75,7 +75,8 @@ const camera = new Entity('camera');
75
75
  camera.addComponent('camera', {
76
76
  toneMapping: TONEMAP_ACES2
77
77
  });
78
- camera.setPosition(0, 0, 3);
78
+ camera.setPosition(2.6, 1.5, 3.2);
79
+ camera.lookAt(0, 0, 0);
79
80
  camera.addComponent('script');
80
- camera.script?.create(CameraControls);
81
+ camera.script?.create(CameraControls, { properties: { sceneSize: 2.5 } });
81
82
  app.root.addChild(camera);