Monday 11 April 2022

Web Tutorial: Easter Egg Hunt (Part 3/4)

Now that we have a content and choices display, we will do inventory display. And this is only possible via checking which sections have been visited. To do that, we need a new method, hasVisited(), which will read the visited property. This is relatively straightforward. The method has a parameter, sectionName. We return true or false depending on whether sectionName appears in the visited array.

index.html
    "modifyEggs" : function(qty)
    {
        if (qty != null)
        {
            if (qty == 0)
            {
                game.eggs = 0;
            }
            else
            {
                game.eggs += qty;

                if (game.eggs < 0) game.eggs = 0;    
            }
        }
    },
    "hasVisited" : function(sectionName) {
        return (game.visited.indexOf(sectionName) != -1);
    }

};


But where do we modify the visited property? Ha! Glad you asked!

In the gotoSection() method, add this conditional check. If the flag property of the current section is true, add sectionName to the visited array. Now, this case is not going to come up simply because the only section we have added in sections.js so far, has the flag property set to false.

index.html
game.modifyTime(mins);
game.modifyEggs(eggs);

if (section.flag) game.visited.push(sectionName);

var content = section.content;
var choices = JSON.parse(JSON.stringify(section.choices));


So in sections.js, we are going to add two more elements. They will be sections named "test" and "testGetMercedes". I've added some test content. The flag property for section "testGetMercedes" is set to true.

sections.js
"begin" :
{
    "content" : "<p>Easter has come. The sky is bright and cheery. You are on the porch of the house you live in, facing the Easter Bunny. The Easter Bunny wiggles his little nose and tells you, &quot;<b>Happy Easter! I have hidden several Easter eggs all around the garden, outside of the house. Your mission is to find 30 eggs within 120 minutes. Good hunting!</b>&quot; With that, he hops away.</p><p><img src='img_easterbunny.jpg'></p><p>You are now seated on the steps, and the hunt is under way.</p>",
    "flag" : false,
    "visitedChecks" : null,
    "messages" : [],
    "choices" :
    [
        { "time" : -1, "eggs" : null, "section" : "test", "text" : "Begin the hunt!"}
    ]
},    
"test" :
{
    "content" : "<p>(test) You see a Mercedes.</p>",
    "flag" : false,
    "visitedChecks" : null,
    "messages" : [],
    "choices" : []
},
"testGetMercedes" :
{
    "content" : "<p>(test) You grab the Mercedes.</p>",
    "flag" : true,
    "visitedChecks" : null,
    "messages" : [],
    "choices" : []
},


For these two sections, we now add an entry into their choices arrays. For "test", we add a choice that deducts 1 minute, does nothing to eggs and goes to "testGetMercedes". For "testGetMercedes", we add a choice that deducts 1 minute, does nothing to eggs and goes to "test".

sections.js
"test" :
{
    "content" : "<p>(test) You see a Mercedes.</p>",
    "flag" : false,
    "visitedChecks" : null,
    "messages" : [],
    "choices" : [
        { "time" : -1, "eggs" : null, "section" : "testGetMercedes", "text" : "Get the Mercedes"},
    ]
},
"testGetMercedes" :
{
    "content" : "<p>(test) You grab the Mercedes.</p>",
    "flag" : true,
    "visitedChecks" : null,
    "messages" : [],
    "choices" : [
        { "time" : -1, "eggs" : null, "section" : "test", "text" : "Go back to test"},
    ]
},


Clicking on "Get the Mercedes" should bring you to the second screenshot. And clicking on "Go back to test" should bring you back to the first!





But the Mercedes is still not in your inventory! No sweat, you just need a line in showContent(). In there, you use the hasVisited() method to check if "testGetMercedes" is in the visited array, and if so, add the info to invStr.

