M_Sea
M_Sea

Reputation: 491

python pygame put random coordinates stars on screen but overlap

I am trying to put the stars on screen and give them random x,y coordinates

but when the screen refresh the previous stars still on the screen and it overlap with the next stars

I put the setting.screen.fill((255,0,0)) why this background not refresh the previous stars? what cause it????

here's the codes:

#!/usr/bin/python
import sys
import pygame as p
from random import randint

#13-1

class Setting():
    def __init__(self,width,height):
        self.w=width
        self.h=height
        self.screen=p.display.set_mode((self.w,self.h),p.RESIZABLE,0)
        p.display.set_caption("EXE 13-1")

class Star(p.sprite.Sprite):
    def __init__(self):
        super().__init__()
        pic=p.image.load("../image/star.jpg").convert_alpha()
        self.image=p.transform.smoothscale(pic,(100,100))
        self.rect=self.image.get_rect()
        self.rect.x=(self.rect.width)/2
    def create(self,setting,stars):
        spacex=setting.w-2*self.rect.x
        numbers=int(spacex/(2*self.rect.x))
        rows=int(setting.h/(2*self.rect.height))
        for row in range(rows):
            for number in range(numbers):
                star=Star()
                star.rect.x=randint(-10,10)+2*self.rect.width*number
                star.rect.y=randint(-10,10)+2*self.rect.height*row
                stars.add(star)
    def blit(self,setting,stars):
        stars.draw(setting.screen)
        # for star in stars.sprites():
        #    setting.screen.blit(star.image,star.rect)


def game():
    p.init()
    setting=Setting(1200,800)
    star=Star()
    stars=p.sprite.Group()
    while True:
        for event in p.event.get():
            if event.type == p.QUIT:
                sys.exit()
            elif event.type == p.KEYDOWN:
                if event.key == p.K_ESCAPE:
                    sys.exit()
        setting.screen.fill((255,0,0))
        star.create(setting,stars)
        star.blit(setting,stars)
        p.display.flip()
game()

Upvotes: 1

Views: 410

Answers (1)

Rabbid76
Rabbid76

Reputation: 210889

The issue is caused, because the entire stars a recreated in each frame and append to the pygame.sprite.Group stars. But the group is never emptied and grows continuously:

while True:

   # [...]

   star.create(setting,stars) # <-- adds new objects to Group "stars" in every frame

The easiest solution would be to empty() the Group in every frame

def game():

    # [...]

    while True:

        # [...]

        # remove all stars from the group
        stars.empty()
        # create new stars
        star.create(setting,stars)

But the much better solution would be to keep the stars in the Group and to randomize their positions. Note, recreating the stars in every frame will gain a performance impact.
Create the stars one before the mein application loop and set a new random position to each star in the main application loop:

class Star(p.sprite.Sprite):

    # [...]

    def create(self,setting,stars):
        spacex=setting.w-2*self.rect.x
        numbers=int(spacex/(2*self.rect.x))
        rows=int(setting.h/(2*self.rect.height))
        for row in range(rows):
            for number in range(numbers):
                star=Star()

                # store row and colume of the stare 
                star.col = number
                star.row = row

                star.randomize()
                stars.add(star)

    # calculate random position
    def randomize(self):
        self.rect.x=randint(-10,10)+2*self.rect.width*self.col
        self.rect.y=randint(-10,10)+2*self.rect.height*self.row
def game():
    p.init()
    setting=Setting(1200,800)
    star=Star()
    stars=p.sprite.Group()
    star.create(setting,stars)
    while True:
        for event in p.event.get():
            if event.type == p.QUIT:
                sys.exit()
            elif event.type == p.KEYDOWN:
                if event.key == p.K_ESCAPE:
                    sys.exit()

        # randomize positions of stars
        for star in stars:
            star.randomize()

        setting.screen.fill((255,0,0))
        star.blit(setting,stars)
        p.display.flip()

Finally I recommend to remove the self parameter from the class methods create and blit. It is sufficient to lad the image of the star once:

class Star(p.sprite.Sprite):
    def __init__(self, col, row, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
        self.col, self.row = col, row
        self.randomize()

    def randomize(self):
        self.rect.x=randint(-10,10)+2*self.rect.width*self.col
        self.rect.y=randint(-10,10)+2*self.rect.height*self.row

    def create(setting,stars):
        pic = p.image.load("../image/star.jpg").convert_alpha()
        pic = p.transform.smoothscale(pic,(100,100))
        numbers, rows = setting.w // 100, setting.h // 100
        for row in range(rows):
            for number in range(numbers):
                star=Star(number, row, pic)
                stars.add(star)

    def randomizeStars(stars):
        for star in stars:
            star.randomize()

    def blit(setting,stars):
        stars.draw(setting.screen)
def game():
    p.init()
    setting=Setting(1200,800)
    stars=p.sprite.Group()
    Star.create(setting,stars)
    while True:
        for event in p.event.get():
            if event.type == p.QUIT:
                sys.exit()
            elif event.type == p.KEYDOWN:
                if event.key == p.K_ESCAPE:
                    sys.exit()

        Star.randomizeStars(stars)

        setting.screen.fill((255,0,0))
        Star.blit(setting,stars)
        p.display.flip()

Upvotes: 1

Related Questions