create-playcanvas 0.16.0 → 0.17.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 (62) hide show
  1. package/README.md +16 -16
  2. package/dist/index.mjs +20 -20
  3. package/package.json +2 -2
  4. package/templates/_shared/{ar-placement → ar}/README.md +1 -1
  5. package/templates/_shared/blank/README.md +7 -0
  6. package/templates/_shared/first-person-game/AGENTS.md +11 -0
  7. package/templates/_shared/first-person-game/README.md +21 -0
  8. package/templates/_shared/first-person-game/public/level.glb +0 -0
  9. package/templates/_shared/first-person-game/src/game.css +47 -0
  10. package/templates/_shared/first-person-game/src/game.ts +232 -0
  11. package/templates/_shared/{sprite-game → platformer}/README.md +1 -1
  12. package/templates/_shared/{sprite-game/src/sprite-game.ts → platformer/src/platformer.ts} +3 -3
  13. package/templates/_shared/{third-person-controller → third-person-game}/README.md +1 -1
  14. package/templates/_shared/{vr-starter → vr}/README.md +1 -1
  15. package/templates/engine/ar/index.html +20 -0
  16. package/templates/engine/{ar-placement → ar}/src/main.ts +22 -12
  17. package/templates/engine/base/package.json +2 -2
  18. package/templates/engine/first-person-game/index.html +26 -0
  19. package/templates/engine/first-person-game/src/main.ts +167 -0
  20. package/templates/engine/platformer/index.html +19 -0
  21. package/templates/engine/{sprite-game → platformer}/src/main.ts +21 -13
  22. package/templates/engine/product-configurator/index.html +30 -0
  23. package/templates/engine/product-configurator/src/main.ts +33 -32
  24. package/templates/engine/third-person-game/index.html +19 -0
  25. package/templates/engine/{third-person-controller → third-person-game}/src/main.ts +16 -11
  26. package/templates/engine/vr/index.html +20 -0
  27. package/templates/engine/{vr-starter → vr}/src/main.ts +22 -12
  28. package/templates/index.ts +14 -14
  29. package/templates/react/{ar-placement → ar}/src/App.tsx +1 -1
  30. package/templates/react/base/package.json +2 -2
  31. package/templates/react/first-person-game/src/App.tsx +140 -0
  32. package/templates/react/{sprite-game → platformer}/src/App.tsx +3 -3
  33. package/templates/react/{third-person-controller → third-person-game}/src/App.tsx +1 -1
  34. package/templates/react/{vr-starter → vr}/src/App.tsx +1 -1
  35. package/templates/web-components/{ar-placement → ar}/index.html +2 -2
  36. package/templates/web-components/base/package.json +2 -2
  37. package/templates/web-components/first-person-game/index.html +80 -0
  38. package/templates/web-components/first-person-game/src/main.ts +74 -0
  39. package/templates/web-components/{sprite-game → platformer}/index.html +2 -2
  40. package/templates/web-components/{sprite-game → platformer}/src/main.ts +2 -2
  41. package/templates/web-components/{third-person-controller → third-person-game}/index.html +2 -2
  42. package/templates/web-components/{vr-starter → vr}/index.html +2 -2
  43. package/templates/_shared/first-person-controller/README.md +0 -7
  44. package/templates/_shared/first-person-controller/src/controller.ts +0 -18
  45. package/templates/_shared/spinning-cube/README.md +0 -7
  46. package/templates/engine/first-person-controller/src/main.ts +0 -138
  47. package/templates/react/first-person-controller/src/App.tsx +0 -115
  48. package/templates/web-components/first-person-controller/index.html +0 -163
  49. package/templates/web-components/first-person-controller/src/main.ts +0 -15
  50. /package/templates/_shared/{ar-placement → ar}/src/ar-placement.ts +0 -0
  51. /package/templates/_shared/{first-person-controller → first-person-game}/src/scripts.d.ts +0 -0
  52. /package/templates/_shared/{third-person-controller → third-person-game}/src/controller.ts +0 -0
  53. /package/templates/_shared/{third-person-controller → third-person-game}/src/scripts.d.ts +0 -0
  54. /package/templates/_shared/{vr-starter → vr}/src/vr.ts +0 -0
  55. /package/templates/_shared/{vr-starter → vr}/src/xr.d.ts +0 -0
  56. /package/templates/engine/{spinning-cube → blank}/src/main.ts +0 -0
  57. /package/templates/react/{spinning-cube → blank}/src/App.tsx +0 -0
  58. /package/templates/web-components/{ar-placement → ar}/src/main.ts +0 -0
  59. /package/templates/web-components/{spinning-cube → blank}/index.html +0 -0
  60. /package/templates/web-components/{spinning-cube → blank}/src/main.ts +0 -0
  61. /package/templates/web-components/{third-person-controller → third-person-game}/src/main.ts +0 -0
  62. /package/templates/web-components/{vr-starter → vr}/src/main.ts +0 -0
