Friday 24 March 2023

Web Tutorial: Easter Egg Line Game (Part 2/4)

We're getting to the more visual part of the web tutorial - the eggs. The grid that we defined is going to be filled with eggs. Eggs of 3 possible different styles, and more importantly, 7 possible different colors. Now, we will start testing with one color and one style.

Add a div in the div styled using square. In it, add three divs, each with a non-breaking space as content.
<div class="square" v-for="(s, square) in col" v-on:click="selectSquare(c, s)">
    <div class="square" v-for="(s, square) in col">
        <div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
        </div>

    </div>
</div>


Now, bind the style attribute using the getEggClass() method. We pass in c and s, which are respectively the indexes of the outer For loop and the inner For loop.
<div class="square" v-for="(s, square) in col" v-on:click="selectSquare(c, s)">
    <div class="square" v-for="(s, square) in col">
        <div v-bind:class="getEggClass(c, s)">
            <div>&nbsp;</div>
            <div>&nbsp;</div>
            <div>&nbsp;</div>
        </div>
    </div>
</div>


Now we create the method. It has two parameters - c and s.
    getMarginTop: function(color)
    {
        var percentage = this.max - this.rainbow[color];
        return "margin-top:" + ((percentage / this.max) * 480) + "px";
    },
    getEggClass: function(c, s)
    {
        
    }

}                        


Now, to test, we return the string "egg".
getEggClass: function(c, s)
{
    return "egg";
}


Now, we create the CSS class for egg. The setting for the border-radius property gives it the egg shape. I've set the width and height to be less than 100% of the parent. The position property is set to relative because we have other divs within which are going to be positioned pretty explicitly. The margin property is set to center the egg. The filter property is set to 100% opacity, and this is specified because later on we will be animating this.
.bottom button:hover
{
    background-color: rgb(200, 200, 200);
}

.egg
{
    width: 70%;
    height: 90%;
    border-radius: 50%/60% 60% 40% 40%;
    position: relative;
    margin: 2px auto 0 auto;
    filter: opacity(100);
}


.outline_red
{
    border: 1px solid rgb(150, 0, 0);
    background-color: rgba(150, 0, 0, 0.2);
}


And now you can see the outlines of the eggs!




Now change the string to include the string "style1". This is one possible design of the egg.
getEggClass: function(c, s)
{
    return "egg style1";
}


Each div inside the CSS class egg, has the position property set to absolute. We are going to be moving those divs around.
.egg
{
    width: 70%;
    height: 90%;
    border-radius: 50%/60% 60% 40% 40%;
    position: relative;
    margin: 2px auto 0 auto;
    filter: opacity(100);
}

.egg div
{
    position: absolute;
}


.outline_red
{
    border: 1px solid rgb(150, 0, 0);
    background-color: rgba(150, 0, 0, 0.2);
}


This creates styles for the first, second and third div within any element styled using both egg and style1.
.egg
{
    width: 70%;
    height: 90%;
    border-radius: 50%/60% 60% 40% 40%;
    position: relative;
    margin: 2px auto 0 auto;
    filter: opacity(100);
}

.egg div
{
    position: absolute;
}

.egg.style1 div:nth-of-type(1)
{

}

.egg.style1 div:nth-of-type(2)
{

}

.egg.style1 div:nth-of-type(3)
{

}


.outline_red
{
    border: 1px solid rgb(150, 0, 0);
    background-color: rgba(150, 0, 0, 0.2);
}


Each of these have 100% width of its parent, and we will rotate them 20 degrees anti-clockwise.
.egg.style1 div:nth-of-type(1)
{
    width: 100%;
    transform: rotate(-20deg);

}

.egg.style1 div:nth-of-type(2)
{
    width: 100%;
    transform: rotate(-20deg);

}

.egg.style1 div:nth-of-type(3)
{
    width: 100%;
    transform: rotate(-20deg);

}


We then give them varying height and margin-top properties.
.egg.style1 div:nth-of-type(1)
{
    width: 100%;
    height: 3px;
    margin-top: 5px;

    transform: rotate(-20deg);
}

