pygame isn't redrawing rectangles after they've disappeared

303 views Asked by At

I'm making a pacman game and I have the basics working at the moment, but I can't get the pac pellets to respawn after they have all been eaten. At the moment I have it set up that after a pac pellet is eaten it is removed from the list of pacpellets. When the list is empty it is refilled and then told to redraw all pac pellets onto the screen. It goes though all the correct functions and everything, I've checked with print statements, but pygame.draw.rect isn't working and I can't figure out why.

import pygame
import os
import sys
import copy


#intialise the game 
pygame.init()
myfont = pygame.font.SysFont("monospace", 15)
screen = pygame.display.set_mode((448, 576))
done = False
score=0

y = 416
x = 232

#sets up clock and loads pacman image
clock = pygame.time.Clock()
PACMANSPRITE = pygame.image.load("pacman.png").convert_alpha()
PACMAN_MAP = pygame.image.load("pacman_map.png").convert_alpha()

#gets pacman intro music, sets music to lower volume then plays it
pygame.mixer.music.load('pacman_beginning.WAV')
pygame.mixer.music.set_volume(0.01)
pygame.mixer.music.play(0)


#box class, used for boxes to border pacmans map
class boxcollisions(pygame.sprite.Sprite):
    def __init__(self, x, y):
        self.y = y
        self.x = x
        self.rect = pygame.Rect(self.x, self.y, 12, 12)
        self.colour = (0, 128, 255)

    def draw(self, screen):
        pygame.draw.rect(screen, self.colour, self.rect)

class pointclass(pygame.sprite.Sprite):
    def __init__(self, x, y):
        self.y = y
        self.x = x
        self.rect = pygame.Rect(self.x, self.y, 12, 12)
        self.colour = (255, 204, 153)
        self.score=0

    def draw(self, screen):
        pygame.draw.rect(screen, self.colour, self.rect)


#pacmans class
class pacman(pygame.sprite.Sprite):
    def __init__(self, image, x, y):
        self.image = image
        self.y=416
        self.x=216
        self.currentx=self.x
        self.currenty=self.y
        self.rect = self.image.get_rect()
        self.rect.left = self.x
        self.rect.top = self.y
        self.rect.width=16
        self.rect.height=16

    # move pacman 
    def movement(self):
        pressed= pygame.key.get_pressed()
        if pressed[pygame.K_UP]:
            self.y -= 2
        if pressed[pygame.K_DOWN]:
            self.y += 2
        if pressed[pygame.K_LEFT]:
            self.x -= 2
        if pressed[pygame.K_RIGHT]:
            self.x += 2
        self.rect.left = self.x
        self.rect.top = self.y

    def draw(self, surface):
        # blit yourself at your current position
        surface.blit(self.image, (self.x, self.y))
        self.currentx=self.x
        self.currenty=self.y

    def outofbounds(self):
        self.y=self.currenty
        self.x=self.currentx
        self.rect.left = self.x
        self.rect.top = self.y



#spawn pellets function
def spawnpellets(pointspawns):
    broken=0
    abc=0
    efg=0
    px=0
    py=-16
    for row in pointspawns:
        #y co ordinate
        py=py+16    
        for n in row:
            #x co ordinate
            n=n-1
            px=n*16
            point=(pointclass(px, py))
            #used to draw points
            point.draw(screen)
            if pygame.sprite.collide_rect(sprite, point):
                removepellets(pointspawns, row, n , py)
                global score
                score+=1
                allpelletsremoved(pointspawns, copyofpointspawns)

def allpelletsremoved(pointspawns, copyofpointspawns):
    total=0
    print()
    print('start of allpelletsremoved')
    for row in pointspawns:
        print('have gone through a row')
        if not row:
            total+=1
            print('current total: ', total)
    #if total =5 it means all rows are emtpy and thereofr all pellets have been eaten 
    if total==5:
        pointspawns= copy.deepcopy(copyofpointspawns)
        spawnpellets(pointspawns)



