Friday 12 April 2019

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

This web tutorial is early this month, and that's because it's pretty big. It's a four-parter, so I thought I'd start early before Easter arrives.

Have you ever played the River Crossing Game? We'll be implementing something like that, with an Easter theme. The passengers are - a fox, the Easter Bunny, and an Easter egg. The objective of this game is to ferry all these guys over to the opposite bank of a river. Only one passenger is allowed on the raft. At any point in time, the fox may not be left alone with the Easter Bunny, and the Easter Bunny may not be left alone with the Easter egg.

Here's some basic HTML markup. For this, we have a div in the middle of the screen, rectangular in shape and with a solid black outline.
<!DOCTYPE html>
<html>
    <head>
        <title>Easter Bunny River Crossing Game</title>
        <style>
            #container
            {
                width: 600px;
                height: 450px;
                outline: 1px solid #000000;
                margin-left: auto;
                margin-right: auto;
                margin-top: 10%;
            }
        </style>

        <script>

        </script>
    </head>

    <body>
        <div id="container">

        </div>
    </body>
</html>


Off to a good start!


We'll start on the background next. Create another div within the container div, and give it an id of backgroundContainer.
        <div id="container">
            <div id="backgroundContainer">

            </div>
        </div>


Then style this div. It will fit the container div exactly. The background is a nice blue faded horizontally to a very light blue. The code was generated from this site.
        <style>
            #container
            {
                width: 600px;
                height: 450px;
                outline: 1px solid #000000;
                margin-left: auto;
                margin-right: auto;
                margin-top: 10%;
            }

            #backgroundContainer
            {
                width: 100%;
                height: 100%;
                background: #1e5799; /* Old browsers */
                background: -moz-linear-gradient(top, #1e5799 0%, #a7cae5 57%); /* FF3.6-15 */
                background: -webkit-linear-gradient(top, #1e5799 0%,#a7cae5 57%); /* Chrome10-25,Safari5.1-6 */
                background: linear-gradient(to bottom, #1e5799 0%,#a7cae5 57%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#a7cae5',GradientType=0 ); /* IE6-9 */
            }
        </style>


Good. We have a sky.


We want a rainbow!

Now what's an Easter game without a rainbow, huh? Let's make one. It'll be another div, nested within backgroundContainer.
        <div id="container">
            <div id="backgroundContainer">
                <div class="rainbow">

                </div>
            </div>
        </div>


We style the CSS class rainbow like so. 

height and width: 90% - it won't fit the parent completely because we want to give it some space around the edges.
border-radius: 50% - because we want this elliptical.
margin-left: auto, margin-right: auto - so that this sits nicely in the middle.
border: 10px solid rgba(255, 0, 255, 1) - makes this ellipse violet.
            #backgroundContainer
            {
                width: 100%;
                height: 100%;
                background: #1e5799; /* Old browsers */
                background: -moz-linear-gradient(top, #1e5799 0%, #a7cae5 57%); /* FF3.6-15 */
                background: -webkit-linear-gradient(top, #1e5799 0%,#a7cae5 57%); /* Chrome10-25,Safari5.1-6 */
                background: linear-gradient(to bottom, #1e5799 0%,#a7cae5 57%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#a7cae5',GradientType=0 ); /* IE6-9 */
            }

            .rainbow
            {
                width: 90%;
                height: 90%;
                border-radius: 50%;
                border: 10px solid rgba(255, 0, 255, 1);
                margin-left: auto;
                margin-right: auto;
            }


OK, so there's a nice violet ellipse.


There are seven colors in a rainbow. We just did the first one. Put six more divs in the div, and nest all of them within each other like so.
                <div class="rainbow">
                    <div>
                        <div>
                            <div>
                                <div>
                                    <div>
                                        <div>

                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>


And style the next div this way. It has 96% width and 95% height of its parent, border-radius is still set to 50% but now the border is indigo.
            .rainbow
            {
                width: 90%;
                height: 90%;
                border-radius: 50%;
                border: 10px solid rgba(255, 0, 255, 1);
                margin-left: auto;
                margin-right: auto;
            }

            .rainbow div
            {
                width: 96%;
                height: 95%;
                border-radius: 50%;
                border: 10px solid rgba(155, 0, 255, 1);
            }


Uh-oh, all six ellipses are now indigo!


No sweat. We're not done here, not by a long shot. Style the rest. We no longer need to specify border-radius and height and width because the styles cascade. So we just need to change the border color!
            .rainbow
            {
                width: 90%;
                height: 90%;
                border-radius: 50%;
                border: 10px solid rgba(255, 0, 255, 1);
                margin-left: auto;
                margin-right: auto;
            }

            .rainbow div
            {
                width: 96%;
                height: 95%;
                border-radius: 50%;
                border: 10px solid rgba(155, 0, 255, 1);
            }

            .rainbow div div
            {
                border: 10px solid rgba(0, 0, 255, 1);
            }

            .rainbow div div div
            {
                border: 10px solid rgba(0, 255, 0, 1);
            }

            .rainbow div div div div
            {
                border: 10px solid rgba(255, 255, 0, 1);
            }

            .rainbow div div div div div
            {
                border: 10px solid rgba(255, 155, 0, 1);
            }

            .rainbow div div div div div div
            {
                border: 10px solid rgba(255, 0, 0, 1);
            }


Brilliant, amirite?

Time for some water...

Yes, the player needs to cross a river, yeah? Add another div after the rainbow. Style this one using water.
            <div id="backgroundContainer">
                <div class="rainbow">
                    <div>
                        <div>
                            <div>
                                <div>
                                    <div>
                                        <div>

                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="water">

                </div>
            </div>


Style water. Again, we apply a nice gradient background. It will take up the full width of backgroundContainer, but only 60% of the height. And we need it covering the bottom half of the rainbow, so set the margin-top property to a negative amount, say, -35%.
            .rainbow
            {
                width: 90%;
                height: 90%;
                border-radius: 50%;
                border: 10px solid rgba(255, 0, 255, 1);
                margin-left: auto;
                margin-right: auto;
            }

            .rainbow div
            {
                width: 96%;
                height: 95%;
                border-radius: 50%;
                border: 10px solid rgba(155, 0, 255, 1);
            }

            .rainbow div div
            {
                border: 10px solid rgba(0, 0, 255, 1);
            }

            .rainbow div div div
            {
                border: 10px solid rgba(0, 255, 0, 1);
            }

            .rainbow div div div div
            {
                border: 10px solid rgba(255, 255, 0, 1);
            }

            .rainbow div div div div div
            {
                border: 10px solid rgba(255, 155, 0, 1);
            }

            .rainbow div div div div div div
            {
                border: 10px solid rgba(255, 0, 0, 1);
            }

            .water
            {
                width: 100%;
                height: 60%;
                background: #0e1449; /* Old browsers */
                background: -moz-linear-gradient(left, #0e1449 17%, #383566 51%, #0e1449 80%); /* FF3.6-15 */
                background: -webkit-linear-gradient(left, #0e1449 17%,#383566 51%,#0e1449 80%); /* Chrome10-25,Safari5.1-6 */
                background: linear-gradient(to right, #0e1449 17%,#383566 51%,#0e1449 80%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0e1449', endColorstr='#0e1449',GradientType=1 ); /* IE6-9 */
                margin-top: -35%;
            }


Beautifully done.


Now, you'll probably see that the rainbw is a tad too brilliant, so let's mute it some.
            .rainbow
            {
                width: 90%;
                height: 90%;
                border-radius: 50%;
                border: 10px solid rgba(255, 0, 255, 0.2);
                margin-left: auto;
                margin-right: auto;
            }

            .rainbow div
            {
                width: 96%;
                height: 95%;
                border-radius: 50%;
                border: 10px solid rgba(155, 0, 255, 0.2);
            }

            .rainbow div div
            {
                border: 10px solid rgba(0, 0, 255, 0.2);
            }

            .rainbow div div div
            {
                border: 10px solid rgba(0, 255, 0, 0.2);
            }

            .rainbow div div div div
            {
                border: 10px solid rgba(255, 255, 0, 0.2);
            }

            .rainbow div div div div div
            {
                border: 10px solid rgba(255, 155, 0, 0.2);
            }

            .rainbow div div div div div div
            {
                border: 10px solid rgba(255, 0, 0, 0.2);
            }


Ah, now that the opacity has been set to 20%, it looks much better. At the very least, it will not be clashing with the rest of the other objects we will be placing in that box.


Let's have some river banks!

Because what is a river without river banks? For this, we will create an entirely new div. Let's give it an id of gameContainer and place it before backgroundContainer. gameContainer will be where most of the game controls take place, hence the name.
        <div id="container">
            <div id="gameContainer">

            </div>

            <div id="backgroundContainer">
                <div class="rainbow">
                    <div>
                        <div>
                            <div>
                                <div>
                                    <div>
                                        <div>

                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="water">

                </div>
            </div>
        </div>


This is how we'll style it. It will take up all of container, just like backgroundContainer.
            .water
            {
                width: 100%;
                height: 60%;
                background: #0e1449; /* Old browsers */
                background: -moz-linear-gradient(left, #0e1449 17%, #383566 51%, #0e1449 80%); /* FF3.6-15 */
                background: -webkit-linear-gradient(left, #0e1449 17%,#383566 51%,#0e1449 80%); /* Chrome10-25,Safari5.1-6 */
                background: linear-gradient(to right, #0e1449 17%,#383566 51%,#0e1449 80%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0e1449', endColorstr='#0e1449',GradientType=1 ); /* IE6-9 */
                margin-top: -35%;
            }

            #gameContainer
            {
                width: 100%;
                height: 100%;
            }


Uh-oh, it just displaced backgroundContainer! Not to worry. That was expected. We'll handle this later.


Now, we're going to want another div inside gameContainer. Give it an id of bankContainer because, you guessed it, it will contain the river banks.
            <div id="gameContainer">
                <div id="bankContainer">

                </div>
            </div>


This is how bankContainer is styled. It will take up the full width of its parent, and only 60% of the height. We'll also give it a black outline so we can see what we're working with.
           
            #gameContainer
            {
                width: 100%;
                height: 100%;
            }

            #bankContainer
            {
                width: 100%;
                height: 60%;
                outline: 1px solid #000000;
            }


OK, so now you see bankContainer as a rectangular area taking up the top part of gameContainer.


Inside bankContainer, add two more divs. Their classes will be leftBank and rightBank, respectively.
                <div id="bankContainer">
                    <div class="leftBank">

                    </div>

                    <div class="rightBank">

                    </div>
                </div>


And inside those divs, add a div with a class of bank.
                <div id="bankContainer">
                    <div class="leftBank">
                        <div class="bank">

                        </div>
                    </div>

                    <div class="rightBank">
                        <div class="bank">

                        </div>
                    </div>
                </div>


Time for some styling. bank will be styled as follows...

width: 100%, height: 40% - that's how much of their parents they will take.
border-radius: 50% - because they're elliptical.
background-color: #009900 - because grass is green.
margin-top: 95% - because we want them pushed down.

            #bankContainer
            {
                width: 100%;
                height: 60%;
                outline: 1px solid #000000;
            }

            .bank
            {
                width: 100%;
                height: 40%;
                border-radius: 50%;
                background-color: #009900;
                margin-top: 95%;
            }


leftBank and rightBank are the styles used by the divs that contain the divs styled by bank. Their widths are 40% of bankContainer, with full heights. And - this is really important - leftBank floats left and is pushed left further by 20% of bankContainer's width, while rightBank floats right and is pushed right further by 20% of bankContainer's width. Again, they both have black outlines so we can see what's going on.
            .bank
            {
                width: 100%;
                height: 40%;
                border-radius: 50%;
                background-color: #009900;
                margin-top: 95%;
            }

            .leftBank
            {
                width: 40%;
                height: 100%;
                float: left;
                margin-left: -20%;
                outline: 1px solid #000000;
            }

            .rightBank
            {
                width: 40%;
                height: 100%;
                float: right;
                margin-right: -20%;
                outline: 1px solid #000000;
            }


You'll see that the left and right banks are pretty much where they should be.


Let's make this clearer by setting bankContainer's overflow property to hidden.
            #bankContainer
            {
                width: 100%;
                height: 60%;
                overflow: hidden;
                outline: 1px solid #000000;
            }


Like magic!


Let's make a raft and boatman!

Way ahead of you. Add one more div between the banks. Style it using path. It actually is the path that the raft will travel; namely, between the left and right banks.
                <div id="bankContainer">
                    <div class="leftBank">
                        <div class="bank">

                        </div>
                    </div>

                    <div class="path">

                    </div>

                    <div class="rightBank">
                        <div class="bank">

                        </div>
                    </div>
                </div>


This is how we'll style it. It takes up 60% of bankContainer's width. While the two banks each take up 40%, which is a total of 80%, each of them are displaced by 20%. This leaves an extra 40% to the remainder of 20%, to make 60%. We float the div left and give it a red outline.
            .leftBank
            {
                width: 40%;
                height: 100%;
                float: left;
                margin-left: -20%;
                outline: 1px solid #000000;
            }

            .rightBank
            {
                width: 40%;
                height: 100%;
                float: right;
                margin-right: -20%;
                outline: 1px solid #000000;
            }

            .path
            {
                width: 60%;
                height: 100%;
                float: left;
                outline: 1px solid #FF0000;
            }


Nice!

Now add a raft in there. It's a flat div in the div styled by path.
                    <div class="path">
                        <div id="raft">

                        </div>
                    </div>


It's 80 by 5 pixels, and is colored brown. margin-left is set to 0%, and this is important because it's a property that will later change when we move the raft to the opposite bank. We set margin-top to 73% so that it sits at the bottom of the parent div.
            .path
            {
                width: 60%;
                height: 100%;
                float: left;
                outline: 1px solid #FF0000;
            }

            #raft
            {
                width: 80px;
                height: 5px;
                background-color: #440000;
                margin-top: 73%;
                margin-left: 0%;
            }


Yep, there's that raft!


Let's make a boatman next. Add a div within raft and give it a class of boatman.
                    <div class="path">
                        <div id="raft">
                            <div class="boatman"></div>
                        </div>
                    </div>


Here, this is how we style the boatman.

width: 30px - not too wide, just enough to occupy, say, a third of the raft.
height: 60px - this will be important soon.
margin-top: -60px - because the height is 60 pixels and the raft is really flat and the boatman is within the raft div, we need to offset the top so that the boatman looks like he's on the raft. You could always set this to 0px and see what happens!
float: right - to give the passenger some space on the left of the raft.
font-size: 20px - this looks like a strange property to set considering there is no text... yet.
cursor: pointer - the boatman is supposed to be clickable.
            #raft
            {
                width: 80px;
                height: 5px;
                background-color: #440000;
                margin-top: 73%;
                margin-left: 0%;
            }

            .boatman
            {
                width: 30px;
                height: 60px;
                margin-top: -60px;
                float: right;
                font-size: 20px;
                cursor: pointer;
            }


Now, we're not done yet. Let's give the boatman a head. We use the before pseudoselector, setting the display property to block. width and height should be the same. We set those to 20px to create a square. Remember font size was set to 20px too? Well, that's because we're using a HTML symbol for the head. margin and text-align properties are set so that the head sits in the middle of the div.
            .boatman
            {
                width: 30px;
                height: 60px;
                margin-top: -60px;
                float: right;
                font-size: 20px;
                cursor: pointer;
            }

            .boatman:before
            {
                display: block;
                content: "\263B";
                width: 20px;
                height: 20px;
                margin: 0 auto 0 auto;
                text-align: center;
            }


Would you look at that... a little smiling black face floating above the raft. Time to give it a body.


Now we use the after pseudoselector. Again, display is set to block though this time there's no content. I've set width, height and margin so that the body aligns nicely with the head. Make your own adjustments! border-radius is set so we get a nice shape as a body.
            .boatman:before
            {
                display: block;
                content: "\263B";
                width: 20px;
                height: 20px;
                margin: 0 auto 0 auto;
                text-align: center;
            }

            .boatman:after
            {
                display: block;
                content: "";
                width: 20px;
                height: 42px;
                margin: -2px auto 0 auto;
                border-radius: 50% 50% 50% 50% / 20% 20% 80% 80%;
                background-color: #000000;
            }


Now we have a little black boatman! This isn't a racist thing, by the way. Just that the HTML symbol was the quickest way to get something up, and the only way it wouldn't look weird was to use the default color.


Now, let's put it all together. Set the margin-bottom property of the gameContainer div to negative 450 pixels.
            #gameContainer
            {
                width: 100%;
                height: 100%;
                margin-bottom: -450px;
            }


Ah, see how nicely it overlaps! More adjustments needed though...


Set the overflow property of backgroundContainer to hidden, and the margin-top property of the rainbow CSS class to 50px.
            #backgroundContainer
            {
                width: 100%;
                height: 100%;
                background: #1e5799; /* Old browsers */
                background: -moz-linear-gradient(top, #1e5799 0%, #a7cae5 57%); /* FF3.6-15 */
                background: -webkit-linear-gradient(top, #1e5799 0%,#a7cae5 57%); /* Chrome10-25,Safari5.1-6 */
                background: linear-gradient(to bottom, #1e5799 0%,#a7cae5 57%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
                filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#a7cae5',GradientType=0 ); /* IE6-9 */
                overflow: hidden;
            }

            .rainbow
            {
                width: 90%;
                height: 90%;
                border-radius: 50%;
                border: 10px solid rgba(255, 0, 255, 0.2);
                margin-left: auto;
                margin-right: auto;
                margin-top: 50px;
            }


Just perfect. Need to get rid of the lines next...


            #bankContainer
            {
                width: 100%;
                height: 60%;
                overflow: hidden;
                outline: 0px solid #000000;
            }

            .bank
            {
                width: 100%;
                height: 40%;
                border-radius: 50%;
                background-color: #009900;
                margin-top: 95%;
            }

            .leftBank
            {
                width: 40%;
                height: 100%;
                float: left;
                margin-left: -20%;
                outline: 0px solid #000000;
            }

            .rightBank
            {
                width: 40%;
                height: 100%;
                float: right;
                margin-right: -20%;
                outline: 0px solid #000000;
            }

            .path
            {
                width: 60%;
                height: 100%;
                float: left;
                outline: 0px solid #FF0000;
            }


Yep, and that's it! Sit back, give yourself a clap on the back. Well done.


Next

You now have a nice background for the game. After this, we'll concentrate on game tokens - the passengers for the raft!

No comments:

Post a Comment