用 python 的柏林噪声库(noise)实现随机行走

柏林噪声太神奇了,最近在看一本 processing 的书,里面讲到随机行走,就想着能不能在 pygame 里实现,查了一通,发现案例很少,有个 noise 库,直接 pip install 还 错,需要编译环境。

在 CSDN 上找到一篇文章,《柏林噪声(Python)》,里面有相关的介绍和解决办法,根据自己的 windows 和 python 版本下载对应的 whl 文件,然后在下载目录下安装。

pip install noise-1.2.3-cp39-cp39-win_amd64.whl

关于 noise 的库,介绍文章好少,我也是简单了解一些,至少可以用了。

1、随机游走

核心代码如下,生成随机位置(x,y)

x_scale,y_scale,scale = W/2,H/2,512seed_x,seed_y = random.random(),random.random()px,py = random.randint(0,W),random.randint(0,H)def random_pos():		'''生成随机位置'''    global px,py    px += 1    py += 1    x = int(W/2 - snoise2(px/scale,seed_y)*x_scale)    y = int(H/2 - snoise2(seed_x,py/scale)*y_scale)    return x,y
  • snoise2() 返回的是一个 (-1,1)之间的数,所以要乘以长宽比例进行放大
  • 用 W/2 和 H/2 减,是实现坐标变换,以屏幕中心为原点
  • 我现在把 snoise2(x,y) 当一维噪声来调用,所以有一个参数要设置为常量
  • scale 越大,随机数前后变化幅度越小,表现就越丝滑
  • 完整代码:

    import pygamefrom pygame.locals import *import randomfrom noise import snoise2pygame.init()screen = pygame.display.set_mode((0,0),FULLSCREEN)  # SurfaceW,H = screen.get_size()canvas = screen.convert_alpha()pygame.display.set_caption('my game')x_scale,y_scale,scale = W/2,H/2,512seed_x,seed_y = random.random(),random.random()px,py = random.randint(0,100),random.randint(0,100)def random_pos():    global px,py    px += 1    py += 1    x = int(W/2 - snoise2(px/scale,seed_y)*x_scale)    y = int(H/2 - snoise2(seed_x,py/scale)*y_scale)    return x,ydef draw_rect(x,y,width,height,alpha):    pygame.draw.rect(canvas,(0,255,0,alpha),(x,y,width,height),3)def fill_rect(x,y,n):    wstep = W/n    hstep = H/n    sw = x / n    sh = y / n    sa = 200/n    for i in range(n+1,0,-1):        alpha = sa * i        draw_rect(x-i*sw,y-i*sh,i*wstep,i*hstep,alpha)x0,y0 = W/2,H/2n = 30bright = ntime_count = 0pygame.mouse.set_visible(False)clock = pygame.time.Clock()running = Truewhile running:    for event in pygame.event.get():        if event.type == QUIT:            running = False        if event.type == KEYDOWN:            if event.key == K_ESCAPE:                running = False    screen.fill(0)    canvas.fill((0,0,0,0))    # x0,y0 = pygame.mouse.get_pos()    x0,y0 = random_pos()    fill_rect(x0,y0,n)    screen.blit(canvas,(0,0))    pygame.display.update()    clock.tick(60)pygame.quit()

    效果图:

    我用 imageio 生成的 gif,alpha 通道的信息没保存进去,有高手可以在评论里指点一下。

    2、随机画线

    把生成的随机点存到列表里,就可以随机画线了,效果就是文章最上面的图,我觉得可以用它生成无数 NFT。全屏运行时,笔走龙蛇,很有书法大师的范儿。。

    import pygamefrom pygame.locals import *import randomfrom noise import snoise2screen_size = W,H = 800,600pygame.init()# screen = pygame.display.set_mode((W,H))  # Surfacescreen = pygame.display.set_mode((0,0),FULLSCREEN)  # SurfaceW,H = screen.get_size()canvas = screen.convert_alpha()pygame.display.set_caption('my game')x_scale,y_scale,scale = W/2,H/2,512seed_x,seed_y = random.random(),random.random()lines = []points = []px,py = random.randint(0,W),random.randint(0,H)def gen_point():    global px,py,points    for i in range(20):        px += 1        py += 1        x = int(W/2 - snoise2(px/scale,seed_y)*x_scale)        y = int(H/2 - snoise2(seed_x,py/scale)*y_scale)        points.append((x,y))        if len(points) >10 and  (x,y) == points[0]:            lines.append(points)            points=[]        if len(points)>1000:            points.pop(0)clock = pygame.time.Clock()running = Truewhile running:    for event in pygame.event.get():        if event.type == QUIT:            running = False        if event.type == KEYDOWN:            if event.key == K_ESCAPE:                running = False    screen.fill(0)    canvas.fill((0,0,0,0))    if len(points)>1:        pygame.draw.lines(canvas,(0,255,0,255),False,points,3)    gen_point()    screen.blit(canvas,(0,0))    pygame.display.update()    clock.tick(60)pygame.quit()

    3、随机画圆

    随机画圆,要用到 snoise3 通过变化 z 参数来获取圆周半径的变化,youtube 上有个 code challenge 专门讲了这个专题,我就不贴代码了。

    闺女说我这个圆蠕动起来有点像史莱姆,我就简单封装了一下,写了个史莱姆的类,再加上随机游走,运行起来后,有点显微镜下观察细胞的感觉。

    可惜,《黑客帝国4》不能在国内上映。

    声明:本站部分文章内容及图片转载于互联 、内容不代表本站观点,如有内容涉及侵权,请您立即联系本站处理,非常感谢!

    (0)
    上一篇 2021年12月21日
    下一篇 2021年12月21日

    相关推荐