@@ -0,0 +1,74 @@
1
+ import type { AssetElement, EntityElement } from '@playcanvas/web-components';
2
+ import { whenReady } from '@playcanvas/web-components';
3
+ import type { Asset } from 'playcanvas';
4
+ import { ProceduralSky } from 'playcanvas/scripts/esm/sky/procedural-sky.mjs';
5
+
6
+ import { CARDS, Game } from './game';
7
+ import type { GameEvents } from './game';
8
+ import './game.css';
9
+ import './starter.css';
10
+
11
+ // The HUD follows the game's state
12
+ const hud = {
13
+ orbs: document.getElementById('orbs')!,
14
+ time: document.getElementById('time')!,
15
+ card: document.getElementById('card')!,
16
+ title: document.getElementById('card-title')!,
17
+ hint: document.getElementById('card-hint')!,
18
+ joystick: document.getElementById('joystick')!,
19
+ knob: document.getElementById('joystick-knob')!
20
+ };
21
+
22
+ const onState: GameEvents['game:state'] = (state, found, total, seconds) => {
23
+ const card = CARDS[state];
24
+ hud.orbs.textContent = `${found} / ${total}`;
25
+ hud.time.textContent = `${seconds}s`;
26
+ hud.card.hidden = !card;
27
+ if (card) {
28
+ hud.title.textContent = card.title;
29
+ hud.hint.textContent = card.hint;
30
+ }
31
+ };
32
+
33
+ // A thumb on the left of the screen steers, and the circle and knob show where it is
34
+ const onJoystick: GameEvents['joystick:left'] = (baseX, baseY, knobX, knobY) => {
35
+ hud.joystick.hidden = hud.knob.hidden = baseX < 0;
36
+ hud.joystick.style.left = `${baseX}px`;
37
+ hud.joystick.style.top = `${baseY}px`;
38
+ hud.knob.style.left = `${knobX}px`;
39
+ hud.knob.style.top = `${knobY}px`;
40
+ };
41
+
42
+ const { app } = await whenReady('pc-app');
43
+ app!.on('game:state', onState);
44
+ app!.on('joystick:left', onJoystick);
45
+
46
+ // The player is awaited as its components rather than the <pc-entity> holding them - an entity
47
+ // becomes ready before its component children do, and the game needs its rigid body to exist
48
+ await Promise.all([
49
+ whenReady('pc-entity[name="player"] > pc-collision'),
50
+ whenReady('pc-entity[name="player"] > pc-rigid-body'),
51
+ whenReady('pc-entity[name="sun"] > pc-light'),
52
+ whenReady('pc-camera')
53
+ ]);
54
+ const [level, sun, sky, player, camera, game] = await Promise.all([
55
+ whenReady<AssetElement>('pc-asset#level'),
56
+ whenReady<EntityElement>('pc-entity[name="sun"]'),
57
+ whenReady<EntityElement>('pc-entity[name="sky"]'),
58
+ whenReady<EntityElement>('pc-entity[name="player"]'),
59
+ whenReady<EntityElement>('pc-entity[name="camera"]'),
60
+ whenReady<EntityElement>('pc-entity[name="game"]')
61
+ ]);
62
+
63
+ // Engine scripts are resolved by the bundler, so they are attached through the entity rather than
64
+ // with <pc-script-instance name="...">, which only resolves scripts fetched at runtime by <pc-asset>.
65
+ // The sky's default luminance is scene-scale bright, so turn it down to keep the yard out of clipping
66
+ sky.entity!.addComponent('script');
67
+ sky.entity!.script!.create(ProceduralSky, {
68
+ properties: { luminance: 0.3, azimuth: 150, elevation: 45, sunLight: sun.entity }
69
+ });
70
+
71
+ game.entity!.addComponent('script');
72
+ game.entity!.script!.create(Game, {
73
+ properties: { level: level.asset as Asset<'container'>, player: player.entity, camera: camera.entity }
74
+ });
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>Sprite Game</title>
7
+ <title>Platformer</title>
8
8
  </head>