.egg.style1 div:nth-of-type(2)
{
    width: 100%;
    height: 10px;
    margin-top: 20px;

    transform: rotate(-20deg);
}

.egg.style1 div:nth-of-type(3)
{
    width: 100%;
    height: 5px;
    margin-top: 40px;

    transform: rotate(-20deg);
}


See what we did here?




Let's do one more thing. For the egg CSS class, set the overflow property to hidden.
.egg
{
    width: 70%;
    height: 90%;
    border-radius: 50%/60% 60% 40% 40%;
    overflow: hidden;
    position: relative;
    margin: 2px auto 0 auto;
    filter: opacity(100);
}


Much neater!




Let's try another style. Change this to "style2".
getEggClass: function(c, s)
{
    return "egg style2";
}


Now this gives us circles of varying sizes and positions within the egg.
.egg.style1 div:nth-of-type(3)
{
    width: 100%;
    height: 5px;
    margin-top: 40px;
    transform: rotate(-20deg);
}

.egg.style2 div:nth-of-type(1)
{
    width: 15px;
    height: 15px;
    margin-top: 10px;
    margin-left: 10px;
    border-radius: 50%;
}

.egg.style2 div:nth-of-type(2)
{
    width: 10px;
    height: 10px;
    margin-top: 20px;
    margin-left: 30px;
    border-radius: 50%;
}

.egg.style2 div:nth-of-type(3)
{
    width: 5px;
    height: 5px;
    margin-top: 30px;
    margin-left: 10px;
    border-radius: 50%;
}


.outline_red
{
    border: 1px solid rgb(150, 0, 0);
    background-color: rgba(150, 0, 0, 0.2);
}


Nice!




Let's do one last design.
getEggClass: function(c, s)
{
    return "egg style3";
}


It's almost identical to the last one, except that instead of circles, we have squares with rounded corners.
.egg.style2 div:nth-of-type(3)
{
    width: 5px;
    height: 5px;
    margin-top: 30px;
    margin-left: 10px;
    border-radius: 50%;
}

.egg.style3 div:nth-of-type(1)
{
    width: 10px;
    height: 10px;
    margin-top: 10px;
    margin-left: 5px;
    transform: rotate(45deg);
    border-radius: 2px;
}

.egg.style3 div:nth-of-type(2)
{
    width: 12px;
    height: 12px;
    margin-top: 30px;
    margin-left: 0px;
    transform: rotate(45deg);
    border-radius: 2px;
}

.egg.style3 div:nth-of-type(3)
{
    width: 8px;
    height: 8px;
    margin-top: 20px;
    margin-left: 20px;
    transform: rotate(45deg);
    border-radius: 2px;
}

            
.outline_red
{
    border: 1px solid rgb(150, 0, 0);
    background-color: rgba(150, 0, 0, 0.2);
}


Here we go.




Now let's work on colors. I'm going to go with green as a starting color. Make this change in the getEggClass() method.
getEggClass: function(c, s)
{
    return "egg style3 green";
},


If you refresh, you should see this. That's because we already specified that all elements styled using green has this background color.




Let's get a little bit more specific. All divs within any element styled using both egg and green, have a darker shade of green.
.outline_green
{
    border: 1px solid rgb(0, 150, 0);
    background-color: rgba(0, 150, 0, 0.2);
}

.egg.green div
{
    background-color: rgb(0, 50, 0);
}


.green
{
    background-color: rgb(0, 150, 0);
}


See what we did here?!




Now just add in the other colors and test them accordingly. You don't have to follow my recommendation.
.outline_red
{
    border: 1px solid rgb(150, 0, 0);
    background-color: rgba(150, 0, 0, 0.2);
}

.egg.red div
{
    background-color: rgb(255, 0, 0);
}


.red
{
    background-color: rgb(150, 0, 0);
}

.outline_orange
{
    border: 1px solid rgb(200, 150, 0);
    background-color: rgba(200, 150, 0, 0.2);
}

.egg.orange div
{
    background-color: rgb(255, 200, 0);
}


.orange
{
    background-color: rgb(200, 150, 0);
}

