I'm trying to generate random terrain for my game (In Unity3D, C#). All I need is water and grass. No height to it (no mountains or hills.) I'd preferably like to do it by placing individual cubes. On top of that the terrain needs to be infinite.
I've searched every where for even a hint on how to do it, but everything I found had either height to it, didn't use individual cubes (edited the terrain as a whole), or wasn't infinite.
Any help would be much appreciated! :)
EDIT: I'm looking for something somewhat similar to a game called Factorio. Here's a screenshot: http://i.ytimg.com/vi/Uns15OfPWbo/maxresdefault.jpg As you can see there is a big body of water, and a ton of land. I want to create something that randomly does that every time (random bodies of water and random land shapes). Something like Minecraft without all the height.
I've heard about something called Perlin noise, but because of a lack of tutorials and documentation, I can't figure out for the life of me on how to use it to generate random terrain.
Perlin noise would be great for your needs.
It generates natural looking random noise. It is infinite in all directions, so basically how it works is you choose a random starting point and use that as a base or your (0,0) point. The you add to that a sampling point. If you pass to it the same sampling point, you will get the same result. All you have to do then is give it different sampling points to get different values and spread out in all directions like this:
for (int x = 0; x < Width; x++) {
for (int y = 0; z < Length ; y++) {
terrain[x,y] = Mathf.PerlinNoise(randomLocation.x + (float)x/scale, randomLocation.y + (float)y/scale);
}
}
where you could then expand your Width/Length in the desired direction based on where the player wants to go or where you want to generate new terrain.
Your terrain[,] would then contain floats from 0 to 1 and the as another comment suggested you'd interpret everything above .5 as land and bellow as water. Then you'd just instantiate a cube at that location, color it blue(water) if terrain[x,y] <0.5 and as brown (land) if terrain[x,y]>0.5 and that would be it.
Keep in mind that you can adjust scale to get bigger/smaller islands of land. But it has to be the same for X and Y, otherwise you'll get a stretched looking islands.
Hope this helps or isn't too late :)
Related
Im fairly new to both Unity or C# or even anything GUI connected but im trying to make a simple hexagonal grid, i followed this tutorial: http://forum.unity3d.com/threads/procedural-hexagon-terrain-tutorial.233296/ and it created nice chunks of hexes. Now the thing is i'd like to make a borderline for each hex. I tried to use ToonShader but it doesn't seem to work with such structure. I also tried to make a LineRenderer in every hex, containing coordinates of it's edgepoints, but after some lurking I realised that I should probably use 6 LineRenderers for each hex. Here comes my question, does using so many LineRenderers makes any sense? Is there any more convinient (I'm sure there is) or prettier way to do this?
Thanks in advance.
LineRenderer supports more than one line, :) so you need only 1 LineRenderer per hex. You can do this:
LineRenderer lineRenderer = ... ; // Add or get LineRenderer component to game object
lineRenderer.SetVertexCount(7); // 6+1 since vertex 6 has to connect to vertex 1
for (int i = 0; i < 7; i++) {
Vector3 pos = ... ; // Positions of hex vertices
lineRenderer.SetPosition(i, pos);
}
Though this might be not very efficient depending on how many tiles you have. If you have a lot of them, but not too many, you could create a single LineRenderer for all tiles. And if you have really lots of them, then subdivide the map into regions containing X x Y tiles, and generate one LineRenderer per region. Also notice that adjacent hexes can share lines if you go with those methods.
If you don't mind spending about $20, Vectrosity is a nice Unity plugin that allows you to draw lines. I used it in a graph drawing application that I made with Unity to draw vertices between nodes.
I'm trying to make a spherical burst of rays for the purpose of checking collision, but having specific interactions happen based upon what or where each ray hit. Hence why I'm using rays rather then something simpler such as OverlapSphere.
The reason I'm looking for how to make a sphere is because I can use the same math for my rays, by having them go to the vertices of where the sphere would be. But every way I can find for making a sphere has the lines get closer the near to the poles, which makes sense, as its pretty easy to do. But as you can imagine, its not that useful for my current project.
TL;DR:
How do I make a sphere with equidistant vertices? If its not perfectly equidistant its fine, it just needs to pretty close. If this happens, it would be great if you could give how much the difference would be, and where, if applicable.
Extra notes:
I've looked at this and this, but the math is way over my head, so what I've been looking for might've just been staring me in the face this whole time.
You could use an icosphere. As the vertices are distributed on equilateral triangles, your vertices are guaranteed to be equidistant.
To construct the icosphere, first you make an icosahedron and then split the faces recursively in smaller triangles as explained in this article.
Are you aware that the sphere given to you by Unity is in fact designed
with this exact goal in mind?
ie, the entire raison d'etre of the sphere built-in to Unity is that the points are fairly smoothly space ...... roughly equidistant, as you phrase it.
To bring up such a sphere in Unity, just do this:
You can then instantly get access to the verts, as you know
Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] vv = mesh.vertices;
int kVerts=vv.Length
for (int i=0; i<kVerts; ++i)
Debug.Log ... vv[i]
Note you can easily check "which part of the sphere" they are on by (for example) checking how far they are from your "cities" (or whatever) or just check (for example) the z values to see which hemisphere they are in .. et cetera.
Furthermore...
Please note. Regarding your overall reason for wanting to do this:
but having specific interactions happen based upon what or where each ray hit
Note that it could not be easier to do this using PhysX. (The completely built-in game physics in Unity.) Indeed, I have never, ever, looked at a collision without doing something "specific" depending on "where it hit!"
You can for example get the point where the contact was with http://docs.unity3d.com/ScriptReference/RaycastHit-point.html
It's worth noting it is absolutely inconceivable one could write something approaching the performance of PhysX in casual programming.
I hope this makes things easier!
slice the sphere into N circles
compute perimeter of it
divide it by the same angle that create the slice
this gives you the number of vertexes
and also angle step inside circle
cast rays
This is how I coded it in C++ + OpenGL:
// draw unit sphere points (r=1 center=(0,0,0)) ... your rays directions
int ia,na,ib,nb;
double x,y,z,r;
double a,b,da,db;
na=16; // number of slices
da=M_PI/double(na-1); // latitude angle step
for (a=-0.5*M_PI,ia=0;ia<na;ia++,a+=da) // slice sphere to circles in xy planes
{
r=cos(a); // radius of actual circle in xy plane
z=sin(a); // height of actual circle in xy plane
nb=ceil(2.0*M_PI*r/da);
db=2.0*M_PI/double(nb); // longitude angle step
if ((ia==0)||(ia==na-1)) { nb=1; db=0.0; } // handle edge cases
for (b=0.0,ib=0;ib<nb;ib++,b+=db) // cut circle to vertexes
{
x=r*cos(b); // compute x,y of vertex
y=r*sin(b);
// this just draw the ray direction (x,y,z) as line in OpenGL
// so you can ignore this
// instead add the ray cast of yours
double w=1.2;
glBegin(GL_LINES);
glColor3f(1.0,1.0,1.0); glVertex3d(x,y,z);
glColor3f(0.0,0.0,0.0); glVertex3d(w*x,w*y,w*z);
glEnd();
}
}
This is how it looks like:
R,G,B lines are the sphere coordinate system axises X,Y,Z
White-ish lines are your Vertexes (White) + direction (Gray)
[Notes]
do not forget to include math.h
and replace the OpenGL stuff with yours
If you want 4, 6, 8, 12 or 20 vertices then you can have exactly equidistant vertices as the Platonic solid which all fit inside a sphere. The actual coordinates of these should be easy to get. For other numbers of vertices you can use other polyhedra and scale the verties so they lie on a sphere. If you need lots of points then a geodesic dome might be a good base. The C60 bucky-ball could be a good base with 60 points. For most of these you should be able to find 3D models from which you can extract coordinates.
I think the easiest way to control points on a sphere is by using spherical coordinates. Then you can control position of points around the sphere by using two angles (rho and phi) and the radius.
Example code for filling points uniformly around a rotating sphere (for fun):
var time = 1; // Increment this variable every frame to see the rotation
var count = 1000;
for (int i = 0; i < count; i++)
{
var rho = time + i;
var phi = 2 * Math.PI * i / count;
var x = (float)(radius * Math.Sin(phi) * Math.Cos(rho));
var z = (float)(radius * Math.Sin(phi) * Math.Sin(rho));
var y = (float)(radius * Math.Cos(phi));
Draw(x, y, z); // your drawing code for rendering the point
}
As some answers have already suggested, use an icosahedron based solution. The source for this is quite easy to come by (and I have written my own several times) but I find the excellent Primitives Pro plugin extremely handy under many other circumstances, and always use their sphere instead of the built-in Unity one.
Link to Primitives Pro component
Primitives Pro options
I have read some tutorials on perlin noise (for example this one) for my terrain generation, and I wanted to make sure that I understood it and can correctly implement it.
I start with 1 Dimension:
amplitude = persistence^i
// persistence can have any value but mostly it is 1 or lower. It changes the amplitude of the graphs with higher frequency since:
frequency = 2^i
//the 2 effects, that each graph reflects one octave, wich is not 100% necessary but the example happens do do it like this
'i' is the octave we are looking at.
Here is my attempt:
private float[] generateGraph()
{
float[] graph = new float[output.Width];
for (int i = 0; i < output.Width; i += 1/frequency)
{
graph[i] = random.Next((int)(1000000000000*persistence))/1000000000000f;
}
return graph;
}
I imagined the array as a graph, where the index is X and the value is Y. I search for a value for every multiple of texture.Width/frequency until the end of the array.
I have some random values I am using for now, which I have to connect with either Linear Interpolation/Cosine Interpolation or Cubic Interpolation.
Which one should I use? Which is the most performant when I want to use the noise for terrain generation in 2D?
I would like to put the graphs in a 2D-array after this and then check for each value, if its higher than 0.5, it should get some material or texture.
Is this situation, how should I do it? Am I totally on the wrong track?
edit1: Before I put the graph in a 2D array, I would like to generate perhaps 5 other graphs with a higher 'i' and blend them (which shouldn't be too hard).
edit2: this implementation is nice and 'easy'.
Define "too much performance" any kind of interpolation should be fine for 2D data. If you are really worried about performance, you might try implementing Simplex Noise, but that is much harder to understand and implement and it really becomes better at 3D and higher. In 2D they are somehow comparable.
Also, perlin noise is usually implemented as function of x parameters, where x is number of dimensions and the function has internal array of random values, that is accessed based on integer values of the parameters. You should try studying the original source code.
Okay so, i have a tiled map (obviously) and implemented a collision detection system which is working really well for me. It has trouble with those pesky corners though. I do know why that is, since i don't even check the corners. And that's the point, i don't know how to do that. So, first of all here is my current code:
Body body = currentObject.Body; // Body is a class storing position, velocity, bounds and so on.
int tileDimensions = level.TileWidth; // Since the tiles are squares...
int leftTile = body.Bounds.Left / tileDimensions;
int topTile = body.Bounds.Top / tileDimensions;
int rightTile = (int)Math.Ceiling((float)body.Bounds.Right / tileDimensions - 1);
int bottomTile = (int)Math.Ceiling(((float)body.Bounds.Bottom / tileDimensions) - 1);
if (body.Velocity.Y > 0) // Moving down.
{
for (int x = leftTile; x <= rightTile; x++)
{
for (int y = bottomTile + 1; y <= (bottomTile + 1) + (body.Velocity.Y / tileDimensions); y++)
{
if (tiles[x, y] != null && !tiles[x, y].IsPassable)
{
newVelocity = new Vector2(body.Velocity.X, MathHelper.Clamp(body.Velocity.Y, 0, tiles[x, y].Body.Bounds.Top - body.Bounds.Bottom));
body.Velocity = newVelocity;
break;
}
}
}
}
So thats just for moving down. There are 3 other constructs like that for up, left and right. The only real difference is the loop and the way i clamp the velocity.
As you can see i just loop through all tiles i could potentially collide with. Then i clamp the velocity, which will slow it down in case there is indeed a tile in it's way.
Now, i'm afraid it's hard to explain my problem with just words, so i'll have to post a picture too.
In this screenshot yellow means unpassable tile, black are the tiles the above code is currently checking for collision and red is the player.
To show you what the problem is, imagine i were to accelerate up and right in this frame. As you can see, there would be a collision with the tile on the upper right of my player but the player will just move into the tile since i don't check it for collision. And i will not check it in the next frame either, since i don't check for blocks i'm in because ... i don't even know, that would betray the whole idea behind my code, wouldn't it ? :P
Of course, i could just extend my "searching" range, but then i would collide with tiles, i shouldn't collide with.
Currently, i'm fixing this with an extra check for all the tiles my bounds are overlapping with and... you know, just moving the player back if i find any. But this is really messy and it doesn't preserve the initial velocity. If the player hits a corner he will move into it, i will detect that, move him back and null his velocity. That just doesn't feel right, it's clunky.
I just can't seem to figure out a good way of dealing with such cases. I doesn't happen too often (since it's really hard to reproduce) but once in a while it happens and that is of course unacceptable.
I'd really like to not even have a bugfix-type thing for it but to integrate it in my other code as nicely as possible. This is not mandatory, but it would be cool to be able to do that.
So i'd really appreciate if anyone of you guys could throw something at me.
Anyway, i hope you were able to follow what i was trying to say. Since english isn't my native language it's a little hard to explain such things at times. Also i'm just really bad at explaining things :/
I suppose you could just add 4 more cases, handing when the currentObject is moving in a diagonal, no?
However, you might want to investigate collision based on bounding volumes.
In my office at work, we are not allowed to paint the walls, so I have decided to frame out squares and rectangles, attach some nice fabric to them, and arrange them on the wall.
I am trying to write a method which will take my input dimensions (9' x 8' 8") and min/max size (1' x 3', 2', 4', etc..) and generate a random pattern of squares and rectangles to fill the wall. I tried doing this by hand, but I'm just not happy with the layout that I got, and it takes about 35 minutes each time I want to 'randomize' the layout.
One solution is to start with x*y squares and randomly merge squares together to form rectangles. You'll want to give differing weights to different size squares to keep the algorithm from just ending up with loads of tiny rectangles (i.e. large rectangles should probably have a higher chance of being picked for merging until they get too big).
Sounds like a Treemap
Another idea:
1. Randomly generate points on the wall
Use as many points as the number of rectangles you want
Introduce sampling bias to get cooler patterns
2. Build the kd-tree of these points
The kd-tree will split the space in a number of rectangles. There might be too much structure for what you want, but its still a neat geeky algorithm.
(see: http://en.wikipedia.org/wiki/Kd-tree)
Edit: Just looked at JTreeMap, looks a bit like this is what its doing.
If you're talking on a pure programing problem ;) There is a technique called Bin Packing that tries to pack a number of bins into the smallest area possible. There's loads of material out there:
http://en.wikipedia.org/wiki/Bin_packing_problem
http://mathworld.wolfram.com/Bin-PackingProblem.html
http://www.cs.sunysb.edu/~algorith/files/bin-packing.shtml
So you 'could' create a load of random squares and run it through a bin packer to generate your pattern.
I've not implemented a bin packing algorithm myself but I've seen it done by a colleague for a Nike website. Best of luck
Since you can pick the size of the rectangles, this is not a hard problem.
I'd say you can do something as simple as:
Pick an (x,y) coordinate that is not currently inside a rectangle.
Pick a second (x,y) coordinate so that when you draw a rectangle between
the two coordinates, it won't overlap anything. The bounding box of
valid points is just bounded by the nearest rectangles' walls.
Draw that rectangle.
Repeat until, say, you have 90% of the area covered. At that point you
can either stop, or fill in the remaining holes with as big rectangles
as possible.
It might be interesting to parametrize the generation of points, and then make a genetic algorithm. The fitness function will be how much you like the arrangement - it would draw hundreds of arrangements for you, and you would rate them on a scale of 1-10. It would then take the best ones and tweak those, and repeat until you get an arrangement you really like.
Bin packing or square packing?
Bin packing:
http://www.cs.sunysb.edu/~algorith/files/bin-packing.shtml
Square packing:
http://www.maa.org/editorial/mathgames/mathgames_12_01_03.html
This actually sounds more like an old school random square painting demo, circa 8-bit computing days, especially if you don't mind overlaps. But if you want to be especially geeky, create random squares and solve for the packing problem.
Building off Philippe Beaudoin answer.
There are treemap implementations in other languages that you can also use. In Ruby with RubyTreeMap you could do
require 'Treemap'
require 'Treemap/image_output.rb'
root = Treemap::Node.new 0.upto(100){|i| root.new_child(:size => rand) }
output = Treemap::ImageOutput.new do |o|
o.width = 800
o.height = 600
end
output.to_png(root, "C:/output/test.png")
However it sorts the rectangles, so it doesn't look very random, but it could be a start. See rubytreemap.rubyforge.org/docs/index.html for more info
I would generate everything in a spiral slowly going in. If at any point you reach a point where your solution is proven to be 'unsolvable' (IE, can't put any squares in the remaining middle to satisfy the constraints), go to an earlier draft and change some square until you find a happy solution.
Pseudocode would look something like:
public Board GenerateSquares(direction, board, prevSquare)
{
Rectangle[] rs = generateAllPossibleNextRectangles(direction, prevSquare, board);
for(/*all possible next rectangles in some random order*/)){
if(board.add(rs[x]){
//see if you need to change direction)
Board nBoard = GenerateSquares(direction, board, rs[x]);
if(nBoard != null) return nBoard; //done
else board.remove(rs[x]);
}
}
//all possibilities tried, none worked
return null;
}
}
I suggest:
Start by setting up a polygon with four vertices to be eaten in varying size (up to maxside) rectangle lumps:
public double[] fillBoard(double width, double height, double maxside) {
double[] dest = new int[0];
double[] poly = new int[10];
poly[0] = 0; poly[1] = 0; poly[2] = width; poly[3] = 0;
poly[4] = width; poly[5] = height; poly[6] = 0; poly[7] = height;
poly[8] = 0; poly[9] = 0;
...
return dest; /* x,y pairs */
}
Then choose a random vertex, find polygon lines within (inclusive) 2 X maxside of the line.
Find x values of all vertical lines and y values of all horizontal lines. Create ratings for the "goodness" of choosing each x and y value, and equations to generate ratings for values in between the values. Goodness is measured as reducing number of lines in remaining polygon. Generate three options for each range of values between two x coordinates or two y coordinates, using pseudo-random generator. Rate and choose pairs of x and pair of y values on weighted average basis leaning towards good options. Apply new rectangle to list by cutting its shape from the poly array and adding rectangle coordinates to the dest array.
Question does not state a minimum side parameter. But if one is needed, algorithm should (upon hitting a hitch with a gap being too small) not include too small candidates in selection lists (whic will occasionally make them empty) and deselect a number of the surrounding rectangles in a certain radius of the problem with size and perform new regeneration attempts of that area, and hopefully the problem area, until the criteria are met. Recursion can remove progressively larger areas if a smaller relaying of tiles fails.
EDIT
Do some hit testing to eliminate potential overlaps. And eat some spinach before starting the typing. ;)
Define input area;
Draw vertical lines at several random horizontal locations through the entire height;
Draw horizontal lines at several vertical positions through the entire width;
Shift some "columns" up or down by arbitrary amounts;
Shift some "rows" left or right by arbitrary amounts (it may be required to subdivide some cells to obtain full horizontal seams;
Remove seams as aesthetically required.
This graphical method has similarities to Brian's answer.