Thursday, 18 April 2019

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

OK, guys! Welcome back for the final installment.

We're going to start off with the raft object now. When you click the boatman, the raft will move. So do this.
                    <div class="path">
                        <div id="raft">
                            <div class="placeholder" id="raftPassenger">

                            </div>
                            <div class="boatman" onclick="raft.move();"></div>
                        </div>
                    </div>


Next, modify the move() method of the raft object. It will work only if the game is started and not paused. So add the conditions in an If block.
            var raft =
            {
                position: "leftBank",
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                       
                    }
                }
            };


Next, declare a variable, destination. The destination can only be "leftBank" or "rightBank". If the raft is currently at the left bank, then its destination must be the right bank. The reverse is also true.
            var raft =
            {
                position: "leftBank",
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = (this.position == "leftBank" ? "rightBank" : "leftBank");                   
                    }
                }
            };


Next, get the raft and set it to a variable, objRaft. if the destination is "leftBank", then the marginLeft property should be 0%. If not, it should be 78%. You'll see why soon.
            var raft =
            {
                position: "leftBank",
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = (this.position == "leftBank" ? "rightBank" : "leftBank");
                        var objRaft = document.getElementById("raft");

                        if (destination == "leftBank")
                        {
                            objRaft.style.marginLeft = "0%";
                        }
                        else
                        {
                            objRaft.style.marginLeft = "78%";
                        }                       
                    }
                }
            };


Then we pause the game.
            var raft =
            {
                position: "leftBank",
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = (this.position == "leftBank" ? "rightBank" : "leftBank");
                        var objRaft = document.getElementById("raft");

                        if (destination == "leftBank")
                        {
                            objRaft.style.marginLeft = "0%";
                        }
                        else
                        {
                            objRaft.style.marginLeft = "78%";
                        }

                        game.paused = true;                       
                    }
                }
            };


And here, we use the setTimeout() function, with an interval of, say, one second. Set raft to the current object...
            var raft =
            {
                position: "leftBank",
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = (this.position == "leftBank" ? "rightBank" : "leftBank");
                        var objRaft = document.getElementById("raft");

                        if (destination == "leftBank")
                        {
                            objRaft.style.marginLeft = "0%";
                        }
                        else
                        {
                            objRaft.style.marginLeft = "78%";
                        }

                        game.paused = true;

                        var raft = this;

                        setTimeout
                        (
                            function()
                            {

                            },
                            1000
                        );                       
                    }
                }
            };


And once the interval of one second is reached, set the raft position, unpause the game, increment the moves property, and run the check() method! We'll be working on the check() method soon.

What this does is, every time the raft moves, it's counted as one move. We pause the game while the raft is moving so that clicks on the passengers and the raft won't affect anything. Of course, we'll update the raft position, and then the check() method ensures that if the fox is left alone with the EasterBunny or the Easter Bunny is left alone with the Easter egg, shit happens.
            var raft =
            {
                position: "leftBank",
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = (this.position == "leftBank" ? "rightBank" : "leftBank");
                        var objRaft = document.getElementById("raft");

                        if (destination == "leftBank")
                        {
                            objRaft.style.marginLeft = "0%";
                        }
                        else
                        {
                            objRaft.style.marginLeft = "78%";
                        }

                        game.paused = true;

                        var raft = this;

                        setTimeout
                        (
                            function()
                            {
                                raft.position = destination;
                                game.paused = false;
                                game.moves ++;
                                game.check();
                            },
                            1000
                        );                       
                    }
                }
            };


For the timeout to make sense, we add this to the raft styling.
            #raft
            {
                width: 80px;
                height: 5px;
                background-color: #440000;
                margin-top: 73%;
                margin-left: 0%;
                transition: all 1s;
            }


Reload, click the orange button, then click on the boatman. Does he move? Click again. Does he move back?


Now, as promised, let's work on the check() method of the game object. It's basically a series of If statements.

The first conditions to check - ensure that the fox isn't left alone with the Easter Bunny. So if fox's position property is the same as bunny's position property and the raft and egg's position properties aren't...
                check: function()
                {
                    if (fox.position == bunny.position && raft.position != fox.position && egg.position != fox.position)
                    {

                    }
                },


...run the showMessage() method of the game object, with the argument "fox". Then set started to false and paused to true. Which effectively means GAME OVER.
                check: function()
                {
                    if (fox.position == bunny.position && raft.position != fox.position && egg.position != fox.position)
                    {
                        this.showMessage("fox");
                        game.started = false;
                        game.paused = true;
                    }
                },


