Python Forum
Something strange happening here !?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Something strange happening here !?
#1
The code below that I created seems simple enough. Create a list that holds current line info, add that current line list to a master list, then draw the lines from the master list. This is supposed to recreate the dancing line type screen saver seen over the years.

However, every line in the master list (mline) has the same current line (cline) listed in it at every index, which should be impossible with the way I have written the code?

I've stared at this for a few hours now, not knowing what I have missed. Would any kind soul care to take a look and show me where I am missing something?

Thank you in advance :)




# Dancing Lines 2.0 # Terry Ritchie # 04/08/17 # # Import libraries # import pygame       # pygame graphics engine library import random       # random number library # # Define variables # SWIDTH = 800        # width of surface (window) SHEIGHT = 600       # height of surface (window) FPS = 60            # frames per second MAXLINES = 256      # total number of lines on screen at once STARTX = 0          # index of start x coordinate or vector in each line list STARTY = 1          # index of start y coordinate or vector in each line list ENDX = 2            # index of end x coordinate or vector in each line list ENDY = 3            # index of end y coordinate or vector in each line list RED = 4             # index of red color component or increment in each line list GREEN = 5           # index of green color component or increment in each line list BLUE = 6            # index of blue color component or increment in each line list SDURATION = 7       # index of line starting point movement duration in vector list EDURATION = 8       # index of line ending point movement duration in vector list mline = []          # the master line list lcount = -1         # current line count # # the structure of the master line list is as follows: # # mline[[sx, sy, ex, ey, r, g, b], ... ] #   sx  = start x coordinate of line #   sy  = start y coordinate of line #   ex  = endx coordinate of line #   ey  = end y coordinate of line #   r   = red color component of line #   g   = green color component of line #   b   = blue color component of line # # the structure of the current line list is as follows: # # cline[sx, sy, ex, ey, r, g, b] #   sx  = start x coordinate of line #   sy  = start y coordinate of line #   ex  = endx coordinate of line #   ey  = end y coordinate of line #   r   = red color component of line #   g   = green color component of line #   b   = blue color component of line # # the structure of the vector list is as follows: # # vector[sxv, syv, exv, eyv, ri, gi, bi, sd, ed] #   sxv = start x coordinate vector direction #   syv = start y coordinate vector direction #   exv = end x coordinate vector direction #   eyv = end y coordinate vector direction #   ri  = red color component increment #   gi  = green color componment increment #   bi  = blue color component increment #   sd  = start line point movement duration #   ed  = end line point movement duration # # # create lists # for i in range(MAXLINES):                               # cycle through number of lines to create     mline.append([0, 0, 0, 0, 0, 0, 0])                 # intitialize line values and add to master list vector = [0, 0, 0, 0, 0, 0, 0, 0, 0]                    # initialize the vector list cline =  [0, 0, 0, 0, 0, 0, 0]                          # initialize the current line list # # populate initial line and vector values # cline[STARTX] = random.randrange(20, SWIDTH - 20)       # start x coordinate value cline[STARTY] = random.randrange(20, SWIDTH - 20)       # start y coordinate value cline[ENDX]   = random.randrange(20, SWIDTH - 20)       # end x coordinate value cline[ENDY]   = random.randrange(20, SWIDTH - 20)       # end y coordinate value cline[RED]    = random.randrange(1, 255)                # red component color cline[GREEN]  = random.randrange(1, 255)                # green component color cline[BLUE]   = random.randrange(1, 255)                # blue component color zero = True                                             # stay in while loop until flag is False while zero:                                             # flag set to True?     vector[STARTX] = random.randrange(-10, 11)          # yes, start x coordinate direction     vector[STARTY] = random.randrange(-10, 11)          # start y coordinate direction     vector[ENDX]   = random.randrange(-10, 11)          # end x coordinate direction     vector[ENDY]   = random.randrange(-10, 11)          # end y coordinate direction     vector[RED]    = random.randrange(-1, 2)            # red color component increment     vector[GREEN]  = random.randrange(-1, 2)            # green color component increment     vector[BLUE]   = random.randrange(-1, 2)            # blue color component increment     zero = False                                        # assume no random values equal zero     for i in range(STARTX, BLUE + 1):                   # cycle through vector index values         if vector[i] == 0:                              # is this index set to zero?             zero = True                                 # yes, set flag to run loop again vector[SDURATION] = random.randrange(100, 501)          # duration of line start point to move vector[EDURATION] = random.randrange(100, 501)          # duration of line end point to move      # # Initialize the pygame engine # pygame.init()                                           # start the pygame library engine # # Create the working surface (window) # screen = pygame.display.set_mode((SWIDTH, SHEIGHT))     # open a window to work in # # set the surface (window) caption # pygame.display.set_caption("Dancing Lines 2.0")         # set the caption with a description of the program # # Manage how fast the screen updates # clock = pygame.time.Clock()                             # create an object to control timers # # initialize main program loop variables # done = False                                            # when set to True main loop will end # # ---------- MAIN PROGRAM LOOP ------------ # while not(done):                                        # stay in loop?     #     # ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT     #          for event in pygame.event.get():                    # yes, did the user do something?         if event.type == pygame.QUIT:                   # yes, did the user click the close button (X)?             done = True                                 # yes, set flag to leave main program loop     #     # ALL GAME LOGIC SHOULD GO BELOW THIS COMMENT     #     lcount += 1                                         # increment current line counter     if lcount == MAXLINES:                              # has current line counter reached maximum value?         lcount = 0                                      # yes, reset the current line counter     vector[SDURATION] -= 1                              # decrement the start point duration counter     if vector[SDURATION] == 0:                          # has the start duration counter reached zero?         vector[SDURATION] = random.randrange(100, 501)  # yes, reset the start duration counter         zero = True                                     # set loop flag         while zero:                                     # is loop flag True?             vector[STARTX] = random.randrange(-10, 11)  # yes, reset start x coordinate vecotr             vector[STARTY] = random.randrange(-10, 11)  # reset start y coordinate vector             zero = False                                # assume neither value is zero             for i in range(STARTX, STARTY + 1):         # cycle through vector indexes                 if vector[i] == 0:                      # does this vector index equal zero?                     zero = True                         # yes, set flag to run loop again     vector[EDURATION] -= 1                              # decrement the end point duration counter     if vector[EDURATION] == 0:                          # has the end duration counter reached zero?         vector[EDURATION] = random.randrange(100, 501)  # yes, reset the end duration counter         zero = True                                     # set loop flag         while zero:                                     # is the loop flag True?             vector[ENDX] = random.randrange(-10, 11)    # yes, reset end x coordinate vector             vector[ENDY] = random.randrange(-10, 11)    # reset end y coordinate vector             zero = False                                # assume neither value is zero             for i in range(ENDX, ENDY + 1):             # cycle through vector indexes                 if vector[i] == 0:                      # does this vector index equal zero?                     zero = True                         # yes, set flag to run loop again                      #     # add vector values to start/end x,y coordinates     #          cline[STARTX] += vector[STARTX]                     # add start x vector to start x coordinate     cline[STARTY] += vector[STARTY]                     # add start y vector to start y coordinate     cline[ENDX]   += vector[ENDX]                       # add end x vector to end x coordinate     cline[ENDY]   += vector[ENDY]                       # add end y vector to end y coordinate     #     # check start/end x,y coordinates leaving screen     # if they do, reverse the associated vector value     #     if cline[STARTX] >= SWIDTH - 1:                     # has start x coordinate hit right side of screen?         cline[STARTX] = SWIDTH - 1                      # yes, set start x coordinate to screen width         vector[STARTX] = -vector[STARTX]                # reverse the start x vector value     elif cline[STARTX] <= 0:                            # no, has start x coordinate hit left side of screen?         cline[STARTX] = 0                               # yes, set start x coordinate to minimum width         vector[STARTX] = -vector[STARTX]                # reverse the start x vector value              if cline[STARTY] >= SHEIGHT - 1:                    # has start y coordinate hit bottom of screen?         cline[STARTY] = SHEIGHT - 1                     # yes, set start y coordinate to screen height         vector[STARTY] = -vector[STARTY]                # reverse the start y vector value     elif cline[STARTY] <= 0:                            # no, has stary y coordinate hit top of screen?         cline[STARTY] = 0                               # yes, set start y coordinate to minimum height         vector[STARTY] = -vector[STARTY]                # reverse the start y vector value              if cline[ENDX] >= SWIDTH - 1:                       # has end x coordinate hit right side of screen?         cline[ENDX] = SWIDTH - 1                        # yes, set end x coordinate to screen width         vector[ENDX] = -vector[ENDX]                    # reverse the end x vector value     elif cline[ENDX] <= 0:                              # no, has end x coordinate hit left side of screen?         cline[ENDX] = 0                                 # yes, set end x coordinate to minimum width         vector[ENDX] = -vector[ENDX]                    # reverse the end x vector value              if cline[ENDY] >= SHEIGHT - 1:                      # has end y coordinate hit bottom of screen?         cline[ENDY] = SHEIGHT - 1                       # yes, set end y coordinate to screen height         vector[ENDY] = -vector[ENDY]                    # reverse the end y vector value     elif cline[ENDY] <= 0:                              # no, has end y coordinate hit top of screen?         cline[ENDY] = 0                                 # yes, set end y coordinate to minimum height         vector[ENDY] = -vector[ENDY]                    # reverse the end y vector value     #     # add color increment values to color components     #          cline[RED]   += vector[RED]                         # add red increment to red color component     cline[GREEN] += vector[GREEN]                       # add green increment to green color component     cline[BLUE]  += vector[BLUE]                        # add blue increment to blue color component     #     # if any color component has reached the maximum     # or minimum value reverse the associated     # increment value     #     if cline[RED] == 0 or cline[RED] == 255:            # has red color component exceeded limit?         vector[RED] = -vector[RED]                      # yes, reverse red increment value     if cline[GREEN] == 0 or cline[GREEN] == 255:        # has green color component exceeded limit?         vector[GREEN] = -vector[GREEN]                  # yes, reverse green increment value     if cline[BLUE] == 0 or cline[BLUE] == 255:          # has blue color component exceeded limit?         vector[BLUE] = -vector[BLUE]                    # yes, reverse blue increment value     mline[lcount] = cline                               # place current line in master line list     #     # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT     #     screen.fill((0, 0, 0))                              # clear the window with a black background     c = lcount     for i in range(MAXLINES):         c += 1         if c == MAXLINES:             c = 0                          #if mline[c][RED] > 0:         #    mline[c][RED] -= 1         #if mline[c][GREEN] > 0:         #    mline[c][GREEN] -= 1         #if mline[c][BLUE] > 0:         #    mline[c][BLUE] -= 1         pygame.draw.line(screen, (mline[c][RED], mline[c][GREEN], mline[c][BLUE]), (mline[c][STARTX], mline[c][STARTY]), (mline[c][ENDX], mline[c][ENDY]), 1)     pygame.display.flip()                               # updates the window with the newly drawn image     #     # limit main program loop to a number of frames per second     #     clock.tick(FPS)                                     # limit frames per second pygame.quit()
Reply
#2
Perhaps I have not explained this well enough. The code as presented when run does in fact make a line that bounces around the screen. However, what you are seeing is MAXLINES number of lines being drawn on top of each other because all of the elements in the mlines list are exactly the same.