.outline_yellow
{
    border: 1px solid rgb(200, 200, 0);
    background-color: rgba(200, 200, 0, 0.2);
}

.egg.yellow div
{
    background-color: rgb(255, 255, 100);
}


.yellow
{
    background-color: rgb(200, 200, 0);
}

.outline_green
{
    border: 1px solid rgb(0, 150, 0);
    background-color: rgba(0, 150, 0, 0.2);
}

.egg.green div
{
    background-color: rgb(0, 50, 0);
}


.green
{
    background-color: rgb(0, 150, 0);
}

.outline_blue
{
    border: 1px solid rgb(0, 0, 150);
    background-color: rgba(0, 0, 150, 0.2);
}

.egg.blue div
{
    background-color: rgb(100, 100, 200);
}


.blue
{
    background-color: rgb(0, 0, 150);
}

.outline_indigo
{
    border: 1px solid rgb(100, 0, 200);
    background-color: rgba(100, 0, 200, 0.2);
}

.egg.indigo div
{
    background-color: rgb(50, 0, 100);
}


.indigo
{
    background-color: rgb(100, 0, 200);
}

.outline_violet
{
    border: 1px solid rgb(200, 50, 200);
    background-color: rgba(200, 50, 200, 0.2);
}

.egg.violet div
{
    background-color: rgb(255, 150, 255);
}


.violet
{
    background-color: rgb(200, 50, 200);
}


But since we're doing this, let's give these suckers a little 3D effect. Add a new specification using the after pseudoselector. This means that any element styled using egg will have one additional element inserted after that element's contents.
.egg
{
    width: 70%;
    height: 90%;
    border-radius: 50%/60% 60% 40% 40%;
    overflow: hidden;
    position: relative;
    margin: 2px auto 0 auto;
    filter: opacity(100);
}

.egg:after
{

}


.egg div
{
    position: absolute;
}


That element will be a block level element, and act like an overlay. This means that we have to set the display property to block and the position property to absolute. The content property is an empty string, while height and width take up 100% of its parent.
.egg
{
    width: 70%;
    height: 90%;
    border-radius: 50%/60% 60% 40% 40%;
    overflow: hidden;
    position: relative;
    margin: 2px auto 0 auto;
    filter: opacity(100);
}

.egg:after
{
    display: block;
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
}


.egg div
{
    position: absolute;
}


Again, here we get specific. If the element is styled using both egg and green, the element that is inserted after that element's contents will have this nice radial gradient.
.egg:after
{
    display: block;
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
}

