dimanche 4 février 2018

Why does this JavaScript comparison operator evaluate to true when it's clearly false?

This is my first question on this exchange so be gentle. I have looked through the "similar" questions to no avail.

I am running this script on my local machine using Opera.

My brain is seriously hurting. I'm in physical pain. I've spent literally hours racking my brain trying to find the fault in this simple (admittedly novice) code. I can't seem to figure it out. Please help me before I run out of aspirin. Yes, I'm new to JavaScript. I apologize for that as I'm sure there are many of you who will see lots of novice mistakes in this code and practices that are less than perfect. But I'm really trying to learn.

Let me explain. Below is the ENTIRE game. I've only included it because I'm really just not sure how to proceed. I've been stepping through the code line by line for hours. The only thing you'd have to do is make a few assets and this crappy game would be up and running. Except for the BUG!

The player in this little game starts in town as denoted by the default value of mapFlag aka "town".

When the player reaches predetermined coordinates on the canvas, the background image is redrawn and mapFlag switches to the new flag, etc. New music plays and all that based on this mapFlag variable.

The problem is this: The game starts. We are in town. We move to the right and the map switches to the GRASS as planned. But the moment we step back to the left again, it goes back to TOWN. The only way this should happen is if the player's X and Y coordinate are less than or equal to those in this statement:

// Grass to town        
if ((px <= 20) && (py <= 20) && (mapFlag == "grass")){
    mapFlag = "town";
    gravestones = [];
    //px=300; py=300;
    ex=200; ey=200;
    return;
}

which is part of my mapSwitch function. However, even though my coordinates are definitely NOT less than 20, the game still switches everything back to TOWN unexpectedly. I've tried rebuilding the mapSwitch function to use if and else if instead but it operates the same. I've commented lines here and there trying to whittle it down and the only thing I can guess is that it has something to do with my ill-planned coordinate system causing some kind of death loop. But very slowly walking through this code line by line, I just can't seem to see how my if statement above could fail? There must be more to this story that I'm just too inexperienced or tired to notice. Please help!

If it matters, I've learned a LOT of things to NOT do during this project. One is that I should not use a coordinate system with individual variables like that but instead use a JavaScript Object (or class?) I guess there's a difference. More reading ahead in my journey. I've also learned that I need to do some serious reading on how to plan the order, layout, and general structure of functions and how they all tie together.

