-1

I am trying to write a rip off 'Brick Breaker' game in Pygame. But I am currently stuck and do not know what to do know.

(blah blah blah, explain scenario much more clearly, blah blah blah, clear, clear scenario)

(I need more random text so I can post all this code)

Here is all of the code, (yes all of it):

import pygame, sys, time, random
from pygame.locals import *
pygame.init()
fpsclock = pygame.time.Clock()

WINDOWWIDTH = 450
WINDOWHEIGHT = 650
mainwindow = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
pygame.display.set_caption('Luzion - Brick Breaker')

paddle = pygame.image.load('Brick Breaker - Paddle.png')
paddlerect = paddle.get_rect()
paddlerect.topleft = (190, 575)

ball = pygame.image.load ('ball.png')
ballrect = ball.get_rect()
ballrect.topleft = (195, 565)

cooltext = pygame.image.load('cooltext1.png')
cooltextrect = cooltext.get_rect()
cooltextrect.topleft = (0, 0)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 128, 0)
BLUE = (0, 0, 255)
LIME = (0, 255, 0)
TEXTCOLOR = WHITE

font = pygame.font.SysFont(None, 48)

def displaytext(text, font, surface, x, y):
    text = font.render(text, 1, TEXTCOLOR)
    textrect = text.get_rect()
    textrect.topleft = (x, y)
    surface.blit(text, textrect)

def waitforplayer():
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pygame.quit()
                    sys.exit()
                return

moveleft = False
moveright = False
SPEED = 7

bmoveup = bmovedown = bmoveleft = bmoveright = False
BALLSPEED = 8

mainwindow.blit(cooltext, cooltextrect)
pygame.display.update()
time.sleep(1)

displaytext('Level 1', font, mainwindow, 150, 100)
pygame.display.update()
time.sleep(1)

displaytext('Press any key to begin...', font, mainwindow, 22, 200)
pygame.display.update()
waitforplayer()

while True:

    rb = pygame.image.load('redblock.png')
    rbrect = rb.get_rect()
    rbrect.topleft = (0, 0)

    rb1 = rb
    rb1rect = rb1.get_rect()
    rb1rect.topleft = (40, 0)

    level1blocks = [rb, rb1]
    level1rects = [rbrect, rb1rect]

    number = random.randint(0, 1)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == ord('a') or event.key == K_LEFT:
                moveleft = True
                moveright = False
            if event.key == ord('d') or event.key == K_RIGHT:
                moveleft = False
                moveright = True
            if event.key == ord('g'):
                bmoveup = True
                if number == 1:
                    bmoveleft = True
                else:
                    bmoveright = True
        if event.type == KEYUP:
            if event.key == ord('a') or event.key == K_LEFT:
                moveleft = False
            if event.key == ord('d') or event.key == K_RIGHT:
                moveright = False

    if moveleft and paddlerect.left > 0:
        paddlerect.left -= SPEED
    if moveright and paddlerect.right < WINDOWWIDTH:
        paddlerect.right += SPEED

    if bmovedown and ballrect.bottom < WINDOWHEIGHT:
        ballrect.top += BALLSPEED
    if bmoveup and ballrect.top > 0:
        ballrect.top -= BALLSPEED
    if bmoveleft and ballrect.left > 0:
        ballrect.left -= BALLSPEED
    if bmoveright and ballrect.right < WINDOWWIDTH:
        ballrect.right += BALLSPEED

    if ballrect.top <= 0:
        bmovedown = not bmovedown
        bmoveup = not bmoveup
    if ballrect.left <= 0:
        bmoveleft = not bmoveleft
        bmoveright = not bmoveright
    if ballrect.right >= WINDOWWIDTH:
        bmoveleft = not bmoveleft
        bmoveright = not bmoveright
    if ballrect.bottom >= WINDOWHEIGHT:
        bmovedown = not bmovedown
        bmoveup = not bmoveup

    mainwindow.fill(WHITE)
    mainwindow.blit(paddle, paddlerect)
    mainwindow.blit(ball, ballrect)

    for x in range(len(level1blocks)):
        mainwindow.blit(level1blocks[x], level1rects[x])

    for x in level1rects:
        if ballrect.colliderect(x):
            level1rects.remove([x])
            level1blocks.remove([x])

    if ballrect.colliderect(paddlerect):
        bmovedown = not bmovedown
        bmoveup = not bmoveup
        bmoveleft = not bmoveleft
        bmoveright = not bmoveright




    pygame.display.update()
    fpsclock.tick(35)

