2d tile based map - How to repeat map on edges? - c#

I'm making a platformer, with tile based map (like a lot of people). I begin in video games's developing so it's a little hard. I wan't to learn by myself but on this problem I'm stuck .
My maps are made with a list like this :
mapList[x][y] = tile
With this list, I can loop on all the Tiles and draw them.
What I want to do is to "Loop" (repeat) the map. I mean, when the character reach the right limit (or left), the map repeats. I don't understand how to do this, I search all the forums and all the question, but I found nothing :(
For instance
I don't know if I'm making myself clear but English is not my best language and i'm sorry for this :p.
Thanks in advance for trying to help me or just for reading my issue.

When you have a grid that is WxH cells, the valid ranges for X are 0..W-1
So as a first approach :
int nextX = (X+1) % W; // wraps around to 0
but you'll also need something for prevX (X-1) and maybe for X+d where d can be positive or negative.
You don't want to mess with the modulo of negative numbers, so
int MoveX(int d) { return (X+W+d) % W; }

Related

How to randomly place objects as player move around in an infinity map without overlap?

I trying to make a game where player only move forward in an infinity map, and the path (just thing of them like points, the path is only the visual) is procedurally generated. I want those path to have different length (something like the tree of life, but only branches of the selected path are generated).
This is how I generate branches without overlap:
List<Vector3> everyPos; //predetermined position
public void Spawn(int amount)
{
List<Vector3> possiblePos = new List<Vector3>(everyPos);
for (int i = 0; i < amount; i++)
{
int index = Random(0, possiblePos.Count); //Find a random position
SpawnObjectAt(currentPosition+possiblePos[index]));//Create a point there
possiblePos.RemoveAt(index); //Remove that position from the list
}
}
The problem is , look at this image(I can't embed image yet):
Red is where player start, green is possible spawn position in the first move.
If there are 2 point spawned at 1 and 2, player choose point1, then the possible position in the second time will be a point in the black zone, which include point2, so if I keep continue there will eventually overlap.
How can I avoid this? I'm making a mobile game so I don't want to cache every single point. Any help would be really appreciated! Thanks!
This is a small web game that have somewhat similar mechanic to what I trying to achieve: newgrounds.com/portal/view/592325/
This is an attempt here to answer, but honestly, you need to provide more information.
Depending on the language you are writing in, you can handle this differently. You may need dynamic allocation, but for now lets assume, since your idea is quite small, that you can just do one large array predefined before compile time.
I assume you know how to make an array, so create one with say, 500 length to start. If you want to 'generate' a link like they did in that game, you simply need a random function, (there is a built in library in pretty much every language I think) and you need to do a little math.
Whatever language you use will surely have a built in graphics library, or you can use a popular easy to use one. I'll just draw a picture to make this clear.
There are a number of ways you can do this mathematically as shown in the image, using angles for example, the simplest way, however, is just to follow the boxes.
If you have worked with graphics before, you know what a vector is, if not, you will need to learn. The 9 vectors presented in this image (0,1) (1,0) (1,1) etc. can be created as vector objects, or even stored as individual ints.
To make your nodes 'move' into another path, you can simply do a rand 1-9 and then correlated the result to one of 9 possible vectors, and then add them to your position vector. It is easiest to do this in array and just use the rand int as the index. In most c derived languages you do that like this:
positionVector += changeVectorArray[rand(1,9)];
You then increment your position vector by one of the 9 vectors as shown above.
The simplest way of making the 'path' is to copy the position before you add the change vector, and then store all of the changes sequentially in another 'path' array.
To show the path on screen, simply draw a line between the first and second, second and third, third and forth elements of your path array. This formula (of joining lines) is discrete mathematics if I'm not mistaken, and you can do much more complicated path shapes if you want, but you get the gist.
That should at least start you off. Without more info I can't really help you.
I could go off on a tangent describe a bunch of different ways you can make this happen differently but its probably easier if you just ask for specifics.
EDIT>>>
Continuing with this answer, yes, looking at it now, the nodes can definitely overlap. To solve this problem you could use collision detection, every time you generate a new 'position', before adding it and drawing the line you have to loop through your array like this:
boolean copy = true;
for(int i = 0; i < getLength(pathArray); i++){
if( newVector == pathArray[i]){
copy=false;
}
}
Then of course, if copy still is true, copy the new position int the pathArray. NOTE: this whole solution is sloppy as hell, and as your array gets larger, your program is going to take longer and longer to search through that loop. This may not also guarantee that the path goes in one direction, but it is likely. And note that the lines will still be able to overlap each other, even though the position vectors can't be on top of one another.
All this considered, I think it will work, the optimization is up to you. I would suggest that there is probably a much more efficient solution using a discrete formula. You can also use such a formula to make the path go in particular directions and do other more complicated things.
You could also quite easily apply constraints on your random rolls if you want to make the path go in a particular direction. But there are so many ways of doing this I can't begin to explain. You could google path-finding algorithms for that.
Good luck.

Path-finding with Depth Limited Search (Unity/C#~)

I am making a grid based game where characters can move their units turn by turn. Each character has a move amount (for example 4 - where they can move 4 tiles).
I've implemented a DLS (which is limited to their move amount). Using this, all available tiles that the player can move to are highlighted.
This works fine. However, I would like modify the algorithm (or implement a specific one) to work out the route. For example, the player wants to G3 - what route should the character take (forward 1, left 1 etc).
Bearing in mind that each tile can have different properties (such as some may be blocked).
Code
private void DLS(int x, int z, int depth, float jump, float previousHeight)
{
int resistance=1;
if (depth >=0)
{
tiles[x,z].GetComponentInChildren<CheckIfClicked>().Selected();
if (x+1 < 25)
{
CheckTile(x+1, z, depth, jump, previousHeight);
}
if (x-1 >= 0)
{
CheckTile(x-1, z, depth, jump, previousHeight);
}
if (z+1 <25)
{
CheckTile(x, z+1, depth, jump, previousHeight);
}
if (z-1 >=0)
{
CheckTile(x, z-1, depth,jump, previousHeight);
}
}
}
private void CheckTile(int x, int z, int depth, float jump, float previousHeight)
{
float tileHeight = tiles[x, z].GetComponent<TileDimensions>().height;
float difference = tileHeight - previousHeight;
if (difference<0) difference*=-1;
if (!tiles[x, z].GetComponentInChildren<CheckIfClicked>().occupied && difference<jump)
{
int resistance = tiles[x, z].GetComponent<TileDimensions>().getResistance();
if (resistance<0) resistance=1;
DLS(x, z, depth-resistance, jump, tileHeight);
}
}
My code takes advantage of the different tile properties (such as the tiles resistance (some tiles limit the movement) and height (you can only climb so far up)).
If you wish to use a more efficient algorithm there are two suggested implementations:
A star. A star is best used when you know the destination you want to travel to but you need to find the way of getting there. e.g if you clicked in tile G3, and were in G1, you know where you need to go. A star takes advantage of a heuristic which tries to "guess" how much further you have to go. This means that when searching for potential routes, A star will attempt to take what should be the shortest route before attempting to look at other routes. There's a fantastic tutorial here: Link
Djikstra's algorithm. This is better used when you don't know where you're going but you want to find the nearest node that contains a certain "thing", i.e. you might want your A.I to search for the nearest health pack in an FPS. I've not implemented Djikstra's algorithm before but there are plenty of tutorials available online.
With both you can add properties such as resistance on certain tiles and whatever else.
Since your algorithm is working, I would like to give you a few suggestions to enhance your code, both involve using list/dictionary.
Perform path searching once
If you can highlight every movable tiles, that means you are able to traverse paths originating from a source tile to different destination tiles, which implies you are validating the tiles one by one until the character cannot make additional moves. Therefore, you can store the results into a dictionary of "destination tile - lists" pairs. Whenever you need to retrieve a path going to a particular tile, just get the previously stored path.
Perform path searching twice
As the aforementioned approach may take up a lot of memory usage, you can run your path-searching algorithm once more when the player makes a move. Time spent for the second execution should be less than the first one, as the player has specified certain tile to be the destination of the path. During the second search, keep updating a list/dictionary while recursively executing the path-searching functions. Have every valid intermediate tile saved to the list/dictionary, then you can get the path after the search.
If you are developing games on mobile platforms, even a little bit of memory usage does matter. I would then suggest to perform path searching twice as long as the time spent for searching is acceptable to players.
Of course, it is always a good practice to monitor the performance via the Unity Profiler to check which approach suits your needs in a better manner.

Comparing two Int variables with room/margin for error

public void checkForCollision () {
int headX = cells[0].x;
int headY = cells[0].y;
int noOfParts = nPoints;
for(int i = 1; i <noOfParts;i++)
{
int tempX = cells[i].x;
int tempY = cells[i].y;
if(tempX == headX && tempY == headY){
JOptionPane.showMessageDialog(null,"Head hit body");
//EndGameCollectScore etc.
}
}
}
EDIT: 'Cells[]' is an array of type Point AND noOfParts is just how many segments the snake has
main Question
With the above code I'm trying to compare tempX to headX but i would like to have a sort of margin for error e.g. +-5 but am unsure how to accomplish this, my reasoning behind this is i'm thinking maybe the x and Y variables might be a few digits apart so if i have the radius of one of the segment of the snake (explanation of 'snake' in Alternate below) then if i'm right and the values are a tiny bit off it should still come back positive.
OR
Alternative
if anyone can suggest a better way for doing this? Basically it's for a Snake game and headX and headY is the head of the snake and the remaining X and Y variables in Cells is the body, and I'm attempting to compare if the head hits the body.
I tested it and it seemed to work but after i tested it again it seems it will only pick up the collision if i make the snake double back on itself for a few squares. e.g. IF i cross the body perpendicular it will not detect the collision.
Also i am fairly certain that this method is called after each block the snake moves.
Cheers,
Shane.
P.S Running of very little sleep and way too much sugar in my blood, If you need further clarification because the above doesn't make alot of sense let me know.
int eps = 5;
if (Math.abs(tempX - headX) <= eps && Math.abs(tempY - headY) <= eps) {
// ...
}
To check if two points are within a delta from each other, compute the distance between them. You can avoid going into the square root territory by using squares, like this:
int distSq = (tempX-headX)*(tempX-headX) + (tempY-headY)*(tempY-headY);
int minDist = 5;
if (distSq < minDist*minDist) {
// too close
}
I don't know how your snake looks, but if it has a complex shape, looking for a hit can be expensive in terms of speed. You can speed up collision detection if you can do a quick test, to see if a collision is possible at all. You can do this by using a bounding box. You would have to keep track of minimum and maximum x and y positions of the snake body. Only if a coordinate lies within these boundaries you would take account of the exact shape of the snake. How this has to be done depends on how the snake is represented. Check for each tile or each pixel the snake is made of or possibly check if the coordinate is within a polygon, if the snake outline is defined by a polygon. (I'm not going to explain how this works here, but you will find algorithms if you google a bit.)
If you need to calculate the distance to another point (the snake head), you can use different metrics for this. If only horizontal and vertical movements are possible within the game, the so called Manhattan or taxi distance can be used: d = |x1-x0| + |y1-y0|. It consists of adding the x and y distances, or you can use the maximum of both distances: d = Max(|x1-x0|, |y1-y0|) (correponds to 2kay's approach).
If you need the exact distance, apply the Pythagorean formula. In order to compare the distance with the error margin, you don't need to calculate the square root. Instead compare the square of the distance with the square of the error margin. This saves time. (x1-x0)^2 + (y1-y0)^2 < error_margin^2.

Implementation of array with negative indices

I am making a game with a world that extends infinitely in every direction. This means that you can be at position X:50, Y:50 or X:-50, Y:-50. But... I can't really do that with a normal C# List...
All the ideas I've come up with seem to be too complicated/inefficient to work...
The easiest way to implement infinite grid is using a sparse matrix with a dictionary with an x,y pair as the key and the data you want to store as the values. This is fast, easy to implement, and memory friendly if your grid is sparse.
Another way is a linked grid (similar to linked list, but with pointers to 4 directions), or a tile-based approach to reduce the overhead of linked grid (a tile is a linked grid of NxN arrays). Implementation of tiles is quite complicated, but is a good tradeoff between memory and performance for very dense grids.
But my personal favorite approach is to use the even-odd transformation. So odd indices are positive, while even numbers are negative. To transform from virtual index to the physical index, you use the formula p = abs(v * 2) - (v > 0 ? 1 : 0) and to convert physical to virtual index you do v = (p % 2 == 1 ? +1 : -1) * ((2*p + 3) / 4). This relation arises because there is one to one and onto relation (bijection) between natural numbers and integers (0 <-> 0), (1 <-> 1), (2 <-> -1), (3 <-> 2), (4 <-> -2), (5 <-> 3), (6 <-> -3), .... This approach is fast, simple and elegant, but not very great memory wise when you have very sparse grid with items extremely far from the center line.
Unless you have a TON (yes, a TON of bits...) of cells, you can use dictionaries. Combine that with a System.Drawing.Point as the key, and you get a good thing going on:
Dictionary<Point,YourGridObject> myMap = new Dictionary<Point,YourGridObject>();
Edit: In addition to the dictionary, each cell can have a reference to it's adjacent cells, this way you can use the dictionary to directly go "somewhere", but then navigate with the adjacent. I used that way to implement an A* pathfinding algorithm in an hex grid.
Edit 2:
For example, if you then want to access a specific coordinate, you can simply
var myTile = myMap[new Point(25, -25)];
Then, you want to get the East tile, you can
var eastTile = myTile.East;
Your grid object could also implement an offset method so you could get the 'West 2, North 5' tile by
var otherTile = myTile.Offset(-2, 5);
How about using two List underneath for expansions in two different directions?
I'm not certain if this is more complicated than you want to deal with, but have you considered using polar coordinates instead of cartesian? There are no negative numbers in that coordinate system. I realize that the coversion is difficult at first, but once you wrap your head around it, it becomes second nature.
You could use Dictionary, which has all the capability of an array except with negative indexes obviously.
Computers cannot store infinite arrays.
There must be a boundary to your array, remind that somewhere in code you declared a specific size during initialization of your array.
Perhaps you resize it somewhere, but that still leaves an number range from 0..to.. max.
So what you should do, write a function that allows for relatively positioning in such a map. So you store your current map[x,y] as a position.
And your able to go up, by having a function that add/substracts from your current position relativly.
This keeps your code easier to understand too.
If your not dealing with game maps but number ranges, lets say vectors
you could create a list of n points, or a 2d dictionary.
I'm posting it here, cause your problem might lead people to writing wrong code.
Also adding for other people in situations where there is a border around a map (typical in games scenario, and image manipulation.
where your data goes from [-1..width+1] just dimension it as [0,width+2]
then loop trough it starting 'for (int x = 1; x < Width+1; x++)'

Looking for pathing algorithms for maps without edges

I have 2D world maps that are basically Mercator-Like projections, (If you walk west long enough you end up east of where you started)
Question I have: Can you use A* for computing paths on these types of maps as well?
I can't think of any reason why you couldn't (I'm thinking that you would simply represent the edge map nodes such that the North, South, East, Wed, "border" nodes simply connected to the opposite side).
Thanks in advance, if anyone has seen something like this before or can give me a few hints I would appreciate it.
Pathfinding algorithms don't really care about global topology of the map. The only tricky part is to get a good estimator for A* but using the 3D distance should be ok if your map is indeed a surface in a 3d space and step cost is step length.
Your map can have all sort of strange "connections" (including for example knotted bridges) and this will not be a problem if you implement A* correctly.
I can't imagine why a Mercator-Like projections would cause a problem for A*, as long as your heuristic function approximates distances correctly. I think something along the below function should work fine
float heuristic(point from, point to, size mapsize) {
float x = from.x - to.x;
if (abs(x) > mapsize.x/2)
x = mapsize.x - x;
float y = from.y - to.y;
if (abs(y) > mapsize.y/2)
y = mapsize.y - y;
return sqrt(x*x+y*y);
}
Edited: I realize know I was misled by the non-graph theoretical) use of the word edge (where the question title strongly suggested a graph algorithm question :))
Why do you suppose there are no edges? There are many logical discrete locations that you could model, and limited connections between (i.e. not where a wall is :)). There you go: you have your edges.
What you probably mean is that you don't want to represent your edges in data (which you don't have to, but still there are the logical edges that connect locations/points.)
That said:
you ask whether someone has seen things like this before. I vaguely recall seeing something relevant to this in Knuths Dancing Links article (DLX) which is an implementation technique for A* algorithms.
http://en.wikipedia.org/wiki/Dancing_Links
original publication [PDF]
The article specifically treats states as 'cells' (in a grid) with east/west/north/south links. It's been a long time so I don't quite recall how you would map (no pun intended) your problem on that algorithm.
The dance steps. One good way to implement algorithm X is to represent each 1 in the
matrix A as a data object x with five fields L[x]; R[x]; U [x]; D[x]; C[x]. Rows of the matrix
are doubly linked as circular lists via the L and R fields ("left" and "right"); columns are
doubly linked as circular lists via the U and D fields ("up" and "down"). Each column
list also includes a special data object called its list header.

Categories

Resources