一种从单个图像生成游戏地图的算法

一种从单个图像生成游戏地图的算法

凯凯我们等你回来 发布于 2021-10-09 字数 842 浏览 854 回复 7 原文

我正在设计一个可以在浏览器中玩的游戏。
游戏是一个太空主题,我需要生成一张“银河系”的地图。
地图的基本思想如下:
game map http://www.oglehq.com/map.png
地图是一个网格,每个网格扇区都可以包含一个行星/系统,并且每个都有到多个相邻网格的链接。
为了生成地图,我想我应该有一组代表网格元素的图像。因此,在上面的示例中,每个正方形都是一个单独的图形。
为了创建一张新地图,我将把这些图像“编织”在一起。
地图元素图像上已经有行星和它们的链接,因此,我需要将地图缝合在一起,这样每个图像都会与其对应的图像一起定位=>因此,下角的图像必须具有与之正确链接的左边和左边对角线的图像。
您将如何创建代码以了解图像的放置位置?
有没有比使用图像更好的方法?
目前不应考虑性能和/或负载(如果我需要生成预配置的贴图,而不是实时生成,我不介意)。
如果有什么不同的话,我将使用HTML、CSS和JavaScript,并由RubyonRails应用程序支持。

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

尐偏执 2021-10-14 7 楼

只要链接的最大长度不太长,那么每个单元格就不会有太多不同的图像。您需要对图像单元的种类进行排序。例如,一个整数,其中每个位表示图像组件的存在或不存在。

Bit 0 : Has planet
Bit 1 : Has line from planet going north
Bit 2 : Has line from planet going northwest
...
Bit 8 : Has line from planet going northeast

好,现在创建512个图像。许多语言都有库,允许您编辑图像并将其写入磁盘。如果你喜欢Ruby,试试这个: http://raa.ruby-lang.org/project/ruby-gd
我不知道你打算如何存储描述行星和链接图的数据结构。一个 adjacency matrix 可能使生成地图变得容易,尽管它不是目前为止最小的表示。然后,非常简单地写出html,如(对于2x2网格):

<table border="0" cellspace="0" cellpadding="0">
<tr>
<td><img src="cell_X.gif"></td>
<td><img src="cell_X.gif"></td>
</tr>
<tr>
<td><img src="cell_X.gif"></td>
<td><img src="cell_X.gif"></td>
</tr>
</table>

当然,用与描述单元外观的位组合相对应的适当数字替换每个X。如果您使用的是邻接矩阵,那么将位放在一起非常简单——只需查看“当前”单元周围的单元。

别再吹冷风 2021-10-14 6 楼

哦,你也可以有一小部分透明的平铺png文件,然后使用css定位的div重叠这些文件,形成一个与你的例子类似的图片,如果这足够的话。
不过,上次我检查时,IE的旧版本对图像文件的透明度并没有很好的支持。是否有人可以编辑此文件以提供有关透明度支持的更好信息?

输什么也不输骨气 2021-10-14 5 楼

就我个人而言,我只会渲染游戏中的链接,让单元格图形只提供背景。这为您提供了更大的灵活性,允许您更轻松地增加单元之间链接的方式,并且通常更具可扩展性。
否则,您将需要考虑单元链接的所有可能方式,即使您考虑旋转对称和镜像对称,这也是相当多的。

梦中楼上月下 2021-10-14 4 楼

我建议使用图形库来绘制地图。如果您这样做了,您就不会有上述问题,并且最终会得到更干净/更简单的代码。有些选项是SVG、Canvas和flash/flex。

彼岸花ソ最美的依靠 2021-10-14 3 楼

有两种方法可以表示地图。
一种方法是将其表示为正方形网格,其中每个正方形中都可以有行星/系统,也可以没有行星/系统。然后,您可以指定,如果在八个方向(NW、N、NE、W、E、SW、S、SE)中的任何一个方向上有一个距离一平方米的邻居,那么就有一个到该邻居的连接。但是请注意,在样例地图中,中心系统未连接到其北部/东部的系统,因此这可能不是您想要的表示形式。但它可以用于构建其他表示
第二种方法是将每个正方形表示为具有八个位,定义是否沿八个相同方向的每个方向都有与邻居的连接。假设只有一个连接,则正方形内部有一个系统,否则如果没有连接,则为空。
因此,在您的示例3x3网格中,数据为:

 Tile   Connections
        nw  n ne  w  e sw  s se
 nw      0  0  0  0  0  0  0  0 
 n       0  0  0  0  1  0  1  0
 ne      0  0  0  1  0  0  0  0
 w       0  0  0  0  0  0  0  0
 center  0  1  0  0  0  0  1  1
 e       0  0  0  0  0  0  0  0
 se      0  0  0  0  0  0  0  0
 s       0  1  0  0  1  0  0  0
 sw      1  0  0  1  0  0  0  0

