游戏中随机地图的实现
来源:互联网 发布:php系统源码 编辑:程序博客网 时间:2024/05/17 06:21
游戏中随机地图的实现
很多游戏都用到了随机地图,比如矮人要塞,CDDA,MineCraft,RimWorld。随机地图带给游戏更多的趣味性,每一次新建游戏都有不同的体验。一般游戏中生成随机地形都是使用柏林噪声,接下来我们就来看看怎么实现。
- 游戏中随机地图的实现
- 白噪声
- 柏林噪声
- 柏林噪声的应用
- 随机地图的生成
- 参考
白噪声
首先我们先来使用一个白噪声函数试试生成一张完全随机的图片。
public float[][] GenerateWhiteNoise(int width,int height,int seed) { Random r = new Random(seed); float[][]noise=new float[width][]; for (int i = 0; i < width; i++) { noise[i] = new float[height]; } for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { noise[i][j] = (float)r.NextDouble() % 1; } } return noise; }
private void mapPanel_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Bitmap bm = new Bitmap(500, 500); float[][] noises = GenerateWhiteNoise(500, 500,6527); for (int i = 0; i < 500; i++) { for (int j = 0; j < 500; j++) { int co = (int)(noises[i][j] * 256); bm.SetPixel(i, j, Color.FromArgb(co, co, co)); } } Pen p = new Pen(Color.Black, 1); g.DrawImage(bm,new Point(0,0)); }
完全随机的话,貌似并不能到到我们要的效果,接下来,我们就试试加一些平滑过渡。
柏林噪声
柏林噪声应用在很多游戏的地形生成上,也应用在图片的处理上。
float Interpolate(float x0, float x1, float alpha) { return x0 * (1 - alpha) + alpha * x1; }public float[][] GenerateSmoothNoise(float[][] baseNoise, int octave) { int width = baseNoise.Length; int height = baseNoise[0].Length; float[][] smoothNoise = new float[width][]; for (int i = 0; i < width; i++) { smoothNoise[i] = new float[height]; } int samplePeriod = 1 << octave; float sampleFrequency = 1.0f / samplePeriod; for (int i = 0; i < width; i++) { //calculate the horizontal sampling indices int sample_i0 = (i / samplePeriod) * samplePeriod; int sample_i1 = (sample_i0 + samplePeriod) % width; //wrap around float horizontal_blend = (i - sample_i0) * sampleFrequency; for (int j = 0; j < height; j++) { //calculate the vertical sampling indices int sample_j0 = (j / samplePeriod) * samplePeriod; int sample_j1 = (sample_j0 + samplePeriod) % height; //wrap around float vertical_blend = (j - sample_j0) * sampleFrequency; //blend the top two corners float top = Interpolate(baseNoise[sample_i0][sample_j0], baseNoise[sample_i1][sample_j0], horizontal_blend); //blend the bottom two corners float bottom = Interpolate(baseNoise[sample_i0][sample_j1], baseNoise[sample_i1][sample_j1], horizontal_blend); //final blend smoothNoise[i][j] = Interpolate(top, bottom, vertical_blend); } } return smoothNoise; }public float[][] GeneratePerlinNoise(float[][] baseNoise, int octaveCount) { int width = baseNoise.Length; int height = baseNoise[0].Length; float[][][] smoothNoise = new float[octaveCount][][]; //an array of 2D arrays containing float persistance = 0.5f; //generate smooth noise for (int i = 0; i <octaveCount; i++) { smoothNoise[i] = GenerateSmoothNoise(baseNoise, i); } float[][] perlinNoise = new float[width][]; for (int i = 0; i < width; i++) { perlinNoise[i] = new float[height]; } float amplitude = 1.0f; float totalAmplitude = 0.0f; //blend noise together for (int octave = octaveCount - 1; octave >= 0; octave--) { amplitude *= persistance; totalAmplitude += amplitude; for (int i = 0; i <width; i++) { for (int j = 0; j < height; j++) { perlinNoise[i][j] += smoothNoise[octave][i][j] * amplitude; } } } //normalisation for (int i = 0; i <width; i++) { for (int j = 0; j <height; j++) { perlinNoise[i][j] /= totalAmplitude; } } return perlinNoise; }
int o=10;private void mapPanel_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Bitmap bm = new Bitmap(500, 500); float[][] noises = GenerateWhiteNoise(500, 500,6527); float[][] smooth = GenerateSmoothNoise(noises, 5); float[][] perlins = GeneratePerlinNoise(noises, o); for (int i = 0; i < 500; i++) { for (int j = 0; j < 500; j++) { int co = (int)(perlins[i][j] * 256); bm.SetPixel(i, j, Color.FromArgb(co, co, co)); } } Pen p = new Pen(Color.Black, 1); g.DrawImage(bm,new Point(0,0)); }
可以看到 octaveCount为10的时候就有很好的烟雾效果,
不过我应用在生成随机地图的时候,取值为6可以获得最好的效果。
柏林噪声的应用
柏林噪声可以应用在图片中,获得类似烟雾,爆炸,气体的效果,可以将两张图片用一定的比例合并在一张。
Color GetColor(Color gradientStart, Color gradientEnd, float t) { float u = 1 - t; Color color = Color.FromArgb( 255, (int)(gradientStart.R * u + gradientEnd.R * t), (int)(gradientStart.G * u + gradientEnd.G * t), (int)(gradientStart.B * u + gradientEnd.B * t)); return color; }Color[][] MapGradient(Color gradientStart, Color gradientEnd, float[][] perlinNoise) { int width = perlinNoise.Length; int height = perlinNoise[0].Length; Color[][] image = new Color[width][]; for (int i = 0; i < width; i++) { image[i] = new Color[height]; } for (int i = 0; i <width; i++) { for (int j = 0; j <height; j++) { image[i][j] = GetColor(gradientStart, gradientEnd, perlinNoise[i][j]); } } return image; }
int o = 5; private void mapPanel_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Bitmap bm = new Bitmap(500, 500); float[][] noises = GenerateWhiteNoise(500, 500,6527); float[][] smooth = GenerateSmoothNoise(noises, 5); float[][] perlins = GeneratePerlinNoise(noises, o); Color[][] map = MapGradient( Color.Red,ColorTranslator.FromHtml("#7FFFD4"), perlins); for (int i = 0; i < 500; i++) { for (int j = 0; j < 500; j++) { int co = (int)(perlins[i][j] * 256); //bm.SetPixel(i, j, Color.FromArgb(co, co, co)); bm.SetPixel(i, j, map[i][j]); } } Pen p = new Pen(Color.Black, 1); g.DrawImage(bm,new Point(0,0)); }
随机地图的生成
查阅了一些资料,不同的游戏有不同的生成方式。
有的是使用维诺图加上柏林函数来生成世界,有的是生成高度图,再生成降水,再经过腐蚀而生成一个接近真实世界的地貌。
这里的实例是一个最简单的实现方法,使用方块格,根据柏林噪声获取该格的高度(0.1~1),再根据其高度来设定其地形。
public Color GetColorByFloat(float noise) { noise = noise * 255; if (noise > 240) return Color.White; if (noise > 210) return ColorTranslator.FromHtml("#AAAAAA"); if (noise > 180) return ColorTranslator.FromHtml("#C5C1AA"); if (noise > 165) return ColorTranslator.FromHtml("#3CB371"); if (noise > 130) return ColorTranslator.FromHtml("#228B22"); if (noise > 70) return ColorTranslator.FromHtml("#71C671"); return Color.SkyBlue; }
private void button2_Click(object sender, EventArgs e) { Random r = new Random(); float[][] whiteNoise = GenerateWhiteNoise(100, 100, r.Next()); float[][] perlinNoise = GeneratePerlinNoise(whiteNoise, 5); for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { SolidBrush sb = new SolidBrush(GetColorByFloat(perlinNoise[i][j])); pbG.FillRectangle(sb, i * width, j * height, width , height ); } } pictureBox1.Invalidate(); }
生成的效果勉强可以,但是如果添加更多的地形,加入更多的处理,相信可以做出更加好看,更加接近真实的地图。如果你有好的建议,请留言告诉我。
参考
噪声函数
柏林噪声的应用
开发者分享地形生成制作经验
地图生成器
1 0
- 游戏中随机地图的实现
- 游戏中小地图的实现
- 关于“搭桥”游戏生成随机地图的设计思路
- Flash网页游戏中实现的地图分块加载(卡马克地图)
- 游戏中如何实现大地图
- VC++游戏开发1------利用图片拼接实现内存中构建游戏地图,许多游戏编辑器的原理。
- 一个游戏地图系统的实现设想
- Cocos2d-x3.2 飞机大战类游戏中实现随机出现敌机的方法
- 游戏中地图画法的优化
- 卷轴式游戏地图实现
- 游戏地图实现方式
- Unity如何利用Mapbox在游戏中实现真实地图?
- Unity如何利用Mapbox在游戏中实现真实地图?
- SpriteKit游戏Delve随机生成地牢地图一个Bug的修复
- iOS-随机点名或抽奖游戏的实现
- 随机地图定位的思考
- C++中实现数组的随机排序
- python中实现产生随机的字符串
- 应用Setting中,不想让用户清除数据怎么办,贱贱的管理空间怎么实现的?
- HibernateTemplate的使用
- Loadrunner java vuser多台机器运行报错 Error: Compilation process failed解决方法
- thrift 继承设计
- cvCreateMTStumpClassifier中MT的含义
- 游戏中随机地图的实现
- 使用 symbolicatecrash 解析崩溃堆栈
- nc 自定义VO
- setsockopt
- laravel5学习笔记(1)——安装
- Android开发中java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx}: java.lang.NullPoi
- 机器学习中的范数规则化之(一)L0、L1与L2范数
- 关于音响系统参数测试的主要参数之一: THD+N(续一: THD+N测量技术揭秘)
- jquery初步(二) 选择器