Skip to content

Commit

Permalink
Add changes to chapters based on prospect feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
MihailTodorov committed Dec 21, 2023
1 parent 7bf9a74 commit 115a639
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 22 deletions.
2 changes: 1 addition & 1 deletion chapters/chapter-2/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</code></pre><p>With a random value.</p><p>Now that we have our object, we can register it as a model. To do that, first we will need to write the following code:</p><pre><code>engine.whenReady.then(() =&gt; {

})
</code></pre><p>This is because we need to wait for Gameface to load before registering our model. To do that we need to use <code>engine.whenReady</code> which will return a Promise. After that promise is resolved in our <code>then()</code> function, we can register and start using our models.</p><div class="alert alert-warning d-flex" role=alert><div class="flex-shrink-1 alert-icon"></div><div class=w-100>A quick note before continuing - as you might have already noticed, every function that we use to leverage Gameface’s features starts with engine. The reason is that the cohtml.js file exports the engine module that contains all of the functions we need to communicate with the backend. You can read more about what the engine module does in our <a href=https://coherent-labs.com/Documentation/cpp-gameface/df/d01/javascript_virtual_machine.html>documentation</a>.</div></div><p>Now that we know Gameface is ready, we can register our model. This happens by using the engine.createJSModel function:</p><pre><code>engine.whenReady.then(() =&gt; {
</code></pre><p>This is because we need to wait for Gameface to load before registering our model. To do that we need to use <code>engine.whenReady</code> which will return a Promise. After that promise is resolved in our <code>then()</code> function, we can register and start using our models.</p><div class="alert alert-warning d-flex" role=alert><div class="flex-shrink-1 alert-icon"></div><div class=w-100>A quick note before continuing - as you might have already noticed, every function that we use to leverage Gameface’s features starts with engine. The reason is that the cohtml.js file exports the engine module that contains all of the functions we need to communicate with the backend. You can read more about what the engine module does in our <a href=https://docs.coherent-labs.com/cpp-gameface/integration/optional_features/javascript_native/>documentation</a>.</div></div><p>Now that we know Gameface is ready, we can register our model. This happens by using the engine.createJSModel function:</p><pre><code>engine.whenReady.then(() =&gt; {
engine.createJSModel('PlayerModel', model);
engine.synchronizeModels();
})
Expand Down
22 changes: 13 additions & 9 deletions chapters/chapter-6/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,20 @@
&lt;dropdown-option slot=&quot;option&quot;&gt;3840x2160&lt;/dropdown-option&gt;
&lt;/gameface-dropdown&gt;
&lt;/div&gt;
</code></pre><p>And in the Player:</p><figure class=border-0><img class="img-fluid lazyload blur-up" data-sizes=auto src=/chapters/chapter-6/chapter-6_1.png width=1120 height=759 alt=chapter-6_1><noscript><img class=img-fluid sizes=100vw src=/chapters/chapter-6/chapter-6_1.png width=1120 height=759 alt=chapter-6_1></noscript><figcaption class=figure-caption><em>A resolution Dropdown</em></figcaption></figure><h3 id=checkbox>Checkbox<a href=#checkbox class=anchor aria-hidden=true>#</a></h3><p>Up next is the show subtitles <code>checkbox</code>. We’ll add another <code>.settings-option-row</code> div and inside we’ll add the label ‘Enable Subtitles’ again in a <code>div</code> and the <code>checkbox</code> component. To add the component, you simply need to add the <code>&lt;gameface-checkbox>&lt;/gameface-checkbox></code> element to the <code>index.html</code>. Inside this element you can add two slots with the <code>&lt;gameface-checkbox>&lt;/gameface-checkbox></code> element -</p><ul><li>One for the checkbox background, which is the checkmark:</li></ul><pre><code>&lt;component-slot data-name=&quot;checkbox-background&quot;&gt;&lt;/component-slot&gt;
</code></pre><ul><li>And another one for the label:</li></ul><pre><code>&lt;component-slot data-name=&quot;label&quot;&gt;&lt;/component-slot&gt;
</code></pre><p>Since we already have a label, we’ll add the component slot for the label with an empty span tag. We’ll then add the one for the <code>checkbox background</code> and inside - a <code>div</code> with a class <code>.checkbox-background</code></p><pre><code>&lt;gameface-checkbox class=&quot;checkbox-component&quot;&gt;
&lt;component-slot data-name=&quot;checkbox-background&quot;&gt;
&lt;div class=&quot;checkbox-background&quot;&gt;&lt;/div&gt;
&lt;/component-slot&gt;
&lt;component-slot data-name=&quot;label&quot;&gt;
&lt;span&gt;&lt;/span&gt;
&lt;/component-slot&gt;
</code></pre><p>And in the Player:</p><figure class=border-0><img class="img-fluid lazyload blur-up" data-sizes=auto src=/chapters/chapter-6/chapter-6_1.png width=1120 height=759 alt=chapter-6_1><noscript><img class=img-fluid sizes=100vw src=/chapters/chapter-6/chapter-6_1.png width=1120 height=759 alt=chapter-6_1></noscript><figcaption class=figure-caption><em>A resolution Dropdown</em></figcaption></figure><h3 id=checkbox>Checkbox<a href=#checkbox class=anchor aria-hidden=true>#</a></h3><p>Up next is the show subtitles <code>checkbox</code>. We’ll add another <code>.settings-option-row</code> div and inside we’ll add the label ‘Enable Subtitles’ again in a <code>div</code> and the <code>checkbox</code> component. To add the component, you simply need to add the <code>&lt;gameface-checkbox>&lt;/gameface-checkbox></code> element to the <code>index.html</code>. Inside this element you can add two slots with the <code>&lt;gameface-checkbox>&lt;/gameface-checkbox></code> element -</p><ul><li>We&rsquo;ll add only a single one for the checkbox background, which is the checkmark:</li></ul><pre><code>&lt;component-slot data-name=&quot;checkbox-background&quot;&gt;&lt;/component-slot&gt;
</code></pre><p>We’ll then add it and then put inside - a <code>div</code> with a class <code>.checkbox-background</code></p><pre><code>&lt;gameface-checkbox class=&quot;checkbox-component&quot;&gt;
&lt;component-slot data-name=&quot;checkbox-background&quot;&gt;
&lt;div class=&quot;guic-checkbox-background&quot;&gt;&lt;/div&gt;
&lt;/component-slot&gt;
&lt;/gameface-checkbox&gt;
</code></pre><p>In the end the code should look like this:</p><pre><code>&lt;div class=&quot;settings-option-row&quot;&gt;
&lt;div&gt;Enable Subtitles&lt;/div&gt;
&lt;gameface-checkbox class=&quot;checkbox-component&quot;&gt;
&lt;component-slot data-name=&quot;checkbox-background&quot;&gt;
&lt;div class=&quot;guic-checkbox-background&quot;&gt;&lt;/div&gt;
&lt;/component-slot&gt;
&lt;/gameface-checkbox&gt;
&lt;/div&gt;
</code></pre><p>The checkbox-background has already been set in our style.css, so if we open the Player we’ll see the following:</p><figure class=border-0><img class="img-fluid lazyload blur-up" data-sizes=auto src=/chapters/chapter-6/chapter-6_2.png width=1281 height=742 alt=chapter-6_2><noscript><img class=img-fluid sizes=100vw src=/chapters/chapter-6/chapter-6_2.png width=1281 height=742 alt=chapter-6_2></noscript><figcaption class=figure-caption><em>The subtitles Checkbox</em></figcaption></figure><h3 id=range-slider>Range slider<a href=#range-slider class=anchor aria-hidden=true>#</a></h3><p>For our final options we’ll be using the range slider component. We’ll firstly use it as a way to control the volume of the game, and then to choose the difficulty level. To do this we’ll need to create a <code>.settings-option-column</code> container; inside we’ll add another <code>.settings-option-row</code>. Inside it, we’ll add a label just like in the previous examples - ‘Volume’ and a new container <code>.volume-value</code> that will display the value of the slider inside.</p><pre><code>&lt;div class=&quot;settings-option-column&quot;&gt;
&lt;div class=&quot;settings-option-row&quot;&gt;
&lt;div&gt;Volume&lt;/div&gt;
Expand Down
10 changes: 6 additions & 4 deletions chapters/chapter-8/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
null,
null
],
</code></pre><div class="alert alert-warning d-flex" role=alert><div class="flex-shrink-1 alert-icon"></div><div class=w-100>Please note that there are multiple ways to create an inventory - it all depends on your preferences, use case and the size of inventory. While this is the simplest way to achieve our current goal, this might not necessarily be the most optimal approach for yours.</div></div><h2 id=building-the-inventory-grid>Building the inventory grid<a href=#building-the-inventory-grid class=anchor aria-hidden=true>#</a></h2><p>We can now start building our Inventory grid - we will first add a new screen in the <code>index.html</code> file called “inventory” and data-bind it like we did for the Settings Menu in the previous chapter. This time, however, the <code>activePauseMenu</code> should be inventory instead of settings.</p><pre><code>&lt;div class=&quot;inventory&quot; data-bind-if=&quot;{{PlayerModel.activePauseMenu}} === 'inventory'&quot;&gt;
</code></pre><div class="alert alert-warning d-flex" role=alert><div class="flex-shrink-1 alert-icon"></div><div class=w-100>Please note that there are multiple ways to create an inventory - it all depends on your preferences, use case and the size of inventory. While this is the simplest way to achieve our current goal, this might not necessarily be the most optimal approach for yours.</div></div><h2 id=building-the-inventory-grid>Building the inventory grid<a href=#building-the-inventory-grid class=anchor aria-hidden=true>#</a></h2><p>We can now start building our Inventory grid - we will first add a new screen in the <code>index.html</code> file in the <code>.pause-menu</code> beneath the <code>.settings-menu</code> called “inventory” and data-bind it like we did for the Settings Menu in the previous chapter. This time, however, the <code>activePauseMenu</code> should be inventory instead of settings.</p><pre><code>&lt;div class=&quot;inventory&quot; data-bind-if=&quot;{{PlayerModel.activePauseMenu}} === 'inventory'&quot;&gt;