您可以将这些连接表示为八个布尔值的数组,或者更紧凑地表示为八位整数。
然后就可以很容易地使用八个布尔值(或八位整数)来形成要为该网格正方形加载的位图的文件名。例如,使用此方案的中心磁贴可以称为“Bitmap01000011.png”(仅使用布尔值),或者称为“Bitmap43.png”(使用表示该二进制模式的八位整数的十六进制值作为较短文件名)。
因为您有256种可能的组合,所以需要256个位图。
您还可以将数据减少到每个磁贴四个布尔/位,因为例如“北”连接意味着磁贴到北有一个“南”连接,但这使得选择位图有点困难,但如果您愿意,您可以解决这个问题。
或者,您可以在每个正方形中的零(空)和九(完全连接+系统圆)位图之间分层。您只需要使用transparent.png,这样就可以将它们组合在一起。缺点是浏览器绘制每个正方形(尤其是完全连接的正方形)的速度可能较慢。这样做的好处是您可以创建更少的数据,并且可以从您的网站加载更少的数据。
您可以将贴图本身表示为一个表,并根据需要将位图作为图像链接添加到每个单元格。
要映射的伪代码为:

draw_map(connection_map):
    For each grid_square in connection_map
        connection_data = connection_map[grid_square]
        filenames = bitmap_filenames_from(connection_data)
        insert_image_references_into_table(grid_square,filenames)

# For each square having one of 256 bitmaps:
bitmap_filenames_from(connection_data):
    filename="Bitmap"
    for each bit in connection_data:
      filename += bit ? "1" : 0
    return [filename,]

# For each square having zero through nine bitmaps:
bitmap_filename_from(connection_data):
    # Special case - square is empty
    if 1 not in connection_data:
        return []
    filenames=[]
    for i in 0..7:
        if connection_data[i]:
            filenames.append("Bitmap"+i)
    filenames.append("BitmapSystem");
    return filenames

嗯。如果每个框只能链接到它的8个邻居,那么你只有2^8=256个瓷砖类型。如果限制任何一个磁贴的可能链接数量,则会减少。
您可以使用8字符文件名对图像中存在的链接进行编码:

11000010.jpeg

或者保存一些字节并将其转换为十进制或十六进制

196.jpg

然后是代码。有很多方法可以选择在内部表示地图。一种方法是让每个行星都有一个物体。行星物体知道自己在网格中的位置,以及与其相连的行星的位置。因此,它有足够的信息来选择适当的文件。
或者有一个二维数组。要计算每个数组项要显示的图像,请查看相邻的8个数组项。如果这样做,可以通过使阵列在两个轴上都变大两个,并在边缘周围有一个空的“边界”,从而避免对边界进行编码。这样就省去了检查相邻阵列项是否脱离阵列的时间。

平定天下 2021-10-10 1 楼

有两个非常好的基于浏览器的vector/javascript可操作图形包,它们一起几乎是通用的:SVG和VML。它们通常以低带宽生成高质量的基于矢量的图像。
SVG 受firefox、opera、safari和chrome的支持-技术上只支持部分规范,但出于实际目的,您应该能够做您需要的事情。w3schools有 a good reference for learning/using svg
VML 是微软对SVG的回应,而且(令人惊讶的是)IE本机支持SVG,尽管SVG不是。Msdn拥有最好的 reference for vml
尽管这需要更多的工作,但您可以为这两种技术编写两个类似的/有点集成的代码库。真正的好处是,用户不必安装任何东西就可以在线玩游戏——对99.9%的用户来说,它可以正常工作。
顺便说一下,您说您需要一个算法,而我提供的是技术(如果这是SVG/VML的正确术语)。如果您可以澄清输入/输出规范,以及可能是哪一部分提出了挑战(例如,哪一个简单的实现不起作用,以及为什么),这将澄清问题,并可能提供更集中的答案。
附录 The canvas tag 正得到越来越广泛的支持,IE是一个显著的例外。这可能是在html中嵌入图形元素的一种更干净的方法。
有用的画布材料: Opera's canvas tutorial Mozilla's canvas tutorial canvas-in-IE partial implementation