9
9
  <body>
10
10
  <pc-app>
@@ -25,7 +25,7 @@
25
25
  </pc-app>
26
26
  <div class="hud">
27
27
  <section class="panel">
28
- <h1>Sprite Game</h1>
28
+ <h1>Platformer</h1>
29
29
  <p>Use A/D or the arrow keys to move and Space to jump.</p>
30
30
  </section>
31
31
  </div>
@@ -1,9 +1,9 @@
1
1
  import type { EntityElement } from '@playcanvas/web-components';
2
2
  import { whenReady } from '@playcanvas/web-components';
3
3
 
4
- import { SpriteGame } from './sprite-game';
4
+ import { Platformer } from './platformer';
5
5
  import './starter.css';
6
6
 
7
7
  const game = await whenReady<EntityElement>('pc-entity[name="game"]');
8
8
  game.entity!.addComponent('script');
9
- game.entity!.script!.create(SpriteGame);
9
+ game.entity!.script!.create(Platformer);
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>Third-Person Controller</title>
7
+ <title>Third-Person Game</title>
8
8
  </head>
9
9
  <body>
10
10
  <pc-app>
@@ -184,7 +184,7 @@
184
184
  </pc-app>
185
185
  <div class="hud">
186
186
  <section class="panel">
187
- <h1>Third-Person Controller</h1>
187
+ <h1>Third-Person Game</h1>
188
188
  <p>Click the scene, then use WASD to move, mouse to orbit and Space to jump.</p>
189
189
  </section>
190
190
  </div>
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/png" href="/src/assets/playcanvas.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- <title>VR Starter</title>
7
+ <title>Virtual Reality</title>
8
8
  </head>
9
9
  <body>
10
10
  <pc-app>
@@ -70,7 +70,7 @@
70
70
  </pc-app>
71
71
  <div class="hud">
72
72
  <section class="panel">
73
- <h1>VR Starter</h1>
73
+ <h1>Virtual Reality</h1>
74
74
  <p id="xr-status">Checking VR support…</p>
75
75
  <div class="controls"><button id="xr-button" disabled>Enter VR</button></div>
76
76
  </section>
