Browse Source

add note color and more coroutine info

Gregg Tavares 6 years ago
parent
commit
a7dd46198d
2 changed files with 51 additions and 10 deletions
  1. 42 4
      threejs/lessons/threejs-game.md
  2. 9 6
      threejs/threejs-game-conga-line-w-notes.html

+ 42 - 4
threejs/lessons/threejs-game.md

@@ -1871,10 +1871,31 @@ function* countOTo9() {
 }
 ```
 
-If we passed this function to the `CoroutineRunner` above it would print
+If we added this function to the `CoroutineRunner` above it would print
 out each number, 0 to 9, once per frame or rather once per time we called `runner.update`.
 
-In the player let's use a coroutine to emit a note every half second to 1 second
+```js
+const runner = new CoroutineRunner();
+runner.add(count0To9);
+while(runner.isBusy()) {
+  runner.update();
+}
+```
+
+Coroutines are removed automatically when they are finished. 
+To remove a coroutine early, before it reaches the end you need to keep
+a reference to its generator like this
+
+```js
+const gen = count0To9();
+runner.add(gen);
+
+// sometime later
+
+runner.remove(gen);
+```
+
+In any case, in the player let's use a coroutine to emit a note every half second to 1 second
 
 ```js
 class Player extends Component {
@@ -1928,12 +1949,16 @@ function makeTextTexture(str) {
   ctx.font = '60px sans-serif';
   ctx.textAlign = 'center';
   ctx.textBaseline = 'middle';
+  ctx.fillStyle = '#FFF';
   ctx.fillText(str, ctx.canvas.width / 2, ctx.canvas.height / 2);
   return new THREE.CanvasTexture(ctx.canvas);
 }
 const noteTexture = makeTextTexture('♪');
 ```
 
+The texture we create above is white each means when we use it
+we can set the material's color and get a note of any color.
+
 Now that we have a noteTexture here's the `Note` component.
 It uses `SpriteMaterial` and a `Sprite` like we covered in
 [the article on billboards](threejs-billboards.html) 
@@ -1944,6 +1969,7 @@ class Note extends Component {
     super(gameObject);
     const {transform} = gameObject;
     const noteMaterial = new THREE.SpriteMaterial({
+      color: new THREE.Color().setHSL(rand(1), 1, 0.5),
       map: noteTexture,
       side: THREE.DoubleSide,
       transparent: true,
@@ -1981,8 +2007,8 @@ from the scene and the note itself from active gameobjects.
 {{{example url="../threejs-game-conga-line-w-notes.html"}}}
 
 You might be asking, why not use `setTimeout`? The problem with `setTimeout`
-is it's not related to the game clock. For example above we make the maximum
-amount of time allowed to elapse between frames is 1/20th of a second.
+is it's not related to the game clock. For example above we made the maximum
+amount of time allowed to elapse between frames to be 1/20th of a second.
 Our coroutine system will respect that limit but `setTimeout` would not.
 
 Of course we could have made a simple timer ourselves
@@ -1992,6 +2018,7 @@ class Player ... {
   update() {
     this.noteTimer -= globals.deltaTime;
     if (this.noteTimer <= 0) {
+      // reset timer
       this.noteTimer = rand(0.5, 1);
       // create a gameobject with a note component
     }
@@ -2037,6 +2064,17 @@ function* animalCoroutine() {
 This would have worked but of course as soon as our states were not so linear
 we'd have had to switch to a `FiniteStateMachine`.
 
+It also wasn't clear to me if coroutines should run independently of their
+components. We could have made a global `CoroutineRunner` and put all
+coroutines on it. That would make cleaning them up harder. As it is now
+if the gameobject is removed all of it's components are removed and
+therefore the coroutine runners created are no longer called and it will
+all get garbage collected. If we had global runner then it would be
+the responsibility of each component to remove any coroutines it added
+or else some other mechanism of registering coroutines with a particular
+component or gameobject would be needed so that removing one removes the
+others.
+
 There are lots more issues a
 normal game engine would deal with. As it is there is no order to how
 gameobjects or their components are run. They are just run in the order added.

+ 9 - 6
threejs/threejs-game-conga-line-w-notes.html

@@ -194,11 +194,11 @@ function main() {
   const models = {
     pig:    { url: 'resources/models/animals/Pig.gltf' },
     cow:    { url: 'resources/models/animals/Cow.gltf' },
-    llama:  { url: 'resources/models/animals/Llama.gltf' },
-    pug:    { url: 'resources/models/animals/Pug.gltf' },
-    sheep:  { url: 'resources/models/animals/Sheep.gltf' },
-    zebra:  { url: 'resources/models/animals/Zebra.gltf' },
-    horse:  { url: 'resources/models/animals/Horse.gltf' },
+    llama:  { url: 'resources/models/animals/llama.gltf' },
+    pug:    { url: 'resources/models/animals/pug.gltf' },
+    sheep:  { url: 'resources/models/animals/sheep.gltf' },
+    zebra:  { url: 'resources/models/animals/zebra.gltf' },
+    horse:  { url: 'resources/models/animals/horse.gltf' },
     knight: { url: 'resources/models/knight/KnightCharacter.gltf' },
   };
   {
@@ -676,16 +676,19 @@ function main() {
     ctx.font = '60px sans-serif';
     ctx.textAlign = 'center';
     ctx.textBaseline = 'middle';
+    ctx.fillStyle = '#FFF';
     ctx.fillText(str, ctx.canvas.width / 2, ctx.canvas.height / 2);
     return new THREE.CanvasTexture(ctx.canvas);
   }
+  const noteTexture = makeTextTexture('♪');
 
   class Note extends Component {
     constructor(gameObject) {
       super(gameObject);
       const {transform} = gameObject;
       const noteMaterial = new THREE.SpriteMaterial({
-        map: makeTextTexture('♪'),
+        color: new THREE.Color().setHSL(rand(1), 1, 0.5),
+        map: noteTexture,
         side: THREE.DoubleSide,
         transparent: true,
       });