def removepellets(pointspawns, row, n, py):
    collidedx=n+1
    collidedy=py/16
    collidedy=int(collidedy)
    tempindex=row.index(collidedx)
    del pointspawns[collidedy][tempindex]
    #pointspawns[int(collidedy)].insert(collidedx,0)

#co-ordinates for boxes to set up map boundaries
boxboundaries=[   
    [],
    [],
    [],
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28],
    [1,14,15,28], #5
    [1,3,4,5,6,8,9,10,11,12,14,15,17,18,19,20,21,23,24,25,26,28],
    [1,3,4,5,6,8,9,10,11,12,14,15,17,18,19,20,21,23,24,25,26,28],
    [1,3,4,5,6,8,9,10,11,12,14,15,17,18,19,20,21,23,24,25,26,28],
    [1,28],
    [1,3,4,5,6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,25,26,28], #10
    [1,3,4,5,6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,25,26,28],
    [1,8,9,14,15,20,21,28],
    [1,2,3,4,5,6,8,9,10,11,12,14,15,17,18,19,20,21,23,24,25,26,27,28],
    [1,2,3,4,5,6,8,9,10,11,12,14,15,17,18,19,20,21,23,24,25,26,27,28],
    [6,8,9,20,21,23], #15
    [6,8,9,11,12,13,14,15,16,17,18,20,21,23],
    [1,2,3,4,5,6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,25,26,27,28],
    [1,11,12,13,14,15,16,17,18,28],
    [1,2,3,4,5,6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,25,26,27,28],
    [6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,25,26,27,28], #20
    [6,8,9,20,21,23],
    [6,8,9,11,12,13,14,15,16,17,18,20,21,23],
    [1,2,3,4,5,6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,25,26,27,28],
    [1,14,15,28],
    [1,3,4,5,6,8,9,10,11,12,14,15,17,18,19,20,21,23,24,25,26,28], #25
    [1,3,4,5,6,8,9,10,11,12,14,15,17,18,19,20,21,23,24,25,26,28],
    [1,5,6,23,24,28],
    [1,2,3,5,6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,26,27,28],
    [1,2,3,5,6,8,9,11,12,13,14,15,16,17,18,20,21,23,24,26,27,28],
    [1,8,9,14,15,20,21,28], # 30
    [1,3,4,5,6,7,8,9,10,11,12,14,15,17,18,19,20,21,22,23,24,25,26,28],
    [1,3,4,5,6,7,8,9,10,11,12,14,15,17,18,19,20,21,22,23,24,25,26,28],
    [1,28],
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28],                   
  ]


#point spawn locations, temporarily not using it as collecting
#all points would be to difficult to test
pointspawns1=[ 
    [],
    [],
    [],
    [],
    [2,3,4,5,6,7,8,9,10,11,12,13,16,17,18,19,20,21,22,23,24,25,26,27], #5
    [2,7,13,16,22,27],
    [2,7,13,16,22,27],
    [2,7,13,16,22,27],
    [2,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27], 
    [2,7,10,19,22,27], #10
    [2,7,10,19,22,27],
    [2,3,4,5,6,7,10,11,12,13,16,17,18,19,22,23,24,25,26,27],
    [7,22],
    [7,22],
    [7,22], #15
    [7,22],
    [7,22],
    [7,22],
    [7,22],
    [7,22], #20
    [7,22],
    [7,22],
    [7,22],
    [2,3,4,5,6,7,8,9,10,11,12,13,16,17,18,19,20,21,22,23,24,25,26,27],
    [2,7,13,16,22,27], #25
    [2,7,13,16,22,27],
    [2,3,4,7,8,9,10,11,12,13,16,17,18,19,20,21,22,25,26,27],
    [4,7,10,19,22,25],
    [4,7,10,19,22,25],
    [2,3,4,5,6,7,10,11,12,13,16,17,18,19,22,23,24,25,26,27],
    [2,13,16,27], # 30
    [2,13,16,27],
    [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27],                       
  ]

