скажем, у меня есть сетка 3x3, и каждая ячейка в этой сетке имеет значение 0. Каждый раз, когда шарик проходит над ячейкой, это значение увеличивается на единицу, пока не достигнет 3. Каждый раз, когда значение идет вверх, цвет для этой ячейки меняется. 0 = белый, 1 = красный, 2 = зеленый и 3 = синий. Это то, что я хотел получить на выходе.
У вас есть как часто шарик находится в ячейке, для каждой ячейки. Поскольку шарик покрывает более 1 ячейки (размер шарика больше 1 ячейки), счетчик ячеек будет увеличиваться несколько раз в последовательных кадрах, когда шарик переворачивается на ячейку.
Таким образом, вы должны убедиться, что шарик покинул ячейку, прежде чем его счетчик снова может быть увеличен.
Создание двумерного массива (вложенного списка) целых значений, инициализированного 0 с размером поля. Поданные раны счетчики посещений для клеток. Кроме того, создайте список (hitList
), в котором хранятся индексы ячеек, попавших в кадр.
hitGrid = [[0 for i in range(GRIDX)] for j in range(GRIDY)]
hitList = []
Сетка (hitGrid
) и список (hitList
) имеют быть переданным методу update
класса GridObject
. Если мяч касается поля, а поле не было затронуто в предыдущем кадре, то соответствующая запись в поле должна быть увеличена. Более того, функция может установить глобальную переменную max_hit
с наибольшим количеством совпадений в текущем кадре:
class GridObject(pg.sprite.Sprite):
# [...]
def update(self, boundrect, gridHit):
# [...]
# increment touched filed
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]])
Оценить max_hit
после вызова update
для объектов GridObject
:
sprite_group.update(screen.get_rect(), hitGrid, hitList)
if max_hit >= 4:
print("game over")
done = True
Оттенок цвета поля в зависимости от значения в gridHit
:
for row in range(GRIDY):
for column in range(GRIDX):
rect = [(MARGIN + WIDTH) * column + MARGIN, (MARGIN + HEIGHT) * row + MARGIN, WIDTH, HEIGHT]
colorlist = [WHITE, RED, GREEN, BLUE]
color = colorlist[min(len(colorlist)-1, hitGrid[row][column])]
pg.draw.rect(screen, color, rect)
См. Пример:
from random import randrange
import pygame as pg
# define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# define measurements
WIDTH, HEIGHT, MARGIN = 10, 10, 1
GRIDX, GRIDY = 36, 36
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 = (235, 175, 76)
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 filed
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]])
ballGrid = [[0, 1, 1, 1, 0],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[0, 1, 1, 1, 0]]
def main():
#overlap = False
screen = pg.display.set_mode((GRIDX * (WIDTH+MARGIN) + MARGIN, GRIDY * (HEIGHT+MARGIN)))
# Set title of screen
pg.display.set_caption("Ball With Grid")
clock = pg.time.Clock()
sprite_group = pg.sprite.Group()
ball = GridObject((screen.get_width()//2, screen.get_height()//2), ballGrid, sprite_group)
hitGrid = [[0 for i in range(GRIDX)] for j in range(GRIDY)]
hitList = []
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
if event.type == pg.KEYDOWN and event.key == pg.K_SPACE:
hitGrid = [[0 for i in range(GRIDX)] for j in range(GRIDY)]
screen.fill((0, 0, 0))
# Draw the grid and add values to the cells
for row in range(GRIDY):
for column in range(GRIDX):
rect = [(MARGIN + WIDTH) * column + MARGIN, (MARGIN + HEIGHT) * row + MARGIN, WIDTH, HEIGHT]
colorlist = [WHITE, RED, GREEN, BLUE]
color = colorlist[min(len(colorlist)-1, hitGrid[row][column])]
pg.draw.rect(screen, color, rect)
sprite_group.update(screen.get_rect(), hitGrid, hitList)
if max_hit >= 4:
print("game over")
done = True
sprite_group.draw(screen)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
sys.exit()