private int SIZE = 1; // number of blocks accross (min = 1, max = 128) #endregion Fields #region Constructors public Chunk(int _world_x, int _world_z) { name = string.Format("Chunk [{0},{1}]",_world_x, _world_z); go = new GameObject(name); mesh_filter = go.AddComponent<MeshFilter>(); mesh_renderer = go.AddComponent<MeshRenderer>(); mesh_collider = go.AddComponent<MeshCollider>(); // initialize properties world_x = _world_x; world_z = _world_z; heights = new int[SIZE+1, SIZE+1]; // need a RNG for each corner Rand rand_00 = new Rand((GLOBAL_SEED << 12) ^ ((world_x-1) << 8) ^ ((world_z-1) << 4)); Rand rand_10 = new Rand((GLOBAL_SEED << 12) ^ (world_x << 8) ^ ((world_z-1) << 4)); Rand rand_01 = new Rand((GLOBAL_SEED << 12) ^ ((world_x-1) << 8) ^ (world_z << 4)); Rand rand_11 = new Rand((GLOBAL_SEED << 12) ^ (world_x << 8) ^ (world_z << 4)); if(rand_00.nextf() < noisiness * corner_proclivity){ heights[0,0] += (rand_00.next() & 1)*2 - 1; } if(rand_10.nextf() < noisiness * corner_proclivity){ heights[SIZE,0] += (rand_10.next() & 1)*2 - 1; } if(rand_01.nextf() < noisiness * corner_proclivity){ heights[0,SIZE] += (rand_01.next() & 1)*2 - 1; } if(rand_11.nextf() < noisiness * corner_proclivity){ heights[SIZE,SIZE] += (rand_11.next() & 1)*2 - 1; } Initialize(true); // put in correct position go.transform.Translate(SIZE_RX * (world_x-0.5f), 0, SIZE_RZ * (world_z-0.5f) + (world_x-0.5f)*0.577350269189626f*SIZE_RX); // add collider }
/* * @param _funcType Style of the top line that generated * @param _res Size of mapunits for one linear segment * */ public PolygonActor(World _world, Vector2 _position, uint _seed, FunctionType _funcType, int _res = 5) : base(_world, _position) { int lineCount = (int)Constants.worldSizeX / _res; //make sure to have an even number if (lineCount % 2 != 0) lineCount++; Vec2[] verts = new Vec2[(int)lineCount + 1 + 4]; vertexBuffer = new VertexArray(PrimitiveType.LinesStrip); Vector2 posScreen = _position.toScreenCoord(); //repeatable random sequenze Rand rnd = new Rand(_seed); //start and end have even ground verts[0] = new Vec2(0, 6); verts[1] = new Vec2(_res, 6); verts[2] = new Vec2(_res + _res, 6); verts[lineCount - 2] = new Vec2(_res * (lineCount - 2), 6); verts[lineCount-1] = new Vec2(_res * (lineCount-1), 6); verts[lineCount] = new Vec2(_res * lineCount, 6); vertexBuffer.Append(new Vertex(((Vector2)verts[0] + _position).toScreenCoord())); //create the function if (_funcType == FunctionType.Simple) { for (int i = 2; i <= lineCount; ++i) { //Vector2 pos = new Vec2(i * 5, 10 + Rand.IntValue(10)); Vector2 pos = new Vec2(i * _res, System.Math.Max((verts[i - 1].Y + (int)rnd.next(6) - 3), 0)); verts[i] = pos; } } else if(_funcType == FunctionType.GradientNoise) { for (int i = 2; i < lineCount-3;) { int nextGrad = i + 4; if (nextGrad < lineCount - 2) { verts[nextGrad] = new Vec2(nextGrad * _res, rnd.next((int)maxHeight)); } else nextGrad = lineCount - 2; //interpolate between float relativeA = verts[i].Y / maxHeight; float relativeB = verts[nextGrad].Y / maxHeight; for (int c = i + 1; c < nextGrad; ++c) { verts[c] = new Vec2(c * _res, maxHeight * interpolateCos(relativeA, relativeB, (float)(c - i) / 4)); } i = nextGrad; } } Array.Resize<Body>(ref triangleBodys, lineCount); PolygonDef triangleDef = new PolygonDef(); triangleDef.Density = 0.0f; triangleDef.Friction = 1.0f; triangleDef.VertexCount = 3; BodyDef bodydef = new BodyDef(); bodydef.Position = _position; bodydef.Angle = 0.0f; //convert to triangles for (int i = 0; i < lineCount; ++i) { //always 3 points of the function form a triangle triangleDef.Vertices[0] = verts[i]; triangleDef.Vertices[1] = verts[i] - new Vec2(0.0f, 50.0f); triangleDef.Vertices[2] = verts[i + 1];//.Y < verts[i+1].Y ? verts[i] : verts[i + 1] triangleBodys[i] = _world.CreateBody(bodydef); triangleBodys[i].CreateShape(triangleDef); vertexBuffer.Append(new Vertex(((Vector2)verts[i+1] + _position).toScreenCoord())); } }
private void Randomize() { /* * Check the range of the neighbours heights; * If the neighbours are all the same height or +1, * then maybe increase height; * Do opposite for decreasing height; */ // RNG for non-edge points Rand inside_rand = new Rand((GLOBAL_SEED << 12) ^ (world_x << 8) ^ (world_z << 4) ^ SIZE); /* First lets randomize the edges * we need to a special RNG for this so that other chunks * can generate the same edges */ Rand left_edge = new Rand((GLOBAL_SEED << 12) ^ ((world_z-1) << 8) ^ (heights[0,0] << 4) ^ (heights[SIZE,0])); Rand right_edge = new Rand((GLOBAL_SEED << 12) ^ (world_z << 8) ^ (heights[0,SIZE] << 4) ^ (heights[SIZE,SIZE])); Rand top_edge = new Rand((GLOBAL_SEED << 12) ^ (world_x << 8) ^ (heights[SIZE,0] << 4) ^ (heights[SIZE,SIZE])); Rand bottom_edge = new Rand((GLOBAL_SEED << 12) ^ (world_x-1 << 8) ^ (heights[0,0] << 4) ^ (heights[0,SIZE])); /* * Note that we can only change odd-numbered edge cells * This is because we assume that even-number cells need to line up with * another chunk at half resolution next to this chunk */ // do bottom and top edges for(int z = 1; z < SIZE; z+=2){ // first bottom edge int positives = 0; int negatives = 0; positives += heights[0,z-1]-heights[0,z] >= 1 ? 1 : 0; positives += heights[0,z+1]-heights[0,z] >= 1 ? 1 : 0; negatives += heights[0,z-1]-heights[0,z] <= 1 ? 1 : 0; negatives += heights[0,z+1]-heights[0,z] <= 1 ? 1 : 0; // try increasing height if(negatives == 0 && positives > 0 && bottom_edge.nextf() < noisiness * up_proclivity){ heights[0,z] += 1; } // try decreasing height else if(positives == 0 && negatives > 0 && bottom_edge.nextf() < noisiness * down_proclivity){ heights[0,z] -= 1; } // randomly increase or decrease height on flat terrain else if (positives == 0 && negatives == 0 && bottom_edge.nextf() < noisiness * not_flat_proclivity){ heights[0,z] += (bottom_edge.next() & 1)*2 - 1; } // now top edge positives = 0; negatives = 0; positives += heights[SIZE,z-1]-heights[SIZE,z] >= 1 ? 1 : 0; positives += heights[SIZE,z+1]-heights[SIZE,z] >= 1 ? 1 : 0; negatives += heights[SIZE,z-1]-heights[SIZE,z] <= 1 ? 1 : 0; negatives += heights[SIZE,z+1]-heights[SIZE,z] <= 1 ? 1 : 0; // try increasing height if(negatives == 0 && positives > 0 && top_edge.nextf() < noisiness * up_proclivity){ heights[SIZE,z] += 1; } // try decreasing height else if(positives == 0 && negatives > 0 && top_edge.nextf() < noisiness * down_proclivity){ heights[SIZE,z] -= 1; } // randomly increase or decrease height on flat terrain else if (positives == 0 && negatives == 0 && top_edge.nextf() < noisiness * not_flat_proclivity){ heights[SIZE,z] += (top_edge.next() & 1)*2 - 1; } } // do left and right edges for(int x = 1; x < SIZE; x+=2){ // first left edge int positives = 0; int negatives = 0; positives += heights[x-1,0]-heights[x,0] >= 1 ? 1 : 0; positives += heights[x+1,0]-heights[x,0] >= 1 ? 1 : 0; negatives += heights[x-1,0]-heights[x,0] <= 1 ? 1 : 0; negatives += heights[x+1,0]-heights[x,0] <= 1 ? 1 : 0; // try increasing height if(negatives == 0 && positives > 0 && left_edge.nextf() < noisiness * up_proclivity){ heights[x,0] += 1; } // try decreasing height else if(positives == 0 && negatives > 0 && left_edge.nextf() < noisiness * down_proclivity){ heights[x,0] -= 1; } // randomly increase or decrease height on flat terrain else if (positives == 0 && negatives == 0 && left_edge.nextf() < noisiness * not_flat_proclivity){ heights[x,0] += (left_edge.next() & 1)*2 - 1; } // now right edge positives = 0; negatives = 0; positives += heights[x-1,SIZE]-heights[x,SIZE] >= 1 ? 1 : 0; positives += heights[x+1,SIZE]-heights[x,SIZE] >= 1 ? 1 : 0; negatives += heights[x-1,SIZE]-heights[x,SIZE] <= 1 ? 1 : 0; negatives += heights[x+1,SIZE]-heights[x,SIZE] <= 1 ? 1 : 0; // try increasing height if(negatives == 0 && positives > 0 && right_edge.nextf() < noisiness * up_proclivity){ heights[x,SIZE] += 1; } // try decreasing height else if(positives == 0 && negatives > 0 && right_edge.nextf() < noisiness * down_proclivity){ heights[x,SIZE] -= 1; } // randomly increase or decrease height on flat terrain else if (positives == 0 && negatives == 0 && right_edge.nextf() < noisiness * not_flat_proclivity){ heights[x,SIZE] += (right_edge.next() & 1)*2 - 1; } } // now do the insides with the inside RNG for(int x = 1; x < SIZE; x+=1){ for(int z = 1; z < SIZE; z+=1){ // go clockwise starting at bottom left corner of hexagon int positives = 0; int negatives = 0; // positives += heights[x-1,z]-heights[x,z] >= 1 ? 1 : 0; negatives += heights[x-1,z]-heights[x,z] <= -1 ? 1 : 0; // positives += heights[x,z-1]-heights[x,z] >= 1 ? 1 : 0; negatives += heights[x,z-1]-heights[x,z] <= -1 ? 1 : 0; // positives += heights[x+1,z-1]-heights[x,z] >= 1 ? 1 : 0; negatives += heights[x+1,z-1]-heights[x,z] <= -1 ? 1 : 0; // positives += heights[x+1,z]-heights[x,z] >= 1 ? 1 : 0; negatives += heights[x+1,z]-heights[x,z] <= -1 ? 1 : 0; // positives += heights[x,z+1]-heights[x,z] >= 1 ? 1 : 0; negatives += heights[x,z+1]-heights[x,z] <= -1 ? 1 : 0; // positives += heights[x-1,z+1]-heights[x,z] >= 1 ? 1 : 0; negatives += heights[x-1,z+1]-heights[x,z] <= -1 ? 1 : 0; // try increasing height if(negatives == 0 && positives > 0 && inside_rand.nextf() < noisiness * up_proclivity){ heights[x,z] += 1; } // try decreasing height else if(positives == 0 && negatives > 0 && inside_rand.nextf() < noisiness * down_proclivity){ heights[x,z] -= 1; } // randomly increase or decrease height on flat terrain else if (positives == 0 && negatives == 0 && inside_rand.nextf() < noisiness * not_flat_proclivity){ heights[x,z] += (inside_rand.next() & 1)*2 - 1; } } } }