#temporary point spawn locations, used so it easier to test when they are all eaten
pointspawns=[ 
    [],
    [],
    [],
    [],
    [2,3,4,5,6,7,8,9,10,11,12,13,16,17,18,19,20,21,22,23,24,25,26,27], #5                     
  ]

#makes a copy of pointspawns to reset pointspawns for later
copyofpointspawns= copy.deepcopy(pointspawns)


#instances the pacman class
sprite = pacman(PACMANSPRITE, x ,y)


#main game loop
while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
                    done = True
                    pygame.quit()
                    sys.exit()


    screen.fill((0,0,0))
    screen.blit(PACMAN_MAP, (0, 0))

    #moves pacman
    sprite.movement()

    #spawn pellets
    spawnpellets(pointspawns)

    #builds the boxes
    bx=0
    by=-16
    for row in boxboundaries:
        #y co ordinate
        by=by+16    
        for n in row:
            #x co ordinate
            n=n-1
            bx=n*16
            box=(boxcollisions(bx, by))
            #used to draw boxes for visual repsentation
            #box.draw(screen)
            if pygame.sprite.collide_rect(sprite, box):
                sprite.outofbounds()



    #draws pacman
    sprite.draw(screen)


    #draws score to screen
    label = myfont.render("HIGH SCORE:", 1, (255,255,255))
    screen.blit(label, (180, 0))
    labelscore = myfont.render(str(score), 1, (255,255,255))
    screen.blit(labelscore, (180, 16))


    pygame.display.flip()
    clock.tick(60)
2

There are 2 answers

0
Matt On

If your sure that pygame.rect.draw is not working than try using the draw function I use it and it works. Look here for more on the draw function

https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.Group.draw

and some example code

Displaying platforms using strings (Pygame)

I dont know to much about your long lists you have but you could make it shorter is you used string lists (also in the example code). Hope I could help.

0
skrx On

I would do something like this: Define a function that creates a sprite group and fills it with the pellet sprites, then return it and assign it to a variable in the main function. When the pellets group is empty, just call this function again and assign the new group to the old variable and the pellets will appear again.

import pygame as pg


class Player(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((30, 30))
        self.image.fill(pg.Color('yellow'))
        self.rect = self.image.get_rect(center=pos)
        self.vel = pg.math.Vector2(0, 0)
        self.pos = pg.math.Vector2(pos)

    def update(self):
        self.pos += self.vel
        self.rect.center = self.pos


class Pellet(pg.sprite.Sprite):

    def __init__(self, pos, *groups):
        super().__init__(*groups)
        self.image = pg.Surface((10, 6))
        self.image.fill(pg.Color('turquoise'))
        self.rect = self.image.get_rect(center=pos)


def create_map():
    """Create a sprite group filled with Pellet sprites."""
    group = pg.sprite.Group()
    for i in range(10):
        group.add(Pellet((50, 20*i+50)))
    return group


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    all_sprites = pg.sprite.Group()
    player = Player((100, 300), all_sprites)
    pellets = create_map()
    all_sprites.add(pellets)

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_d:
                    player.vel.x = 5
                elif event.key == pg.K_a:
                    player.vel.x = -5
                elif event.key == pg.K_w:
                    player.vel.y = -5
                elif event.key == pg.K_s:
                    player.vel.y = 5
            elif event.type == pg.KEYUP:
                if event.key == pg.K_d:
                    player.vel.x = 0
                elif event.key == pg.K_a:
                    player.vel.x = 0
                elif event.key == pg.K_w:
                    player.vel.y = 0
                elif event.key == pg.K_s:
                    player.vel.y = 0

        all_sprites.update()
        hit_pellets = pg.sprite.spritecollide(player, pellets, True)
        for pellet in hit_pellets:
            print('Yum!')
        if not pellets:  # If the pellets group is empty.
            print('No food left. Respawing food!')
            pellets = create_map()  # Recreate the group.
            all_sprites.add(pellets)  # And add them to the general group.
        screen.fill((30, 30, 30))
        all_sprites.draw(screen)

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


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