Renuka Prasad A
Renuka Prasad A

Reputation: 107

state in react is returning back to the original value

I'am trying to implement a rogue like dungeon crawler game in react,I render the map before component mounts once and i later re-render the level using levelRender() function,but my state is returning back to its orginal value which is set by componentWillMount() function.Debugging shows that state is being chaged by levelRender() function but at end it returns to original state,which i think shouldn't be happening.I know my code is bit long but i guess problem lies with way i call componentWillMount() and levelRender() function.

In the game,brown box is the portal which should trigger the levelRender,when it is run over by player which is red box.

here is link to my codepen,use arrow keys to move around :)

const Map = React.createClass({

  getInitialState() {
    return {

      width: 40,
      height: 50,
      wallRender: 0,
      gameLevel: 0,
      Probabilities: {
        levelA: [3, 5, 2],
        levelB: [3.5, 3, 3.5],
        levelC: [8, 1, 1]
      }

    }
  },

  componentWillMount() {
    document.addEventListener("keydown", this.handleKeyDown, false);


    var map = [];
    var rooms = [];
    var render = [];
    var level = this.state.gameLevel;
    //use rot.js to generate map
    var w = this.state.width,
      h = this.state.height;
    var objects = ["e", "h", "w"];
    var probability;


    var enemies = [];
    var weapon = [];
    var health = []

    if (level == 0) {
      probability = this.state.Probabilities.levelA;
    } else if (level == 1) {
      probability = this.state.Probabilities.levelB;
    } else {
      probability = this.state.Probabilities.levelC;
    }


    // var map = new ROT.Map.Digger();
    var data = {};
    var rotMap = new ROT.Map.Rogue(w, h);

    var display = new ROT.Display({ width: w, height: h, fontSize: 6 });


    rotMap.create(function (x, y, type) {
      data[x + "," + y] = type;
      display.DEBUG(x, y, type);
    })






    map = rotMap.map;
    var rooms = rotMap.rooms;
    // console.log(map);
    // console.log(rooms)



    var playerPosition = [rooms[0][0].x + 1, rooms[0][0].y + 1];
    var portalPosition = [rooms[2][2].x + 2, rooms[2][2].y + 2];
    // console.log(playerPosition)

    map[playerPosition[0]][playerPosition[1]] = "p";
    map[portalPosition[0]][portalPosition[1]] = "*";
    var pp = playerPosition;
    //     
    // set up enemies and health
    rooms.map(function (rooms) {
      rooms.map(function (room) {


        var rx = room.x; var ry = room.y;

        var noe = Math.floor(Math.random() * ((1 + 2) - 2 + 1)) + 2;


        for (var i = 0; i < noe; i++) {
          //     generate enemy postions
          var ex = Math.floor(Math.random() * ((room.width + rx) - rx + 1)) + rx;
          var ey = Math.floor(Math.random() * ((room.height + ry) - ry + 1)) + ry;




          if ((ex >= rx && ex < room.width + rx) && (ey >= ry && ey < room.height + ry)) {

            var totalProbability = eval(probability.join("+"));//get total weight (in this case, 10)
            var weighedObjects = new Array();//new array to hold "weighted" fruits
            var currentObject = 0;

            while (currentObject < objects.length) {
              for (i = 0; i < probability[currentObject]; i++)
                weighedObjects[weighedObjects.length] = objects[currentObject]
              currentObject++
            }

            var randomnumber = Math.floor(Math.random() * totalProbability)
            var x = weighedObjects[randomnumber];

            if (x == 'e') {
              map[ex][ey] = "e";
              var stats = {
                loc: ex + " " + ey,
                health: 50,
                damage: 20
              }
              enemies.push(stats)

            } else if (x == 'h') {
              map[ex][ey] = "h";
              var stats = {
                loc: ex + " " + ey,
                boost: 80
              }
              health.push(stats)

            } else if (x == 'w') {
              map[ex][ey] = "w";
              var stats = {
                loc: ex + " " + ey,
                damageBoost: 40
              }
              weapon.push(stats)
            }






            // console.log(ex + " " + ey + " " + (room.width + rx) + " " + (room.height + ry))
          }




        }





      })
    })



    //     place enemy

    // console.log(enemies);
    // console.log(health);
    // console.log(weapon)



    //    setup field of view
    var fov = this.setFov(pp)

    this.setState({
      gameState: map,
      gameRooms: rooms,
      playerPosition: playerPosition,
      playerHealth: 50,
      playerDamage: 5,
      portalPosition: portalPosition,
      fov: fov,
      enemies: enemies,
      health: health,
      weapon: weapon

    });




  },

  levelRender(){
    console.log("level rendered")
    var map = [];
    var rooms = [];
    var render = [];
    var level=this.state.gameLevel;

    //use rot.js to generate map
    var w = this.state.width,
      h = this.state.height;
    var objects = ["e", "h", "w"];
    var probability;

    var enemies = [];
    var weapon = [];
    var health = []

    if (level == 0) {
      probability = this.state.Probabilities.levelA;
    } else if (level == 1) {
      probability = this.state.Probabilities.levelB;
    } else {
      probability = this.state.Probabilities.levelC;
    }


    // var map = new ROT.Map.Digger();
    var data = {};
    var rotMap = new ROT.Map.Rogue(w, h);

    var display = new ROT.Display({ width: w, height: h, fontSize: 6 });


    rotMap.create(function (x, y, type) {
      data[x + "," + y] = type;
      display.DEBUG(x, y, type);
    })






    map = rotMap.map;
    var rooms = rotMap.rooms;




    var playerPosition = [rooms[0][0].x + 1, rooms[0][0].y + 1];

    if(level==0 || level ==1){
      var portalPosition = [rooms[2][2].x + 2, rooms[2][2].y + 2];
      map[portalPosition[0]][portalPosition[1]] = "*";
    }else{
      var bossPosition = [rooms[2][2].x + 2, rooms[2][2].y + 2];
      map[portalPosition[0]][portalPosition[1]] = "boss";
    }





    map[playerPosition[0]][playerPosition[1]] = "p";

    var pp = playerPosition;
    //     
    // set up enemies and health
    rooms.map(function (rooms) {
      rooms.map(function (room) {


        var rx = room.x; var ry = room.y;

        var noe = Math.floor(Math.random() * ((1 + 2) - 2 + 1)) + 2;


        for (var i = 0; i < noe; i++) {
          //     generate enemy postions
          var ex = Math.floor(Math.random() * ((room.width + rx) - rx + 1)) + rx;
          var ey = Math.floor(Math.random() * ((room.height + ry) - ry + 1)) + ry;




          if ((ex >= rx && ex < room.width + rx) && (ey >= ry && ey < room.height + ry)) {

            var totalProbability = eval(probability.join("+"));//get total weight (in this case, 10)
            var weighedObjects = new Array();//new array to hold "weighted" fruits
            var currentObject = 0;

            while (currentObject < objects.length) {
              for (i = 0; i < probability[currentObject]; i++)
                weighedObjects[weighedObjects.length] = objects[currentObject]
              currentObject++
            }

            var randomnumber = Math.floor(Math.random() * totalProbability)
            var x = weighedObjects[randomnumber];

            if (x == 'e') {
              map[ex][ey] = "e";
              var stats = {
                loc: ex + " " + ey,
                health: 50,
                damage: 20
              }
              enemies.push(stats)

            } else if (x == 'h') {
              map[ex][ey] = "h";
              var stats = {
                loc: ex + " " + ey,
                boost: 80
              }
              health.push(stats)

            } else if (x == 'w') {
              map[ex][ey] = "w";
              var stats = {
                loc: ex + " " + ey,
                damageBoost: 40
              }
              weapon.push(stats)
            }






            // console.log(ex + " " + ey + " " + (room.width + rx) + " " + (room.height + ry))
          }




        }





      })
    })

    //    setup field of view
    var fov = this.setFov(pp)

    console.log(this.state.gameState)

    this.setState({
      gameState: map,
      gameRooms: rooms,
      playerPosition: playerPosition,
      bossPosition:bossPosition,
      portalPosition: portalPosition,
      fov: fov,
      enemies: enemies,
      health: health,
      weapon: weapon

    });
 console.log(this.state.gameState)


  },

  setFov(playerPos) {
    var pp = playerPos;
    var fov = [];
    var x = pp[0]; var y = pp[1];

    fov.push(x - 2 + "," + (y - 1)); fov.push(x - 2 + "," + y); fov.push(x - 2 + "," + (y + 1));
    fov.push(x - 1 + "," + (y - 2)); fov.push(x - 1 + "," + (y - 1)); fov.push(x - 1 + "," + y); fov.push(x - 1 + "," + (y + 1)); fov.push(x - 1 + "," + (y + 2));
    fov.push(x + "," + (y - 2)); fov.push(x + "," + (y - 1)); fov.push(x + "," + y); fov.push(x + "," + (y + 1)); fov.push(x + "," + (y + 2));
    fov.push(x + 1 + "," + (y - 2)); fov.push(x + 1 + "," + (y - 1)); fov.push(x + 1 + "," + y); fov.push(x + 1 + "," + (y + 1)); fov.push(x + 1 + "," + (y + 2));
    fov.push(x + 2 + "," + (y - 1)); fov.push(x + 2 + "," + y); fov.push(x + 2 + "," + (y + 1));
    fov.push(x - 3 + "," + y); fov.push(x + 3 + "," + y); fov.push(x + "," + (y - 3)); fov.push(x + "," + (y + 3))

    return fov;
  },

  handleKeyDown(e) {
    //     left arrow
    var playerLoc = this.state.playerPosition;
    if (e.keyCode == 37) {

      var map = this.state.gameState;
      var playerPos = this.state.playerPosition;
      var x = playerPos[0], y = playerPos[1];

      // console.log(map)
      // console.log(playerPos)
      if (map[(x)][(y - 1)] == 0 || map[(x)][(y - 1)] == "w" || map[(x)][(y - 1)] == "h" || map[(x)][(y - 1)] == "*") {

        if (map[(x)][(y - 1)] == "*") {
           var level = this.state.gameLevel + 1;

         this.setState({
        gameLevel:level
          })
          this.levelRender();

        }

        if (map[(x)][(y - 1)] == "h") {
          var health = this.state.playerHealth + 30;
          this.setState({
            playerHealth: health
          })
        }
        if (map[(x)][(y - 1)] == "w") {
          var damage = this.state.playerDamage + 20;
          this.setState({
            playerDamage: damage
          })
        }

        map[x][y] = 0;
        map[(x)][(y - 1)] = "p";

        playerPos[0] = x
        playerPos[1] = y - 1;
      }
      //      change fov

      var pp = playerPos;

      var fov = this.setFov(pp)




      this.setState({
        gameState: map,
        playerPosition: playerPos,
        fov: fov
      })

    }
    //  up arrow
    if (e.keyCode == 38) {

      var map = this.state.gameState;
      var playerPos = this.state.playerPosition;
      var x = playerPos[0], y = playerPos[1];
      // console.log(map)
      // console.log(playerPos)

      if (map[(x - 1)][(y)] == 0 || map[(x - 1)][(y)] == "w" || map[(x - 1)][(y)] == "h") {

        // update player health and damage
        if (map[(x - 1)][(y)] == "h") {
          var health = this.state.playerHealth + 30;
          this.setState({
            playerHealth: health
          })
        }
        if (map[(x - 1)][(y)] == "w") {
          var damage = this.state.playerDamage + 20;
          this.setState({
            playerDamage: damage
          })
        }


        map[x][y] = 0;
        map[(x - 1)][(y)] = "p";

        playerPos[0] = x - 1
        playerPos[1] = y;
      }

      // console.log(map)
      // console.log(playerPos)
      //      change fov
      var pp = playerPos;

      var fov = this.setFov(pp)

      this.setState({
        gameState: map,
        playerPosition: playerPos,
        fov: fov
      })

    }
    //   right arrow
    if (e.keyCode == 39) {
      var map = this.state.gameState;
      var playerPos = this.state.playerPosition;
      var x = playerPos[0], y = playerPos[1];
      // console.log(map)
      // console.log(playerPos)
      if (map[(x)][(y + 1)] == 0 || map[(x)][(y + 1)] == "w" || map[(x)][(y + 1)] == "h") {

        // update player health and damage
        if (map[(x)][(y + 1)] == "h") {
          var health = this.state.playerHealth + 30;
          this.setState({
            playerHealth: health
          })
        }
        if (map[(x)][(y + 1)] == "w") {
          var damage = this.state.playerDamage + 20;
          this.setState({
            playerDamage: damage
          })
        }


        map[x][y] = 0;
        map[(x)][(y + 1)] = "p";
        playerPos[0] = x
        playerPos[1] = y + 1;;
      }


      //console.log(map)
      //console.log(playerPos)

      //      change fov
      var pp = playerPos;

      var fov = this.setFov(pp)
      this.setState({
        gameState: map,
        playerPosition: playerPos,
        fov: fov
      })
    }
    //    down arrow
    if (e.keyCode == 40) {
      var map = this.state.gameState;
      var playerPos = this.state.playerPosition;
      var x = playerPos[0], y = playerPos[1];

      if (map[(x + 1)][(y)] == 0 || map[(x + 1)][(y)] == "w" || map[(x + 1)][(y)] == "h") {

        // update player health and damage
        if (map[(x + 1)][(y)] == "h") {
          var health = this.state.playerHealth + 30;
          this.setState({
            playerHealth: health
          })
        }
        if (map[(x + 1)][(y)] == "w") {
          var damage = this.state.playerDamage + 20;
          this.setState({
            playerDamage: damage
          })
        }


        map[x][y] = 0;
        map[(x + 1)][(y)] = "p";
        playerPos[0] = x + 1
        playerPos[1] = y;
      }


      // console.log(map)
      // console.log(playerPos)
      //      change fov
      var pp = playerPos;

      var fov = this.setFov(pp)

      this.setState({
        gameState: map,
        playerPosition: playerPos,
        fov: fov
      })
    }


  },

  render() {



    //    rendering map

    var map = this.state.gameState;
    var fov = this.state.fov;

    if(this.state.gameLevel==1){
      console.log(map)
    }


    var render = [];



    for (var i = 0; i < this.state.width; i++) {
      var dummy = [];

      for (var j = 0; j < this.state.height; j++) {
        var arena = { background: "white", color: "white" };
        var wallColor = "grey";






        var wall = { background: wallColor, color: wallColor, border: "2px solid black" };
        var enemy = { background: "blue", color: "blue" };
        var player = { background: "red", color: "red" };
        var health = { background: "green", color: "green" }
        var weapon = { background: "orange", color: "orange" }
        var portal = { background: "brown", color: "brown" }
        var boss ={background:"yellow",color:"yellow"}
        //       check if cell is in fov  
        var val = i + "," + j;




        if (map[i][j] == 0) {
          //           implement field of view
          var x = arena;
          //                       if (fov.includes(val)) {
          //                         x.visibility = "visible";
          //                         console.log(val)

          //                       } else {
          //                         x.visibility = "hidden";
          //                       }

          dummy.push(<td style={x}>00;</td>);
        } else if (map[i][j] == "p") {
          dummy.push(<td style={player}>00;</td>);
        } else if (map[i][j] == "e") {
          var x = enemy;
          //                        if (fov.includes(val)) {
          //                         x.visibility = "visible";


          //                       } else {
          //                         x.visibility = "hidden";
          //                       }

          dummy.push(<td border={5} style={enemy}>00;</td>);
        } else if (map[i][j] == "h") {
          var x = health;
          //                        if (fov.includes(val)) {
          //                         x.visibility = "visible";


          //                       } else {
          //                         x.visibility = "hidden";
          //                       }

          dummy.push(<td style={health}>00;</td>);
        } else if (map[i][j] == "*") {
          var x = portal;
          //                        if (fov.includes(val)) {
          //                         x.visibility = "visible";


          //                       } else {
          //                         x.visibility = "hidden";
          //                       }

          dummy.push(<td style={portal}>00;</td>);
        }

        else if (map[i][j] == "w") {
          var x = weapon;
          //                        if (fov.includes(val)) {
          //                         x.visibility = "visible";


          //                       } else {
          //                         x.visibility = "hidden";
          //                       }

          dummy.push(<td style={weapon}>00;</td>);
        }else if (map[i][j] == "boss") {
          var x = boss;
          //                        if (fov.includes(val)) {
          //                         x.visibility = "visible";


          //                       } else {
          //                         x.visibility = "hidden";
          //                       }

          dummy.push(<td style={boss}>00;</td>);
        }


        else {
          var x = wall;
          //                       if (fov.includes(val)) {
          //                         x.visibility = "visible";
          //             //             console.log(val)

          //                       } else {
          //                         x.visibility = "hidden";
          //                       }
          // generate random hue of colors

          dummy.push(<td style={wall}>00;</td>);
        }
      }

      render.push(<tr>{dummy}</tr>);
    }





    return (
      <div>
        <div id="info">
          <span id="health">Health:{this.state.playerHealth} </span>
          <span id="damage">Damage:{this.state.playerDamage} </span>
          <span id="message">{this.state.playerMessage}</span>
        </div>


        <div id="gameArea" tabIndex="0" >

          <table align="right">
            {render}
          </table>
        </div>
      </div>
    )

  }


})




ReactDOM.render(<Map />, document.getElementById("app"));

Upvotes: 0

Views: 178

Answers (1)

Suhas V
Suhas V

Reputation: 164

You are setting the state in levelRender and overwriting the same with the previous state.

On line 452, this.leverRender is being invoked, which actually sets the new game state (desired). Later, on line 485, state is being overwritten with the variable map which has got the old values, which is responsible for the undesired output. This has to be resolved by setting the state only once, or setting it twice but with updated values of map.

Upvotes: 1

Related Questions