index.html
"showContent" : function(content, messages)
{
    $(".timeleft").html(game.timeLeft + " minutes");

    var invStr = "Eggs x " + game.eggs + "<br />";
    if (game.hasVisited("testGetMercedes")) invStr += "Mercedes x 1<br />";
    $(".inventory").html(invStr);


Now as soon as you click on "Get the Mercedes", you should see "Mercedes x 1" in the sidebar.




More operations involving the hasVisited() method

The hasVisited() method is going to be way more useful than what we have just outlined here. Say, if you don't want the user to get more than one Mercedes (how many of those do you really need anyway, even in an online game?), we want a way to prevent the user from getting to that section again. For that, let's get back to sections.js and modify the section "test".

Firstly, visitedChecks should be an array instead of null. We should also change the content property to just "(test)" because we want to use the text elsewhere.
sections.js
"test" :
{
    "content" : "<p>(test)</p>",
    "flag" : false,
    "visitedChecks" : [],
    "messages" : [],
    "choices" : [
        { "time" : -1, "eggs" : null, "section" : "testGetMercedes", "text" : "Get the Mercedes"},
    ]
},


In visitedChecks, we add one object, which has the following properties.
section - that's the name of the section we're checking. In this case, we're checking if "testGetMercedes" has been visited.
content - the HTML that appears if the section has been visited. The default value is null.
choices - the choices that appear if the section has been visited. The default value is null.
contentElse - the HTML that appears if the section has not been visited. The default value is null.
choicesElse - the choices that appear if the section has not been visited. The default value is null.

sections.js
"test" :
{
    "content" : "<p>(test)</p>",
    "flag" : false,
    "visitedChecks" : [
        { "section": "testGetMercedes", "content" : null, "choices": null, "contentElse" : null, "choicesElse" : null },
    ],
    "messages" : [],
    "choices" : []    
},


So for content, we specify that this HTML will appear if "testGetMercedes" was visited. We don't want any choices to appear for this, so we keep it at null.

sections.js
"test" :
{
    "content" : "<p>(test)</p>",
    "flag" : false,
    "visitedChecks" : [
        { "section": "testGetMercedes", "content" : "<p>You have the Mercedes.</p>", "choices": null, "contentElse" : null, "choicesElse" : null },
    ],
    "messages" : [],
    "choices" : []    
},


Here, for contentElse, we see that "You see a Mercedes" now appears in contentElse, because this HTML only appears if "testGetMercedes" has not been visited.

sections.js
"test" :
{
    "content" : "<p>(test)</p>",
    "flag" : false,
    "visitedChecks" : [
        { "section": "testGetMercedes", "content" : "<p>You have the Mercedes.</p>", "choices": null, "contentElse" : "<p>You see a Mercedes.</p>", "choicesElse" : null },
    ],
    "messages" : [],
    "choices" : []    
},


And this choice only appears if "testGetMercedes" has not been visited. The template is the same as other choices we've created.

sections.js
"test" :
{
    "content" : "<p>(test)</p>",
    "flag" : false,
    "visitedChecks" : [
        { "section": "testGetMercedes", "content" : "<p>You have the Mercedes.</p>", "choices": null, "contentElse" : "<p>You see a Mercedes.</p>", "choicesElse" : { "time" : -1, "eggs" : null, "section" : "testGetMercedes", "text" : "Get the Mercedes"} },
    ],
    "messages" : [],
    "choices" : []    
},


Now, this isn't going to appear just yet. There's more work to be done. In the showContent() method, we declare visitedChecks as a variable and set its value as the visitedChecks property of the current section. And the following code only applies if visitedChecks is not null.

index.html
var content = section.content;
var choices = JSON.parse(JSON.stringify(section.choices));

var visitedChecks = section.visitedChecks;
if (visitedChecks != null)
{
                        
}


game.showContent(content, messages);
game.showChoices(sectionName, choices);


Now since visitedChecks is an array, we want to go through every element in there. For our example, though, we only have one element. In here, we want to check if that section specified by the current element of visitedChecks has been visited, using the hasVisited() method. We'll set up an If-else block for that.

index.html
if (visitedChecks != null)
{
    for (let i = 0; i < visitedChecks.length; i++)
    {
        if (game.hasVisited(visitedChecks[i].section))
        {

        }
        else
        {
            
        }
    }
                        
}

game.showContent(content, messages);
game.showChoices(sectionName, choices);


And in here, if that section has been visited, we next check if the choices property of that element is null. If not, we push that value into the current choices array. We do the same for content, except instead of pushing into it, we just add to it.

index.html
if (visitedChecks != null)
{
    for (let i = 0; i < visitedChecks.length; i++)
    {
        if (game.hasVisited(visitedChecks[i].section))
        {
            if (visitedChecks[i].choices != null) choices.push(visitedChecks[i].choices);
            if (visitedChecks[i].content != null) content += visitedChecks[i].content;

        }
        else
        {
            
        }
    }                        
}

game.showContent(content, messages);
game.showChoices(sectionName, choices);


And here we repeat the process, except for contentElse and choicesElse. Now after this block of code, the choices and content will be run through the showChoices() and showContent() methods.

index.html
if (visitedChecks != null)
{
    for (let i = 0; i < visitedChecks.length; i++)
    {
        if (game.hasVisited(visitedChecks[i].section))
        {
            if (visitedChecks[i].choices != null) choices.push(visitedChecks[i].choices);
            if (visitedChecks[i].content != null) content += visitedChecks[i].content;
        }
        else
        {
            if (visitedChecks[i].choicesElse != null) choices.push(visitedChecks[i].choicesElse);
            if (visitedChecks[i].contentElse != null) content += visitedChecks[i].contentElse;  
         
        }
    }                        
}

game.showContent(content, messages);
game.showChoices(sectionName, choices);


Let's test this! You see "(test)", followed by the HTML and choices that should appear if you have not visited "testGetMercedes".




If you click n "Get the Mercedes", you should see what you got the last time. Now click "Go back to test"...




...and now you should see something completely different! The HTML has changed for the section "test" and there are no choices other than the default "Restart" button.




Next

Good work! With all this done, all that's really left is to work on win/lose scenarios.

No comments:

Post a Comment