Использование матрицы в качестве спрайта и тестирование, если два спрайта перекрываются - PullRequest
1 голос
/ 25 февраля 2020

Прямо сейчас у меня есть шар, который движется по экрану в случайном диагональном направлении и отскакивает от стены, когда сталкивается с ним.

Изображение указанной программы

Моя конечная цель - сделать так, чтобы мяч был матрицей, и он выполнял те же самые действия вокруг сетки 30x30.


Я пробовал перечислять (), но не мог придумать, как заставить его работать так же, как на картинке и в коде, на который я ссылался в конце этого поста.

при выполнении, я имею в виду случайное перемещение в диагональное направление на экране

Это матричный шарик:

Ball = [[0, 1, 1, 1, 0],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [0, 1, 1, 1, 0]]

Вот моя сетка:

class Grid():
    grid = []
    for row in range(36):
        # An empty array that will hold each cell in this row
        grid.append([])
        for column in range(91):
            grid[row].append(0)  # Append cells

А вот мое перечисление l oop:

# coordinates for where the ball will reside
    offset = (3, 3)
    # enumerate the matrices to form one object
    for x, row in enumerate(Ball):
        for y, e in enumerate(row):
            Grid[x + offset[0]][y + offset[1]] = e

Еще одна вещь, которую я хочу сделать, - если шар касается или перекрывает ячейку / коробку в сетке, ячейка / коробка становятся красными.
Делать Вы полагаете, что это сработает, как только я уберу цитаты?

# Draw the grid and add values to the cells
for row in range(36):
    for column in range(91):
        count = { (row,column):0 for row in range(36) for column in range(90) }
        color= WHITE
        """
            while self.overlap == False:
                for i in range(0, 36):
                    for j in range(0, 91):
                        if self.pos == row[i] and self.pos == column[j]:
                            self.overlap = True
                            if self.overlap == True:
                                color = RED
        """

Я надеюсь, что кто-то может помочь. При необходимости могу предоставить любую дополнительную информацию. Вот мой полный код для справки:

import sys
import math
from random import randrange
import pygame as pg

# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

# This sets the WIDTH and HEIGHT of each grid location
WIDTH = 10
HEIGHT = 10

# This sets the margin between each cell
MARGIN = 1

# Create a ball, add movement (diagonally for now)
class Ball(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(groups)

        self.image = pg.Surface((100,100), pg.SRCALPHA) # creates a surface
        col = randrange(256), randrange(256), randrange(256) # random colors
        pg.draw.circle(self.image, col, (50, 50), 50) # draws a circle
        self.rect = self.image.get_rect(center=pos)
        self.vel = pg.math.Vector2(8, 0).rotate(randrange(360)) # defines a velocity
        self.pos = pg.math.Vector2(pos) # defines position
        self.overlap = False

    def update(self): # moves balls
        self.pos += self.vel
        self.rect.center = self.pos
        if self.rect.left < 0 or self.rect.right > 990:
            self.vel.x *= -1                             # makes ball bounce off walls
        if self.rect.top < 0 or self.rect.bottom > 385:
            self.vel.y *= -1


class Grid():
    grid = []
    for row in range(36):
        # An empty array that will hold each cell in this row
        grid.append([])
        for column in range(91):
            grid[row].append(0)  # Append cells

def main():
    #self.overlap = False
    screen = pg.display.set_mode((1000, 395))
    # Set title of screen
    pg.display.set_caption("Ball With Grid")
    clock = pg.time.Clock()
    sprite_group = pg.sprite.Group()
    ball = Ball((495, 193), sprite_group)
    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
                # Used to track the grid coordinates
                if event.type == pg.MOUSEBUTTONDOWN:
                    # Get the position is screen is clicked
                    pos = pg.mouse.get_pos()
                    # Change the x/y screen coordinates to grid coordinates
                    column = pos[0] // (WIDTH + MARGIN)
                    row = pos[1] // (HEIGHT + MARGIN)
                    # Set that location to one
                    grid[row][column] = 1
                    print("Click ", pos, "Grid coordinates: ", row, column)
                if event.type == pg.KEYDOWN:
                    if event.key == pg.K_SPACE:
                        sprite_group.add(Ball((320, 240)))


                # Draw the grid and add values to the cells
            for row in range(36):
                for column in range(91):
                    count = { (row,column):0 for row in range(36) for column in range(90) }
                    color= WHITE
                    """
                        while self.overlap == False:
                            for i in range(0, 36):
                                for j in range(0, 91):
                                    if self.pos == row[i] and self.pos == column[j]:
                                        self.overlap = True
                                        if self.overlap == True:
                                            color = RED
                    """
                    pg.draw.rect(screen,
                                     color,
                                     [(MARGIN + WIDTH) * column + MARGIN,
                                      (MARGIN + HEIGHT) * row + MARGIN,
                                      WIDTH,
                                      HEIGHT])


            sprite_group.update()
            sprite_group.draw(screen)

            pg.display.flip()
            clock.tick(30)

if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()
    sys.exit()


Я не знаю, является ли это чем-то очевидным / прямо у меня под носом или что-то слишком сложное. В любом случае, если вы можете помочь, как бы вы предложили мне достичь своей конечной цели?

1 Ответ

1 голос
/ 25 февраля 2020

Создать класс спрайта, который может генерировать атрибут .image из сетки:

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 = randrange(256), randrange(256), randrange(256)
        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)

Когда позиция спрайта обновляется, атрибут .rect должен быть выровнен по сетке :

class GridObject(pg.sprite.Sprite):
    # [...]

    def update(self, boundrect):
        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) 

Создание спрайта "gridball":

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]]
ball = GridObject((495, 193), ballGrid, sprite_group)

См. Пример:

import sys
import math
from random import randrange
import pygame as pg

# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
WIDTH, HEIGHT, MARGIN = 10, 10, 1
GRIDX, GRIDY = 91, 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 = randrange(256), randrange(256), randrange(256)
        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):
        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)   

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():
    #self.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((495, 193), ballGrid, sprite_group)
    done = False
    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True

        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]
                pg.draw.rect(screen, WHITE, rect)

        sprite_group.update(screen.get_rect())
        sprite_group.draw(screen)

        pg.display.flip()
        clock.tick(30)

if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()
    sys.exit()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...