@@ -1,7 +0,0 @@
1
- ## First-Person Controller
2
-
3
- A physics-backed player controller, camera and simple obstacle course.
4
-
5
- ### Controls
6
-
7
- Click the scene, use WASD to move, move the mouse to look and press Space to jump.
@@ -1,18 +0,0 @@
1
- import type { Entity, RigidBodyComponentSystem } from 'playcanvas';
2
- import { FirstPersonController } from 'playcanvas/scripts/esm/first-person-controller.mjs';
3
-
4
- export const addFirstPersonController = (player: Entity, camera: Entity) => {
5
- (player.rigidbody!.system as RigidBodyComponentSystem).gravity.set(0, -18, 0);
6
- if (!player.script) player.addComponent('script');
7
- player.script!.create(FirstPersonController, {
8
- properties: {
9
- camera,
10
- jumpForce: 650,
11
- speedGround: 55
12
- }
13
- });
14
-
15
- return () => {
16
- player.script?.destroy('firstPersonController');
17
- };
18
- };
@@ -1,7 +0,0 @@
1
- ## Spinning Cube
2
-
3
- A rotating cube, a camera and a directional light. It is the smallest PlayCanvas scene in the catalog.
4
-
5
- ### Controls
6
-
7
- The scene runs automatically; no input is required.
@@ -1,138 +0,0 @@
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
- });
27
- await new Promise<void>((resolve) => {
28
- WasmModule.getInstance('Ammo', () => resolve());
29
- });
30
-
31
- document.body.insertAdjacentHTML(
32
- 'beforeend',
33
- '<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>'
34
- );
35
-
36
- const canvas = document.getElementById('application-canvas') as HTMLCanvasElement;
37
- const device = await createGraphicsDevice(canvas);
38
- const options = new AppOptions();
39
- options.graphicsDevice = device;
40
- options.componentSystems = [
41
- RenderComponentSystem,
42
- CameraComponentSystem,
43
- LightComponentSystem,
44
- ScriptComponentSystem,
45
- CollisionComponentSystem,
46
- RigidBodyComponentSystem
47
- ];
48
-
49
- const app = new AppBase(canvas);
50
- app.init(options);
51
- app.start();
52
- app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
53
- app.setCanvasResolution(RESOLUTION_AUTO);
54
-
55
- const material = (color: Color) => {
56
- const result = new StandardMaterial();
57
- result.diffuse = color;
58
- result.emissive = new Color(color.r * 0.2, color.g * 0.2, color.b * 0.2);
59
- result.update();
60
- return result;
61
- };
62
-
63
- const floor = material(new Color(0.28, 0.3, 0.32));
64
- const wall = material(new Color(0.42, 0.45, 0.48));
65
- const blue = material(new Color(0.08, 0.29, 0.48));
66
- const green = material(new Color(0.18, 0.4, 0.22));
67
- const wood = material(new Color(0.48, 0.27, 0.1));
68
- const metal = material(new Color(0.28, 0.33, 0.38));
69
-
70
- const block = (
71
- name: string,
72
- position: [number, number, number],
73
- scale: [number, number, number],
74
- blockMaterial: StandardMaterial
75
- ) => {
76
- const entity = new Entity(name);
77
- entity.setPosition(...position);
78
- entity.setLocalScale(...scale);
79
- entity.addComponent('render', { type: 'box', material: blockMaterial });
80
- entity.addComponent('collision', {
81
- type: 'box',
82
- halfExtents: new Vec3(scale[0] / 2, scale[1] / 2, scale[2] / 2)
83
- });
84
- entity.addComponent('rigidbody', { type: 'static' });
85
- app.root.addChild(entity);
86
- };
87
-
88
- block('floor', [0, -0.1, 0], [18, 0.2, 18], floor);
89
- block('back-wall', [0, 1.5, -9], [18, 3, 0.3], wall);
90
- block('front-wall', [0, 1.5, 9], [18, 3, 0.3], wall);
91
- block('left-wall', [-9, 1.5, 0], [0.3, 3, 18], wall);
92
- block('right-wall', [9, 1.5, 0], [0.3, 3, 18], wall);
93
- block('blue-crate', [-2, 0.75, -3], [1.5, 1.5, 1.5], blue);
94
- block('green-crate', [3, 0.5, 1], [2.5, 1, 1], green);
95
- block('cargo-left-0', [-5.5, 0.75, -5.5], [2, 1.5, 2], wood);
96
- block('cargo-left-1', [-5.5, 2, -5.5], [1.5, 1, 1.5], blue);
97
- block('cargo-right-0', [5.3, 0.6, -4.8], [2.4, 1.2, 2], green);
98
- block('cargo-right-1', [5.3, 1.7, -4.8], [1.5, 1, 1.5], wood);
99
- block('cargo-center', [0, 0.6, -6.5], [2.2, 1.2, 1.8], blue);
100
- for (const [i, z] of [-3.5, 0, 3.5].entries()) {
101
- block(`shelf-left-post-${i}`, [-6.8, 1.4, z], [0.25, 2.8, 0.25], metal);
102
- block(`shelf-right-post-${i}`, [6.8, 1.4, z], [0.25, 2.8, 0.25], metal);
103
- }
104
- block('shelf-left-low', [-6.8, 0.65, 0], [1.1, 0.18, 7.5], metal);
105
- block('shelf-left-high', [-6.8, 2.1, 0], [1.1, 0.18, 7.5], metal);
106
- block('shelf-right-low', [6.8, 0.65, 0], [1.1, 0.18, 7.5], metal);
107
- block('shelf-right-high', [6.8, 2.1, 0], [1.1, 0.18, 7.5], metal);
108
- block('pallet', [-2.5, 0.15, 2.5], [3, 0.3, 2], wood);
109
-
110
- const player = new Entity('player');
111
- player.setPosition(0, 1, 5);
112
- player.addComponent('collision', { type: 'capsule', radius: 0.45, height: 1.8 });
113
- player.addComponent('rigidbody', { type: 'dynamic', mass: 80, angularFactor: Vec3.ZERO });
114
- app.root.addChild(player);
115
-
116
- const camera = new Entity('camera');
117
- camera.addComponent('camera', { clearColor: new Color(0.38, 0.64, 0.86), fov: 80 });
118
- camera.setLocalPosition(0, 0.65, 0);
119
- player.addChild(camera);
120
- addFirstPersonController(player, camera);
121
-
122
- const light = new Entity('light');
123
- light.addComponent('light', {
124
- type: 'directional',
125
- intensity: 2.5,
126
- castShadows: true,
127
- shadowBias: 0.2,
128
- normalOffsetBias: 0.05
129
- });
130
- light.setEulerAngles(50, 30, 0);
131
- app.root.addChild(light);
132
-
133
- const fill = new Entity('fill');
134
- fill.addComponent('light', { type: 'directional', intensity: 0.8 });
135
- fill.setEulerAngles(-25, -140, 0);
136
- app.root.addChild(fill);
137
-
138
- window.addEventListener('resize', () => app.resizeCanvas());
@@ -1,115 +0,0 @@
1
- import { Application, Entity } from '@playcanvas/react';
2
- import { Camera, Collision, Light, Render, RigidBody } from '@playcanvas/react/components';
3
- import { useMaterial, usePhysics } from '@playcanvas/react/hooks';
4
- import type { Entity as PcEntity, StandardMaterial } from 'playcanvas';
5
- import { useEffect, useRef } from 'react';
6
-
7
- import { addFirstPersonController } from './controller';
8
- import './starter.css';
9
-
10
- function Block({
11
- name,
12
- position,
13
- scale,
14
- material
15
- }: {
16
- name: string;
17
- position: [number, number, number];
18
- scale: [number, number, number];
19
- material: StandardMaterial;
20
- }) {
21
- return (
22
- <Entity name={name} position={position} scale={scale}>
23
- <Render type="box" material={material} />
24
- <Collision type="box" halfExtents={[scale[0] / 2, scale[1] / 2, scale[2] / 2]} />
25
- <RigidBody type="static" />
26
- </Entity>
27
- );
28
- }
29
-
30
- function Scene() {
31
- const player = useRef<PcEntity>(null);
32
- const camera = useRef<PcEntity>(null);
33
- const { isPhysicsLoaded } = usePhysics();
34
- const floor = useMaterial({ diffuse: '#474d52', emissive: '#0e0f10', gloss: 0.2 });
35
- const wall = useMaterial({ diffuse: '#6b737a', emissive: '#151718', gloss: 0.25 });
36
- const blue = useMaterial({ diffuse: '#154a7a', emissive: '#040f18', gloss: 0.4 });
37
- const green = useMaterial({ diffuse: '#2e6638', emissive: '#09140b', gloss: 0.2 });
38
- const wood = useMaterial({ diffuse: '#7a451a', emissive: '#180e05', gloss: 0.2 });
39
- const metal = useMaterial({ diffuse: '#475461', emissive: '#0e1113', gloss: 0.5 });
40
-
41
- useEffect(() => {
42
- if (isPhysicsLoaded && player.current && camera.current) {
43
- return addFirstPersonController(player.current, camera.current);
44
- }
45
- }, [isPhysicsLoaded]);
46
-
47
- return (
48
- <>
49
- <Entity name="light" rotation={[50, 30, 0]}>
50
- <Light type="directional" intensity={2.5} castShadows shadowBias={0.2} normalOffsetBias={0.05} />
51
- </Entity>
52
- <Entity name="fill" rotation={[-25, -140, 0]}>
53
- <Light type="directional" intensity={0.8} />
54
- </Entity>
55
- <Block name="floor" position={[0, -0.1, 0]} scale={[18, 0.2, 18]} material={floor} />
56
- <Block name="back-wall" position={[0, 1.5, -9]} scale={[18, 3, 0.3]} material={wall} />
57
- <Block name="front-wall" position={[0, 1.5, 9]} scale={[18, 3, 0.3]} material={wall} />
58
- <Block name="left-wall" position={[-9, 1.5, 0]} scale={[0.3, 3, 18]} material={wall} />
59
- <Block name="right-wall" position={[9, 1.5, 0]} scale={[0.3, 3, 18]} material={wall} />
60
- <Block name="blue-crate" position={[-2, 0.75, -3]} scale={[1.5, 1.5, 1.5]} material={blue} />
61
- <Block name="green-crate" position={[3, 0.5, 1]} scale={[2.5, 1, 1]} material={green} />
62
- <Block name="cargo-left-0" position={[-5.5, 0.75, -5.5]} scale={[2, 1.5, 2]} material={wood} />
63
- <Block name="cargo-left-1" position={[-5.5, 2, -5.5]} scale={[1.5, 1, 1.5]} material={blue} />
64
- <Block name="cargo-right-0" position={[5.3, 0.6, -4.8]} scale={[2.4, 1.2, 2]} material={green} />
65
- <Block name="cargo-right-1" position={[5.3, 1.7, -4.8]} scale={[1.5, 1, 1.5]} material={wood} />
66
- <Block name="cargo-center" position={[0, 0.6, -6.5]} scale={[2.2, 1.2, 1.8]} material={blue} />
67
- {[-3.5, 0, 3.5].flatMap((z, i) => [
68
- <Block
69
- key={`left-${i}`}
70
- name={`shelf-left-post-${i}`}
71
- position={[-6.8, 1.4, z]}
72
- scale={[0.25, 2.8, 0.25]}
73
- material={metal}
74
- />,
75
- <Block
76
- key={`right-${i}`}
77
- name={`shelf-right-post-${i}`}
78
- position={[6.8, 1.4, z]}
79
- scale={[0.25, 2.8, 0.25]}
80
- material={metal}
81
- />
82
- ])}
83
- <Block name="shelf-left-low" position={[-6.8, 0.65, 0]} scale={[1.1, 0.18, 7.5]} material={metal} />
84
- <Block name="shelf-left-high" position={[-6.8, 2.1, 0]} scale={[1.1, 0.18, 7.5]} material={metal} />
85
- <Block name="shelf-right-low" position={[6.8, 0.65, 0]} scale={[1.1, 0.18, 7.5]} material={metal} />
86
- <Block name="shelf-right-high" position={[6.8, 2.1, 0]} scale={[1.1, 0.18, 7.5]} material={metal} />
87
- <Block name="pallet" position={[-2.5, 0.15, 2.5]} scale={[3, 0.3, 2]} material={wood} />
88
- <Entity name="player" ref={player} position={[0, 1, 5]}>
89
- <Collision type="capsule" radius={0.45} height={1.8} />
90
- <RigidBody type="dynamic" mass={80} angularFactor={[0, 0, 0]} />
91
- <Entity name="camera" ref={camera} position={[0, 0.65, 0]}>
92
- <Camera clearColor="#61a3db" fov={80} />
93
- </Entity>
94
- </Entity>
95
- </>
96
- );
97
- }
98
-
99
- function App() {
100
- return (
101
- <>
102
- <Application usePhysics>
103
- <Scene />
104
- </Application>
105
- <div className="hud">
106
- <section className="panel">
107
- <h1>First-Person Controller</h1>
108
- <p>Click the scene, then use WASD, mouse look and Space to jump.</p>
109
- </section>
110
- </div>
111
- </>
112
- );
113
- }
114
-
115
- export default App;
@@ -1,163 +0,0 @@
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>First-Person Controller</title>
8
- </head>
9
- <body>
10
- <pc-app>
11
- <pc-material id="floor-material" diffuse="#474d52" emissive="#0e0f10" gloss="0.2"></pc-material>
12
- <pc-material id="wall-material" diffuse="#6b737a" emissive="#151718" gloss="0.25"></pc-material>
13
- <pc-material id="blue-material" diffuse="#154a7a" emissive="#040f18" gloss="0.4"></pc-material>
14
- <pc-material id="green-material" diffuse="#2e6638" emissive="#09140b" gloss="0.2"></pc-material>
15
- <pc-material id="wood-material" diffuse="#7a451a" emissive="#180e05" gloss="0.2"></pc-material>
16
- <pc-material id="metal-material" diffuse="#475461" emissive="#0e1113" gloss="0.5"></pc-material>
17
- <pc-wasm name="Ammo" glue="./ammo/ammo.wasm.js" wasm="./ammo/ammo.wasm.wasm"></pc-wasm>
18
- <pc-scene>
19
- <pc-entity name="light" rotation="50 30 0"
20
- ><pc-light
21
- type="directional"
22
- intensity="2.5"
23
- cast-shadows
24
- shadow-bias="0.2"
25
- normal-offset-bias="0.05"
26
- ></pc-light
27
- ></pc-entity>
28
- <pc-entity name="fill" rotation="-25 -140 0"
29
- ><pc-light type="directional" intensity="0.8"></pc-light
30
- ></pc-entity>
31
- <pc-entity name="floor" position="0 -0.1 0" scale="18 0.2 18"
32
- ><pc-render type="box" material="floor-material"></pc-render
33
- ><pc-collision type="box" half-extents="9 0.1 9"></pc-collision
34
- ><pc-rigid-body type="static"></pc-rigid-body
35
- ></pc-entity>
36
- <pc-entity name="back-wall" position="0 1.5 -9" scale="18 3 0.3"
37
- ><pc-render type="box" material="wall-material"></pc-render
38
- ><pc-collision type="box" half-extents="9 1.5 0.15"></pc-collision
39
- ><pc-rigid-body type="static"></pc-rigid-body
40
- ></pc-entity>
41
- <pc-entity name="front-wall" position="0 1.5 9" scale="18 3 0.3"
42
- ><pc-render type="box" material="wall-material"></pc-render
43
- ><pc-collision type="box" half-extents="9 1.5 0.15"></pc-collision
44
- ><pc-rigid-body type="static"></pc-rigid-body
45
- ></pc-entity>
46
- <pc-entity name="left-wall" position="-9 1.5 0" scale="0.3 3 18"
47
- ><pc-render type="box" material="wall-material"></pc-render
48
- ><pc-collision type="box" half-extents="0.15 1.5 9"></pc-collision
49
- ><pc-rigid-body type="static"></pc-rigid-body
50
- ></pc-entity>
51
- <pc-entity name="right-wall" position="9 1.5 0" scale="0.3 3 18"
52
- ><pc-render type="box" material="wall-material"></pc-render
53
- ><pc-collision type="box" half-extents="0.15 1.5 9"></pc-collision
54
- ><pc-rigid-body type="static"></pc-rigid-body
55
- ></pc-entity>
56
- <pc-entity name="blue-crate" position="-2 0.75 -3" scale="1.5 1.5 1.5"
57
- ><pc-render type="box" material="blue-material"></pc-render
58
- ><pc-collision type="box" half-extents="0.75 0.75 0.75"></pc-collision
59
- ><pc-rigid-body type="static"></pc-rigid-body
60
- ></pc-entity>
61
- <pc-entity name="green-crate" position="3 0.5 1" scale="2.5 1 1"
62
- ><pc-render type="box" material="green-material"></pc-render
63
- ><pc-collision type="box" half-extents="1.25 0.5 0.5"></pc-collision
64
- ><pc-rigid-body type="static"></pc-rigid-body
65
- ></pc-entity>
66
- <pc-entity name="cargo-left-0" position="-5.5 0.75 -5.5" scale="2 1.5 2"
67
- ><pc-render type="box" material="wood-material"></pc-render
68
- ><pc-collision type="box" half-extents="1 0.75 1"></pc-collision
69
- ><pc-rigid-body type="static"></pc-rigid-body
70
- ></pc-entity>
71
- <pc-entity name="cargo-left-1" position="-5.5 2 -5.5" scale="1.5 1 1.5"
72
- ><pc-render type="box" material="blue-material"></pc-render
73
- ><pc-collision type="box" half-extents="0.75 0.5 0.75"></pc-collision
74
- ><pc-rigid-body type="static"></pc-rigid-body
75
- ></pc-entity>
76
- <pc-entity name="cargo-right-0" position="5.3 0.6 -4.8" scale="2.4 1.2 2"
77
- ><pc-render type="box" material="green-material"></pc-render
78
- ><pc-collision type="box" half-extents="1.2 0.6 1"></pc-collision
79
- ><pc-rigid-body type="static"></pc-rigid-body
80
- ></pc-entity>
81
- <pc-entity name="cargo-right-1" position="5.3 1.7 -4.8" scale="1.5 1 1.5"
82
- ><pc-render type="box" material="wood-material"></pc-render
83
- ><pc-collision type="box" half-extents="0.75 0.5 0.75"></pc-collision
84
- ><pc-rigid-body type="static"></pc-rigid-body
85
- ></pc-entity>
86
- <pc-entity name="cargo-center" position="0 0.6 -6.5" scale="2.2 1.2 1.8"
87
- ><pc-render type="box" material="blue-material"></pc-render
88
- ><pc-collision type="box" half-extents="1.1 0.6 0.9"></pc-collision
89
- ><pc-rigid-body type="static"></pc-rigid-body
90
- ></pc-entity>
91
- <pc-entity name="shelf-left-post-0" position="-6.8 1.4 -3.5" scale="0.25 2.8 0.25"
92
- ><pc-render type="box" material="metal-material"></pc-render
93
- ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
94
- ><pc-rigid-body type="static"></pc-rigid-body
95
- ></pc-entity>
96
- <pc-entity name="shelf-left-post-1" position="-6.8 1.4 0" scale="0.25 2.8 0.25"
97
- ><pc-render type="box" material="metal-material"></pc-render
98
- ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
99
- ><pc-rigid-body type="static"></pc-rigid-body
100
- ></pc-entity>
101
- <pc-entity name="shelf-left-post-2" position="-6.8 1.4 3.5" scale="0.25 2.8 0.25"
102
- ><pc-render type="box" material="metal-material"></pc-render
103
- ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
104
- ><pc-rigid-body type="static"></pc-rigid-body
105
- ></pc-entity>
106
- <pc-entity name="shelf-right-post-0" position="6.8 1.4 -3.5" scale="0.25 2.8 0.25"
107
- ><pc-render type="box" material="metal-material"></pc-render
108
- ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
109
- ><pc-rigid-body type="static"></pc-rigid-body
110
- ></pc-entity>
111
- <pc-entity name="shelf-right-post-1" position="6.8 1.4 0" scale="0.25 2.8 0.25"
112
- ><pc-render type="box" material="metal-material"></pc-render
113
- ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
114
- ><pc-rigid-body type="static"></pc-rigid-body
115
- ></pc-entity>
116
- <pc-entity name="shelf-right-post-2" position="6.8 1.4 3.5" scale="0.25 2.8 0.25"
117
- ><pc-render type="box" material="metal-material"></pc-render
118
- ><pc-collision type="box" half-extents="0.125 1.4 0.125"></pc-collision
119
- ><pc-rigid-body type="static"></pc-rigid-body
120
- ></pc-entity>
121
- <pc-entity name="shelf-left-low" position="-6.8 0.65 0" scale="1.1 0.18 7.5"
122
- ><pc-render type="box" material="metal-material"></pc-render
123
- ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
124
- ><pc-rigid-body type="static"></pc-rigid-body
125
- ></pc-entity>
126
- <pc-entity name="shelf-left-high" position="-6.8 2.1 0" scale="1.1 0.18 7.5"
127
- ><pc-render type="box" material="metal-material"></pc-render
128
- ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
129
- ><pc-rigid-body type="static"></pc-rigid-body
130
- ></pc-entity>
131
- <pc-entity name="shelf-right-low" position="6.8 0.65 0" scale="1.1 0.18 7.5"
132
- ><pc-render type="box" material="metal-material"></pc-render
133
- ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
134
- ><pc-rigid-body type="static"></pc-rigid-body
135
- ></pc-entity>
136
- <pc-entity name="shelf-right-high" position="6.8 2.1 0" scale="1.1 0.18 7.5"
137
- ><pc-render type="box" material="metal-material"></pc-render
138
- ><pc-collision type="box" half-extents="0.55 0.09 3.75"></pc-collision
139
- ><pc-rigid-body type="static"></pc-rigid-body
140
- ></pc-entity>
141
- <pc-entity name="pallet" position="-2.5 0.15 2.5" scale="3 0.3 2"
142
- ><pc-render type="box" material="wood-material"></pc-render
143
- ><pc-collision type="box" half-extents="1.5 0.15 1"></pc-collision
144
- ><pc-rigid-body type="static"></pc-rigid-body
145
- ></pc-entity>
146
- <pc-entity name="player" position="0 1 5">
147
- <pc-collision type="capsule" radius="0.45" height="1.8"></pc-collision>
148
- <pc-rigid-body type="dynamic" mass="80" angular-factor="0 0 0"></pc-rigid-body>
149
- <pc-entity name="camera" position="0 0.65 0"
150
- ><pc-camera clear-color="#61a3db" fov="80"></pc-camera
151
- ></pc-entity>
152
- </pc-entity>
153
- </pc-scene>
154
- </pc-app>
155
- <div class="hud">
156
- <section class="panel">
157
- <h1>First-Person Controller</h1>
158
- <p>Click the scene, then use WASD, mouse look and Space to jump.</p>
159
- </section>
160
- </div>
161
- <script type="module" src="/src/main.ts"></script>
162
- </body>
163
- </html>
@@ -1,15 +0,0 @@
1
- import type { EntityElement } from '@playcanvas/web-components';
2
- import { whenReady } from '@playcanvas/web-components';
3
-
4
- import { addFirstPersonController } from './controller';
5
- import './starter.css';
6
-
7
- await Promise.all([
8
- whenReady('pc-entity[name="player"] > pc-collision'),
9
- whenReady('pc-entity[name="player"] > pc-rigid-body')
10
- ]);
11
- const [player, camera] = await Promise.all([
12
- whenReady<EntityElement>('pc-entity[name="player"]'),
13
- whenReady<EntityElement>('pc-entity[name="camera"]')
14
- ]);
15
- addFirstPersonController(player.entity!, camera.entity!);
File without changes