<canvas id="board" width="620" height="720" tabindex='1'></canvas>
    <script>


        // Constants and variables
            const cvs = document.getElementById('board').getContext('2d');;
            const movUnit = 20; //one block is 10 x 10 in game
            const gameSpeed = 200;
            const scoreIncrease = 1;

                var px = 300;
                var py = 300;
                var ex = 100;
                var ey = 100;
                var mapFlag = "town";
                var gravestones = [];
                var score = 0;
                var movAI=0;
                var playerDeaths = 0;

        // Setup Objects
            var player = {
                    x: 40,
                    y: 40,

                };

            var enemy = {
                    x: 100,
                    y: 100,
                };

        // Graphics
                let imgPlayer = new Image();
                    imgPlayer.src = "img/player.png";
                let imgGrass = new Image();
                    imgGrass.src = "img/grass.png";
                let imgTown = new Image();
                    imgTown.src = "img/town.png";
                let imgCave = new Image();
                    imgCave.src = "img/cave.png";
                let imgScore = new Image();
                    imgScore.src = "img/score.png";
                let enemyPlayer = new Image();
                    enemyPlayer.src = "img/enemy.png";
                let imgGrave = new Image();
                    imgGrave.src = "img/grave.png";

        // Load or play audio
                let sndFootstep = new Audio();
                    sndFootstep.src ="snd/footstep.mp3"; 
                let sndDeath = new Audio();
                    sndDeath.src ="snd/death.mp3";
                let sndMusic = new Audio();
                    sndMusic.src = "snd/music.mp3";
                let sndCave = new Audio();
                    sndCave.src = "snd/cave.mp3";
                //let sndTown = new Audio();
                    //sndTown.src = "";

        // Listener
                window.addEventListener("keydown", direction);

    function mapSwitch(){
        // Map Switch Checks
            // Home Town to Grassy
            if ((px >= 560) && (py >= 350) && (py <= 380) && (mapFlag == "town")){
                mapFlag = "grass";
                //px=100; py=360;
                ex=200; ey=200;
                return;
            }

            // Grass to town        
            if ((px <= 20) && (py <= 20) && (mapFlag == "grass")){
                mapFlag = "town";
                gravestones = [];
                //px=300; py=300;
                ex=200; ey=200;
                return;
            }
            // grass to cave
            if ((px >= 560) && (py >= 560) && (mapFlag == "grass")){
                mapFlag = "cave";
                gravestones = [];
                px=60; py=60;
                ex=40; ey=40;
                return;
            }
            // cave to grass
            if ((px <= 40) && (py <= 40) && (mapFlag == "cave")){
                mapFlag = "grass";
                gravestones = [];
                px=540; py=540;
                ex=560; ey=560;
                return;
            }

    }   

    function detectHit(){
            // Enemy Collides with Wall
                if (ex >= 580){ex = 580;}
                if (ex <= 20){ex = 20;}
                if (ey >= 580){ey = 580;}
                if (ey <= 20){ey = 20;}

            // Player Collides with Wall
                if (px <= 20){px=20;}       
                if (py <= 20){py=20;}       
                if (px >= 580){px=580;}     
                if (py >= 580){py=580;}

            // Enemy kills player

                if (ex == px && ey == py && mapFlag != "town"){
                    sndDeath.play();
                    playerDeaths += 1;
                    score -= 50;
                    gravestones.push([px, py]);
                    px = 200; py = 200;
                }
                mapSwitch();        
    }

    function enemyAI(){

        // Skip Enemy AI if in town
            if (mapFlag == "town"){ return; }

        // Pick a random number
            movAI = Math.floor(Math.random() * 8) + 1;

        // Enemy AI behavior based on random number
            switch (movAI){
                case 1:
                    ex += movUnit;
                    break;

                case 2:
                    ex -= movUnit;
                    break;

                case 3:
                    ey += movUnit;
                    break;

                case 4:
                    ey -= movUnit;
                    break;

                case 5:
                    chase();
                    break;

                case 6:
                    chase();
                    break;

                case 7:
                    chase();
                    break;

                case 8:
                    chase();
                    break;
            }
        // See if enemy hit anything important
            detectHit();
                }

    function chase(){
        // If in town, skip chase
            if (mapFlag = "town"){ return; }

        // If in playable area get closer to player
            if (ex < px) {ex += movUnit;} 
            if (ey < py) {ey += movUnit;}
            if (ex > px) {ex -= movUnit;}
            if (ey > py) {ey -= movUnit;}
    }

    function bgMusic(){
        if (mapFlag == "town"){
            sndMusic.pause();
            sndCave.pause();
        }
        if (mapFlag == "grass"){
            sndMusic.play();
            sndCave.pause();
        }

        if (mapFlag == "cave") {
            sndCave.play();
            sndMusic.pause();
        }

    }   

    function draw(){

        // Draw the current state of the game
            enemyAI();
            if (mapFlag == "town") { cvs.drawImage(imgTown, 0, 0);}
            if (mapFlag == "grass"){ cvs.drawImage(imgGrass, 0, 0);}
            if (mapFlag == "cave") { cvs.drawImage(imgCave, 0, 0);}

            cvs.drawImage(imgScore, 0, 620);
            cvs.drawImage(imgPlayer, px, py);

        // Draw enemy as long as we're not in town
            if (mapFlag != "town"){cvs.drawImage(enemyPlayer, ex, ey);}

        // Show Death Count
            cvs.fillStyle = "maroon";
            cvs.font = "46px Arial";
            cvs.fillText(playerDeaths, 180,670);

        // Show Score and stop scoring if in town
            if (mapFlag != "town") { score += scoreIncrease; }
            cvs.fillStyle = "gold";
            cvs.font = "46px Arial";
            cvs.fillText(score, 240,715);

        // Show coordinates for testing 

            cvs.fillStyle = "gray";
            cvs.font = "10px Arial";
            cvs.fillText("px: " + px + " py: " + py + " ex: " + ex + " ey: " + ey + " map: " + mapFlag, 400,640);

        // Show Gravestones
                for (var i = 0; i <= gravestones.length; i++){
                    for (var j = 0; j <= 2; j++){
                        cvs.drawImage(imgGrave, gravestones[i][0], gravestones[i][1]);
                    }
                }

    }


    //   GAME LOOPS
    setInterval(draw, gameSpeed, px, py, ex, ey); // game loop
    setInterval(bgMusic, 1000); // music loop


    function direction(event){
        let key = event.keyCode;

        if(key == 37){
            // LEFT
            px -= movUnit;

        }else if(key == 38){
            // UP
            py -= movUnit;

        }else if(key == 39){
            // RIGHT
            px += movUnit;

        }else if(key == 40){
            // DOWN
            py += movUnit;

        }
        sndFootstep.play();
        detectHit();

    }


    </script>

Aucun commentaire:

Enregistrer un commentaire