create-playcanvas 0.15.0 → 0.16.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/README.md +69 -24
- package/dist/index.mjs +11 -11
- package/package.json +1 -1
- package/templates/_shared/scene-editor/AGENTS.md +8 -0
- package/templates/_shared/scene-editor/README.md +15 -2
- package/templates/_shared/scene-editor/src/scene-editor.ts +186 -36
- package/templates/engine/ar-placement/index.html +20 -0
- package/templates/engine/ar-placement/src/main.ts +22 -12
- package/templates/engine/base/AGENTS.md +1 -0
- package/templates/engine/base/README.md +1 -1
- package/templates/engine/first-person-controller/index.html +19 -0
- package/templates/engine/first-person-controller/src/main.ts +16 -11
- package/templates/engine/product-configurator/index.html +30 -0
- package/templates/engine/product-configurator/src/main.ts +33 -32
- package/templates/engine/scene-editor/index.html +33 -0
- package/templates/engine/scene-editor/src/main.ts +56 -47
- package/templates/engine/sprite-game/index.html +19 -0
- package/templates/engine/sprite-game/src/main.ts +19 -11
- package/templates/engine/third-person-controller/index.html +19 -0
- package/templates/engine/third-person-controller/src/main.ts +16 -11
- package/templates/engine/vr-starter/index.html +20 -0
- package/templates/engine/vr-starter/src/main.ts +22 -12
- package/templates/index.ts +1 -14
- package/templates/react/base/AGENTS.md +1 -0
- package/templates/react/scene-editor/src/App.tsx +73 -40
- package/templates/web-components/base/AGENTS.md +1 -0
- package/templates/web-components/scene-editor/index.html +32 -25
- package/templates/web-components/scene-editor/src/main.ts +33 -11
- package/templates/_shared/interactive-sphere/README.md +0 -7
- package/templates/_shared/interactive-sphere/public/environment-map.png +0 -0
- package/templates/_shared/interactive-sphere/src/counter.css +0 -19
- package/templates/_shared/physics-playground/README.md +0 -7
- package/templates/engine/interactive-sphere/src/App.ts +0 -182
- package/templates/engine/interactive-sphere/src/main.ts +0 -16
- package/templates/engine/interactive-sphere/src/utils.ts +0 -16
- package/templates/engine/physics-playground/src/main.ts +0 -131
- package/templates/react/interactive-sphere/src/App.tsx +0 -21
- package/templates/react/interactive-sphere/src/Scene.tsx +0 -70
- package/templates/react/physics-playground/src/App.tsx +0 -85
- package/templates/web-components/interactive-sphere/index.html +0 -36
- package/templates/web-components/interactive-sphere/src/main.ts +0 -76
- package/templates/web-components/physics-playground/index.html +0 -46
- package/templates/web-components/physics-playground/src/main.ts +0 -32
|
@@ -1,131 +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
|
-
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
20
|
-
|
|
21
|
-
import './starter.css';
|
|
22
|
-
|
|
23
|
-
const COLORS = [new Color(0.16, 0.68, 0.9), new Color(0.95, 0.34, 0.22), new Color(0.98, 0.68, 0.18)];
|
|
24
|
-
const TYPES = ['box', 'sphere', 'capsule', 'cylinder'] as const;
|
|
25
|
-
const SCALES: [number, number, number][] = [
|
|
26
|
-
[0.9, 0.9, 0.9],
|
|
27
|
-
[0.9, 0.9, 0.9],
|
|
28
|
-
[0.7, 1.1, 0.7],
|
|
29
|
-
[0.8, 1.1, 0.8]
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
WasmModule.setConfig('Ammo', {
|
|
33
|
-
glueUrl: './ammo/ammo.wasm.js',
|
|
34
|
-
wasmUrl: './ammo/ammo.wasm.wasm'
|
|
35
|
-
});
|
|
36
|
-
await new Promise<void>((resolve) => {
|
|
37
|
-
WasmModule.getInstance('Ammo', () => resolve());
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
document.body.insertAdjacentHTML(
|
|
41
|
-
'beforeend',
|
|
42
|
-
'<div class="hud"><section class="panel"><h1>Physics Playground</h1><p>Rigid bodies, collisions and runtime spawning.</p><div class="controls"><button id="spawn">Spawn object</button><button id="reset">Reset</button></div></section></div>'
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
const canvas = document.getElementById('application-canvas') as HTMLCanvasElement;
|
|
46
|
-
const device = await createGraphicsDevice(canvas);
|
|
47
|
-
const options = new AppOptions();
|
|
48
|
-
options.graphicsDevice = device;
|
|
49
|
-
options.componentSystems = [
|
|
50
|
-
RenderComponentSystem,
|
|
51
|
-
CameraComponentSystem,
|
|
52
|
-
LightComponentSystem,
|
|
53
|
-
ScriptComponentSystem,
|
|
54
|
-
CollisionComponentSystem,
|
|
55
|
-
RigidBodyComponentSystem
|
|
56
|
-
];
|
|
57
|
-
|
|
58
|
-
const app = new AppBase(canvas);
|
|
59
|
-
app.init(options);
|
|
60
|
-
app.start();
|
|
61
|
-
app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
|
|
62
|
-
app.setCanvasResolution(RESOLUTION_AUTO);
|
|
63
|
-
app.systems.rigidbody!.gravity.set(0, -9.81, 0);
|
|
64
|
-
|
|
65
|
-
const materials = COLORS.map((color) => {
|
|
66
|
-
const material = new StandardMaterial();
|
|
67
|
-
material.diffuse = color;
|
|
68
|
-
material.gloss = 0.45;
|
|
69
|
-
material.update();
|
|
70
|
-
return material;
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
const floorMaterial = new StandardMaterial();
|
|
74
|
-
floorMaterial.diffuse = new Color(0.18, 0.2, 0.24);
|
|
75
|
-
floorMaterial.gloss = 0.2;
|
|
76
|
-
floorMaterial.update();
|
|
77
|
-
|
|
78
|
-
const floor = new Entity('floor');
|
|
79
|
-
floor.setLocalScale(10, 0.2, 10);
|
|
80
|
-
floor.setPosition(0, -0.1, 0);
|
|
81
|
-
floor.addComponent('render', { type: 'box', material: floorMaterial });
|
|
82
|
-
floor.addComponent('collision', { type: 'box', halfExtents: new Vec3(5, 0.1, 5) });
|
|
83
|
-
floor.addComponent('rigidbody', { type: 'static' });
|
|
84
|
-
app.root.addChild(floor);
|
|
85
|
-
|
|
86
|
-
const bodies: Entity[] = [];
|
|
87
|
-
const spawn = () => {
|
|
88
|
-
const i = bodies.length;
|
|
89
|
-
const type = TYPES[i % TYPES.length];
|
|
90
|
-
const entity = new Entity(type);
|
|
91
|
-
entity.setPosition(((i % 4) - 1.5) * 1.1, 0.7 + Math.floor(i / 4) * 1.1, (Math.floor(i / 4) - 1) * 1.4);
|
|
92
|
-
entity.setEulerAngles(i * 13, i * 29, 0);
|
|
93
|
-
entity.setLocalScale(...SCALES[i % SCALES.length]);
|
|
94
|
-
entity.addComponent('render', { type, material: materials[i % materials.length] });
|
|
95
|
-
entity.addComponent('collision', {
|
|
96
|
-
type,
|
|
97
|
-
halfExtents: new Vec3(0.5, 0.5, 0.5),
|
|
98
|
-
radius: 0.5
|
|
99
|
-
});
|
|
100
|
-
entity.addComponent('rigidbody', { type: 'dynamic', mass: 1, restitution: 0.35 });
|
|
101
|
-
app.root.addChild(entity);
|
|
102
|
-
bodies.push(entity);
|
|
103
|
-
};
|
|
104
|
-
const reset = () => {
|
|
105
|
-
bodies.splice(0).forEach((entity) => entity.destroy());
|
|
106
|
-
for (let i = 0; i < 12; i++) spawn();
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const camera = new Entity('camera');
|
|
110
|
-
camera.setPosition(10, 8, 10);
|
|
111
|
-
camera.lookAt(0, 2, 0);
|
|
112
|
-
camera.addComponent('camera', { clearColor: new Color(0.05, 0.07, 0.11) });
|
|
113
|
-
camera.addComponent('script');
|
|
114
|
-
camera.script!.create(CameraControls, { properties: { sceneSize: 10 } });
|
|
115
|
-
app.root.addChild(camera);
|
|
116
|
-
|
|
117
|
-
const light = new Entity('light');
|
|
118
|
-
light.addComponent('light', {
|
|
119
|
-
type: 'directional',
|
|
120
|
-
intensity: 2.5,
|
|
121
|
-
castShadows: true,
|
|
122
|
-
shadowBias: 0.2,
|
|
123
|
-
normalOffsetBias: 0.05
|
|
124
|
-
});
|
|
125
|
-
light.setEulerAngles(45, 35, 0);
|
|
126
|
-
app.root.addChild(light);
|
|
127
|
-
|
|
128
|
-
document.getElementById('spawn')!.onclick = spawn;
|
|
129
|
-
document.getElementById('reset')!.onclick = reset;
|
|
130
|
-
reset();
|
|
131
|
-
window.addEventListener('resize', () => app.resizeCanvas());
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Application } from '@playcanvas/react';
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
|
|
4
|
-
import './counter.css';
|
|
5
|
-
import Scene from './Scene';
|
|
6
|
-
import './starter.css';
|
|
7
|
-
|
|
8
|
-
function App() {
|
|
9
|
-
const [count, setCount] = useState(0);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<>
|
|
13
|
-
<Application className="playcanvas-app">
|
|
14
|
-
<Scene onClick={() => setCount((count) => count + 1)} />
|
|
15
|
-
</Application>
|
|
16
|
-
<p className="counter">Click count: {count}</p>
|
|
17
|
-
</>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default App;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Entity } from '@playcanvas/react';
|
|
2
|
-
import { Camera, Environment, Render, Script } from '@playcanvas/react/components';
|
|
3
|
-
import { useEnvAtlas, useMaterial } from '@playcanvas/react/hooks';
|
|
4
|
-
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
5
|
-
import { Grid } from 'playcanvas/scripts/esm/grid.mjs';
|
|
6
|
-
import { useEffect, useState } from 'react';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The Scene renders a sphere with a grid and camera controls
|
|
10
|
-
*/
|
|
11
|
-
function Scene({ onClick }: SceneProps) {
|
|
12
|
-
const [hovering, setHovering] = useState(false);
|
|
13
|
-
|
|
14
|
-
// Set a material color based on the hover state
|
|
15
|
-
const diffuse = hovering ? '#40ccff' : '#e6edf9';
|
|
16
|
-
|
|
17
|
-
// Create a material for the sphere
|
|
18
|
-
const material = useMaterial({ diffuse });
|
|
19
|
-
|
|
20
|
-
// Load the environment map
|
|
21
|
-
const { asset: envMap } = useEnvAtlas('./environment-map.png');
|
|
22
|
-
|
|
23
|
-
// Change the mouse cursor based on the hover state
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
document.body.style.cursor = hovering ? 'pointer' : 'default';
|
|
26
|
-
|
|
27
|
-
return () => {
|
|
28
|
-
document.body.style.cursor = '';
|
|
29
|
-
};
|
|
30
|
-
}, [hovering]);
|
|
31
|
-
|
|
32
|
-
// Don't render until the environment map is loaded
|
|
33
|
-
if (!envMap) return null;
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<>
|
|
37
|
-
{/* Render some environment lighting using the environment map */}
|
|
38
|
-
<Environment envAtlas={envMap} showSkybox={false} />
|
|
39
|
-
|
|
40
|
-
{/* Render a background grid */}
|
|
41
|
-
<Entity scale={[12, 12, 12]}>
|
|
42
|
-
<Script script={Grid} />
|
|
43
|
-
</Entity>
|
|
44
|
-
|
|
45
|
-
{/* Create a camera entity with camera controls */}
|
|
46
|
-
<Entity name="camera" position={[3.2, 1.5, 3.2]} rotation={[-10, 45, 0]}>
|
|
47
|
-
<Camera clearColor="#07101a" />
|
|
48
|
-
<Script script={CameraControls} sceneSize={3} />
|
|
49
|
-
</Entity>
|
|
50
|
-
|
|
51
|
-
{/* Create and position entity with pointer events */}
|
|
52
|
-
<Entity
|
|
53
|
-
position={[0, 0.7, 0]}
|
|
54
|
-
scale={[1.25, 1.25, 1.25]}
|
|
55
|
-
onClick={onClick}
|
|
56
|
-
onPointerOver={() => setHovering(true)}
|
|
57
|
-
onPointerOut={() => setHovering(false)}
|
|
58
|
-
>
|
|
59
|
-
{/* Render a sphere with the material */}
|
|
60
|
-
<Render type="sphere" material={material} />
|
|
61
|
-
</Entity>
|
|
62
|
-
</>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
type SceneProps = {
|
|
67
|
-
onClick: () => void;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export default Scene;
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { Application, Entity } from '@playcanvas/react';
|
|
2
|
-
import { Camera, Collision, Light, Render, RigidBody, Script } from '@playcanvas/react/components';
|
|
3
|
-
import { useMaterial } from '@playcanvas/react/hooks';
|
|
4
|
-
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
5
|
-
import { useState } from 'react';
|
|
6
|
-
|
|
7
|
-
import './starter.css';
|
|
8
|
-
|
|
9
|
-
const COLORS = ['#29ade6', '#f25738', '#f9ad2e'];
|
|
10
|
-
const TYPES = ['box', 'sphere', 'capsule', 'cylinder'] as const;
|
|
11
|
-
const SCALES: [number, number, number][] = [
|
|
12
|
-
[0.9, 0.9, 0.9],
|
|
13
|
-
[0.9, 0.9, 0.9],
|
|
14
|
-
[0.7, 1.1, 0.7],
|
|
15
|
-
[0.8, 1.1, 0.8]
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
function Body({ i }: { i: number }) {
|
|
19
|
-
const type = TYPES[i % TYPES.length];
|
|
20
|
-
const material = useMaterial({ diffuse: COLORS[i % COLORS.length], gloss: 0.45 });
|
|
21
|
-
return (
|
|
22
|
-
<Entity
|
|
23
|
-
position={[((i % 4) - 1.5) * 1.1, 0.7 + Math.floor(i / 4) * 1.1, (Math.floor(i / 4) - 1) * 1.4]}
|
|
24
|
-
rotation={[i * 13, i * 29, 0]}
|
|
25
|
-
scale={SCALES[i % SCALES.length]}
|
|
26
|
-
>
|
|
27
|
-
<Render type={type} material={material} />
|
|
28
|
-
<Collision type={type} />
|
|
29
|
-
<RigidBody type="dynamic" mass={1} restitution={0.35} />
|
|
30
|
-
</Entity>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function Floor() {
|
|
35
|
-
const material = useMaterial({ diffuse: '#2e333d', gloss: 0.2 });
|
|
36
|
-
return (
|
|
37
|
-
<Entity name="floor" position={[0, -0.1, 0]} scale={[10, 0.2, 10]}>
|
|
38
|
-
<Render type="box" material={material} />
|
|
39
|
-
<Collision type="box" halfExtents={[5, 0.1, 5]} />
|
|
40
|
-
<RigidBody type="static" />
|
|
41
|
-
</Entity>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function App() {
|
|
46
|
-
const [count, setCount] = useState(12);
|
|
47
|
-
const [reset, setReset] = useState(0);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<>
|
|
51
|
-
<Application usePhysics>
|
|
52
|
-
<Entity name="camera" position={[10, 8, 10]} rotation={[-23, 45, 0]}>
|
|
53
|
-
<Camera clearColor="#0d121c" />
|
|
54
|
-
<Script script={CameraControls} sceneSize={10} />
|
|
55
|
-
</Entity>
|
|
56
|
-
<Entity name="light" rotation={[45, 35, 0]}>
|
|
57
|
-
<Light type="directional" intensity={2.5} castShadows shadowBias={0.2} normalOffsetBias={0.05} />
|
|
58
|
-
</Entity>
|
|
59
|
-
<Floor />
|
|
60
|
-
{Array.from({ length: count }, (_, i) => (
|
|
61
|
-
<Body key={`${reset}-${i}`} i={i} />
|
|
62
|
-
))}
|
|
63
|
-
</Application>
|
|
64
|
-
<div className="hud">
|
|
65
|
-
<section className="panel">
|
|
66
|
-
<h1>Physics Playground</h1>
|
|
67
|
-
<p>Rigid bodies, collisions and runtime spawning.</p>
|
|
68
|
-
<div className="controls">
|
|
69
|
-
<button onClick={() => setCount((value) => value + 1)}>Spawn object</button>
|
|
70
|
-
<button
|
|
71
|
-
onClick={() => {
|
|
72
|
-
setCount(12);
|
|
73
|
-
setReset((value) => value + 1);
|
|
74
|
-
}}
|
|
75
|
-
>
|
|
76
|
-
Reset
|
|
77
|
-
</button>
|
|
78
|
-
</div>
|
|
79
|
-
</section>
|
|
80
|
-
</div>
|
|
81
|
-
</>
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export default App;
|
|
@@ -1,36 +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>PlayCanvas + Web Components</title>
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<pc-app>
|
|
11
|
-
<!-- Materials are declared once and referenced by id -->
|
|
12
|
-
<pc-material id="sphere-material" diffuse="#e6edf9"></pc-material>
|
|
13
|
-
|
|
14
|
-
<pc-scene>
|
|
15
|
-
<!-- Camera. Orbit controls are attached in src/main.ts -->
|
|
16
|
-
<pc-entity name="camera" position="3.2 1.5 3.2" rotation="-10 45 0">
|
|
17
|
-
<pc-camera clear-color="#07101a"></pc-camera>
|
|
18
|
-
</pc-entity>
|
|
19
|
-
|
|
20
|
-
<!-- Lighting comes from the environment map, which is applied in src/main.ts -->
|
|
21
|
-
|
|
22
|
-
<!-- Background grid. The grid script is attached in src/main.ts -->
|
|
23
|
-
<pc-entity name="grid" scale="12 12 12"></pc-entity>
|
|
24
|
-
|
|
25
|
-
<!-- The sphere. pc-app dispatches pointer events onto whatever the pointer hits -->
|
|
26
|
-
<pc-entity name="sphere" position="0 0.7 0" scale="1.25 1.25 1.25">
|
|
27
|
-
<pc-render type="sphere" material="sphere-material"></pc-render>
|
|
28
|
-
</pc-entity>
|
|
29
|
-
</pc-scene>
|
|
30
|
-
</pc-app>
|
|
31
|
-
|
|
32
|
-
<p id="counter" class="counter">Click count: 0</p>
|
|
33
|
-
|
|
34
|
-
<script type="module" src="/src/main.ts"></script>
|
|
35
|
-
</body>
|
|
36
|
-
</html>
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import type { EntityElement } from '@playcanvas/web-components';
|
|
2
|
-
import { whenReady } from '@playcanvas/web-components';
|
|
3
|
-
import { Asset, TEXTURETYPE_RGBP } from 'playcanvas';
|
|
4
|
-
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
5
|
-
import { Grid } from 'playcanvas/scripts/esm/grid.mjs';
|
|
6
|
-
|
|
7
|
-
import './counter.css';
|
|
8
|
-
import './starter.css';
|
|
9
|
-
|
|
10
|
-
const HOVER_COLOR = '#40ccff';
|
|
11
|
-
const DEFAULT_COLOR = '#e6edf9';
|
|
12
|
-
|
|
13
|
-
// The camera is awaited as <pc-camera> rather than the <pc-entity> holding it - an entity becomes
|
|
14
|
-
// ready before its component children do, and CameraControls needs the camera component to exist
|
|
15
|
-
const [appElement, cameraComponent, grid, sphere] = await Promise.all([
|
|
16
|
-
whenReady('pc-app'),
|
|
17
|
-
whenReady('pc-camera'),
|
|
18
|
-
whenReady<EntityElement>('pc-entity[name="grid"]'),
|
|
19
|
-
whenReady<EntityElement>('pc-entity[name="sphere"]')
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
// This is a pre-generated environment atlas rather than an equirectangular image, so it is applied
|
|
23
|
-
// straight to the scene instead of through <pc-sky>
|
|
24
|
-
const app = appElement.app!;
|
|
25
|
-
const envAtlas = new Asset(
|
|
26
|
-
'env-atlas',
|
|
27
|
-
'texture',
|
|
28
|
-
{ url: './environment-map.png' },
|
|
29
|
-
{
|
|
30
|
-
type: TEXTURETYPE_RGBP,
|
|
31
|
-
mipmaps: false
|
|
32
|
-
}
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
app.assets.add(envAtlas);
|
|
36
|
-
await new Promise<void>((resolve) => {
|
|
37
|
-
envAtlas.ready(() => resolve());
|
|
38
|
-
app.assets.load(envAtlas);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Light the scene from the environment, with the skybox itself left hidden
|
|
42
|
-
app.scene.envAtlas = envAtlas.resource!;
|
|
43
|
-
const skyboxLayer = app.scene.layers.getLayerByName('Skybox');
|
|
44
|
-
if (skyboxLayer) {
|
|
45
|
-
skyboxLayer.enabled = false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Engine scripts are resolved by the bundler, so they are attached through the entity rather than
|
|
49
|
-
// with <pc-script-instance name="...">, which only resolves scripts fetched at runtime by <pc-asset>
|
|
50
|
-
const camera = cameraComponent.closestEntity;
|
|
51
|
-
camera?.entity?.addComponent('script');
|
|
52
|
-
camera?.entity?.script?.create(CameraControls, { properties: { sceneSize: 3 } });
|
|
53
|
-
grid.entity?.addComponent('script');
|
|
54
|
-
grid.entity?.script?.create(Grid);
|
|
55
|
-
|
|
56
|
-
const material = document.querySelector('pc-material')!;
|
|
57
|
-
const counterElement = document.getElementById('counter')!;
|
|
58
|
-
|
|
59
|
-
let count = 0;
|
|
60
|
-
|
|
61
|
-
// pc-app picks whatever is under the pointer and dispatches a regular DOM PointerEvent on it, so
|
|
62
|
-
// the sphere is wired up like any other element
|
|
63
|
-
sphere.addEventListener('pointerenter', () => {
|
|
64
|
-
material.setAttribute('diffuse', HOVER_COLOR);
|
|
65
|
-
document.body.style.cursor = 'pointer';
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
sphere.addEventListener('pointerleave', () => {
|
|
69
|
-
material.setAttribute('diffuse', DEFAULT_COLOR);
|
|
70
|
-
document.body.style.cursor = 'default';
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
sphere.addEventListener('pointerup', () => {
|
|
74
|
-
count++;
|
|
75
|
-
counterElement.textContent = `Click count: ${count}`;
|
|
76
|
-
});
|
|
@@ -1,46 +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>Physics Playground</title>
|
|
8
|
-
</head>
|
|
9
|
-
<body>
|
|
10
|
-
<pc-app>
|
|
11
|
-
<pc-wasm name="Ammo" glue="./ammo/ammo.wasm.js" wasm="./ammo/ammo.wasm.wasm"></pc-wasm>
|
|
12
|
-
<pc-material id="floor-material" diffuse="#2e333d" gloss="0.2"></pc-material>
|
|
13
|
-
<pc-material id="cyan-material" diffuse="#29ade6" gloss="0.45"></pc-material>
|
|
14
|
-
<pc-material id="coral-material" diffuse="#f25738" gloss="0.45"></pc-material>
|
|
15
|
-
<pc-material id="yellow-material" diffuse="#f9ad2e" gloss="0.45"></pc-material>
|
|
16
|
-
<pc-scene>
|
|
17
|
-
<pc-entity name="camera" position="10 8 10" rotation="-23 45 0"
|
|
18
|
-
><pc-camera clear-color="#0d121c"></pc-camera
|
|
19
|
-
></pc-entity>
|
|
20
|
-
<pc-entity name="light" rotation="45 35 0"
|
|
21
|
-
><pc-light
|
|
22
|
-
type="directional"
|
|
23
|
-
intensity="2.5"
|
|
24
|
-
cast-shadows
|
|
25
|
-
shadow-bias="0.2"
|
|
26
|
-
normal-offset-bias="0.05"
|
|
27
|
-
></pc-light
|
|
28
|
-
></pc-entity>
|
|
29
|
-
<pc-entity name="floor" position="0 -0.1 0" scale="10 0.2 10"
|
|
30
|
-
><pc-render type="box" material="floor-material"></pc-render
|
|
31
|
-
><pc-collision type="box" half-extents="5 0.1 5"></pc-collision
|
|
32
|
-
><pc-rigid-body type="static"></pc-rigid-body
|
|
33
|
-
></pc-entity>
|
|
34
|
-
<pc-entity id="bodies"></pc-entity>
|
|
35
|
-
</pc-scene>
|
|
36
|
-
</pc-app>
|
|
37
|
-
<div class="hud">
|
|
38
|
-
<section class="panel">
|
|
39
|
-
<h1>Physics Playground</h1>
|
|
40
|
-
<p>Rigid bodies, collisions and runtime spawning.</p>
|
|
41
|
-
<div class="controls"><button id="spawn">Spawn object</button><button id="reset">Reset</button></div>
|
|
42
|
-
</section>
|
|
43
|
-
</div>
|
|
44
|
-
<script type="module" src="/src/main.ts"></script>
|
|
45
|
-
</body>
|
|
46
|
-
</html>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { whenReady } from '@playcanvas/web-components';
|
|
2
|
-
import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
|
|
3
|
-
|
|
4
|
-
import './starter.css';
|
|
5
|
-
|
|
6
|
-
const MATERIALS = ['cyan-material', 'coral-material', 'yellow-material'];
|
|
7
|
-
const TYPES = ['box', 'sphere', 'capsule', 'cylinder'];
|
|
8
|
-
const SCALES = ['0.9 0.9 0.9', '0.9 0.9 0.9', '0.7 1.1 0.7', '0.8 1.1 0.8'];
|
|
9
|
-
|
|
10
|
-
const camera = (await whenReady('pc-camera')).closestEntity!.entity!;
|
|
11
|
-
camera.addComponent('script');
|
|
12
|
-
camera.script!.create(CameraControls, { properties: { sceneSize: 10 } });
|
|
13
|
-
|
|
14
|
-
const bodies = document.getElementById('bodies')!;
|
|
15
|
-
let count = 0;
|
|
16
|
-
const spawn = () => {
|
|
17
|
-
const i = count++;
|
|
18
|
-
const type = TYPES[i % TYPES.length];
|
|
19
|
-
bodies.insertAdjacentHTML(
|
|
20
|
-
'beforeend',
|
|
21
|
-
`<pc-entity data-body position="${((i % 4) - 1.5) * 1.1} ${0.7 + Math.floor(i / 4) * 1.1} ${(Math.floor(i / 4) - 1) * 1.4}" rotation="${i * 13} ${i * 29} 0" scale="${SCALES[i % SCALES.length]}"><pc-render type="${type}" material="${MATERIALS[i % MATERIALS.length]}"></pc-render><pc-collision type="${type}"></pc-collision><pc-rigid-body type="dynamic" mass="1" restitution="0.35"></pc-rigid-body></pc-entity>`
|
|
22
|
-
);
|
|
23
|
-
};
|
|
24
|
-
const reset = () => {
|
|
25
|
-
bodies.replaceChildren();
|
|
26
|
-
count = 0;
|
|
27
|
-
for (let i = 0; i < 12; i++) spawn();
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
document.getElementById('spawn')!.onclick = spawn;
|
|
31
|
-
document.getElementById('reset')!.onclick = reset;
|
|
32
|
-
reset();
|