#python #arrays #matrix #pygame
#python #массивы #матрица #pygame
Вопрос:
Прямо сейчас у меня есть класс, который создает сетку, выравнивает объект по сетке, а затем, когда объект перемещается по сетке, он подсчитывает, сколько раз объект перекрывается с определенной ячейкой.
Моя цель состоит в том, чтобы вместо подсчета количества перекрытий вычесть количество перекрытий из N-значения. Например, вместо завершения программы, когда значение в hitGrid равно 10, программа будет вычитать из 10 и завершится, когда hitGrid равно 0.
Вот мой код:
WIDTH, HEIGHT, MARGIN = 10, 10, 1
Object = [[1]]
class GridObject(pg.sprite.Sprite):
def __init__(self, pos, grid, *groups):
super().__init__(groups)
# create image from grid
self.grid = grid
self.gridsize = (len(grid[0]), len(grid))
imgsize = self.gridsize[0] * (WIDTH MARGIN), self.gridsize[1] * (HEIGHT MARGIN)
self.image = pg.Surface(imgsize, flags = pg.SRCALPHA)
self.image.fill((0, 0, 0, 0))
col = BLACK
for c in range(self.gridsize[0]):
for r in range(self.gridsize[1]):
if self.grid[r][c] == 1:
rect = [(MARGIN WIDTH) * c MARGIN, (MARGIN HEIGHT) * r MARGIN, WIDTH, HEIGHT]
pg.draw.rect(self.image, col, rect)
self.rect = self.image.get_rect(center=pos)
self.vel = pg.math.Vector2(8, 0).rotate(randrange(360))
self.pos = pg.math.Vector2(pos)
def update(self, boundrect, hitGrid, hitList):
self.pos = self.vel
self.rect.center = self.pos
if self.rect.left <= boundrect.left or self.rect.right >= boundrect.right:
self.vel.x *= -1
if self.rect.top <= boundrect.top or self.rect.bottom >= boundrect.bottom:
self.vel.y *= -1
# align rect to grid
gridpos = round(self.rect.x / (WIDTH MARGIN)), round(self.rect.y / (HEIGHT MARGIN))
self.rect.topleft = gridpos[0] * (WIDTH MARGIN), gridpos[1] * (HEIGHT MARGIN)
# increment touched filled
global max_hit
max_hit = 0
oldHitList = hitList[:]
hitList.clear()
for c in range(self.gridsize[0]):
for r in range(self.gridsize[1]):
p = gridpos[1] r, gridpos[0] c
if p in oldHitList:
hitList.append(p)
elif self.grid[r][c] == 1:
if p[0] < len(hitGrid) and p[1] < len(hitGrid[p[0]]):
hitList.append(p)
if p not in oldHitList:
hitGrid[p[0]][p[1]] =1
max_hit = max(max_hit, hitGrid[p[0]][p[1]])
print(hitGrid[p[0]][p[1]])
Ответ №1:
Не совсем ясно, каковы ваши намерения здесь, потому что приведенный выше код является неполным в нескольких областях… Тем не менее, есть пара стратегий, о которых вам следует подумать. И блок, в котором вы пытаетесь это вычислить, находится на пути к награде «блок уродливого кода года», поэтому нам нужно что-то сделать.
Пара вещей, о которых стоит подумать…
- Как вы хотите обработать случай, когда объект остается в одном и том же квадрате сетки в течение нескольких временных шагов? Возможно, вам нужно отслеживать «последний квадрат сетки» и выполнять обновление только при наличии изменений…
в псевдокоде…
old_gridpos = None <- set at start of game
# compute new pos in update()
if current_gridpos != old_gridpos:
check for grid square usage (see below)
old_gridpos = current_gridpos
- Я вижу, что у вас есть 2-мерный угловой вектор для скорости… Что, если объект движется достаточно быстро по диагонали или в любом направлении и «перескакивает» угол квадрата? (Это становится жестким.)
- Теперь ваша система отслеживания выглядит как список попаданий в сетки. С этим сложно работать в вычислительном плане. Вы должны перевернуть это и использовать 2-d индекс и вести подсчет для каждой точки. Намного проще. Вы могли бы использовать
dictionary
2-d список илиnumpy
массив. Любой из них будет достаточно быстрым для простой игры, поэтому используйте то, что вам удобно. Эта структура данных отслеживания должна быть свойством игры и инициализироваться при запуске и т. Д. Вот эскизный набросок того, как вы могли бы сделать это со словарем, что, вероятно, проще всего.
In [12]: grid_count = {}
In [13]: max_hits = 3
In [14]: def check_max_hits(position):
...: grid_count[position] = grid_count.get(position, 0) 1
...: if grid_count[position] >= max_hits:
...: return True
...: return False
...:
...:
In [15]: check_max_hits((1,2))
Out[15]: False
In [16]: check_max_hits((2,4))
Out[16]: False
In [17]: check_max_hits((1,2))
Out[17]: False
In [18]: grid_count
Out[18]: {(1, 2): 2, (2, 4): 1}
In [19]: check_max_hits((1,2))
Out[19]: True
Вы могли бы создать аналогичную функцию и вызвать ее из своей update
функции после вычисления gridpos
Комментарии:
1. Можете ли вы привести пример с Numpy? Я хотел бы посмотреть, как это будет выглядеть. Это кажется интересным