Tuesday 16 April 2019

Web Tutorial: Easter Bunny River Crossing Game (Part 3/4)

This is where we lay the foundation for the code we're going to write later. First, we prepare objects. There'll be an object for the game, an object for the passengers, and the raft.
        <script>
            var game =
            {

            }

            var passenger =
            {
              
            }

            var raft =
            {
              
            }
        </script>


The game object

We'll start with the game object. This object controls the flow of the game - when it starts, ends and pauses. It helps track of the passengers and the raft, and displays helpful messages.

Here's an introduction to this object's properties.
- started is defaulted to false and is true when the game has started.
- paused is used to disable button clicks when you need to.
- moves is a number which keeps track of how many times the raft has moved.
            var game =
            {
                started: false,
                paused: false,
                moves: 0
            }


Now for the methods...
- reset() brings everything back to the game's initial state
- start() sets the started flag to true and prepares the game for play.
- check() does an inventory of each passenger's position, and the raft's, and determines if the game has ended in either victory or defeat.
- showMessage() displays the appropriate message in the water according to what messageType is passed in, and also dictates the text in the orange button.
            var game =
            {
                started: false,
                paused: false,
                moves: 0,
                reset: function()
                {

                },
                start: function()
                {

                },
                check: function()
                {

                },
                showMessage: function(messageType)
                {

                }
            }


The passenger object

This object has two properties - id and position. The value of id depends on whether it's the fox, bunny or egg. position has basically three values - "leftBank", "rightBank" and "raft". By default, this is "leftBank".
            var passenger =
            {
                id: "",
                position: "leftBank"  
            };


passenger also has two methods - render() and move(). render() places the HTML and CSS of the passenger in the placeholder dictated by the parameter position. move(), well, moves the passenger from bank to raft, or vice versa.
            var passenger =
            {
                id: "",
                position: "leftBank",
                render: function(position)
                {

                },
                move: function()
                {

                }  
            };


After that, we clone the passenger object to three new objects - fox, bunny and egg. So now these three new objects inherit the properties and methods of the passenger object. We don't have to declare them three more times. This is done using the assign() method of the Object object.

Read up more here.
            var passenger =
            {
                id: "",
                position: "leftBank",
                render: function(position)
                {

                },
                move: function(position)
                {

                }  
            };

            var fox = Object.assign({}, passenger);
            fox.id = "fox";

            var bunny = Object.assign({}, passenger);
            bunny.id = "bunny";

            var egg = Object.assign({}, passenger);
            egg.id = "egg";



The raft object

The raft object has one property only - position. It's either "leftBank" (the default) or "rightBank".
            var raft =
            {
                position: "leftBank"
            }


It also has a move() function, which moves the raft from bank to bank.
            var raft =
            {
                position: "leftBank",
                move: function()
                {

                }
            }


Filling in the methods!

Let's begin with the reset() method of the game object. First, we set all passengers' position property to "leftBank".
            var game =
            {
                started: false,
                paused: false,
                moves: 0,
                reset: function()
                {
                    bunny.position = "leftBank";
                    egg.position = "leftBank";
                    fox.position = "leftBank";
                },
                start: function()
                {

                },
                check: function()
                {

                },
                showMessage: function(messageType)
                {

                }
            }


Then we clear all placeholders where the passengers could appear in, except for the left bank.
                reset: function()
                {
                    bunny.position = "leftBank";
                    egg.position = "leftBank";
                    fox.position = "leftBank";

                    document.getElementById("raftPassenger").innerHTML = "";
                    document.getElementById("rightBank_bunny").innerHTML = "";
                    document.getElementById("rightBank_egg").innerHTML = "";
                    document.getElementById("rightBank_fox").innerHTML = "";
                },


Next, we run the render() method of each passenger, to place them on the left bank. We'll be building these methods soon.
                reset: function()
                {
                    bunny.position = "leftBank";
                    egg.position = "leftBank";
                    fox.position = "leftBank";

                    document.getElementById("raftPassenger").innerHTML = "";
                    document.getElementById("rightBank_bunny").innerHTML = "";
                    document.getElementById("rightBank_egg").innerHTML = "";
                    document.getElementById("rightBank_fox").innerHTML = "";

                    bunny.render("leftBank");
                    egg.render("leftBank");
                    fox.render("leftBank");
                },


Then we set the position property of the raft object, to "leftBank". And the marginLeft property of raft to 0%.
                reset: function()
                {
                    bunny.position = "leftBank";
                    egg.position = "leftBank";
                    fox.position = "leftBank";

                    document.getElementById("raftPassenger").innerHTML = "";
                    document.getElementById("rightBank_bunny").innerHTML = "";
                    document.getElementById("rightBank_egg").innerHTML = "";
                    document.getElementById("rightBank_fox").innerHTML = "";

                    bunny.render("leftBank");
                    egg.render("leftBank");
                    fox.render("leftBank");

                    raft.position = "leftBank";
                    document.getElementById("raft").style.marginLeft = "0%";
                },


After that, run the showMessage() method using the argument "title". Again, we'll build this method later.

