将矩阵数据分块为偶数大小,如何处理余数



下面的代码是我目前如何将2D游戏中的方块划分为块以进行性能优化。然而,只有当我使用矩阵宽度和高度时,这才有可能,这两个矩阵都可以被块大小整除。

如果需要的话,我希望程序能够在宽度或高度的末尾制作一个较小的块大小,能够用任何类型的块大小创建任何类型的映射大小。

瓦片已经在先前的函数中创建,并作为矩阵(列表列表(放置在self.tiles_list中以模仿实际数据矩阵self.data


def create_chunks(self):

#-----Create chunks lists-----
amount_chunks = (self.w * self.h) / (self.chunk_length * self.chunk_length)
amount_chunks = int(amount_chunks)
amount_chunks_width = self.w / self.chunk_length
amount_chunks_width = int(amount_chunks_width)
for i in range(amount_chunks):
chunk = Chunk(i, self.chunk_length, self.chunk_length)
self.chunks_list.append(chunk)

#-----Insert tiles into chunks-----
count_tile_list = 0
count_chunk_list = 0
count_chunk_list_adder = 0
count_y = 0
chunk_length = self.chunk_length

for y, i in enumerate(self.data):
if count_y == self.chunk_length:
count_chunk_list_adder += amount_chunks_width
count_y = 0
for x in range(amount_chunks_w):

for z in range(chunk_length):
chunk = self.chunks_list[count_chunk_list + count_chunk_list_adder]
chunk.tiles_list_temp.append(self.tiles_list[y][count_tile_list])
tile = self.tiles_list[y][count_tile_list]
tile.chunk = count_chunk_list + count_chunk_list_adder
count_tile_list += 1
count_chunk_list += 1

count_y += 1
count_chunk_list = 0
count_tile_list = 0

如果你只是愉快地沿着地图切片,而不考虑事先分配块,你会过得更好。

由于你对地图布局等实际细节的了解很少,我不能给你一个具体的例子,但这里解释了它的要点

我在这里使用Numpy矩阵作为地图,因为它很容易分割成。。。嗯,大块的

现在,它同时支持Numpy矩阵和二维列表。

from collections import namedtuple
import numpy as np
Chunk = namedtuple('Chunk', 'y x tiles')

def slice_chunk(map, x: int, y: int, chunk_w: int, chunk_h: int):
"""
Get a chunk of (up to) (chunk_w x chunk_h) tiles from the map at (x, y).
:rtype: if map is a list-of-lists, a list-of-lists; if map is a numpy array, a numpy array
"""
if isinstance(map, list):
return [row[x:x + chunk_w] for row in map[y:y + chunk_h]]
elif isinstance(map, np.ndarray):
return map[y:y + chunk_h, x:x + chunk_w]
raise NotImplementedError("Don't know how to slice this")

def get_size(arr):
"""
Get the size of a list-of-lists or a numpy array.
:return: (width, height)
"""
if isinstance(arr, list):
return len(arr), len(arr[0])
elif isinstance(arr, np.ndarray):
return arr.shape[:2]
raise NotImplementedError("Don't know how to measure this")

def get_chunks(map, chunk_w: int, chunk_h: int):
"""
Yield chunks of (up to) (chunk_w x chunk_h) tiles from the map.
:param map:
:param chunk_w:
:param chunk_h:
:return:
"""
w, h = get_size(map)
for y in range(0, h, chunk_h):
for x in range(0, w, chunk_w):
chunk_tiles = slice_chunk(map, x, y, chunk_w, chunk_h)
yield Chunk(y, x, chunk_tiles)

def main():
tile_list = np.random.randint(0, 2, (100, 100)).tolist()
for i, chunk in enumerate(get_chunks(tile_list, chunk_w=8, chunk_h=8)):
print(f'Chunk {i} at {chunk.y}, {chunk.x} has {get_size(chunk.tiles)} tiles')

if __name__ == '__main__':
main()

这会打印出来,例如

Chunk 0 at 0, 0 has (8, 8) tiles
Chunk 1 at 0, 8 has (8, 8) tiles
Chunk 2 at 0, 16 has (8, 8) tiles
...
Chunk 12 at 0, 96 has (8, 4) tiles
Chunk 13 at 8, 0 has (8, 8) tiles
...
...
Chunk 155 at 88, 96 has (8, 4) tiles
Chunk 156 at 96, 0 has (4, 8) tiles
Chunk 157 at 96, 8 has (4, 8) tiles
...
Chunk 168 at 96, 96 has (4, 4) tiles

正如你所看到的,在一个大小为100x100、块大小为8x8的映射中,你会得到168个块,其中大多数是请求的8x8,但有些是8x4,一个是4x4。

最新更新