.egg.green:after
{            
    background: -moz-radial-gradient(left,  rgba(100, 255, 100, 0.5) 0%, rgba(100, 255, 100, 0.5) 10%, rgba(0, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(100, 255, 100, 0.5) 0%, rgba(100, 255, 100, 0.5) 10%, rgba(0, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(100, 255, 100, 0.5) 0%, rgba(100, 255, 100, 0.5) 10%, rgba(0, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}


.egg div
{
    position: absolute;
}



Beautiful!




Again, here are the rest of the gradient backgrounds. It's not extremely important that you follow this.
.egg:after
{
    display: block;
    position: absolute;
    content: "";
    width: 100%;
    height: 100%;
}

.egg.red:after
{            
    background: -moz-radial-gradient(left,  rgba(255, 100, 100, 0.5) 0%, rgba(255, 100, 100, 0.5) 10%, rgba(100, 0, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(255, 100, 100, 0.5) 0%, rgba(255, 100, 100, 0.5) 10%, rgba(100, 0, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(255, 100, 100, 0.5) 0%, rgba(255, 100, 100, 0.5) 10%, rgba(100, 0, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}

.egg.orange:after
{            
    background: -moz-radial-gradient(left,  rgba(255, 200, 100, 0.5) 0%, rgba(255, 200, 100, 0.5) 10%, rgba(100, 50, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(255, 200, 100, 0.5) 0%, rgba(255, 200, 100, 0.5) 10%, rgba(100, 50, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(255, 200, 100, 0.5) 0%, rgba(255, 200, 100, 0.5) 10%, rgba(100, 50, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}

.egg.yellow:after
{            
    background: -moz-radial-gradient(left,  rgba(255, 255, 100, 0.5) 0%, rgba(255, 255, 100, 0.5) 10%, rgba(100, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(255, 255, 100, 0.5) 0%, rgba(255, 255, 100, 0.5) 10%, rgba(100, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(255, 255, 100, 0.5) 0%, rgba(255, 255, 100, 0.5) 10%, rgba(100, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}


.egg.green:after
{            
    background: -moz-radial-gradient(left,  rgba(100, 255, 100, 0.5) 0%, rgba(100, 255, 100, 0.5) 10%, rgba(0, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(100, 255, 100, 0.5) 0%, rgba(100, 255, 100, 0.5) 10%, rgba(0, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(100, 255, 100, 0.5) 0%, rgba(100, 255, 100, 0.5) 10%, rgba(0, 100, 0, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}

.egg.blue:after
{            
    background: -moz-radial-gradient(left,  rgba(100, 100, 255, 0.5) 0%, rgba(100, 100, 255, 0.5) 10%, rgba(0, 0, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(100, 100, 255, 0.5) 0%, rgba(100, 100, 255, 0.5) 10%, rgba(0, 0, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(100, 100, 255, 0.5) 0%, rgba(100, 100, 255, 0.5) 10%, rgba(0, 0, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}

.egg.indigo:after
{            
    background: -moz-radial-gradient(left,  rgba(200, 100, 255, 0.5) 0%, rgba(200, 100, 255, 0.5) 10%, rgba(50, 0, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(200, 100, 255, 0.5) 0%, rgba(200, 100, 255, 0.5) 10%, rgba(50, 0, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(200, 100, 255, 0.5) 0%, rgba(200, 100, 255, 0.5) 10%, rgba(50, 0, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}

.egg.violet:after
{            
    background: -moz-radial-gradient(left,  rgba(255, 100, 255, 0.5) 0%, rgba(255, 100, 255, 0.5) 10%, rgba(100, 50, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: -webkit-radial-gradient(left,  rgba(255, 100, 255, 0.5) 0%, rgba(255, 100, 255, 0.5) 10%, rgba(100, 50, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
    background: radial-gradient(to right,  rgba(255, 100, 255, 0.5) 0%, rgba(255, 100, 255, 0.5) 10%, rgba(100, 50, 100, 0.5) 75%, rgba(0, 0, 0, 0.5) 100%);
}


.egg div
{
    position: absolute;
}


Now, of course it's not going to be a grid full of eggs of the same color. We want them all in different colors and patterns! The idea here is to leverage on VueJS and make the grid reactive to changes in the array grid. So make this change to getEggClass(). We still want the final string to start with "egg", but we want the style to take its value from grid. So if c is the column index and s is the row index, we can get the element in grid that these two values point to, to get the style and color properties.
getEggClass: function(c, s)
{
    //return "egg style3 green";
    return "egg " + this.grid[c][s].style + " " + this.grid[c][s].color;
},


Of course there won't be any changes just yet. But we can test this by making a change here in resetEggs(), in the first few elements of the first array of grid.
resetEggs: function()
{
    this.grid=[];
    this.grid = [
        [{style: "style1", color: "red"}, {style: "style2", color: "blue"}, {style: "style3", color: "yellow"}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}]
    ];                            
},


There you go - a red egg, a blue egg and a yellow egg! All in different styles!




Change the values back. We want the array to be filled programmatically. To do this, we call the method fillMissingEggs().
resetEggs: function()
{
    this.grid=[];
    this.grid = [
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}]
    ];

    this.fillMissingEggs();
},


Create the method. We'll begin by declaring arr as a temporary variable, and assigning the value of grid to it. At the end, we will set grid to an empty array, then set grid to the value of arr.
getEggClass: function(c, s)
{
    return "egg " + this.grid[c][s].style + " " + this.grid[c][s].color;
    return "egg " + this.grid[c][s].style + " " + this.grid[c][s].color + " " + (this.isInSelection(c, s) ? "outline" : "");
},
fillMissingEggs: function()
{
    var arr = this.grid;

    this.grid = [];
    this.grid = arr;
}


Now for a nested For loop! We will be going through both dimensions of arr.
fillMissingEggs: function()
{
    var arr = this.grid;

    for (var i = 0; i < arr.length; i++)
    {
        for (var j = 0; j < arr[i].length; j++)
        {

        }
    }


    this.grid = [];
    this.grid = arr;
}


If the style and color properties are both empty strings, fill in the value using the getRandomPair() method.
fillMissingEggs: function()
{
    var arr = this.grid;

    for (var i = 0; i < arr.length; i++)
    {
        for (var j = 0; j < arr[i].length; j++)
        {
            if (arr[i][j].style == "" && arr[i][j].color == "")
            {
                arr[i][j] = this.getRandomPair();
            }

        }
    }

    this.grid = [];
    this.grid = arr;
}


And here we define getRandomPair().
fillMissingEggs: function()
{
    var arr = this.grid;

    for (var i = 0; i < arr.length; i++)
    {
        for (var j = 0; j < arr[i].length; j++)
        {
            if (arr[i][j].style == "" && arr[i][j].color == "")
            {
                arr[i][j] = this.getRandomPair();
            }
        }
    }

    this.grid = [];
    this.grid = arr;
},
getRandomPair: function()
{

}


Declare randomIndex. Use the Math object's floor() and random() methods to get a number from 1 to 3. And then declare style and set the value to the concatenated string of "style" and randomIndex. Thus, you should get "style1", "style2" or "style3".
getRandomPair: function()
{
    var randomIndex;
    randomIndex = Math.floor(Math.random() * 3) + 1;
    var style = "style" + randomIndex;

}


Reuse randomIndex, and this time get a number from 0 to 6. Use the new value of randomIndex to point to an element in an array of all colors of the rainbow, then assign the value to the variable color.
getRandomPair: function()
{
    var randomIndex;
    randomIndex = Math.floor(Math.random() * 3) + 1;
    var style = "style" + randomIndex;

    randomIndex = Math.floor(Math.random() * 7);
    var color = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"][randomIndex];

}


Finally, return an object containing these two values.
getRandomPair: function()
{
    var randomIndex;
    randomIndex = Math.floor(Math.random() * 3) + 1;
    var style = "style" + randomIndex;

    randomIndex = Math.floor(Math.random() * 7);
    var color = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"][randomIndex];

    return {"style": style, "color": color};
}


Now we're talking!




Handling the edge case...

You realize that this is a typical ideal scenario - where there are eggs of the same color right next to each other. Our rules are that eggs need to be next to each other, either horizontally or vertically, to be selectable. And if there are no eggs of the same color next to each other in that entire grid (unlikely, but possible), then it's an impossible scenario and we need to cater for it.

To do that, we call the handleImpossibleScenario() method inside reset().
reset: function()
{
    this.resetEggs();
    this.remainingMoves = this.moves;
    this.score = 0;
    //this.selection = [];
    this.rainbow = {
        red: 0,
        orange: 0,
        yellow: 0,
        green: 0,
        blue: 0,
        indigo: 0,
        violet: 0
    };

    this.handleimpossibleScenario();
},


Create this method.
resetEggs: function()
{
    this.grid=[];
    this.grid = [
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}]
    ];

    this.fillMissingEggs();
},
handleimpossibleScenario: function()
{

},

getMarginTop: function(color)
{
    var percentage = this.max - this.rainbow[color];
    return "margin-top:" + ((percentage / this.max) * 480) + "px";
},


We declare the variable possible, which we then set by calling the isPossibleToMove() method, which we will create after this.
handleimpossibleScenario: function()
{
    var possible = this.isPossibleToMove();
},


isPossibleToMove() returns either true or false. If possible is false, we flash a message and run resetEggs(), then set the value of possible by running isPossibleToMove() again. This repeats until possible is true.
handleimpossibleScenario: function()
{
    var possible = this.isPossibleToMove();

    while(!possible)
    {
        alert("No more possible moves! Re-randomizing...")

        this.resetEggs();

        possible = this.isPossibleToMove();
    }

},


Now for isPossibleToMove()! Begin by declaring the variable possible, which is false by default. At the end of the method, we will return the value of possible. Also declare a temporary variable, arr, which we will set to the value of the array grid.
getRandomPair: function()
{
    var randomIndex;
    randomIndex = Math.floor(Math.random() * 3) + 1;
    var style = "style" + randomIndex;

    randomIndex = Math.floor(Math.random() * 7);
    var color = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"][randomIndex];

    return {"style": style, "color": color};
},
isPossibleToMove: function()
{
    var possible = false;
    var arr = this.grid;

    return possible;
}


So we first iterate through arr. During this, is possible has been set to true, exit the For loop with a break statement. Our goal here is to determine if any of the eggs are the same color as their horizontal or vertical neighbor. Thus, as soon as we find one case, we get out of there.
isPossibleToMove: function()
{
    var possible = false;
    var arr = this.grid;

    for (var i = 0; i < arr.length; i++)
    {
        if (possible) break;
    }


    return possible;
}


Within the first For loop, use another For loop to iterate through that current element of arr, which should have 10 elements in turn.
isPossibleToMove: function()
{
    var possible = false;
    var arr = this.grid;

    for (var i = 0; i < arr.length; i++)
    {
        if (possible) break;

        for (var j = 0; j < arr[i].length; j++)
        {

        }

    }

    return possible;
}


If i is greater than 0, we check if that object pointed to by i and j, has a color property that is the same as the one on its left. We do this by using i minus 1. And since the minimum value of i here is 0, this can only be checked if i is greater than 0, otherwise we might run into an out of bounds error. If there's a match, set possible to true and exit the loop.
isPossibleToMove: function()
{
    var possible = false;
    var arr = this.grid;

    for (var i = 0; i < arr.length; i++)
    {
        if (possible) break;

        for (var j = 0; j < arr[i].length; j++)
        {
            if (i > 0)
            {
                if (arr[i][j].color == arr[i - 1][j].color)
                {
                    possible = true;
                    break;
                }
            }

        }
    }

    return possible;
}


Of course, we'll then check if i is less then the length of arr less 1 and check the color property of the element to the right. Repeat for the top and bottom... I really shouldn't have to explain the rest, should I? You're smart enough to be reading this blog, you'll figure it out.
isPossibleToMove: function()
{
    var possible = false;
    var arr = this.grid;

    for (var i = 0; i < arr.length; i++)
    {
        if (possible) break;

        for (var j = 0; j < arr[i].length; j++)
        {
            if (i > 0)
            {
                if (arr[i][j].color == arr[i - 1][j].color)
                {
                    possible = true;
                    break;
                }
            }

            if (i < arr.length - 1)
            {
                if (arr[i][j].color == arr[i + 1][j].color)
                {
                    possible = true;
                    break;
                }                                            
            }

            if (j > 0)
            {
                if (arr[i][j].color == arr[i][j - 1].color)
                {
                    possible = true;
                    break;
                }        
            }

            if (j < arr[i].length - 1)
            {
                if (arr[i][j].color == arr[i][j + 1].color)
                {
                    possible = true;
                    break;
                }    
            }

        }
    }

    return possible;
}


Now, to test! Set grid here to these test values. It's only temporary, so maybe copy the entire array and comment out the old one so we can get it back quickly. Basically, make sure every column has alternating colors of, say, indigo and orange. That should be enough to trigger the alert.
resetEggs: function()
{
    this.grid=[];

    this.grid = [
        [{style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}],
        [{style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}],
        [{style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}],
        [{style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}],
        [{style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}],
        [{style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}],
        [{style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}],
        [{style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}],
        [{style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}],
        [{style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}, {style: "style1", color: "orange"}, {style: "style1", color: "indigo"}]
    ];
    
    /*

    this.grid = [
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}],
        [{style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}, {style: "", color: ""}]
    ];
    */

    this.fillMissingEggs();
},


There you go! This will run infinitely, so revert to the original grid and refresh.




So now we have a nice grid... but there's more to come!

Next

Starting the game and playing it.

No comments:

Post a Comment