Xna случайный тайл рельеф
Так что я работаю над небольшой игрой, в основном ради забавы, но я столкнулся с небольшим затруднением, я пытаюсь генерировать случайную местность каждый раз, используя этот алгоритм, который я получил из источника мини-проекта Notch, я полагаю.
Если кто-нибудь может мне помочь, я буду очень благодарен
моя проблема в том, что я понятия не имею, как нарисовать это на экране или сохранить как текстуру 2d, чтобы нарисовать на экране
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using System.Runtime.InteropServices;
using Microsoft.Xna.Framework.Media;
namespace Tile_Engine.Game
{
public class LevelGen
{
private static Random random = new Random();
public double[] values;
private int w, h;
public static MediaLibrary mlb;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern uint MessageBox(IntPtr hWnd, String text, String caption, uint type);
public LevelGen(int w, int h, int featureSize)
{
this.w = w;
this.h = h;
mlb = new MediaLibrary();
values = new double[w * h];
for (int y = 0; y < w; y += featureSize)
{
for (int x = 0; x < w; x += featureSize)
{
setSample(x, y, random.NextDouble() * 2 - 1);
}
}
int stepSize = featureSize;
double scale = 1.0 / w;
double scaleMod = 1;
do
{
int halfStep = stepSize / 2;
for (int y = 0; y < w; y += stepSize)
{
for (int x = 0; x < w; x += stepSize)
{
double a = sample(x, y);
double b = sample(x + stepSize, y);
double c = sample(x, y + stepSize);
double d = sample(x + stepSize, y + stepSize);
double e = (a + b + c + d) / 4.0 + (random.NextDouble() * 2 - 1) * stepSize * scale;
setSample(x + halfStep, y + halfStep, e);
}
}
for (int y = 0; y < w; y += stepSize)
{
for (int x = 0; x < w; x += stepSize)
{
double a = sample(x, y);
double b = sample(x + stepSize, y);
double c = sample(x, y + stepSize);
double d = sample(x + halfStep, y + halfStep);
double e = sample(x + halfStep, y - halfStep);
double f = sample(x - halfStep, y + halfStep);
double H = (a + b + d + e) / 4.0 + (random.NextDouble() * 2 - 1) * stepSize * scale * 0.5;
double g = (a + c + d + f) / 4.0 + (random.NextDouble() * 2 - 1) * stepSize * scale * 0.5;
setSample(x + halfStep, y, H);
setSample(x, y + halfStep, g);
}
}
stepSize /= 2;
scale *= (scaleMod + 0.8);
scaleMod *= 0.3;
} while (stepSize > 1);
}
private double sample(int x, int y)
{
return values[(x & (w - 1)) + (y & (h - 1)) * w];
}
private void setSample(int x, int y, double value)
{
values[(x & (w - 1)) + (y & (h - 1)) * w] = value;
}
public static byte[][] createAndValidateTopMap(int w, int h)
{
int attempt = 0;
do
{
byte[][] result = createTopMap(w, h);
int[] count = new int[256];
for (int i = 0; i < w * h; i++)
{
count[result[0][i] & 0xff]++;
}
if (count[Tile.Dirt.id & 0xff] < 100) continue;
if (count[Tile.Sand.id & 0xff] < 100) continue;
// if (count[Tile.grass.id & 0xff] < 100) continue;
// if (count[Tile.tree.id & 0xff] < 100) continue;
//if (count[Tile.stairsDown.id & 0xff] < 2) continue;
return result;
} while (true);
}
private static byte[][] createTopMap(int w, int h) {
LevelGen mnoise1 = new LevelGen(w, h, 16);
LevelGen mnoise2 = new LevelGen(w, h, 16);
LevelGen mnoise3 = new LevelGen(w, h, 16);
LevelGen noise1 = new LevelGen(w, h, 32);
LevelGen noise2 = new LevelGen(w, h, 32);
byte[] map = new byte[w * h];
byte[] data = new byte[w * h];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int i = x + y * w;
double val = Math.Abs(noise1.values[i] - noise2.values[i]) * 3 - 2;
double mval = Math.Abs(mnoise1.values[i] - mnoise2.values[i]);
mval = Math.Abs(mval - mnoise3.values[i]) * 3 - 2;
double xd = x / (w - 1.0) * 2 - 1;
double yd = y / (h - 1.0) * 2 - 1;
if (xd < 0) xd = -xd;
if (yd < 0) yd = -yd;
double dist = xd >= yd ? xd : yd;
dist = dist * dist * dist * dist;
dist = dist * dist * dist * dist;
val = val + 1 - dist * 20;
if (val < -0.5) {
map[i] = Tile.Sand.id;
} else if (val > 0.5 && mval < -1.5) {
//map[i] = Tile.rock.id;
} else {
map[i] = Tile.Dirt.id;
}
}
}
for (int i = 0; i < w * h / 2800; i++) {
int xs = random.Next(w);
int ys = random.Next(h);
for (int k = 0; k < 10; k++) {
int x = xs + random.Next(21) - 10;
int y = ys + random.Next(21) - 10;
for (int j = 0; j < 100; j++) {
int xo = x + random.Next(5) - random.Next(5);
int yo = y + random.Next(5) - random.Next(5);
for (int yy = yo - 1; yy <= yo + 1; yy++)
for (int xx = xo - 1; xx <= xo + 1; xx++)
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == Tile.Dirt.id) {
map[xx + yy * w] = Tile.Sand.id;
}
}
}
}
}
/*
* for (int i = 0; i < w * h / 2800; i++) { int xs = random.Next(w); int ys = random.Next(h); for (int k = 0; k < 10; k++) { int x = xs + random.Next(21) - 10; int y = ys + random.Next(21) - 10; for (int j = 0; j < 100; j++) { int xo = x + random.Next(5) - random.Next(5); int yo = y + random.Next(5) - random.Next(5); for (int yy = yo - 1; yy <= yo + 1; yy++) for (int xx = xo - 1; xx <= xo + 1; xx++) if (xx >= 0 && yy >= 0 && xx < w && yy < h) { if (map[xx + yy * w] == Tile.grass.id) { map[xx + yy * w] = Tile.dirt.id; } } } } }
*/
for (int i = 0; i < w * h / 400; i++) {
int x = random.Next(w);
int y = random.Next(h);
for (int j = 0; j < 200; j++) {
int xx = x + random.Next(15) - random.Next(15);
int yy = y + random.Next(15) - random.Next(15);
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == Tile.Dirt.id) {
//map[xx + yy * w] = Tile.tree.id;
}
}
}
}
for (int i = 0; i < w * h / 400; i++) {
int x = random.Next(w);
int y = random.Next(h);
int col = random.Next(4);
for (int j = 0; j < 30; j++) {
int xx = x + random.Next(5) - random.Next(5);
int yy = y + random.Next(5) - random.Next(5);
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == Tile.Dirt.id) {
//map[xx + yy * w] = Tile.flower.id;
// data[xx + yy * w] = (byte) (col + random.Next(4) * 16);
}
}
}
}
for (int i = 0; i < w * h / 100; i++) {
int xx = random.Next(w);
int yy = random.Next(h);
if (xx >= 0 && yy >= 0 && xx < w && yy < h) {
if (map[xx + yy * w] == Tile.Sand.id) {
// map[xx + yy * w] = Tile.cactus.id;
}
}
}
int count = 0;
stairsLoop: for (int i = 0; i < w * h / 100; i++) {
int x = random.Next(w - 2) + 1;
int y = random.Next(h - 2) + 1;
for (int yy = y - 1; yy <= y + 1; yy++)
for (int xx = x - 1; xx <= x + 1; xx++) {
//if (map[xx + yy * w] != Tile.rock.id) continue stairsLoop;
}
//map[x + y * w] = Tile.stairsDown.id;
count++;
if (count == 4) break;
}
return new byte[][] { map, data };
}
public static void main(String[] args)
{
int d = 0;
int w = 128;
int h = 128;
byte[] map = LevelGen.createAndValidateTopMap(w, h)[0];
MessageBox(new IntPtr(0), "Completed!", "File Save Done", 0);
while (true)
{
//int w = 128;
// int h = 128;
//byte[] map = LevelGen.createAndValidateTopMap(w, h)[0];
// byte[] map = LevelGen.createAndValidateUndergroundMap(w, h, (d++ % 3) + 1)[0];
// byte[] map = LevelGen.createAndValidateSkyMap(w, h)[0];
int[] pixels = new int[w * h];
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int i = x + y * w;
// if (map[i] == Tile.water.id) pixels[i] = 0x000080;
if (map[i] == Tile.Dirt.id) pixels[i] = 0x604040;
if (map[i] == Tile.Sand.id) pixels[i] = 0xa0a040;
}
}
// System.IO.File.WriteAllBytes("C:\\TESTPNG.png", map);
}
}
/*
* for (int i = 0; i < w * h / 2800; i++) { int xs = random.Next(w); int ys = random.Next(h); for (int k = 0; k < 10; k++) { int x = xs + random.Next(21) - 10; int y = ys + random.Next(21) - 10; for (int j = 0; j < 100; j++) { int xo = x + random.Next(5) - random.Next(5); int yo = y + random.Next(5) - random.Next(5); for (int yy = yo - 1; yy <= yo + 1; yy++) for (int xx = xo - 1; xx <= xo + 1; xx++) if (xx >= 0 && yy >= 0 && xx < w && yy < h) { if (map[xx + yy * w] == Tile.Dirt.id) { map[xx + yy * w] = Tile.dirt.id; } } } } }
*/
}
}
1 ответ
Почему вы прокомментировали некоторые части кода?
Если вы просто хотите иметь возможность поместить его в изображение, вы можете сделать:
System.Drawing.Image yourNewMap;
using (MemoryStream ms = new MemoryStream(myByteArray,0,myByteArray.Length))
{
ms.Write(myByteArray,0,myByteArray.Length);
yourNewMap = Image.FromStream(ms,true);
}
Или вы можете преобразовать это консольное приложение в класс, добавив весь этот код в класс и добавив статический метод, возвращающий вам изображение:
public static Image getRandomMap()
{
int d = 0;
int w = 128;
int h = 128;
byte[] map = LevelGen.createAndValidateTopMap(w, h)[0];
int w = 128;
int h = 128;
byte[] map = LevelGen.createAndValidateTopMap(w, h)[0];
byte[] map = LevelGen.createAndValidateUndergroundMap(w, h, (d++ % 3) + 1)[0];
byte[] map = LevelGen.createAndValidateSkyMap(w, h)[0];
int[] pixels = new int[w * h];
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
int i = x + y * w;
// if (map[i] == Tile.water.id) pixels[i] = 0x000080;
if (map[i] == Tile.Dirt.id) pixels[i] = 0x604040;
if (map[i] == Tile.Sand.id) pixels[i] = 0xa0a040;
}
}
System.Drawing.Image yourNewMap;
using (MemoryStream ms = new MemoryStream(myByteArray,0,myByteArray.Length))
{
ms.Write(myByteArray,0,myByteArray.Length);
yourNewMap = Image.FromStream(ms,true);
}
return yourNewMap;
}
Затем из вашей игры вы можете сделать это, чтобы получить свой имидж.
Image myMap = Tile_Engine.Game.getRandomMap();
Тем не менее, я не понимаю, почему некоторые части вашего кода помечены как комментарии.