&lt;/div&gt;
</code></pre><p>Inside we’ll add:</p><pre><code>&lt;div class=&quot;inventory-grid&quot;&gt;
Expand All @@ -42,8 +42,10 @@
&lt;div class=&quot;inventory-details&quot;&gt;

&lt;/div&gt;
</code></pre><h3 id=looping-through-the-inventory-elements>Looping through the inventory elements<a href=#looping-through-the-inventory-elements class=anchor aria-hidden=true>#</a></h3><p>To build the grid, we’ll use another data-binding called <code>data-bind-for</code>. This is a structural data-binding just like data-bind-if and allows you to loop through an array and duplicate html elements based on that array.</p><p>The syntax for data-bind-for is <code>“iterator:{{Model}}”</code>, which is quite similar to <code>data-bind-class-toggle</code>. Here we have an iterator and the model; optionally, we can also use the index of the looped element if we need it - <code>“index, iterator:{{Model}}”</code>. We can then leverage the iterator or index as a separate model that corresponds to that array item.</p><p>In our case we’ll make a div element with the <code>.inventory-grid-cell</code> class and inside we’ll add another with the <code>.inventory-item</code> one:</p><pre><code>&lt;div class=&quot;inventory-grid-cell&quot;&gt;
&lt;div class=&quot;inventory-item&quot;&gt;&lt;/div&gt;
</code></pre><h3 id=looping-through-the-inventory-elements>Looping through the inventory elements<a href=#looping-through-the-inventory-elements class=anchor aria-hidden=true>#</a></h3><p>To build the grid, we’ll use another data-binding called <code>data-bind-for</code>. This is a structural data-binding just like data-bind-if and allows you to loop through an array and duplicate html elements based on that array.</p><p>The syntax for data-bind-for is <code>“iterator:{{Model}}”</code>, which is quite similar to <code>data-bind-class-toggle</code>. Here we have an iterator and the model; optionally, we can also use the index of the looped element if we need it - <code>“index, iterator:{{Model}}”</code>. We can then leverage the iterator or index as a separate model that corresponds to that array item.</p><p>In our case we’ll make a div element with the <code>.inventory-grid-cell</code> class and inside we’ll add another with the <code>.inventory-item</code> one and place them in the <code>.inventory-grid</code> element:</p><pre><code>&lt;div class=&quot;inventory-grid&quot;&gt;
&lt;div class=&quot;inventory-grid-cell&quot;&gt;
&lt;div class=&quot;inventory-item&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</code></pre><p>It’s time to fill our inventoryItems model objects with data:</p><pre><code> inventoryItems: [
{
Expand Down Expand Up @@ -131,7 +133,7 @@
&lt;div class=&quot;inventory-details-description&quot; data-bind-value=&quot;PlayerModel.inventoryItems[{{PlayerModel.selectedItem}}].description&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</code></pre><p>If we open the Player we’ll see the details of the first item appear:</p><figure class=border-0><img class="img-fluid lazyload blur-up" data-sizes=auto src=/chapters/chapter-8/chapter-8_5.png width=1281 height=750 alt=chapter-8_5><noscript><img class=img-fluid sizes=100vw src=/chapters/chapter-8/chapter-8_5.png width=1281 height=750 alt=chapter-8_5></noscript><figcaption class=figure-caption><em></em></figcaption></figure><p>Since we have already set up our logic for changing the selected item, if we click on other items their details will be shown:</p><figure class=border-0><img class="img-fluid lazyload blur-up" data-sizes=auto src=/chapters/chapter-8/chapter-8_6.png width=1280 height=750 alt=chapter-8_6><noscript><img class=img-fluid sizes=100vw src=/chapters/chapter-8/chapter-8_6.png width=1280 height=750 alt=chapter-8_6></noscript><figcaption class=figure-caption><em>We have two beers, nice!</em></figcaption></figure><p>While this works, it’s not an ideal solution for when we have large codebases or models, as it will make our code harder to read and increase the chance of making mistakes. This is why Gameface allows the use of something called an <a href=https://coherent-labs.com/Documentation/cpp-gameface/d1/ddb/data_binding.html>Observable model (<em>Under Observable Model</em>)</a>.</p><p>An <code>Observable model</code> is a smart object which will automatically push itself for update when some of its properties are changed. This is especially useful in situations where we need to keep an active state (as is our case in the inventory active item).</p><p>To create an Observable model, we’ll just need to add the following code in our <code>model.js</code> file:</p><pre><code> engine.createJSModel(&quot;PlayerModel&quot;, model);
</code></pre><p>If we open the Player we’ll see the details of the first item appear:</p><figure class=border-0><img class="img-fluid lazyload blur-up" data-sizes=auto src=/chapters/chapter-8/chapter-8_5.png width=1281 height=750 alt=chapter-8_5><noscript><img class=img-fluid sizes=100vw src=/chapters/chapter-8/chapter-8_5.png width=1281 height=750 alt=chapter-8_5></noscript><figcaption class=figure-caption><em></em></figcaption></figure><p>Since we have already set up our logic for changing the selected item, if we click on other items their details will be shown:</p><figure class=border-0><img class="img-fluid lazyload blur-up" data-sizes=auto src=/chapters/chapter-8/chapter-8_6.png width=1280 height=750 alt=chapter-8_6><noscript><img class=img-fluid sizes=100vw src=/chapters/chapter-8/chapter-8_6.png width=1280 height=750 alt=chapter-8_6></noscript><figcaption class=figure-caption><em>We have two beers, nice!</em></figcaption></figure><p>While this works, it’s not an ideal solution for when we have large codebases or models, as it will make our code harder to read and increase the chance of making mistakes. This is why Gameface allows the use of something called an <a href=https://coherent-labs.com/Documentation/cpp-gameface/d1/ddb/data_binding.html>Observable model (<em>Under Observable Model</em>)</a>.</p><p>An <code>Observable model</code> is a smart object which will automatically push itself for update when some of its properties are changed. This is especially useful in situations where we need to keep an active state (as is our case in the inventory active item).</p><p>To create an Observable model, we’ll just need to create the <code>observableModel</code> in our <code>model.js</code> file in the <code>engine.whenReady</code>:</p><pre><code> engine.createJSModel(&quot;PlayerModel&quot;, model);

engine.createObservableModel(&quot;activeItem&quot;);
activeItem.item = PlayerModel.inventoryItems[PlayerModel.selectedItem];
Expand Down
Loading

0 comments on commit 115a639

Please sign in to comment.