Изменение направления спрайтов каждые 10 секунд - PullRequest
0 голосов
/ 02 марта 2020

Я пишу программу, в которой шар случайно перемещается по экрану и имеет след, который меняет цвет по мере того, как след перезаписывается. Этот шар является матрицей, а не спрайтом и использует прямоугольник вместо круга.

Я нашел вопрос, похожий на мой, но он не применяется таким же образом, по крайней мере из моего понимания. (ссылка: Изменение направления вращения Pygame )

По сути, вместо вращения и изменения направления спрайта мне нужно, чтобы скорость изменялась заданным значением c градус каждые 10 секунд. Я узнал о функции transform.rotate в pygame, но не смог выяснить, как реализовать ее в моем коде без всплывающей ошибки.

Вот мое использование transform.rotate, которое не ' Работа:

#change direction every ten seconds
while True:
   newsurf = pg.transform.rotate(ballGrid, -45)
   screen.blit(newball, [[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]])
   pg.display.flip()
   time.sleep(10)

Остальная часть моего кода для справки:

import sys
from random import randrange
import pygame as pg

# define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
RED2 = (231, 0, 0)
RED3 = (207,0,0)
RED4 = (183,0,0)
RED5 = (159,0,0)
RED6 = (135,0,0)
RED7 = (111,0,0)
RED8 = (87,0,0)
RED9 = (63,0,0)
RED10 = (39,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
        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

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)
    #change direction every ten seconds
    while True:
       newsurf = pg.transform.rotate(ballGrid, -90)
       screen.blit(newball, (100,100))
       pg.display.flip()
       time.sleep(10)

    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, RED2, RED3, RED4, RED5, RED6, RED7, RED8, RED9, RED10, GREEN]
                color = colorlist[min(len(colorlist)-1, hitGrid[row][column])]
                pg.draw.rect(screen, color, rect)
                if color == GREEN:
                    pg.quit()

        sprite_group.update(screen.get_rect(), hitGrid, hitList)
        sprite_group.draw(screen)

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

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

Ответы [ 2 ]

1 голос
/ 02 марта 2020

Рекомендую использовать событие таймера. Используйте pygame.time.set_timer(), чтобы повторно создать USEREVENT и изменить ангел вектора направления (ball.vel) на определенную величину степени (например, 30 °):

# create timer event
change_delay = 10000 # 10 seconds
change_event = pg.USEREVENT + 1
pg.time.set_timer(change_event, change_delay)

# [...]

while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True

        # receive timer event
        if event.type == change_event:
            # change angle by 30°
            ball.vel = ball.vel.rotate(30)

Обратите внимание, в Pygame могут быть определены события клиента. Каждому событию нужен уникальный идентификатор. Идентификаторы для пользовательских событий должны быть между pygame.USEREVENT (24) и pygame.NUMEVENTS (32). В этом случае pygame.USEREVENT+1 - это идентификатор события таймера.
Событие таймера можно остановить, передав 0 параметру времени.

0 голосов
/ 02 марта 2020

Первый аргумент для pygame.transfrom.rotate - это объект pygame.Surface. Вы передаете список. Вместо этого попробуйте передать ball.image.

...