Sign in to follow this  
shawnre

Storing room exits and level exits, little help needed

Recommended Posts

Hello all, Basically I have a level that is composed of rooms. Each room has four exits (N,S,E,W) which may lead to another room or may be blocked. Within each level, one of the rooms is marked as the level exit. This particular room needs to mark either its N,S,E or W exit as the level exit. Looking for a logical way to manage an arrangement like this, or possibly another strategy if someone has any suggestions. Here is a little outline of what I have structure/class wise: Level - Room[,] rooms (stores a room array) Room - bool isLevelExit, Texture2D floor, walls, doors Currently I have the level rooms array select a random room and set the isLevelExit to true for that room. In that way I am assured that at least one room within the level is an exit. However, what I am trying to do now is set up the one room that is the level's exit to have one of its exits equate to the actual exit for the level....if that made any sense to anyone. *Edit* - I was thinking of setting up an enum in the Room class for the exits like so: enum Exits { North, South, East, West } and somehow setting up a system as to whether or not each exit is a valid exit or dead end, and also using that somehow to determine if that room exit is also the level exit. Maybe I am over complicating things a bit like I usually do. Any help/ideas appreciated. Thanks! *Edit...again* - I am finding myself also having another issue that I guess is design related. How to determine in each individual room whether or not its exits should be blocked or open to the next room. Obviously if the room is on the edge of the array (say the top left corner) it's north and west walls would be dead ends. However, how do I get the room class, which is just an individual room, with no knowledge of the 'other' rooms or the array that the level contains, to know if it is on the edge.... Am I just over complicating this or what? I figure the rooms should be able to handle themselves (meaning knowing if their exit should be blocked or not), however I am not seeing how exactly to do this without knowing about the level array. Thanks again for any help!! [Edited by - shawnre on January 17, 2009 10:17:09 PM]

Share this post


Link to post
Share on other sites
Just because your level/room locations are stored in an array does not mean that you have to represent them like that. What I would do is something like this:


struct Doorway;

struct Room
{
Doorway North, South, East, West;
};

struct Doorway
{
Room* nextRoom;
unsigned char roomState; // 0 for accessable, 1 for blocked, 2 for exit
};

Share this post


Link to post
Share on other sites
Your rooms are layed out in a grid, with a physical edge, right? If so, then yes, the rooms on the edge should have their doors blocked on those sides, because there's obviously no room behind those doors. Rooms themselves don't know this, but the Level does, because it contains the grid of rooms. I wouldn't make rooms too self-aware here, especially because the level already knows what needs to be done.

Also, an open door always leads to the room that lies next to it on the grid, right? In that case, Brain me's suggestion is unnecessary, because it's already known what door leads to what room - all you need to store is whether a door is blocked or not, or if it's the exit door. An enum (OPEN, CLOSED, EXIT) would be more clear there than an unsigned char.


So, to recap, I'd let the level do the maze generating, and in the rooms I'd store an enum for each door. Rooms don't need to store an isExit boolean, because that information is already stored in their door states: if a room has an exit door, then it's obviously the exit room.

Share this post


Link to post
Share on other sites
I think I see what both of you are saying. I think I may put a door class into the mix at this point. Every room, even if on the edge will have four doors. What the doors do when entered, at this point I have not decided, other than rooms that connect to each other on the grid will allow walking through.

I guess a little info on what exactly I am doing would help solidify this a little bit. Basically I am attempting to, on a 2-d level, model after the movie called Cube. Each room within the game can have items in it, can perform actions...The goal for the player is of course to find the level exit. The game starts out fairly easily, as a 1 x 1 cube. So, four doors, one is the level exit, the other three blocked. If you pass through the level exit door, level two is created which is 2 x 2. There you have 4 rooms obviously, and 16 exits. Level three, and so on, just makes the cube (I guess I should call it a square not a cube), the same size as the current level you are on. So, in a way, I guess it is like a maze as Captain P alluded to, even though I did not think of it in that way at first.

Anyhow, I think it sounds ok to create a door class with the room then containing a list of the four doors it contains. The reason I was using the bool isLevelExit in the room was to let a room know if it needs to select one of its four doors to be the level exit that would trigger the creation of the next level and place the character somewhere within that new level.

So, with a door class, I could just store an enum in it about whether or not the door is blocked, links to another room, or if it is the level exit. Then if I change my mind about how a door works, I would just have to add behavior in the door class (say I decide I want to make a door teleport to a random room rather than just lead to the room beside it).

That sound like a pretty good plan? Anything you see wrong design wise? Anything I may be overlooking?

Thanks again guys, your ideas helped me to develop what (I think) is a better plan.

Share this post


Link to post
Share on other sites
I think my OOP skills are severely lacking or something. I went to try and put these thoughts into practice and here is what I have:


class Level
{
Random random;
Room[,] rooms;

public Level(ContentManager content, int currentLevel)
{
random = new Random();

rooms = new Room[currentLevel, currentLevel];

for (int i = 0; i < currentLevel; i++)
{
for (int j = 0; j < currentLevel; j++)
{
rooms[i, j] = new Room(content);
}
}
//Select a random room for level exit
rooms[random.Next(0, currentLevel), random.Next(0, currentLevel)].IsLevelExit = true;
}

public void Draw(SpriteBatch spriteBatch, int row, int col)
{
rooms[row, col].Draw(spriteBatch);
}
}




class Room
{
const int SIZE = 2;
const int OFFSET = 256;
Texture2D floor;
bool isLevelExit;

Door north;
Door south;
Door east;
Door west;

public bool IsLevelExit
{
set { isLevelExit = value; }
}

public Room(ContentManager content)
{
isLevelExit = false;
north = new Door();
south = new Door();
east = new Door();
west = new Door();
floor = content.Load<Texture2D>("Ground");
}

public void Draw(SpriteBatch spriteBatch)
{
for (int i = 0; i < SIZE; i++)
for (int j=0; j < SIZE; j++)
spriteBatch.Draw(floor, new Vector2(i * OFFSET, j * OFFSET), Color.White);
}
}




class Door
{
enum State { Blocked, Exit, LevelExit }
State doorState;

public Door()
{
doorState = State.Blocked;
}
}




1. I do not like that I made 4 instances of Door within the room class. Is there a better way to do that while maintaining a direction name with each door?

2. I figured I would create an initialize method in Room which Level could call to set the state of each one of the doors, since the level will know which doors are going to be blocked and such. I tried doing a public property in the Door class to return doorState but get a inaccessibility error doing that. I guess I will ask, how exactly should I do that then?

Thanks again for any more help!

Share this post


Link to post
Share on other sites
1. Since Door only contains an enum, why not store these enums directly in Room? So, instead of having 4 Doors, you have 4 States (which I would then call DoorState or something instead).

2. Your State enum inside Door is not public. So, while you do expose the doorState variable, it's type is not exposed. Solution: make that enum public, or declare it outside the Door class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this