Now check if the Easter Bunny and the Easter egg are left alone, and do something similar.
                check: function()
                {
                    if (fox.position == bunny.position && raft.position != fox.position && egg.position != fox.position)
                    {
                        this.showMessage("fox");
                        game.started = false;
                        game.paused = true;
                    }

                    if (bunny.position == egg.position && raft.position != bunny.position && fox.position != bunny.position)
                    {
                        this.showMessage("bunny");
                        game.started = false;
                        game.paused = true;
                    }
                },


Next, check if the fox, bunny and egg all have their positions as "rightBank". If so, the game is won and we need to run the showMessage() method with the argument "win". It's still GAME OVER, so set the flags accordingly.
                check: function()
                {
                    if (fox.position == bunny.position && raft.position != fox.position && egg.position != fox.position)
                    {
                        this.showMessage("fox");
                        game.started = false;
                        game.paused = true;
                    }

                    if (bunny.position == egg.position && raft.position != bunny.position && fox.position != bunny.position)
                    {
                        this.showMessage("bunny");
                        game.started = false;
                        game.paused = true;
                    }

                    if (bunny.position == "rightBank" && egg.position == "rightBank" && fox.position == "rightBank")
                    {
                        this.showMessage("win");
                        game.started = false;
                        game.paused = true;
                    }
                },


Now add a couple more conditions to the showMessage() method. Show different messages depending on whether messageType is "fox", "bunny" or "win". In the "win" scenario, we'll even display the number of moves made. How cool is that?
                check: function()
                {
                    if (fox.position == bunny.position && raft.position != fox.position && egg.position != fox.position)
                    {
                        this.showMessage("fox");
                        game.started = false;
                        game.paused = true;
                    }

                    if (bunny.position == egg.position && raft.position != bunny.position && fox.position != bunny.position)
                    {
                        this.showMessage("bunny");
                        game.started = false;
                        game.paused = true;
                    }

                    if (bunny.position == "rightBank" && egg.position == "rightBank" && fox.position == "rightBank")
                    {
                        this.showMessage("win");
                        game.started = false;
                        game.paused = true;
                    }
                },
                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";
                    }

                    if (messageType == "fox")
                    {
                        messageBox.innerHTML = "The fox has eaten the Easter Bunny!";
                        button.innerHTML = "Restart";
                    }

                    if (messageType == "bunny")
                    {
                        messageBox.innerHTML = "The Easter Bunny has escaped with the egg!";
                        button.innerHTML = "Restart";
                    }

                    if (messageType == "win")
                    {
                        messageBox.innerHTML = "All three have crossed! You have completed this game in " + game.moves + " moves.";
                        button.innerHTML = "Restart";
                    }
                }


One final method!

Yep, that's the move() method of the passenger object. Without it, it's impossible to play. Again, stuff only happens if the game is started and not paused.
                move: function()
                {
                    if (game.started && !game.paused)
                    {

                    }
                }   


Declare a variable, destination, and make it undefined. Now, if the passenger's position is either on the left bank or right bank, then its destination can only be "raft".
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {

                        }
                    }
                }   


But only if the raft is at the same position! For example, if the fox is on the right bank and the raft is at the left bank, then the fox cannot move on the raft.
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {
                            if (this.position == raft.position)
                            {
                                destination = "raft";
                            }
                        }
                    }
                }   


If the passenger is currently on the raft, then its destination is, naturally, the raft's position. For example, if the fox is on the raft and the raft is at the left bank, then when the fox moves, its destination is the left bank.
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {
                            if (this.position == raft.position)
                            {
                                destination = "raft";
                            }
                        }

                        if (this.position == "raft")
                        {
                            destination = raft.position;
                        }
                    }
                }   


After all that, destination should be set. This If block is just to compensate for the off chance that it's still undefined, but it really shouldn't be. Anyway, within this If block, create an If-else block to check if the destination is "raft". If some other passenger is already on the raft...
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {
                            if (this.position == raft.position)
                            {
                                destination = "raft";
                            }
                        }

                        if (this.position == "raft")
                        {
                            destination = raft.position;
                        }

                        if (destination != undefined)
                        {
                            if (destination == "raft" && (fox.position == "raft" || bunny.position == "raft" || egg.position == "raft"))
                            {

                            }
                            else
                            {
                           
                            }                           
                        }
                    }
                }   


... warn using an alert() function.
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {
                            if (this.position == raft.position)
                            {
                                destination = "raft";
                            }
                        }

                        if (this.position == "raft")
                        {
                            destination = raft.position;
                        }

                        if (destination != undefined)
                        {
                            if (destination == "raft" && (fox.position == "raft" || bunny.position == "raft" || egg.position == "raft"))
                            {
                                alert("Only one passenger is allowed!");
                            }
                            else
                            {
                               
                            }                       
                        }
                    }
                }


