public void LoadContent(GraphicsDevice graphicsDevice, Dictionary <String, Texture2D> textureAtlas) { // set private members mGraphicsDevice = graphicsDevice; mTextureAtlas = textureAtlas; osn = new OpenSimplexNoise(); // create a 'pixel' texture mPixel = new Texture2D(mGraphicsDevice, mGridSize, mGridSize); // populate the texture with white List <Color> colorList = new List <Color>(); for (int i = 0; i < mGridSize * mGridSize; ++i) { colorList.Add(Color.White); } mPixel.SetData(colorList.ToArray()); mWinWidth = mGraphicsDevice.PresentationParameters.BackBufferWidth; mWinHeight = mGraphicsDevice.PresentationParameters.BackBufferHeight; mGridWidth = mWinWidth / mGridSize; mGridHeight = mWinHeight / mGridSize; mWinCentre = new Vector2(mWinWidth / 2, mWinHeight / 2); mGridCentre = new Vector2(mGridWidth / 2, mGridHeight / 2); ball = mWinCentre; // map mMap = new RenderTarget2D( mGraphicsDevice, mWinWidth, mWinHeight); // init world grid mWorld = new WorldGenTile[mWinWidth, mWinHeight]; mWorldBackBuffer = new WorldGenTile[mWinWidth, mWinHeight]; for (int y = 0; y < mWinHeight; y++) { for (int x = 0; x < mWinWidth; x++) { mWorld[x, y] = new WorldGenTile(); mWorldBackBuffer[x, y] = new WorldGenTile(); } } // run this async GenWorld(); GenRivers(); DoGradients(); // draw game world DrawWorldToTexture(); }
// Convolution, aka applying a kernel void ApplyKernel() { // move the ball by the gradient of it's current tile ball += ToCartesian(mWorld[(int)(ball.X / mGridSize), (int)(ball.Y / mGridSize)].mGradient) * 10; // do water stuff // add a water source mWorld[(int)mGridCentre.X, (int)mGridCentre.Y].water = 1f; for (int y = 1; y < mGridHeight - 1; y++) { for (int x = 1; x < mGridWidth - 1; x++) { // clear backbuffer mWorldBackBuffer[x, y].water = 0; mWorldBackBuffer[x, y].height = mWorld[x, y].height; mWorldBackBuffer[x, y].mGradient = mWorld[x, y].mGradient; WorldGenTile thisTile = mWorld[x, y]; float water = thisTile.water / 4f; // up if (thisTile.mGradient.Y >= 1 * Math.PI / 4 && thisTile.mGradient.Y < 3 * Math.PI / 4) { mWorldBackBuffer[x - 1, y].water += water; thisTile.water -= water; } // left if (thisTile.mGradient.Y >= 3 * Math.PI / 4 && thisTile.mGradient.Y < 5 * Math.PI / 4) { mWorldBackBuffer[x, y - 1].water += water; thisTile.water -= water; } // down if (thisTile.mGradient.Y >= 5 * Math.PI / 4 && thisTile.mGradient.Y < 7 * Math.PI / 4) { mWorldBackBuffer[x + 1, y].water += water; thisTile.water -= water; } //right if (thisTile.mGradient.Y >= 7 * Math.PI / 4 || thisTile.mGradient.Y < 1 * Math.PI / 4) { mWorldBackBuffer[x, y + 1].water += water; thisTile.water -= water; } } } // switch buffers mWorld = mWorldBackBuffer; }
// Convolution, aka applying a kernel void ApplyKernel2() { //mWorldBackBuffer = mWorld; //float[,] identityKernel = new float[,] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }; //float[,] edgeKernel1 = new float[,] { { 0, 1, 0 }, { 1, -4, 1 }, { 0, 1, 0 } }; //float[,] blurKernel = new float[,] { { 1, 1, 1 }, { 1, 1, 1}, { 1, 1, 1} }; //float[,] sharpenKernel = new float[,] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } }; //float[,] kernel = identityKernel; mWorld[(int)mWinCentre.X / mGridSize, (int)mWinCentre.Y / mGridSize].water = 2f; for (int y = 1; y < mGridHeight - 1; y++) { for (int x = 1; x < mGridWidth - 1; x++) { mWorldBackBuffer[x, y].water = 0; mWorldBackBuffer[x, y].height = mWorld[x, y].height; // if this is the ocean, make it a sink // and do not convolute it if (mWorld[x, y].height == 0) { mWorld[x, y].water = 0; //mWorld[x+1, y].water = 0; //mWorld[x-1, y].water = 0; //mWorld[x, y+1].water = 0; //mWorld[x, y-1].water = 0; continue; } //float accumulator = 0; // add rain //mWorld[x, y].water += mWorld[x, y].height / 8; WorldGenTile thisTile = mWorld[x, y]; float water = (thisTile.water) / 4f; // spread water between the four tiles if (thisTile.height > mWorld[x - 1, y].height) { mWorldBackBuffer[x - 1, y].water += water; thisTile.water -= water; } if (thisTile.height > mWorld[x + 1, y].height) { mWorldBackBuffer[x + 1, y].water += water; thisTile.water -= water; } if (thisTile.height > mWorld[x, y - 1].height) { mWorldBackBuffer[x, y - 1].water += water; thisTile.water -= water; } if (thisTile.height > mWorld[x, y + 1].height) { mWorldBackBuffer[x, y + 1].water += water; thisTile.water -= water; } // overflow //if (thisTile.water > 1f) //{ // // counts the number of tiles we used for overflow // int count = 0; // // overflow amount // float overflow = thisTile.water - 1f; // if (mWorld[x - 1, y].height + mWorld[x - 1, y].water < thisTile.height + thisTile.water) // { // mWorldBackBuffer[x - 1, y].water += overflow; // count++; // } // if (mWorld[x + 1, y].height + mWorld[x + 1, y].water < thisTile.height + thisTile.water) // { // mWorldBackBuffer[x + 1, y].water += overflow; // count++; // } // if (mWorld[x, y - 1].height + mWorld[x, y - 1].water < thisTile.height + thisTile.water) // { // mWorldBackBuffer[x, y - 1].water += overflow; // count++; // } // if (mWorld[x, y + 1].height + mWorld[x, y + 1].water < thisTile.height + thisTile.water) // { // mWorldBackBuffer[x, y + 1].water += overflow; // count++; // } // // finally subtract any realised overflows // thisTile.water -= count * overflow; //} // convolute //for (int ky = 0; ky < kernel.GetLength(0); ky++) //{ // for (int kx = 0; kx < kernel.GetLength(1); kx++) // { // Tile thisTile2 = mWorldBackBuffer[x - (kx - 1), y - (ky - 1)]; // accumulator += // kernel[kx, ky] * // thisTile2.water * // (1 - (float)Math.Pow(thisTile2.height, 2)); // we do 1 minus to get water to flow down instead of up // } //} // normalise (if necessary) //accumulator /= 9; //if (accumulator < 0.05f) // accumulator = 0; // update world //mWorldBackBuffer[x, y].height = mWorld[x, y].height; // mWorldBackBuffer[x, y].water = accumulator; } } // switch buffers mWorld = mWorldBackBuffer; }