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++)'
Related
Ok, so I have a 2D array of objects that are represented in a 2D space with columns and raws translated into (x,y) points (Cartesian coordinate system).
The problem began when I wanted to get access from one object to their neighbours.
I immediately thought that I can get access to them by looking i,j from an iteration into the 2D array like this:
(i,j+1)
↑
(i-1,j) ← (i,j) → (i+1,j)
↓
(i,j-1)
Everything was fine until my grid changed shape into a non-rectangle shape.
Then a java guy told me that I should use a custom data structure to hold the references of my objects that is literally a Double Link List with not only next and previous pointers but instead with top , down, right and left pointers. That I shouldn't write code like this for a regular array, and to use a proper data structure that is going to give me more power and flexibility on how to insert, delete, initialize and many other functions for my objects.
For some reason, I thought he is right.
In this way, I think that I can create more complex functions like getting all objects in a radius from one point. This is for game dev purposes and latter on algorithms like A* for pathfinding are going to be developed and run on this structure.
So my question is:
Is any build-in structure in c# that can help me with this or if not, should I try to create one custom structure from scratch or try to extend-inherit an already build-in c# structure.
What is the proper terminology for that structure? Maxtrix Link List? Multiway Link List?
P.S. I avoided posting code because it's from a custom game engine that needs a lot of explanation.
just an idea...
I would develop a class (i.e. Space) holding a simple list of another custom class (i.e. Point).
The master class could have some properties defining space shape and extension, and can implement a series of question method (Point GetNearest(Point p), List<Point> GetPointsInRadius(int center, int radius), ...) each of them iterating throw the list of points, and a set of add/delete/move Points methods
Your Point class have a list of properties( int x, int y, Point top, Point down, Point left, Point right) and a series of method (int DistanceFrom(Point p), bool IncludedIn(int center, int radius), int DistanceFromLeft/Right/Top/Down(), ... and so on
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.
Using ILNumerics, I am trying to take the first n number of columns of an ILArray<> in the most efficient way possible.
using(ILScope.Enter(inframe)
{
ILArray<complex> frame = ILMath.check(inframe);
int[] dims = frame.Size.ToIntArray(); //frame is a 2d ILArray
frame.SetRange(complex.Zero, dims[0] -1 , (dims[1] * 2 - 1)); //doubles the size of the array with zeros.
//TODO- various computations.
frame.SetRange(null, dims[0], dims[1] - 1); //EXCEPTION: why doesn't this work?
}
In this example I am trying to take only the first half of the frame, but I am unable to size it back to the original dimensions. I have tried various permutations based on http://ilnumerics.net/ArrayAlter.html but have been unsuccessful.
The documentation for shrinking of ILNumerics arrays says:
The range definition must address the full dimension - for all dimensions except the one, which is to be removed.
You want to remove the last half from the 2nd dimension. So you must define full ranges for all other dimensions involved. Here, since frame is a matrix, there are only 2 dimensions. Hence, the first must get fully addressed.
It should work easier by using the C# indexer. The following example assumes your code in a class derived from ILMath. Otherwise, add ILMath. before all the full, r, and end functions / properties:
A[full, r(end / 2, end)] = null;
Watch out for ‘off by one’ errors and addressing with ‘end’. You may want to use end / 2 + 1 instead ?
Since you want the most efficient way, performance seems to be important to you. In this case, you should try to prevent from expanding and shrinking arrays! It is better to work with two arrays of different sizes: a large one and the original one. Copy the data accordingly. Expanding and shrinking does copy the data anyway, so this is not a disadvantage. Furthermore, frame.Size.ToIntArray() is not needed here. Simply use frame.S[0]and frame.S[1] for the length of the dimensions 0 and 1.
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; }
I have very little data for my analysis, and so I want to produce more data for analysis through interpolation.
My dataset contain 23 independent attributes and 1 dependent attribute.....how can this done interpolation?
EDIT:
my main problem is of shortage of data, i hv to increase the size of my dataset, n attributes are categorical for example attribute A may be low, high, meduim, so interpolation is the right approach for it or not????
This is a mathematical problem but there is too little information in the question to properly answer. Depending on distribution of your real data you may try to find a function that it follows. You can also try to interpolate data using artificial neural network but that would be complex. The thing is that to find interpolations you need to analyze data you already have and that defeats the purpose. There is probably more to this problem but not explained. What is the nature of the data? Can you place it in n-dimensional space? What do you expect to get from analysis?
Roughly speaking, to interpolate an array:
double[] data = LoadData();
double requestedIndex = /* set to the index you want - e.g. 1.25 to interpolate between values at data[1] and data[2] */;
int previousIndex = (int)requestedIndex; // in example, would be 1
int nextIndex = previousIndex + 1; // in example, would be 2
double factor = requestedIndex - (double)previousIndex; // in example, would be 0.25
// in example, this would give 75% of data[1] plus 25% of data[2]
double result = (data[previousIndex] * (1.0 - factor)) + (data[nextIndex] * factor);
This is really pseudo-code; it doesn't perform range-checking, assumes your data is in an object or array with an indexer, and so on.
Hope that helps to get you started - any questions please post a comment.
If the 23 independent variables are sampled in a hyper-grid (regularly spaced), then you can choose to partition into hyper-cubes and do linear interpolation of the dependent value from the vertex closest to the origin along the vectors defined from that vertex along the hyper-cube edges away from the origin. In general, for a given partitioning, you project the interpolation point onto each vector, which gives you a new 'coordinate' in that particular space, which can then be used to compute the new value by multiplying each coordinate by the difference of the dependent variable, summing the results, and adding to the dependent value at the local origin. For hyper-cubes, this projection is straightforward (you simply subtract the nearest vertex position closest to the origin.)
If your samples are not uniformly spaced, then the problem is much more challenging, as you would need to choose an appropriate partitioning if you wanted to perform linear interpolation. In principle, Delaunay triangulation generalizes to N dimensions, but it's not easy to do and the resulting geometric objects are a lot harder to understand and interpolate than a simple hyper-cube.
One thing you might consider is if your data set is naturally amenable to projection so that you can reduce the number of dimensions. For instance, if two of your independent variables dominate, you can collapse the problem to 2-dimensions, which is much easier to solve. Another thing you might consider is taking the sampling points and arranging them in a matrix. You can perform an SVD decomposition and look at the singular values. If there are a few dominant singular values, you can use this to perform a projection to the hyper-plane defined by those basis vectors and reduce the dimensions for your interpolation. Basically, if your data is spread in a particular set of dimensions, you can use those dominating dimensions to perform your interpolation, since you don't really have much information in the other dimensions anyway.
I agree with the other commentators, however, that your premise may be off. You generally don't want to interpolate to perform analysis, as you're just choosing to interpolate your data in different ways and the choice of interpolation biases the analysis. It only makes sense if you have a compelling reason to believe that a particular interpolation is physically consistent and you simply need additional points for a particular algorithm.
May I suggest Cubic Spline Interpolation
http://www.coastrd.com/basic-cubic-spline-interpolation
unless you have a very specific need, this is easy to implement and calculates splines well.
Have a look at the regression methods presented in Elements of statistical learning; most of them may be tested in R. There are plenty of models that can be used: linear regression, local models and so on.