And here is my error:

    Traceback (most recent call last):
  File "C:/Python32/Luzion - Brick Breaker", line 144, in <module>
    level1rects.remove([x])
ValueError: list.remove(x): x not in list

Please help.

user1952081
  • 23
  • 1
  • 8

2 Answers2

4

As you mention in the comments, both for loops are inside a larger while loop. That means that when the line

level1rects.remove(x)

happens, it will decrease the size of level1rects and cause level1rects[x] (when x is 1) to raise an exception.

The best way to fix this is to change your for loops to the following:

for b in level1blocks:
     mainwindow.blit(b, b.get_rect())

for x in level1blocks[:]:
    if ballrect.colliderect(x.get_rect()):
        level1blocks.remove(x)

This obliviates the need for level1rects- it caused too many problems, because you were removing items from the list of rectangles without removing the corresponding block from the list of blocks. Changing the first loop to for b in level1blocks: allows the code to work even as blocks disappear.

David Robinson
  • 77,383
  • 16
  • 167
  • 187
  • Oh god, I feel terrible now. I must have not read what you said closely enough, I meant the code was in a larger while loop. Not a larger for loop. My bad. – user1952081 Jan 06 '13 at 01:49
  • @user1952081: No reason to- it's a great lesson about what kind of code to provide in your question. Welcome to StackOverflow! – David Robinson Jan 06 '13 at 01:50
  • @user1952081: Whether it's a larger for loop or a larger while loop makes absolutely no difference. Please try the change and see if it works. – David Robinson Jan 06 '13 at 01:57
  • @user1952081: So it doesn't throw an exception at all? In that case, it's probably an entirely new problem. How is it not working? If it's entirely different than this problem, it might deserve a new question (but only once you've tried debugging it yourself) – David Robinson Jan 06 '13 at 02:23
  • I shall edit the post and post the whole code. I am now getting a different error and editing some things in the code. – user1952081 Jan 06 '13 at 02:24
  • 1
    @user1952081: You're new here (and we are glad to have you!), but please be cautious of making a [chameleon question](http://meta.stackexchange.com/questions/43478/exit-strategies-for-chameleon-questions). Why don't you spend some time trying to fix the new error on your own? – David Robinson Jan 06 '13 at 02:28
  • That is what I was doing for the last twenty minutes when you gave me your code. I changed it a little, added some things that should make sense and am now stuck with this error. – user1952081 Jan 06 '13 at 02:30
  • @user1952081: Why didn't you use the code I supplied in my answer? Unless I'm mistaken, it fixes your new problem. – David Robinson Jan 06 '13 at 02:32
  • I have used it (sorry if I forgot to mention that). It works in the sense that there is no more error code, but then I cannot change the coordinates of the blocks (thats why I had level1rects, because that was the only way to get all the coordinates to display the blocks in different areas. And whenever the ball hit the block, it just stayed there. – user1952081 Jan 06 '13 at 02:34
  • @user1952081: Sure you can change them- you can do `level1blocks[0].get_rect().topleft = (30, 30)` or whatever. That would be the same as doing `level1rects[0].topleft = (30, 30)` in the equivalent. – David Robinson Jan 06 '13 at 02:36
  • @user1952081 We aren't here to fix all the bugs in your program, one after another. I believe the question you asked was answered long ago. Time to accept the answer and move on. – David Heffernan Jan 06 '13 at 02:36
  • @DavidRobinson Yes, but that does not change the fact that when the ball hits the block, the block does not disappear. (I may be sounding grumpy but I really appreciate all the help your are giving) – user1952081 Jan 06 '13 at 02:40
  • @user1952081: The blocks aren't disappearing because you are defining `rb` and `rb1` (and loading the associated images) inside your `while` loop, which means they are being put on the screen in every single cycle. Take those definitions out of the while loop. – David Robinson Jan 06 '13 at 02:44
  • @DavidRobinson Thank you very very very much. That fixed it, now I can continue to program :) – user1952081 Jan 06 '13 at 02:51
  • @user1952081: glad to hear! – David Robinson Jan 06 '13 at 02:55
-1

Do a print or pprint on the level1blocks and level1rects lists, one of them doesn't have enough members for the range(2) iterator, which will try accessing the first (index 0) and second (index 1) members of each list.

kasceled
  • 548
  • 1
  • 6
  • 18