The Moron Test – Game Logic

But at this moment you are most likely to learn the most…

Tutorial

We at this point have a working game board that can be setup using JS, cleared, and reset with different icons. But for the moment we have to call the start of the game calling the unique name of an array of icon property objects. For example in the JS Console you can call start(ghosts) or start(paperAirplanes). These clear the game board icons, set new icons, and then attach event listeners to each icon. Presently each icon clicked returns the icon element and the index value as well as adds the hidden class so that it’s not visible.

Using unique array names for each level is not ideal as well as having each be a separate variable. So it’s time to nest these arrays in a larger data structure! We want to create an array of objects, one per scene level. That object will have the icon array as well as other pieces of data necessary for each scene including: an array of instructions, an answer sequence array, and a function for logic particular to your scene.

Creating the scene data structure
var scene = [
    //scene level 1 object
    {
        //array for instructions of scene
        instructions: ["Click the red ghost to continue"],
        //array of icon properties objects
        icons: [{
                class: "fas fa-ghost",
                color: blue,
                content: null,
                size: 8,
                transform: null,
                left: 10,
                top: 75,
            },
            {
                class: "fas fa-ghost",
                color: green,
                content: null,
                size: 8,
                transform: null,
                left: 65,
                top: 35,
            },
            {
                class: "fas fa-ghost",
                color: red,
                content: null,
                size: 8,
                transform: null,
                left: 25,
                top: 25,
            },
            {
                class: "fas fa-ghost",
                color: yellow,
                content: null,
                size: 8,
                transform: null,
                left: 80,
                top: 70,
            },
        ],
        //answer sequence array
        //ordered number values are the icon index values
        //to be clicked in sequence
        answer: [2],
    },
    //scene level 2 object
    {},
    //scene level 3 object
    {},
]

You’ll now be able to access your icon properties array with index values instead of the unique variable names previously used – ghosts is now scene[0].icons.

With a data structure that allows us to move from level to level using index values, we can now write a core set of logic which tests whether the correct icon has been clicked and whether the answer sequence is complete. That’s really the core of the Moron Test game, so we’re going to focus on that first.

We’re going to work this out by focusing on what values we need to track and what conditions we need to test.

Preparing for game logic

Adding a level variable to track which scene we are on and updating map icons function to incorporate this level – mapIcons(level).

//create a global variable level to track progress through scenes in the scene array
var level = 0

//works our global named icon arrays such as "ghosts"
function mapIcons(iconArr) {
    iconArr.forEach(function (iconObj) {
        var iconEl = iconBuilder(iconObj)
        iconSpace.appendChild(iconEl)
    })
}


//ghosts is now in the scene array of level objects 
// so we can access using scene[0].icons
//or instead of hardcoding an index value we'll use 'level'
//scene[level].icons access the icons array of any scene object
function mapIcons(level) {
    scene[level].icons.forEach(function (iconObj) {
        var iconEl = iconBuilder(iconObj)
        iconSpace.appendChild(iconEl)
    })
}
the main or core game logic

There are three “tests” we have to do

//track clicks or "guesses" for the scene
//global variable clickCount
var clickCount = 0

//main logic of the game how to run a scene
//we must pass the icon (<i>) and the index value, i to 
//this function because it is used within the 
//iconListener function
function runScene(icon, i) {
    //set in the local scope a value for the number
    //of clicks needed based on the scene answer
    //array length
    var clicksNeeded = scene[level].answer.length

    //TEST ONE
    //listen for click guesses while 
    //clickCount is less than the number of clicks needed
    if (clickCount < clicksNeeded) {

        //TEST TWO
        //test for the correct index value of the icon
        //against the answer in the answer array
        //we use click count to track which answer in 
        //the answer array to use
        if (i === scene[level].answer[clickCount]) {

            //if a click is correct increment click count
            clickCount++
            
            //TEST THREE
            //test to see if the scene is complete
            // if click count equals clicks needed 
            if (clickCount === clicksNeeded) {
                //player has completed the level
                //increment the level and start the next scene
                level++
                start()
            }
        } else {
            //fail
            console.log(fail)
            clearIcons()
        }
    }
}
finally add the game logic to event listener
//ORIGINAL ICON LISTENER FUNCTION
function iconListener() {
    var iconsToClick = document.querySelectorAll("i")

    Array.prototype.forEach.call(iconsToClick, function (icon, i) {
        icon.addEventListener("click", function () {
            //originally we had just the same thing happen to all icons clicked
            console.log(icon, i)
            icon.classList.add("hidden")
        })
    })
}

//UPDATED ICON LISTENER FUNCTION
//now we add runScene to the click listener
function iconListener() {
    var iconsToClick = document.querySelectorAll("i")
    Array.prototype.forEach.call(iconsToClick, function (icon, i) {
        icon.addEventListener("click", function () {
            //runScene uses the icon and i values from
            //the selected nodeList turned into an array
            runScene(icon, i)
        })
    })
}
Oh and one more for those with your start function
function start() {
    //reset click count for the next scene
    clickCount = 0
    
    //call the three functions for icons
    clearIcons()
    mapIcons(level)
    iconListener()

    //call the two functions for instructions
    //you need to write these two
    clearInstr()
    mapInstr(level)
}

 

Problem Set

Building the new data structure
  • Create a new JS file scenes.js file which will contain the array of scene objects.
  • Create your scene variable with an array of level objects. You should have 2-3 objects, one for each level you’re working on.
  • Move your arrays of icon property objects to the icons value in each scene level object.
  • Using the <script src=""> tag, add the scenes.js file to your index.html file the line above your moron.js script tag.
Building the main scene logic
  • create your necessary global variables to track the level and the clickCount
  • update your mapIcons(level) function to use the level as an argument not the icon properties array
  • create a runScene(icon, i) function that incorporates the core three tests for guesses (clicks) against answers
  • add runScene(icon, i) to the iconListener()
  • create/update your start() function

Blogging Questions

How does the test sequence for each scene level work? What’s the first test? The second test? The third test? What are the true/false responses to each test?

Leave a comment

Your email address will not be published. Required fields are marked *