Специальность по дизайну и разработке программного обеспечения: Pygame Smudge Trails

Во-первых, я искал в Интернете и на этом веб-сайте решения, и те, которые я пробовал, не работают, поэтому я решил опубликовать свой индивидуальный вопрос и код. Эта программа была создана с использованием Python 3.2.2 и соответствующей совместимой версии pygame. Я также понимаю, что более эффективным методом было бы использование спрайтов, групп спрайтов и обновление «грязных прямоугольников», но я не смог преобразовать программу, поэтому я продолжу без дополнительных преимуществ таких функций.

Проблема: следы пятен там, где движутся «астероиды», остаются позади.
Гипотеза: фон переливается на экран, однако астероиды перебрасываются на фон.

Пожалуйста, ответьте - кстати, я старшеклассник из Австралии: D

import pygame
import random
import math
pygame.init()

height = 550
width = 750
screen = pygame.display.set_mode((width, height))
background = pygame.image.load("Planet.jpg")
Clock = pygame.time.Clock()


class asteroid(pygame.sprite.Sprite):
    def __init__(self, x, y, size):
        pygame.sprite.Sprite.__init__(self)
        self.x = x
        self.y = y
        self.size = 15
        self.speed = 0.0
        self.angle = 0
        self.colour = (171, 130, 255)
        self.thickness = 0

def display(self):
     pygame.draw.circle(background, self.colour, (int(self.x),int(self.y)), self.size, self.thickness)

     pygame.draw.circle(background, (255, 255, 255), (int(self.x),int(self.y)), self.size, 1)

def move(self):
    self.x += math.sin(self.angle) * self.speed
    self.y -= math.cos(self.angle) * self.speed

def boundaries(self):
    if self.x > width - self.size:
        self.x = 0 + self.size
    elif self.x < self.size:
        self.x = width - self.size
    if self.y > height - self.size:
        self.y = 0 + self.size
    elif self.y <self.size:
        self.y = height - self.size




num_target = 5
my_particles = []
num_particles = len(my_particles)
while num_particles < 5:
    for n in range(num_target):
        size = 20
        x = random.randint(size, height - size)
        y = random.randint(size, width - size)
        target = asteroid(x, y, size)
        target.speed = random.uniform(1.0, 1.0)
        target.angle = random.uniform(0, math.pi*2)
        my_particles.append(target)
        num_particles = num_particles + 1


def main():
    pygame.display.set_caption("Anyu's Game")
    screen.blit(background, (0,0))
    pygame.display.update()
    score = (pygame.time.get_ticks()/1000)
    print (score)


while True:
    pygame.display.update()
    screen.blit(background, (0,0))
    MouseP = pygame.mouse.get_pos()
    frames = Clock.get_fps
    pygame.mouse.set_visible
    score = (pygame.time.get_ticks()/1000)
    print (score)
    print (MouseP)
    for target in my_particles:
        target.move()
        target.boundaries()
        target.display()
        pygame.display.update()


    for event in pygame.event.get():

        if event.type == pygame.QUIT:
            pygame.quit();

if __name__=='__main__':
    main()

person AnjewGS    schedule 05.05.2012    source источник
comment
+1 за работу над этим в старшей школе   -  person Andrew Walker    schedule 05.05.2012


Ответы (2)


В принципе, вы правы! Круги рисуются прямо на фоне, и каждый раз, когда рисуются новые круги, старые круги остаются. В результате появляются пятна/следы.

Вы можете просто изменить background на screen в своем методе draw. Это исправит ситуацию.

Но действительно стоит использовать классы Sprite по назначению. Я внес несколько изменений в ваш код, чтобы переключить его для вас. С этими изменениями он работает без следов :)

Вот изменения и пояснения:

Добавьте это вверху:

#Create a new `pygame.Surface`, and draw a circle on it, then set transparency:
circle = pygame.Surface((30,30))
circle = circle.convert()
pygame.draw.circle(circle, (171, 130, 255), (int(15),int(15)), 15, 0)
circle.set_colorkey(circle.get_at((0, 0)), pygame.RLEACCEL)

