在六边形内生成随机点以用于程序性游戏内容

mik*_*era 9 language-agnostic random algorithm procedural-generation

我正在使用程序技术为我正在编写的游戏生成图形.

为了生成一些树林,我想在以<0,0>为中心的正六边形区域内随机散布树木.

以统一的方式生成这些点的最佳方法是什么?

Aar*_*ron 13

如果你能为六边形找到一个好的矩形边界框,那么生成均匀随机点的最简单方法就是拒绝采样(http://en.wikipedia.org/wiki/Rejection_sampling)

也就是说,找到一个完全包含六边形的矩形,然后在矩形内生成均匀的随机点(这很容易,只需为右边的每个坐标独立生成随机值).检查随机点是否落在六边形内.如果是,请保留它.如果不是,请提出另一点.

只要你能找到一个好的边界框(矩形的面积不应该大于它所包围的六边形面积的常数因子),这将是非常快的.

  • 如果你使用一个圆圈,你的p值会接近4/5,但是创建生成点的费用可能会超过矩形所需的大约5%的查找成本.对于圆形中的均匀分布,您使用极坐标并选择[0,2pi]中的角度和半径= R*sqrt(rand()) (3认同)

小智 8

一个可能简单的方法如下:

    F ____ B
     /\  /\
  A /__\/__\ E
    \  /\  /
     \/__\/
     D     C
Run Code Online (Sandbox Code Playgroud)

考虑平行四边形ADCO(中心为O)和AOBF.

其中的任何一点都可以写成两个矢量AO和AF的线性组合.

这两个平行四边形中的点P满足

P = x*AO + y*AF或x AO + y AD.

其中0 <= x <1且0 <= y <= 1(我们对与BECO共享的边缘进行折扣).

类似地,平行四边形BECO中的任何点Q可以被写为矢量BO和BE的线性组合,使得

Q = x BO + y BE其中0 <= x <= 1且0 <= y <= 1.

从而选择一个随机点

我们选择

A概率为2/3,B概率为1/3.

如果选择了A,则选择[0,1]中的x(注意,半开区间[0,1))和[-1,1]中的y,如果y> 0 ,则选择点P = x AO + y AF选择P = x*AO + | y |*AD.

如果选择了B,请选择[0,1]中的x和[0,1]中的y,然后选择点Q = x BO + y BE.

因此,需要三个随机数调用来选择一个点,这可能足够好,具体取决于您的情况.


Gre*_*erg 6

如果它是正六边形,最简单的方法就是把它分成三个菱形.这样(a)它们具有相同的区域,并且(b)你可以在任何一个菱形中选择一个随机点,其中包含0到1的两个随机变量.这是一个有效的Python代码.

from math import sqrt
from random import randrange, random
from matplotlib import pyplot

vectors = [(-1.,0),(.5,sqrt(3.)/2.),(.5,-sqrt(3.)/2.)]

def randinunithex():
    x = randrange(3);
    (v1,v2) = (vectors[x], vectors[(x+1)%3])
    (x,y) = (random(),random())
    return (x*v1[0]+y*v2[0],x*v1[1]+y*v2[1])

for n in xrange(500):
    v = randinunithex()
    pyplot.plot([v[0]],[v[1]],'ro')

pyplot.show()
Run Code Online (Sandbox Code Playgroud)

讨论中的几个人提出了均匀采样离散版六边形的问题.最自然的离散化是三角形格子,并且上述解决方案的一个版本仍然有效.您可以稍微修剪菱形,使它们各自包含相同数量的点.他们只是错过了原点,必须作为一个特例单独允许.这是一个代码:

from math import sqrt
from random import randrange, random
from matplotlib import pyplot

size = 10

vectors = [(-1.,0),(.5,sqrt(3.)/2.),(.5,-sqrt(3.)/2.)]

def randinunithex():
    if not randrange(3*size*size+1): return (0,0)
    t = randrange(3);
    (v1,v2) = (vectors[t], vectors[(t+1)%3])
    (x,y) = (randrange(0,size),randrange(1,size))
    return (x*v1[0]+y*v2[0],x*v1[1]+y*v2[1])

# Plot 500 random points in the hexagon
for n in xrange(500):
    v = randinunithex()
    pyplot.plot([v[0]],[v[1]],'ro')

# Show the trimmed rhombuses
for t in xrange(3):
    (v1,v2) = (vectors[t], vectors[(t+1)%3])
    corners = [(0,1),(0,size-1),(size-1,size-1),(size-1,1),(0,1)]
    corners = [(x*v1[0]+y*v2[0],x*v1[1]+y*v2[1]) for (x,y) in corners]
    pyplot.plot([x for (x,y) in corners],[y for (x,y) in corners],'b')

pyplot.show()
Run Code Online (Sandbox Code Playgroud)

这是一张照片.

alt text http://www.freeimagehosting.net/uploads/0f80ad5d9a.png

  • 此解决方案(原则上是你的)是连续分布的有效浮点实现,其中获得任何特定点的概率为0.唯一的偏差与舍入误差和随机数源的有限精度有关.离散解决方案也是一个很好的问题,但它与提出的问题不同.作者必须具体说明他想如何离散六边形. (2认同)