Roguelike Dungeon Crawler Game Planning

Hello all,

I am about to start working on my Roguelike Dungeon Crawler game, and I wanted to plan ahead for my game, so I don’t run in blind.

For my components, I’ve decided to format them as such:

However, I still have a lot of questions that maybe some people can give me advice on:

  1. How do I draw the board? What exactly is the board element? How do I make sure the board generates in such a way that it is playable?

  2. How do I handle the user interactions with walls? Are walls just groups of pixels that are colored black in CSS?

  3. Does my player move around the board by being a CSS class? (i.e. when the player moves, the “cell” that he was in goes back to white, and the cell he moved to changes to red or something)

  4. How do I make the darkness? How do I toggle the darkness or the light ring around the character?

Thanks for all the help.

1 Like
  1. You draw the board the same way you did in the Game of Life. It is a grid of data. Presumably you have an array of codes in state, codes that say what is currently on each cell.

  2. For me, the walls were codes in my array of data held in state. If the player tried to move into a cell that had a wall code, it wouldn’t let him. If he tried to move into a cell with a weapon code, it would let him and upgrade his weapon. Etc.

  3. For me, the player moved around by being a code in the array of data. When the player tried to move, I would check if he was allowed to move there, and then change the new cell to the player code and change the old cell to an “empty space” code.

  4. I would suggest looking into the opacity property in css. For me, I was able to have three opacity levels - light, dark, and “light but half lit to represent it is known but not currently in LOS”. Then, as the character moves, I figured out what the adjacent cells were and changed that css class.

1 Like

@ksjazzguitar

That actually all makes a lot of sense. My question would be how do I generate a map structure that is actually playable, but keep it still random? Additionally, would player health be better off in the highest parent state possible? Or keep it local?

To be clear, the map does not have to be randomly generated. The user stories state that only the items and enemies have to be randomly placed. So I would start out by creating a small static map to get everything else working before trying to create a random map.

I would advise making the player its own object in your code and keeping it on the global scope. There is no reason to make it a component. For me I just had a basic map-unit component that I passed a parameter to(based of the map array) that determined how it should be drawn. All the game logic was handled in vanilla javascript.

@josh

Thanks for the understanding on the map tip, I guess the health could be okay off in a global variable because the game does not have to re-render when the player loses life, but isn’t it better convention for React projects to keep things in state? Also, I was thinking about making my character change colors depending on how low its health got. Then, I would definitely need it in state

You could also use a library like rot.js to help manage the roguelike stuff.

@freddydumont Ehh I know I could get it to work, and I know that the challenge says you can use any libraries that you want, but I feel like doing it from scratch will help me get better at React.

What about Redux? Keeping all data in a single global store would actually make sense for a project like that. You can choose to connect components or not depending on whether they need to be updated with the global store.

1 Like

I’ve never really learned redux. I started the FCC Alpha Challenges, but did not go past redux because I didn’t need it for my last project

Well if you wanna learn, check out the official redux docs. They’re really great and there’s a video tutorial from the creator. I also used this awesome React+Redux course on udemy which you can get for 10-15$ by searching for coupons online. But there’s a lot of free resources online.

As Josh mentioned, there is no requirement that the map be random. I just made one and used that. I actually created a program to allow me to click on the cells I wanted to be walls and then outputted that object to the console. Then I cut and pasted that as a constant in my program. The only thing that was random were the objects in the dungeon. I put the player in the center and had the other things put at random (but keeping them always at least one cell from a wall, so they didn’t block any passages.)

It would be nice to do a random map. There are people on the web explaining how they did, but for now I’ll be happy with what I did. If I ever redo this, I’ll try doing random.

To me, it made sense to keep this in state. Remember that I keep everything in one state, the lowest component that is an ancestor to all the components that are dynamic. Since the players health is being updated during the game and that is being displayed on the screen, then I want that in state to take advantage of data binding.

All information that affects the screen is kept in the state of my Game component. For example, in my state I had property:

player: { location: 0, health: 0, weapon: { name: "", attack: 0 }, level: 1 },

With the exception of location, all of that is data that will output to the screen as player stats. By keeping it in state, it will automatically update. That is the beauty of React.

People are mentioning Redux. That is a powerful companion for React. I think it’s good to learn React without it at first. But perhaps you have. All of these projects are small enough that you don’t really need Redux, but it would definitely be something to learn in the future if you’re serious about React.

@ksjazzguitar

I notice that in Quincy’s project while the frame stays one size, the character moves with the map, and the map is actually larger. I can’t wrap my head around how he did that. Also, I decided to do the same thing as you, and I made a program that allows me to make a map. I was just wondering if it was possible to have a “Draggable” grid in which when you’re hovering over something and your mouse is down it will toggle a wall. See what I’ve got so far: https://codepen.io/njanne19/pen/WOPVZj?editors=1111

The simplest way is to just have a big map “behind” (inside) the smaller game area, positioned relative to the game area and with it’s ‘overflow’ hidden so that you can only see the part in the middle. Then you check where the player is and move the map if they get too close to one of the edges (if there is room to move the map).

So the blackness would once again be its own component that is laid on top of the bigger map?

I decided not to go with the “larger than the viewer area dungeon” - it wasn’t in the requirements and it seemed an unnecessary complication.

I did think about it though. Richard offers a suggestion. I was thinking about keeping my dungeon grid just like before, but having a separate grid representing the view area. I would keep track of where the player was and after each move I would recopy the relevant section of the dungeon grid onto the viewer grid and allow React to redraw the screen. I think that would work well.

@ksjazzguitar

Ok, freeCodeCamp must have used some sort of algorithm to generate their map because this is painful. Is there an easier way than doing this cell by cell? I’ll be here all week

I just created a grid program. I spun it off from my Game of Life program since it already had a grid and the ability to click them. I’d already decided that a status of 0 would be a wall and a status of 1 would be open floor. So I went around clicking where I wanted the walls to be (changing the data points to 0) and then ouputted that to the console. Then I cut and pasted data. I may have had to manipulate it a little in excel or something to get it in the right format, but I don’t remember. If I’d been more comfortable working locally, I probably would have done that and outputted the data in exactly the correct format in a file.

It took some work, but it was a lot easier than trying to come up with an algorithm to generate them randomly.

@ksjazzguitar I’ll try doing that. Is there any good way to have a “drag” event so I can just drag over with my mouse down to highlight an entire row to make a wall (like one would when drawing with a mouse in MS paint)

My cells were defined with this:

class Cell extends React.Component {
  render() {
    return (
      <span draggable="true" className={"cell " + this.props.color + "-" + this.props.cellLife} onClick={this.onCellClick.bind(this, this.props.id)} onDragEnter={this.onCellDrag.bind(this, this.props.id)}></span>
    )
  }
  
  onCellClick(id) {
    this.props.passCellClick(id);
  }
  
  onCellDrag(id, e) {
    this.props.passCellClick(id);
  }
}

which eventually passed down to the parent component in:

  handleCellClick(id) {
    let newLife = this.state.life;
    newLife[id] = (this.state.life[id])?0:1;
    this.setState({
      life: newLife
    });
  }

life was the name of the array in state where I held my grid data (name left over from the Game of Life) and id is the name of the cell clicked.

Why would you opt for binding your methods inside your event listeners? What does binding in this situation even do exactly? Also, if my map is 10000 cells, that’s a lot of excel work.