Suppose you have certain tiles with data on them, like say your on an island and theres water. How do I give the water special properties so the player cant walk over it using the tile class?
I'm not entirely sure I understand your question, so forgive me if I get off on the wrong track…
What it sounds like you're saying is your entire game level is filled with things like ground or water tiles. (Perhaps there's other things, like mountains or whatever, but let's ignore them for now.) You add the two types of tiles as images in Realm Factory and then build your level and load it into XNA. And now you're sitting here wondering how you determine what kind of tile is at what spot? Or are you trying to decide, once you know what kind of tile is at what spot, how to actually implement behavior for those tiles, like preventing people from entering?
There's a tutorial that you should take a look at, if you haven't already, that kind of walks you through the process of getting the types of tiles out of your level.
As far as how to provide the implementation for specific tiles, that's up to you in your XNA code. And the details of how to actually do it depend on how you've structured your game and your game's mechanics.
Does that help at all?
Thats mostly what I was wondering and I have checked out your tutorial.
And there is no way you can use the Tile class to get/implement information about a specific tile? Thats what I have been trying to look into figuring out.
What you're saying is an area I'd actually like to improve Realm Factory in, to make this simpler. Obviously, in one form or another, you're going to have to tell your game what the different tile types actually mean. But yes, you can take the tile type and do different things based on what types of tiles you get. Furthermore, you can take the tiles that you load and in code, convert that over to whatever in-game data structure you're using that already has it's own implementation. Remember that Realm Factory is designed to be simply a level editor. Something that a non-programmer can use to define what levels look like, or something that programmers can use to quickly define levels, while the implementation is separated from the level design.
What you're saying, though, might go something like this:
Tile tile = (Tile)currentLevel.GetTile(row, column); if (tile == null) { continue; } Texture2D texture = tile.Texture; if(texture == waterTexture) { // Write code to handle what to do if the player tries to enter the water. } if(texture == landTexture) { // Write code to handle what to do if the player tries to enter a land square. }
This, of course, is the kind of code you'd see in the Update method instead of the Draw method.
Another option would be to load in the level data and then build a complete "logical" model from that up front, instead of checking against textures the whole time.
As an example, you might create an enumeration for the different terrain types:
public enum TerrainType { Land, Water, Mountain, Lava };
Then when you create the level, you'd do something like this:
TerrainType[,] terrain = new TerrainType[currentLevel.Rows, currentLevel.Columns]; for (int row = 0; row < currentLevel.Rows; row++) { for (int column = 0; column < currentLevel.Columns; column++) { Tile tile = (Tile)currentLevel.GetTile(row, column); if(tile.Id == 0) { terrain[row, column] = TerrainType.Land; } if(tile.Id == 1) { terrain[row, column] = TerrainType.Water; } if(tile.Id == 2) { terrain[row, column] = TerrainType.Mountain; } if(tile.Id == 3) { terrain[row, column] = TerrainType.Lava; } } }
Be warned: this code wasn't written with a compiler or anything. It may not work by directly dropping it into Visual Studio. The point is to just show you an idea of how this might work. This simply converts the level data into a "behind the scenes" logical data structure that you can then add methods to and make do whatever you want. The code here is kind of rough, but I can assure you the general approach works, at least in some situations. I just recently used this kind of approach in a game I was making.
Hope that helps!
Thanks alot rbwhitaker!
I dont know if the code example you posted will work or not, but it did help give me some new ways to tackle the problem. I did not think of checking to see wether the tile was set to a specific texture or not (silly me I know…)
I had been busy trying a multitude of other ways to get/implement data into certain tiles for a while now….biet through your Realm Factory, the traditional way of using a text/xml file and reading the data from that and through another tile program called tIDE.
All of them works wonders for making the maps, yet I cant seem to find a way to deal with the get/implement part, but I'll give your way another shot again to see if I can get things working. And also I'd like to say your RealmFactory tile editor is the best one I've used yet! (not just in XNA, but tile editors in general). Everything is simple and easy to access, although I do feel that, when working on big maps, perhaps when you get the chance, could you add a folder tree section to make it easier to categorize all your imported tiles in folders?
How would you draw the rectangles for each tile in order to check for collision? I am making a simple Breakout clone using Realm Factory and need a little insight into this.
I don't know how much experience you have with programming, so I'll just go for it. If any of the following doesn't make sense, ask away, and I'll try to address those questions as well.
The first thing I'd suggest is that you separate your game logic from your rendering state. It should hypothetically be easy to completely rewrite the game drawing code without touching the game updating code. This means that your game drawing code is nothing more than a view of the internal game state. Making this kind of separation goes a very long way towards forcing a good design.
The collision detection is a function of the internal game state, while the drawing is a function of the view/rendering code. So there should be little overlap between the two.
With that behind us, the place to start is with designing that internal game structure. There are a lot of ways you could approach this. Probably an infinite number. I'm not going to tell you what you're supposed to do, or what will be best in your particular case; I'll leave that to you to decide. But I'll give you some thoughts on what I'd probably do. I made a Breakout clone once a long time ago, but it's been so long, I don't recall what I actually did.
The place I'd start is with a Brick class. I'm not sure what it would contain, but probably not much, to start. Perhaps some static readonly fields that define the size of a brick within the internal game state. (Or alternatively, a static readonly Vector2 for this size.) Each individual brick will need some specific information about the brick itself, starting with the color. So I might have a Color property (of type Color) but I might also make an enumeration of the different types of bricks and use that instead. It really depends on how the rest of the game plays out. Of course, that kind of detail would probably be easy to change if we/I later decide that I made the wrong choice.
I'd also create a Ball class that represents the ball. This may not have much in it besides a Vector2 Position property and perhaps a double Radius property or something.
I'd probably also create a Paddle class that defines the position, length, and other properties of the player's paddle as well.
Next, I'd build a GameState class. This class will represent the internal, underlying game state. Remember, this class should know nothing about how it is being drawn. So things like sizes and positions are in terms of an abstract notion of space within your game, as opposed to being tied to pixels or anything like that. This GameState object will have a Ball (depending on what you want, you may end up with it having a list of Balls so that multiple balls can be bouncing around in your game) a Paddle (same thing here, though multiple paddles is a bit rarer in Breakout clones) and my best initial guess would be a two-dimensional array of Block objects (i.e., Brick[,] bricks = new Brick[20, 10];). This //GameState class is probably also going to need to have some knowledge about where the walls are in the world of the internal game state. How wide is the level exactly? (Not in pixels, but in some abstract units. For instance we might say that each brick is one unit across. One foot, one inch, one meter, whatever. But the entire game state is in the same world, so if the ball is one unit to the left of a brick that is one unit wide, we know it has missed it.) It may also need to know where the top corner of the grid is, with respect to the entire world.
When a level starts, I'd build a new instance of the GameState class based on what Realm Factory loads for you. (In other words, for most of the game, you won't be using Realm Factory's storage structures. You'll be using your own that you can manipulate however you see fit. Realm Factory is there to be a level designer and to bridge the gap from the saved level file to your game.)
As the game runs, you'll detect various input events from the user. Button presses, mouse movements, whatever. A part of your game will pick up on those events and transform them into requests to this GameState class. Things like, "There was a timer tick—34 milliseconds passed, so update the level accordingly (GameTime object)." Or "The mouse moved to this other location, so the player is attempting to put the paddle over here."
The GameState class will provide methods to respond to these events and update itself appropriately. This includes things like checking for collisions between the ball and the bricks, the ball and the paddle (and how to have the ball bounce off of the paddle), or where the player's paddle should actually end up, given a request from outside the game to move to a particular location.
You were specifically asking about collision detection, so let me try to address that in a little more detail. This is all happening within your GameState class at this point, and is completely separate from the drawing code. We know the ball has a certain size, and we know bricks have a certain size. When you know the ball is supposed to move, you can try moving the ball forward, and if the new position is in the bounds of any of the bricks in the game, it's a collision. There are algorithms out there that will tell you if a circle overlaps an axis-aligned rectangle (which is probably what it will be, since the bricks usually can't be rotated). In a nutshell, this might boil down to something like this. If any of the following are true, it's an intersection:
- If the center of the ball is contained in the block's rectangle, it's an intersection.
- If the position of the ball - the position of any of the four corners is < the size of the ball, it's an intersection.
- If the ball's x-coordinate is between the left and right sides of the ball and the ball's y-coordinate is between the top and bottom coordinates of the brick, plus the size of the radius, it is an intersection. Repeat for the other direction as well.
Otherwise it's not an intersection. (Somebody else can double check my math on that. I threw it together pretty quickly.)
One of the problems that you'll likely encounter is if a ball is moving fast enough, the ball could skip right through a brick. People often fix this by comparing the intersection of the brick with a swept circle instead. I won't get into those details right now. It's something to look at after you've got most of a game built and you're trying to clean things up.
So that's how I'd structure the game in general, and how I'd handle collision detection. Since you brought drawing code up, when it comes time to draw, you'd probably have just a method that can draw the game in it's current state, probably being passed the current GameState object.
Like I said, there's a lot in what I just covered, and at the same time, I've left out a lot of details as well. Hopefully that's enough to get you started, but if you're still stumped, don't hesitate to ask a follow-up question or two.