Okay so, I have looked at a lot of question from people like my self who are beginners in programming. And most of the time their questions are hard to answer or understand what the question really is. I will do my best to be as specific as possible about my problems so the above mentioned doesn't happen.
First off I have been following the tutorials over at http://xnagpa.net/xna4rpg.php. And my tile engine is based off the one that Jamie McMahon makes in his rpg tutorial series. Just so you know what the general structure of my tile engine is like.
Secondly I will try to explain what I'm trying to do inside the tile engine. I recently found an article about how the original Civilization generated their maps. http://forums.civfanatics.com/showthread.php?t=498630
And I rather like this approach to generating a "world" style map if you will. ie: oceans, continents, islands ect. So I decided to try to take this and implement it into my tile engine. It works for the most part. The parts that I added to the tile engine are supposed to randomly pick a location in the specified map layer (y,x) and then from that location generate a chunk of land(or tiles) and then replace the tiles in the map layer with the tiles created in the chunk of land. (ill show the code in a minute) and then do that for a desired amount of either number of landmasses(chunks) or continue creating chunks of land until the number of land tiles is equal to a desired amount of land tiles.
My Problem:
My program does what its supposed to (as mentioned above) except it only ever makes one landmass.(Chunk of land tiles) It does everything else just fine but it for some reason will not make more than one landmass. Now I suspect that it actually is making the other landmasses but somehow the way the tile engine is set up to display map layers is causing the landmass's to be covered up with water. Maybe its a layering issue. But It shouldn't be because the landmass's are all part of the same layer. So I'm completely baffled as to why its doing this.
public void GenerateLandChunks(MapLayer layer)
{
Tile tile = new Tile(0, 3);
Random random = new Random();
int x = random.Next(8, layer.Width - 10);
int y = random.Next(10, layer.Height - 20);
int length = random.Next(10, 70);
for (int i = 0; i < length; i++)
{
if (length != 0 && x > 8 || x < layer.Width - 10 && y > 10 || y < layer.Height - 20)
{
layer.SetTile(y, x, tile);
layer.SetTile(y, x + 1, tile);
layer.SetTile(y + 1, x, tile);
}
x = random.Next(x - 1, x + 2);
y = random.Next(y - 1, y + 2);
}
}
This is my method for generating the actual chunks it does what I want it to. (ABOVE)
MapLayer randomLayer = new MapLayer(100, 100);
for (int y = 0; y < randomLayer.Height; y++)
{
for (int x = 0; x < randomLayer.Width; x++)
{
Tile tile = new Tile(1, 3);
randomLayer.SetTile(x, y, tile);
}
}
int landMasses = 5;
for (int i = 0; i < landMasses; i++)
{
randomLayer.GenerateLandChunks(randomLayer);
}
This is where I create the map layer. I initially set the entire map to water tiles(tile (1,3)) then I tell it to generate 5 landmasses.
It seems like this should work. And it does but like I said only for the first one. It doesn't display the other 4 land masses.
My Question:
Is there anything you can see here that I'm doing wrong in order to accomplish what I'm trying to do?
If you need more of the code to understand whats going on let me know and ill post what ever you need. And like I said everything other than what I have posted is the exact same as it is in Jamie McMahon's tile engine.
I'm sorry if I have come off as unclear or if my question is hard to answer. I tried to make it as straight forward as possible. Thank you for your time.
So much text for such a simple answer. The problem is that a new Random object is generated every time, and so the "random" values are the same every time. That is how random number generators work, the numbers are not actually random, but "pseudorandom", and if you use the same random function and the same seed you will get the same progression of seemingly random numbers.
Default Random constructor seeds the generator with some value based on time, but if two generators are created with very small time period then that time value will be the same.
Move the Random object outside the function, so that it is used for all random generations, or move the loop inside (but Random outside the loop).
Related
I want to create a 2D map of tiles. Example:
Cell[,] cells;
for(int x = 0; x < columns; x++)
{
for(int y = 0; y < rows; y++)
{
cells[x, y] = new Cell();
}
}
The first cell would be at (0|0). What if I want to have this cell as my center and create new cells on the left and top side? These cells would have negative indices.
One way to fix this would be a value that determines the maximum length of one direction. Having a map of 100 tiles per side would place the center of the map at (50|50).
Let's say there would be no hardware limitations and no maximum length per side, what is the best way to create a 2D map with a (0|0) center? I can't image a better way than accessing a cell by its x and y coordinate in a 2D array.
Well, Arrays are logical constructs, not physical ones.
This means that the way we look at the the 0,0 as the top left corner, while might help visualize the content of a 2-D array (and in fact, a 2-D array is also somewhat of a visualization aid), is not accurate at all - the 0,0 "cell" is not a corner, and indexes are not coordinates, though it really helps to understand them when you think about them like they are.
That being said, there is nothing stopping you from creating your own class, that implement an indexer that can take both positive and negative values - in fact, according to Indexers (C# Programming Guide) -
Indexers do not have to be indexed by an integer value; it is up to you how to define the specific look-up mechanism.
Since you are not even obligated to use integers, you most certainly can use both positive and negative values as your indexer.
I was testing an idea to use a list of lists for storage and dynamically calculate the storage index based on the class indexer, but it's getting too late here and I guess I'm too tired to do it right. It's kinda like the solution on the other answer but I was attempting to do it without making you set the final size in the constructor.
Well, you can't use negative indices in an array or list, they're just not the right structure for a problem like this... You could, however, write your own class that handles something like this.
Simply pass in the size of the grid into the constructor, and then use the index operator to return a value based off of an an adjusted index... Something like this... Wrote it up really fast, so it probably isn't ideal in terms of optimization.
public class Grid<T> {
T[,] grid { get; }
int adjustment { get; }
int FindIndex(int provided) {
return provided + adjustment;
}
public Grid(int dimension) {
if (dimension <= 0)
throw new ArgumentException("Grid dimension cannot be <= 0");
if (dimension % 2 != 0)
throw new ArgumentException("Grid must be evenly divisible");
adjustment = dimension / 2;
grid = new T[dimension, dimension];
}
public T this[int key, int key2] {
get {
return grid[FindIndex(key), FindIndex(key2)];
}
set {
grid[FindIndex(key), FindIndex(key2)] = value;
}
}
}
I used these to test it:
var grid = new Grid<int>(100);
grid[-50, -50] = 5;
grid[0, 1] = 10;
You can just switch it to:
var grid = new Grid<Cell>(100);
This only works for a grid with equal dimensions... If you need separate dimensions, you'll need to adjust the constructor and the FindIndex method.
I think that an infinitely sized grid would be dangerous. If you increase the size to the right, you'd have to reposition the center.. Which means, what you think will be at 0,0 will now be shifted as the grid is no longer properly centered.
Additionally, performance of such a structure would be a nightmare as you cannot rely on an array to be infinite (as it inherently isn't). So you'd either have to continuously copy the array (like how a list works) or use a linked list.. If using a linked list, you would have to do enormous amounts of iteration to get whatever value you want.
I am new to Unity as well as C#. Yet, I am trying to make a simple 2D platform game where I made a prefab of an object called Block. What I want to be able to do is to create an array tile map with 0s and 1s where the 1s are blocks and 0s are nothing. Also, I don't want the tile map to be random. I want the blocks to be instantiated from another object called GameController. A perfect example of what I would like to achieve is something like this.
But I don't really know how to do this with an array. I want to keep things simple since I am trying to learn how unity and c# work. Any help would be appreciated.
So you can use some assets from the asset store( for example: https://www.assetstore.unity3d.com/en/#!/list/2965-procedural-generation) This is a pretty hard challange. I would recomand this video: https://www.youtube.com/watch?v=k1pWpYEt2UE , but the closest one to what you want to achieve is this one: https://www.youtube.com/watch?v=gIUVRYViG_g
Hope it helped.
You can make a 2 dimensional array, e.g. int[40, 100] and loop through it twice, and if the number in the array is one, multiply your position in the array by the length or width of your block respectively. For example:
int[,] positions = new int[40,100];
for (int i = 0; i < 41; i++) {
for (int j = 0; j < 100; j++) {
if (positions[i,j] = 1) {
GameObject temp = Instantiate(block, new Vector3(j * blockWidth, i * blockHeight, 0), Quaternion.identity) as GameObject;
}
}
}
It would take a long while to set all of the coordinates for an array this large, but you could loop through with parameters, or just do it the hard way if it is smaller. Otherwise, I would just try doing it without a script.
I am working on a game somewhat similar to Tetris. I have arrived at a roadblock when it comes to handling the gravity logic. (I'm working in XNA if it's at all relevant)
Without wasting your time by going into details I essentially have a 2D array. There are 4 types of pieces: empty(0), blue(1), green(2), red(3) and yellow(4).
In this game it will be possible to form NxM solid blocks of the same color. This is the part which makes the logic messy. I hope it doesn't sound too vague for now but I will show an example and show my progress so far.
int[,] example = new int[5,5]
{
{ 0,0,1,0,4 },
{ 0,2,2,0,0 },
{ 0,2,2,2,0 },
{ 0,0,0,3,0 },
{ 1,2,2,0,0 }
};
Let's say that this is the board state right now. As you can see there is a 2x2 of 2's(greens) and some pieces floating in mid-air. My plan is to play an animation of those pieces falling down until the place underneath is occupied, update all solids. I was trying to fix this and it worked fine if I was just looking at gravity for single 1x1 pieces. When it came to handling 2x2's and bigger blocks it became a big mess and I just got stuck.
My attempt at this was to have a List to keep track of all blocks that are on the gameboard, this would be updated every time the gravity update method was called.
int[,] board = new int[6, 6];
bool[,] isBlock = new bool[board.GetLength(0), board.GetLength(1)];
List<int[]> blocks = new List<int[]>();
List<int[]> toplayAnimation = new List<int[]>();
for (int x = 0; x < board.GetLength(0); x++)
{
for (int y = 0; y < board.GetLength(1) - 1; y++)
{
if ((isBlock[x, y] == false) && (board[x, y + 1] == 0) && (board[x, y] != 0))
{
}
}
}
If we look at the example the result should be that the board is updated and an animation is played of the pieces falling down it should look like this:
int[,] example = new int[5,5]
{
{ 0,0,0,0,0 },
{ 0,0,1,0,0 },
{ 0,2,2,0,0 },
{ 0,2,2,2,0 },
{ 1,2,2,3,4 }
};
So I basically have the question, what approach do you suggest I take when tackling this problem? I was thinking of having two separate 2D arrays for blocks and single pieces and comparing them two in the loop. I have been stuck on this for a little over two weeks now and I couldn't seem to find any help in already existing threads. Hope I explained everything well, thanks in advance!
I think you should have a look here:
http://farseerphysics.codeplex.com/
Like this you will not have the pain to rebuild an entire engine from scratch :)
There lot more:
https://gamedev.stackexchange.com/questions/318/what-are-some-known-2d-3d-physics-engines-for-xna
In the homework I am doing:
It is stated: "You may NOT use a number to access a tile - if you are using a number to find a tile, then it is most likely your design is not object oriented."
So essentially, my question is this:
If one were to not use an index to get an object from a list of objects, would the only solution be to use a foreach loop, every time you needed to retrieve a specific object?
If not, could you please provide an example (e.x. using a "for loop in an object oriented way", or other solutions instead of using an index)?
My concern is the amount of bloat (in lines) that might be created when not using for loops - and the affect that might have on speed.
e.g., I have the following:
for (int i = dimensions-1; i >= 0; i--)
{
map += "-";
for (int j = 0; j < dimensions; j++)
{
//For 4X4Y is 24. 3X4Y is 19. and so on.
//For 4X3Y is 23. 3X3Y is 18. and so on.
//As you can see: j * dimensions represents a "generalized" x value. adding it by i, represents its y value.
Tile currentTile = _game.TileSet[(j * dimensions) + i];
if (currentTile.Visitor == null)
map += "X-"; //X implies no robot
else
map += "R-"; //R implies robot
}
}
Yes this code is kind of ugly, but my list is formatted in such a way that I can't just use one foreach loop, and split the line on each x amount of tiles per line, as the list is stored vertically, and then horizontally, as opposed to horizontally, and then vertically (which would allow a simple foreach to suffice).
My concern is that if this is "not object oriented" - then using a foreach loop, would require a LOT more iterations.
Anyway, if anyone has an answer to the question I would really appreciate your thoughts.
Thanks.
Edit: Instead of using X and Y values, in a 2D List/Array, the list is 1d, and we are required to use association by having a list of connecting tiles, 4 elements, each element representing a typical compass direction in which the adjacent tile is located. There are no properties - however there is one method which can return an adjacent tile at a specified direction GetTileAtDirection(Direction).
The tileSet is a list of 25 elements, with 0 through 4 being the first 5 elements, X = 0, Y = 0 X = 0, Y = 1 X = 0, Y = 2 X = 0, Y = 3 X = 0, Y = 4. For the next five elements, X is incremented by one, representing the next five values in this "Y line"...
Note that there are no X and Y variables in which each tile can be accessed. This is a requirement in the homework.
If one were to not use an index to get an object from a list of
objects, would the only solution be to use a foreach loop, every time
you needed to retrieve a specific object?
No. I think the idea is that each tile should have a mapping of Direction to Tile, and GetTileAtDirection simply looks it up. The code that creates the tiles would need to assign the relationships, something like this:
nextTile = new Tile();
nextTile.AdjacentTiles[Direction.Left] = previousTile;
previousTile.AdjacentTiles[Direction.Right] = nextTile;
and so on. Of course, this code would probably be looking up the indices in TileSet, but the key is that an individual tile object can be completely independent from it -- the Tile class wouldn't even need a reference to a Game object or TileSet.
Okay guys,
I am having a LOT trouble with this. I simply cannot figure out a way to implement tile picking in a hexagonal map in XNA. I have looked this up prior to asking this question, and all the answers involve complicated algorithms and diagrams my puny mind simply cannot comprehend. So my question for you guys is: How would i be able to hover over tiles, and select them if i wanted to?
If you need any reference as to how my program looks so far, just check out this link, its literally the same except i have a smaller map on mine.
http://www.xnaresources.com/default.asp?page=Tutorial:TileEngineSeries:3
Thanks!
This is code i had stored but never used and its for hex grid where one edge is looking up, so by some minor tweaks it could work in your example. It's not my code, not sure who wrote it.
Hexagon[][] hexagons = new Hexagon[100][100];
double hexagonHeight = 30;
double hexagonWidth = 40;
double halfWidth = hexagonWidth / 2;
// Find rough coordinates of Hexagon at mousepoint
private Hexagon getSelectedHexagon(MouseEvent mouse)
{
// These will represent which box the mouse is in, not which hexagon!
int row = (int) (mouse.y / hexagonHeight);
int column;
boolean rowIsOdd = row % 2 != 0;
// Is the row an even number?
if (rowIsOdd) // No: Calculate normally
column = (int) (mouse.x / hexagonWidth);
else // Yes: Offset mouse.x to match the offset of the row
column = (int) ((mouse.x + halfWidth) / hexagonWidth);
// column is more complex because it has to
// take into account that every other row
// is offset by half the width of a hexagon
return hexagons[row][column];
}
edit: i just found author
Hexagonal Grids, how do you find which hexagon a point is in?