Добавьте это к методу asteroid, __init__:

#Sets the asteroid image, and then the asteroids co-ords (these are in `rect`)
        self.image = circle
        self.rect = self.image.get_rect()

Добавьте это в конец def move(self):

        self.rect[0] = self.x
        self.rect[1] = self.y

сдача:

my_particles = []

to:

#This is a special pygame container class, it has a draw() method that tracks changed areas of the screen.
my_particles = pygame.sprite.RenderUpdates()

сдача:

my_particles.append(target)

to:

my_particles.add(target)

сдача:

while True:
    pygame.display.update()
    screen.blit(background, (0,0))
    MouseP = pygame.mouse.get_pos()
    frames = Clock.get_fps
    pygame.mouse.set_visible
    score = (pygame.time.get_ticks()/1000)
    print (score)
    print (MouseP)
    for target in my_particles:
        target.move()
        target.boundaries()
        target.display()
        pygame.display.update()

to:

#initial screen draw:
screen.blit(background, (0,0))
pygame.display.update()
while True:
    #remove previous drawn sprites and replaces with background:
    my_particles.clear(screen, background)
    MouseP = pygame.mouse.get_pos()
    frames = Clock.get_fps
    pygame.mouse.set_visible
    score = (pygame.time.get_ticks()/1000)
    print (score)
    print (MouseP)
    for target in my_particles:
        target.move()
        target.boundaries()
    #draws changed sprites to the screen:
    pygame.display.update(my_particles.draw(screen))

Удалите метод display, так как он больше не нужен.

Это также будет работать намного быстрее, чем ваш предыдущий код, так как время, затрачиваемое на отрисовку чего-либо, пропорционально размеру области рисования, и раньше он каждый раз рисовал весь фон - теперь он рисует только спрайты и изменения в фон!

Надеюсь это поможет :)

person fraxel    schedule 05.05.2012
comment
Спасибо большое, вы спасатель. Такие подробные ответы, я никогда не ожидал такого приятного сообщества. Также где находится группа спрайтов, которую вы разместили в коде, я не уверен, является ли это my_particles.add(target) или my_particles = pygame.sprite.RenderUpdates(). Мне нужно понять это, чтобы я мог перейти к столкновениям. @фраксель - person AnjewGS; 05.05.2012
comment
@AnjewGS - спасибо :). Если я правильно понимаю ваш вопрос, я изменил ваш список: my_particles в класс pygame: pygame.sprite.RenderUpdates() который фактически представляет собой набор спрайтов, которые нам могут понадобиться для перерисовки каждой итерации. Строка my_particles.add(target) добавляет ваши астероиды в этот набор (поскольку она начинается пустой, add немного похожа на append, но для наборов - если вы не знаете, что это за наборы, вы должны проверить их..). - person fraxel; 05.05.2012
comment
ок круто, еще раз спасибо. Я могу использовать этот pygame.sprite.groupcollide, верно? - person AnjewGS; 05.05.2012
comment
@AnjewGS - Лучший способ - попробовать! groupcollide должен увидеть, какие члены двух групп сталкиваются. Здесь у нас есть только одна группа (на данный момент), поэтому вы можете использовать spritecollide для каждого астероида.. т.е. поместите его в цикл for в самом конце, но вы должны сначала сделать: my_particles.remove(target), затем pygame.sprite.spritecollide(target,my_particles,True), затем my_particles.add(target). Потому что в противном случае он будет сообщать о столкновениях между каждым астероидом и самим собой... попробуйте распечатать вывод этих вещей и почувствуйте, что происходит. - person fraxel; 05.05.2012

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

def draw(self):

    # Blit images
    self.screen.blit(image)

    # Flip display
    pygame.display.flip()

Это будет переворачивать дисплей каждый кадр, а затем рисовать следующий кадр без следа.

Также краткие заметки, не забудьте сделать image = pygame.image.load(image).convert or .convert_alpha(), иначе после добавления изображений игра замедлится. Кроме того, если вы делаете import pygame as pg, вам не нужно каждый раз вводить pygame, вместо этого вы можете просто ввести pg.

person Kai    schedule 26.02.2021