What should be happening is a trailing line effect of MAXLINES following the first line.

How does my code somehow magically make every list element within the master list (mline) exactly the same? The code does not support this?
Reply
#3
After some trial and error I have gotten the program to operate correctly. The corrected code is below.

I had to change line 249 from this:

mline[lcount] = cline

to:

mline[lcount][:6] = cline[:6]

and then the master line list start accepting values correctly. Could someone be so kind and explain why I had to do this? I would think that the first way I coded the line would work without having to specifically spell out which elements to fill.

Thank you.


# Dancing Lines 2.0 # Terry Ritchie # 04/08/17   # # Import libraries #   import pygame       # pygame graphics engine library import random       # random number library   # # Define variables #   SWIDTH = 800        # width of surface (window) SHEIGHT = 600       # height of surface (window) FPS = 60            # frames per second MAXLINES = 256      # total number of lines on screen at once STARTX = 0          # index of start x coordinate or vector in each line list STARTY = 1          # index of start y coordinate or vector in each line list ENDX = 2            # index of end x coordinate or vector in each line list ENDY = 3            # index of end y coordinate or vector in each line list RED = 4             # index of red color component or increment in each line list GREEN = 5           # index of green color component or increment in each line list BLUE = 6            # index of blue color component or increment in each line list SDURATION = 7       # index of line starting point movement duration in vector list EDURATION = 8       # index of line ending point movement duration in vector list mline = []          # the master line list lcount = -1         # current line count   # # the structure of the master line list is as follows: # # mline[[sx, sy, ex, ey, r, g, b], ... ] #   sx  = start x coordinate of line #   sy  = start y coordinate of line #   ex  = endx coordinate of line #   ey  = end y coordinate of line #   r   = red color component of line #   g   = green color component of line #   b   = blue color component of line # # the structure of the current line list is as follows: # # cline[sx, sy, ex, ey, r, g, b] #   sx  = start x coordinate of line #   sy  = start y coordinate of line #   ex  = endx coordinate of line #   ey  = end y coordinate of line #   r   = red color component of line #   g   = green color component of line #   b   = blue color component of line # # the structure of the vector list is as follows: # # vector[sxv, syv, exv, eyv, ri, gi, bi, sd, ed] #   sxv = start x coordinate vector direction #   syv = start y coordinate vector direction #   exv = end x coordinate vector direction #   eyv = end y coordinate vector direction #   ri  = red color component increment #   gi  = green color componment increment #   bi  = blue color component increment #   sd  = start line point movement duration #   ed  = end line point movement duration #   # # create lists #   for i in range(MAXLINES):                               # cycle through number of lines to create     mline.append([0, 0, 0, 0, 0, 0, 0])                 # intitialize line values and add to master list vector = [0, 0, 0, 0, 0, 0, 0, 0, 0]                    # initialize the vector list cline =  [0, 0, 0, 0, 0, 0, 0]                          # initialize the current line list   # # populate initial line and vector values #   cline[STARTX] = random.randrange(20, SWIDTH - 20)       # start x coordinate value cline[STARTY] = random.randrange(20, SWIDTH - 20)       # start y coordinate value cline[ENDX]   = random.randrange(20, SWIDTH - 20)       # end x coordinate value cline[ENDY]   = random.randrange(20, SWIDTH - 20)       # end y coordinate value cline[RED]    = random.randrange(1, 255)                # red component color cline[GREEN]  = random.randrange(1, 255)                # green component color cline[BLUE]   = random.randrange(1, 255)                # blue component color zero = True                                             # stay in while loop until flag is False while zero:                                             # flag set to True?     vector[STARTX] = random.randrange(-10, 11)          # yes, start x coordinate direction     vector[STARTY] = random.randrange(-10, 11)          # start y coordinate direction     vector[ENDX]   = random.randrange(-10, 11)          # end x coordinate direction     vector[ENDY]   = random.randrange(-10, 11)          # end y coordinate direction     vector[RED]    = random.randrange(-1, 2)            # red color component increment     vector[GREEN]  = random.randrange(-1, 2)            # green color component increment     vector[BLUE]   = random.randrange(-1, 2)            # blue color component increment     zero = False                                        # assume no random values equal zero     for i in range(STARTX, BLUE + 1):                   # cycle through vector index values         if vector[i] == 0:                              # is this index set to zero?             zero = True                                 # yes, set flag to run loop again vector[SDURATION] = random.randrange(100, 501)          # duration of line start point to move vector[EDURATION] = random.randrange(100, 501)          # duration of line end point to move       # # Initialize the pygame engine #   pygame.init()                                           # start the pygame library engine   # # Create the working surface (window) #   screen = pygame.display.set_mode((SWIDTH, SHEIGHT))     # open a window to work in   # # set the surface (window) caption #   pygame.display.set_caption("Dancing Lines 2.0")         # set the caption with a description of the program   # # Manage how fast the screen updates #   clock = pygame.time.Clock()                             # create an object to control timers   # # initialize main program loop variables #   done = False                                            # when set to True main loop will end   # # ---------- MAIN PROGRAM LOOP ------------ #   while not(done):                                        # stay in loop?       #     # ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT     #           for event in pygame.event.get():                    # yes, did the user do something?         if event.type == pygame.QUIT:                   # yes, did the user click the close button (X)?             done = True                                 # yes, set flag to leave main program loop       #     # ALL GAME LOGIC SHOULD GO BELOW THIS COMMENT     #       lcount += 1                                         # increment current line counter       if lcount == MAXLINES:                              # has current line counter reached maximum value?         lcount = 0                                      # yes, reset the current line counter       vector[SDURATION] -= 1                              # decrement the start point duration counter       if vector[SDURATION] == 0:                          # has the start duration counter reached zero?         vector[SDURATION] = random.randrange(100, 501)  # yes, reset the start duration counter         zero = True                                     # set loop flag         while zero:                                     # is loop flag True?             vector[STARTX] = random.randrange(-10, 11)  # yes, reset start x coordinate vecotr             vector[STARTY] = random.randrange(-10, 11)  # reset start y coordinate vector             zero = False                                # assume neither value is zero             for i in range(STARTX, STARTY + 1):         # cycle through vector indexes                 if vector[i] == 0:                      # does this vector index equal zero?                     zero = True                         # yes, set flag to run loop again       vector[EDURATION] -= 1                              # decrement the end point duration counter       if vector[EDURATION] == 0:                          # has the end duration counter reached zero?         vector[EDURATION] = random.randrange(100, 501)  # yes, reset the end duration counter         zero = True                                     # set loop flag         while zero:                                     # is the loop flag True?             vector[ENDX] = random.randrange(-10, 11)    # yes, reset end x coordinate vector             vector[ENDY] = random.randrange(-10, 11)    # reset end y coordinate vector             zero = False                                # assume neither value is zero             for i in range(ENDX, ENDY + 1):             # cycle through vector indexes                 if vector[i] == 0:                      # does this vector index equal zero?                     zero = True                         # yes, set flag to run loop again                       #     # add vector values to start/end x,y coordinates     #           cline[STARTX] += vector[STARTX]                     # add start x vector to start x coordinate     cline[STARTY] += vector[STARTY]                     # add start y vector to start y coordinate     cline[ENDX]   += vector[ENDX]                       # add end x vector to end x coordinate     cline[ENDY]   += vector[ENDY]                       # add end y vector to end y coordinate       #     # check start/end x,y coordinates leaving screen     # if they do, reverse the associated vector value     #       if cline[STARTX] >= SWIDTH - 1:                     # has start x coordinate hit right side of screen?         cline[STARTX] = SWIDTH - 1                      # yes, set start x coordinate to screen width         vector[STARTX] = -vector[STARTX]                # reverse the start x vector value     elif cline[STARTX] <= 0:                            # no, has start x coordinate hit left side of screen?         cline[STARTX] = 0                               # yes, set start x coordinate to minimum width         vector[STARTX] = -vector[STARTX]                # reverse the start x vector value               if cline[STARTY] >= SHEIGHT - 1:                    # has start y coordinate hit bottom of screen?         cline[STARTY] = SHEIGHT - 1                     # yes, set start y coordinate to screen height         vector[STARTY] = -vector[STARTY]                # reverse the start y vector value     elif cline[STARTY] <= 0:                            # no, has stary y coordinate hit top of screen?         cline[STARTY] = 0                               # yes, set start y coordinate to minimum height         vector[STARTY] = -vector[STARTY]                # reverse the start y vector value               if cline[ENDX] >= SWIDTH - 1:                       # has end x coordinate hit right side of screen?         cline[ENDX] = SWIDTH - 1                        # yes, set end x coordinate to screen width         vector[ENDX] = -vector[ENDX]                    # reverse the end x vector value     elif cline[ENDX] <= 0:                              # no, has end x coordinate hit left side of screen?         cline[ENDX] = 0                                 # yes, set end x coordinate to minimum width         vector[ENDX] = -vector[ENDX]                    # reverse the end x vector value               if cline[ENDY] >= SHEIGHT - 1:                      # has end y coordinate hit bottom of screen?         cline[ENDY] = SHEIGHT - 1                       # yes, set end y coordinate to screen height         vector[ENDY] = -vector[ENDY]                    # reverse the end y vector value     elif cline[ENDY] <= 0:                              # no, has end y coordinate hit top of screen?         cline[ENDY] = 0                                 # yes, set end y coordinate to minimum height         vector[ENDY] = -vector[ENDY]                    # reverse the end y vector value       #     # add color increment values to color components     #           cline[RED]   += vector[RED]                         # add red increment to red color component     cline[GREEN] += vector[GREEN]                       # add green increment to green color component     cline[BLUE]  += vector[BLUE]                        # add blue increment to blue color component       #     # if any color component has reached the maximum     # or minimum value reverse the associated     # increment value     #       if cline[RED] == 0 or cline[RED] == 255:            # has red color component exceeded limit?         vector[RED] = -vector[RED]                      # yes, reverse red increment value       if cline[GREEN] == 0 or cline[GREEN] == 255:        # has green color component exceeded limit?         vector[GREEN] = -vector[GREEN]                  # yes, reverse green increment value       if cline[BLUE] == 0 or cline[BLUE] == 255:          # has blue color component exceeded limit?         vector[BLUE] = -vector[BLUE]                    # yes, reverse blue increment value       mline[lcount][:6] = cline[:6]                       # place current line in master line list     #     # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT     #       screen.fill((0, 0, 0))                              # clear the window with a black background       c = lcount                                          # used to draw from last line to first     for i in range(MAXLINES):                           # cycle through all lines         c += 1                                          # count from last line drawn to first         if c == MAXLINES:                               # has the counter reached the limit?             c = 0                                       # yes, reset counter back to beginning         if mline[c][RED] > 0:                           # does this line still contain some red?             mline[c][RED] -= 1                          # yes, fade it away by decrementing value           if mline[c][GREEN] > 0:                         # does this line still contain some green?             mline[c][GREEN] -= 1                        # yes, fade it away by decrementing value           if mline[c][BLUE] > 0:                          # does this line still contain some blue?             mline[c][BLUE] -= 1                         # yes, fade it away vy decrementing value           #         # draw the line from the master line list         #                  pygame.draw.line(screen, (mline[c][RED], mline[c][GREEN], mline[c][BLUE]), (mline[c][STARTX], mline[c][STARTY]), (mline[c][ENDX], mline[c][ENDY]), 1)       pygame.display.flip()                               # updates the window with the newly drawn image       #     # limit main program loop to a number of frames per second     #       clock.tick(FPS)                                     # limit frames per second   pygame.quit()
Reply
#4
Upon playing with the code a little bit more I discovered that all I need in line 249 is this:

mline[lcount][:] = cline

This is even stranger to me. I understand the syntax here, I just don't know why I need to specify [:]
Reply
#5
I don't have enough patience to read through all your code, but lists are one of the only things in python to work using references instead of copying values.  So maybe you were using the same list, with two different variable names?

Creating a slice with [:] would force a copy of the original list, thus actually having two lists instead of one with two references.

>>> items = [0, 1, 2, 3] >>> things = items >>> things.append('carrot') >>> items [0, 1, 2, 3, 'carrot'] >>> things [0, 1, 2, 3, 'carrot'] >>> items is things True >>> things = items[:] >>> items is things False >>> things.append('disco') >>> items [0, 1, 2, 3, 'carrot'] >>> things [0, 1, 2, 3, 'carrot', 'disco']
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Lightbulb What's happening here? jesse68 3 2,158 Feb-27-2023, 04:53 PM
Last Post: Gribouillis
  2 if statements happening at the same time M0TH 3 2,081 Nov-19-2022, 11:37 PM
Last Post: M0TH
  Why is this happening? taner7 3 3,511 Oct-14-2020, 10:11 PM
Last Post: Skaperen
  Binding not explicitly declared happening karkas 4 5,016 Aug-05-2019, 05:09 PM
Last Post: karkas
  Why this python ValueError is not happening aurquiel 2 4,358 Aug-20-2018, 07:17 PM
Last Post: aurquiel

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020
This forum uses Lukasz Tkacz MyBB addons.
Forum use Krzysztof "Supryk" Supryczynski addons.