Skip to content

Commit 70cfe2a

Browse files
marklundinwilleastcottLeXXikCopilot
authored
Adds ESM Tutorials (#669)
* Upgrading Script examples to include ESM variants * Add esm variants for tutorials * linting * linting * Update docs/tutorials/collision-and-triggers.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/collision-and-triggers.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/Using-forces-on-rigid-bodies.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/entity-picking.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/first-person-movement.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/keepyup-part-four.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/keepyup-part-three.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/google-ads-for-games.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/keepyup-part-six.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/facebook-api.md Co-authored-by: Will Eastcott <[email protected]> * replaced attributesDefinition with attributes * Add ESM Scripts user manual page * fix link * fixed admonition * content update * updates * CDN * warning * esm-scripts typos (#651) * Update docs/user-manual/publishing/web/communicating-webpage.md Co-authored-by: Will Eastcott <[email protected]> * Remove ScriptType reference * Update docs/user-manual/scripting/script-attributes.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/user-manual/scripting/migration-guide.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/user-manual/scripting/communication.md Co-authored-by: Will Eastcott <[email protected]> * arrow function * Update docs/user-manual/scripting/script-attributes.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/user-manual/scripting/script-attributes.md Co-authored-by: Will Eastcott <[email protected]> * linting fixes * add version flag * renamed Classic -> Legacy. Script Attributes docs * Completed Script Attribute docs * replicate legacy in ja, to fix build * Refactored attribute grouping and added interface attributes * Update legacy scripting system documentation * Update script attributes and loading order documentation * Refactor script creation and import statements * Refactor script attributes documentation * Fix linting issues and update script documentation * Update linting command in package.json * Update migration guide and add legacy loading order documentation * Update loading order title and add redirect for legacy loading order * Remove unnecessary blank line in esm-scripts.md * Refactor watch function to use Object.defineProperty * revert package lock * revert config * revert scripting change * Delete docs/user-manual/scripting/esm-scripts.md * remove legacy * revert * video revert * legacy -> Classic * fix tab issue * Update tutorial documentation to recommend ESM format in code examples * Fixed redundant closing brackets * Update tutorial documentation to change "Legacy" tab to "Classic" for clarity * Update docs/tutorials/custom-shaders.md Co-authored-by: Copilot <[email protected]> * Update docs/tutorials/collision-and-triggers.md Co-authored-by: Copilot <[email protected]> * Refactor old static attributes. Added scriptName * Refactor tutorial scripts to include static scriptName attributes for better clarity and organization. * reverted links * Reverted ESM Recommended label * Update ESM tab label in getting-started.md for consistency * added esm change * localisation * fixes * Update docs/tutorials/keyboard-input.md Co-authored-by: Copilot <[email protected]> * Update docs/tutorials/music-visualizer.md Co-authored-by: Copilot <[email protected]> * Refactor tutorial imports to use 'Script' instead of 'ScriptType' for consistency across multiple files. * Update docs/user-manual/animation/anim-events.md Co-authored-by: Will Eastcott <[email protected]> * revert package lock * Update docs/tutorials/light-halos.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/light-halos.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/ui-elements-buttons.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/keepyup-part-six.md Co-authored-by: Will Eastcott <[email protected]> * Update docs/tutorials/google-ads-for-games.md Co-authored-by: Will Eastcott <[email protected]> * removed script type * tabs > spaces * arrow function * Update docs/tutorials/custom-posteffect.md Co-authored-by: Will Eastcott <[email protected]> * Refactor asset.ready callback to use arrow function for improved context handling * Refactor player initialization and entity creation in real-time multiplayer tutorial for improved clarity and consistency * const * Update pan-camera-to-target tutorial to streamline project links * Update docs/tutorials/keyboard-input.md Co-authored-by: Copilot <[email protected]> * Fix key reference in KeyboardHandler onKeyUp method to use constant KEY_A --------- Co-authored-by: Will Eastcott <[email protected]> Co-authored-by: Alex <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 3f8f9a4 commit 70cfe2a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+4218
-14
lines changed

docs/tutorials/Using-forces-on-rigid-bodies.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,93 @@ We include a reset function that brings the cube to its original position and, a
113113

114114
## Full code listing
115115

116+
import Tabs from '@theme/Tabs';
117+
import TabItem from '@theme/TabItem';
118+
119+
<Tabs defaultValue="classic" groupId='script-code'>
120+
<TabItem value="esm" label="ESM">
121+
122+
```javascript
123+
import {
124+
Script, Vec3,
125+
EVENT_KEYDOWN, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_A, KEY_D, KEY_W, KEY_S, KEY_F, KEY_R
126+
} from 'playcanvas';
127+
128+
export class Movement extends Script {
129+
static scriptName = "movement";
130+
131+
// initialize code called once per entity
132+
initialize() {
133+
this.torque = 7;
134+
this.app.keyboard.on(EVENT_KEYDOWN, this.onKeyDown, this);
135+
136+
this.on('destroy', function() {
137+
this.app.keyboard.off(EVENT_KEYDOWN, this.onKeyDown, this);
138+
}, this);
139+
}
140+
141+
onKeyDown(event) {
142+
event.event.preventDefault();
143+
}
144+
145+
// update code called every frame
146+
update(dt) {
147+
//update player's position
148+
this.playerPos = this.entity.getLocalPosition();
149+
150+
const app = this.app;
151+
152+
//keyboard controls and applying forces and moments.
153+
if (app.keyboard.isPressed(KEY_LEFT) ) {
154+
this.entity.rigidbody.applyImpulse(-1, 0, 0);
155+
}
156+
if (app.keyboard.isPressed(KEY_RIGHT) ) {
157+
this.entity.rigidbody.applyImpulse(1, 0, 0);
158+
}
159+
if (app.keyboard.isPressed(KEY_UP) ) {
160+
this.entity.rigidbody.applyImpulse(0, 1, 0);
161+
}
162+
if (app.keyboard.isPressed(KEY_A) ) {
163+
this.entity.rigidbody.applyTorque(0, this.torque, 0);
164+
}
165+
if (app.keyboard.isPressed(KEY_D) ) {
166+
this.entity.rigidbody.applyTorque(0, -this.torque, 0);
167+
}
168+
if (app.keyboard.isPressed(KEY_W) ) {
169+
this.entity.rigidbody.applyTorque(-this.torque, 0, 0);
170+
}
171+
if (app.keyboard.isPressed(KEY_S) ) {
172+
this.entity.rigidbody.applyTorque(this.torque, 0, 0);
173+
}
174+
if (app.keyboard.isPressed(KEY_F) ) {
175+
this.entity.rigidbody.applyForce(0, 9.8, 0);
176+
}
177+
178+
// Keeping the cube on screen - cube moves off of one screen edge then appears from the opposite edge.
179+
if (this.playerPos.x < -9.0) {
180+
this.entity.rigidbody.teleport(8.8, this.playerPos.y, this.playerPos.z);
181+
}
182+
if (this.playerPos.x > 9.0) {
183+
this.entity.rigidbody.teleport(-8.8, this.playerPos.y, this.playerPos.z);
184+
}
185+
186+
// cube reset control
187+
if (app.keyboard.wasPressed(KEY_R) ) {
188+
this.reset();
189+
}
190+
}
191+
192+
reset() {
193+
this.entity.rigidbody.teleport(0, 2, 0);
194+
this.entity.rigidbody.linearVelocity = Vec3.ZERO;
195+
this.entity.rigidbody.angularVelocity = Vec3.ZERO;
196+
}
197+
}
198+
```
199+
200+
</TabItem>
201+
<TabItem value="classic" label="Classic">
202+
116203
```javascript
117204
var DynamicBody = pc.createScript('dynamicBody');
118205

@@ -184,6 +271,9 @@ DynamicBody.prototype.reset = function () {
184271
};
185272
```
186273

274+
</TabItem>
275+
</Tabs>
276+
187277
[1]: https://api.playcanvas.com/engine/classes/RigidBodyComponent.html#applyforce
188278
[2]: https://api.playcanvas.com/engine/classes/RigidBodyComponent.html#applyimpulse
189279
[3]: https://api.playcanvas.com/engine/classes/RigidBodyComponent.html#applytorque

docs/tutorials/anim-blending.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,39 @@ With the animations fully set up, we now need to make it possible for users to i
7575

7676
Remember that parameter `punch` that we set up before? This script will simply toggle that parameter on and off depending on whether the ‘P’ key is currently pressed and whether the character is currently punching:
7777

78+
import Tabs from '@theme/Tabs';
79+
import TabItem from '@theme/TabItem';
80+
81+
<Tabs defaultValue="classic" groupId='script-code'>
82+
<TabItem value="esm" label="ESM">
83+
84+
```javascript
85+
import { Script, EVENT_KEYDOWN, EVENT_KEYUP, KEY_P } from 'playcanvas';
86+
87+
export class KeyboardControls extends Script {
88+
static scriptName = 'keyboardControls';
89+
90+
// initialize code called once per entity
91+
initialize() {
92+
this.app.keyboard.on(EVENT_KEYDOWN, this.keyDown, this);
93+
this.app.keyboard.on(EVENT_KEYUP, this.keyUp, this);
94+
}
95+
96+
update(dt) {
97+
if (this.app.keyboard.wasPressed(KEY_P) && (this.entity.anim.baseLayer.activeState !== 'Punch')) {
98+
this.entity.anim.setBoolean('punch', true);
99+
}
100+
101+
if (this.app.keyboard.wasReleased(KEY_P) && (this.entity.anim.baseLayer.activeState === 'Punch')) {
102+
this.entity.anim.setBoolean('punch', false);
103+
}
104+
}
105+
}
106+
```
107+
108+
</TabItem>
109+
<TabItem value="classic" label="Classic">
110+
78111
```javascript
79112
var KeyboardControls = pc.createScript('keyboardControls');
80113

@@ -95,6 +128,9 @@ KeyboardControls.prototype.update = function(dt) {
95128
};
96129
```
97130

131+
</TabItem>
132+
</Tabs>
133+
98134
From this point, you are able to add more and more animations to the animstategraph asset and start building much more complex animation state graphs!
99135

100136
See the full Scene [here](https://playcanvas.com/editor/scene/1065029)

docs/tutorials/animation-blending.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,58 @@ In the image you can see the animation component in the Inspector. There are 2 a
4040

4141
So this kind of functionality goes beyond the abilities of the humble animation component. A script component is required to cook up this additional behavior. You can see the script component in the above screenshot of the skinned character entity in Editor and it refers to a JS file called animation_blending.js. The contents of this file is:
4242

43+
import Tabs from '@theme/Tabs';
44+
import TabItem from '@theme/TabItem';
45+
46+
<Tabs defaultValue="classic" groupId='script-code'>
47+
<TabItem value="esm" label="ESM">
48+
49+
```javascript
50+
import { Script, KEY_P } from 'playcanvas';
51+
52+
export class AnimationBlending extends Script {
53+
static scriptName = 'animationBlending';
54+
55+
static states = {
56+
idle: {
57+
animation: 'male.json'
58+
},
59+
punch: {
60+
animation: 'male_uppercut_jab.json'
61+
}
62+
}
63+
64+
// initialize code called once per entity
65+
initialize() {
66+
this.blendTime = 0.2;
67+
68+
this.setState('idle');
69+
};
70+
71+
update(dt) {
72+
if (this.app.keyboard.wasPressed(KEY_P)) {
73+
this.setState('punch');
74+
}
75+
76+
if (this.app.keyboard.wasReleased(KEY_P)) {
77+
this.setState('idle');
78+
}
79+
};
80+
81+
setState(state) {
82+
const states = AnimationBlending.states;
83+
84+
this.state = state;
85+
// Set the current animation, taking 0.2 seconds to blend from
86+
// the current animation state to the start of the target animation.
87+
this.entity.animation.play(states[state].animation, this.blendTime);
88+
};
89+
}
90+
```
91+
92+
</TabItem>
93+
<TabItem value="classic" label="Classic">
94+
4395
```javascript
4496
var AnimationBlending = pc.createScript('animationBlending');
4597

@@ -79,6 +131,9 @@ AnimationBlending.prototype.setState = function (state) {
79131
};
80132
```
81133

134+
</TabItem>
135+
</Tabs>
136+
82137
From this point, you are able to add more and more animations to the animation component and start scripting much more complex animation state charts.
83138

84139
See [the full Scene here][2]

docs/tutorials/collision-and-triggers.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,36 @@ The next Entity we'll need is the trigger.
6363

6464
With this Entity we have a *collision* component but no *rigidbody* so it acts as a trigger. The trigger Entity also has a *script* component with some code attached. Triggers are only useful if something happens when they are triggered, so we need to add some code to fire and listen for events when the trigger is activated.
6565

66+
import Tabs from '@theme/Tabs';
67+
import TabItem from '@theme/TabItem';
68+
69+
<Tabs defaultValue="classic" groupId='script-code'>
70+
<TabItem value="esm" label="ESM">
71+
72+
```javascript
73+
import { Script, Vec3 } from 'playcanvas';
74+
75+
export class Trigger extends Script {
76+
static scriptName = "trigger";
77+
78+
// initialize code called once per entity
79+
initialize() {
80+
this.entity.collision.on('triggerenter', this.onTriggerEnter, this);
81+
};
82+
83+
onTriggerEnter(entity) {
84+
this.entity.rigidbody.linearVelocity = Vec3.ZERO;
85+
this.entity.rigidbody.angularVelocity = Vec3.ZERO;
86+
// Reset back to roughly the position the entity started in.
87+
const position = entity.getPosition();
88+
this.entity.rigidbody.teleport(position.x, 10, 0);
89+
};
90+
}
91+
```
92+
93+
</TabItem>
94+
<TabItem value="classic" label="Classic">
95+
6696
```javascript
6797
var Trigger = pc.createScript('trigger');
6898

@@ -80,6 +110,9 @@ Trigger.prototype.onTriggerEnter = function(entity) {
80110
};
81111
```
82112

113+
</TabItem>
114+
</Tabs>
115+
83116
There two significant parts to the code above.
84117

85118
First in the ```initialize``` method we start listening to the **triggerenter** event. This event fires once when a rigid body enters a trigger volume (where a trigger volume is an entity that has a collision component but no rigidbody component). The companion event is **triggerleave** which is fired once the penetrating rigid body leaves the trigger.
@@ -114,6 +147,31 @@ The difference between **contact** and **collisionstart** is subtle but importan
114147

115148
Both events are useful, but in this demo we'll use the **collisionstart** event to trigger a sound effect that plays when the objects hit the ground. Here's the code:
116149

150+
<Tabs defaultValue="classic" groupId='script-code'>
151+
<TabItem value="esm" label="ESM">
152+
153+
```javascript
154+
import { Script } from 'playcanvas';
155+
156+
export class Collider extends Script {
157+
static scriptName = "collider";
158+
159+
// initialize code called once per entity
160+
initialize() {
161+
this.entity.collision.on('collisionstart', this.onCollisionStart, this);
162+
}
163+
164+
onCollisionStart(result) {
165+
if (result.other.rigidbody) {
166+
this.entity.sound.play("hit");
167+
}
168+
}
169+
}
170+
```
171+
172+
</TabItem>
173+
<TabItem value="classic" label="Classic">
174+
117175
```javascript
118176
var Collider = pc.createScript('collider');
119177

@@ -129,6 +187,9 @@ Collider.prototype.onCollisionStart = function (result) {
129187
};
130188
```
131189

190+
</TabItem>
191+
</Tabs>
192+
132193
In the ```initialize``` method we set up the event listener, and then in the event handler we check to see if the other entity has a **rigidbody** component (this is to avoid playing a sound when we enter a trigger volume) and then we play the "hit" sound effect. So now, every time an Entity with the collider script attached collides with another rigid body, it will play the hit sound.
133194

134195
And that's all there is to handling Collisions and Triggers in PlayCanvas.

0 commit comments

Comments
 (0)