【问题标题】:Random Line Generation For pygamepygame的随机线生成
【发布时间】:2017-01-06 16:29:54
【问题描述】:

我的目标是使用 pygame 制作一款复古的月球着陆器游戏。现在我正在尝试创建山脉和平台的背景以供降落。我希望每次新游戏开始时平台和山脉都不同。我的想法是绘制随机数量的随机长度的水平线作为平台。我对此有一些问题:

  1. 如何确保水平线不重叠,并且在您像着陆一样观看时都可以看到。
  2. 我认为绘制山脉的最佳方法是将平台用更多的线连接起来,形成三角形,但我不知道从哪里开始

我一直在使用的代码目前生成随机行,但我不确定如何进一步开发代码。

for platforms in range(1, random.randint(1, 10)):

            rand_x_start = random.randint(0, 400)
            rand_x_end = random.randint(0, 400)
            rand_y = random.randint(HEIGHT / 2, HEIGHT)

            pygame.draw.line(self.background, white, (rand_x_start, rand_y), (rand_x_end, rand_y), 2)

我尝试浏览了许多有关随机生成的问题和教程,但没有一个与我正在寻找的内容相近。

我必须解决重叠问题的一个想法是,是否有一种方法可以“读取”或“查看”先前创建的线条并基于该方法限制绘图...但我不确定方法这样做。

【问题讨论】:

  • 一个想法可能是使用1D Perlin noise function 随机生成山脉的轮廓。您可以使用类似于生成随机长度平台(水平线)的代码,并使用 Perlin 算法生成中间的山区地形。
  • 这看起来就像我想为山脉做的事情。我将不得不查找如何重新创建它。我的问题是,是否有办法控制它以随机创建平台或仅在屏幕周围随机创建直线?

标签: python random pygame procedural-generation


【解决方案1】:

我将以下代码放在一起可能会对您有所帮助:

import random
from collections import namedtuple

from PIL import Image, ImageDraw

GaussianDistribution = namedtuple('GaussianDistribution', ['mu', 'sigma'])
Platform = namedtuple('Platform', ['start', 'end', 'height'])
Point = namedtuple('Point', ['x', 'y'])

PLATFORM_HEIGHT_DISTRIBUTION = GaussianDistribution(50, 10)
PLATFORM_WIDTH_DISTRIBUTION = GaussianDistribution(100, 10)
INTER_PLATFORM_DISTRIBUTION = GaussianDistribution(500, 20)

RANDOM = random.Random()


def sample_distribution(distribution):
    return RANDOM.normalvariate(distribution.mu, distribution.sigma)


def create_platforms(num_platforms):
    last_platform_end = 0

    for i in range(num_platforms):
        start = int(sample_distribution(INTER_PLATFORM_DISTRIBUTION) + last_platform_end)
        end = int(sample_distribution(PLATFORM_WIDTH_DISTRIBUTION) + start)
        height = int(sample_distribution(PLATFORM_HEIGHT_DISTRIBUTION))

        last_platform_end = end

        yield Platform(start, end, height)


def create_mountains_between_points(p1, p2):
    mountain_start = p1.x
    mountain_end = p2.x

    num_points = int((mountain_end - mountain_start) / 10)

    for i in range(num_points):
        # TODO: use 1D Perlin function to generate point.y
        yield Point(mountain_start + i * 10, RANDOM.random() * 100)


def create_terrain(platforms):
    origin = Point(0, 0)
    first_platform_start = Point(platforms[0].start, platforms[0].height)

    terrain = []
    terrain += list(create_mountains_between_points(origin, first_platform_start))

    for i, platform in enumerate(platforms):
        platform_starts_at = Point(platform.start, platform.height)
        platform_ends_at = Point(platform.end, platform.height)

        terrain.append(platform_starts_at)
        terrain.append(platform_ends_at)

        if i < len(platforms) - 1:
            next_platform = platforms[i + 1]
            next_platform_starts_at = Point(next_platform.start, next_platform.height)
            mountains = create_mountains_between_points(platform_ends_at, next_platform_starts_at)
            terrain += mountains

    return terrain


def draw_terrain(terrain):
    im = Image.new('RGBA', (4000, 200), (255, 255, 255, 0))

    draw = ImageDraw.Draw(im)
    draw.line(terrain, fill=(0, 0, 0, 255))

    im.show()


if __name__ == '__main__':
    platforms = list(create_platforms(num_platforms=10))
    terrain = create_terrain(platforms)
    draw_terrain(terrain)

这会生成以下地形。你可以看到有被山隔开的平坦区域(平台)。保证平台不重叠。它们也被保证是“可访问的”,因为它们上面永远不会生成任何地形。

我通过从均匀分布中采样来生成山脉的 y 坐标。您可以使用我之前提到的 Perlin 噪声算法使山脉看起来更好。我发现 this attempt 在 pygame 应用程序中使用 Perlin 噪声。

【讨论】:

  • 我正在使用 pygame 库来处理我的屏幕和其他游戏制作需求,但它使用左上角为 (0, 0) 的坐标系统。如何更改此代码以使山脉居中朝向屏幕底部?我尝试更改我看到的所有必须处理高度的变量
  • window.height 设为“base”并从中减去生成的“height”值。
  • 对不起,我真的很想学,不过好像没影响...
  • @GrahamChapman 屏幕底部的每个点都有最大的 y 值,即window.height。要制作“山丘”和“山脉”,您需要从该 y 值中减去,因为较小的 y 值比较大的“高”。
  • link 这就是它要做的一切......只有平台会调整
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-22
  • 2019-03-23
  • 2022-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多