If not, begin by clearing the passenger from all other placeholders it might be in. If its current positon is "raft", then clear the raftPassenger div. If it isn't "raft", then it's either "leftBank" or "rightBank", and those placeholders should be cleared..
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {
                            if (this.position == raft.position)
                            {
                                destination = "raft";
                            }
                        }

                        if (this.position == "raft")
                        {
                            destination = raft.position;
                        }

                        if (destination != undefined)
                        {
                            if (destination == "raft" && (fox.position == "raft" || bunny.position == "raft" || egg.position == "raft"))
                            {
                                alert("Only one passenger is allowed!");
                            }
                            else
                            {
                                if (this.position == "raft")
                                {
                                    document.getElementById("raftPassenger").innerHTML = "";
                                }
                                else
                                {
                                    document.getElementById(this.position + "_" + this.id).innerHTML = "";
                                }                               
                            }                           
                        }
                    }
                }


Then run the render() method of the current object, putting in destination as an argument. Also, set the position property to destination.
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {
                            if (this.position == raft.position)
                            {
                                destination = "raft";
                            }
                        }

                        if (this.position == "raft")
                        {
                            destination = raft.position;
                        }

                        if (destination != undefined)
                        {
                            if (destination == "raft" && (fox.position == "raft" || bunny.position == "raft" || egg.position == "raft"))
                            {
                                alert("Only one passenger is allowed!");
                            }
                            else
                            {
                                if (this.position == "raft")
                                {
                                    document.getElementById("raftPassenger").innerHTML = "";
                                }
                                else
                                {
                                    document.getElementById(this.position + "_" + this.id).innerHTML = "";
                                }

                                this.render(destination);
                                this.position = destination;                               
                            }                           
                        }
                    }
                }


Finally, run the check() method of the game object. This will check for a victory condition, meaning, all three passengers on the right bank.
                move: function()
                {
                    if (game.started && !game.paused)
                    {
                        var destination = undefined;

                        if (this.position == "leftBank" || this.position == "rightBank")
                        {
                            if (this.position == raft.position)
                            {
                                destination = "raft";
                            }
                        }

                        if (this.position == "raft")
                        {
                            destination = raft.position;
                        }

                        if (destination != undefined)
                        {
                            if (destination == "raft" && (fox.position == "raft" || bunny.position == "raft" || egg.position == "raft"))
                            {
                                alert("Only one passenger is allowed!");
                            }
                            else
                            {
                                if (this.position == "raft")
                                {
                                    document.getElementById("raftPassenger").innerHTML = "";
                                }
                                else
                                {
                                    document.getElementById(this.position + "_" + this.id).innerHTML = "";
                                }

                                this.render(destination);
                                this.position = destination;                               
                            }

                            game.check();                           
                        }
                    }
                }


But the move() method will never fire off unless we do this...
        <div id="template_bunny" class="placeholder">
            <div class="bunny" onclick="bunny.move()">
                <div class="bunny_ears"></div>
                <div class="bunny_head"></div>
                <div class="bunny_body"></div>
            </div>
        </div>

        <br />

        <div id="template_fox" class="placeholder">
            <div class="fox" onclick="fox.move()">
                <div class="fox_ears"></div>
                <div class="fox_body"></div>
                <div class="fox_head"></div>
            </div>
        </div>

        <br />

        <div id="template_egg" class="placeholder">
            <div class="egg" onclick="egg.move()">
                <div class="egg_body"></div>
            </div>
        </div>


Enough yakking! Time to test! Start the game and click on the bunny. Does it move on the raft?


Now click on the fox. Does the warning message come up?


Click on the boatman. The bunny should be across the river now.


Click on the bunny again. Now it's on the right bank!


You'll need to test all the cases.




Of course, we still need to get rid of the ugly black lines.
            .placeholder
            {
                width: 40px;
                height: 50px;
                outline: 0px solid #000000;
            }


And make the templates invisible.
            #template_bunny, #template_egg, #template_fox
            {
                display: none;
            }


Final product!


Note

All this vanilla JavaScript isn't going to work on Internet Explorer and Safari, and right now I can't be arsed to jump through those hoops. If you really must get this to work on those browsers, my advice is - use jQuery. All the working has been laid out for you in vanilla JavaScript, so if you understood whatever was going on, it ought to be a piece of cake.


Do enjoy your Easter. game.check() back here again next week!
T___T

No comments:

Post a Comment