Finish off by setting the game object's started and paused properties to false, and moves to 0.
                reset: function()
                {
                    bunny.position = "leftBank";
                    egg.position = "leftBank";
                    fox.position = "leftBank";

                    document.getElementById("raftPassenger").innerHTML = "";
                    document.getElementById("rightBank_bunny").innerHTML = "";
                    document.getElementById("rightBank_egg").innerHTML = "";
                    document.getElementById("rightBank_fox").innerHTML = "";

                    bunny.render("leftBank");
                    egg.render("leftBank");
                    fox.render("leftBank");

                    raft.position = "leftBank";
                    document.getElementById("raft").style.marginLeft = "0%";

                    this.showMessage("title");
                    this.started = false;
                    this.paused = false;
                    this.moves = 0;
                },


The purpose of the reset() method is to revert all game properties to initial settings, but without the game being started. This would happen when the site is loaded, so do this.
<body onload="game.reset()">


As promised, we will build the render() method of the passenger object. First, declare a variable placeholder. If position is "raft", then use "raftPassenger" as the value. If not (that is, if it's either "leftBank" or "rightBank"), append an underscore followed by the object's id property. Thus if you were attempting to run the render() method of the fox object, you might get "leftBank_fox" or "rightBank_fox".
            var passenger =
            {
                id: "",
                position: "leftBank",
                render: function(position)
                {
                    var placeholder = (position == "raft" ? "raftPassenger" : position + "_" + this.id);
                },
                move: function(position)
                {

                }  
            };


The use placeholder to get the object that it points to. Remember we declared some placeholders and set their ids in the previous part? Well, now the innerHTML property of that placeholder will be assigned the innerHTML property of the HTML template of this object!
            var passenger =
            {
                id: "",
                position: "leftBank",
                render: function(position)
                {
                    var placeholder = (position == "raft" ? "raftPassenger" : position + "_" + this.id);

                    document.getElementById(placeholder).innerHTML = document.getElementById("template_" + this.id).innerHTML;
                },
                move: function(position)
                {

                }  
            };


Reload your browser. See, the fox, Easter Bunny and Easter egg are on the left bank!


Now let's work on the showMessage() method of the game object. Remember the divs we created in the previous part with the ids messageBox and btnStart? It's time to get them here, and assign them to variables messageBox and button.
                showMessage: function(messageType)
                {
                    var messageBox = document.getElementById("messageBox");
                    var button = document.getElementById("btnStart");
                }


If messageType is "title", put the following content in messageBox and set button's caption to "Start".
                showMessage: function(messageType)
                {
                    var messageBox = document.getElementById("messageBox");
                    var button = document.getElementById("btnStart");

                    if (messageType == "title")
                    {
                        messageBox.innerHTML = "<h3>Easter Bunny River Crossing Game</h3>";
                        button.innerHTML = "Start";
                    }
                }


There you go!


Now let's expand further on the showMessage() method. If messageType is "started", set the content and button caption as follows.
                showMessage: function(messageType)
                {
                    var messageBox = document.getElementById("messageBox");
                    var button = document.getElementById("btnStart");

                    if (messageType == "title")
                    {
                        messageBox.innerHTML = "<h3>Easter Bunny River Crossing Game</h3>";
                        button.innerHTML = "Start";
                    }

                    if (messageType == "started")
                    {
                        messageBox.innerHTML = "<ol><li>The objective of this game is to get all three passengers across to the other bank.</li><li>The raft can hold only one passenger at a time.</li><li>The fox cannot be left alone with the Easter Bunny.</li><li>The Easter Bunny cannot be left alone with the egg.</li></ol>";
                        button.innerHTML = "Restart";
                    }
                }


When will messageType be "started"? Why, when we run the start() method of the game object, of course. It will first run the reset() method, set started to true, and run the showMessage() method with "started" as an argument!
                reset: function()
                {
                    bunny.position = "leftBank";
                    egg.position = "leftBank";
                    fox.position = "leftBank";

                    document.getElementById("raftPassenger").innerHTML = "";
                    document.getElementById("rightBank_bunny").innerHTML = "";
                    document.getElementById("rightBank_egg").innerHTML = "";
                    document.getElementById("rightBank_fox").innerHTML = "";

                    bunny.render("leftBank");
                    egg.render("leftBank");
                    fox.render("leftBank");

                    raft.position = "leftBank";
                    document.getElementById("raft").style.marginLeft = "0%";

                    this.showMessage("title");
                    this.started = false;
                    this.paused = false;
                    this.moves = 0;
                },
                start: function()
                {
                    this.reset();
                    this.started = true;
                    this.showMessage("started");
                },


And when will start() be run? When we click on the orange button!
                <div class="water">
                    <br />
                    <div id="messageBox">

                    </div>
                    <button id="btnStart" onclick="game.start()"></button>
                </div>


Now reload and click on the orange button!


It's looking a little cluttered and misaligned, so let's do this. This makes ordered lists within the messageBox div smaller in font, and aligns them left instead of center.
            #messageBox
            {
                width: 90%;
                height: 40%;
                font-size: 16px;
                font-family: verdana;
                color: #FFFFFF;
                margin: 0 auto 0 auto;
                text-align: center;
            }

            #messageBox ol
            {
                font-size: 12px;
                text-align: left;
            }


Looking good!


Next

This part was a little short, but rest assured that this was merely the groundwork for the real meat of the JavaScript. After this, we'll work on the move() methods of the passenger and raft objects, and tie everything up nicely.

No comments:

Post a Comment