The pong ball is just stopped in the initial point by unknown issue

Viewed 59

I am new to Pygame, and doing a assigned homework. I tried to make an program called Pong by python3. The ball was moving correctly, but after I write something new in the program, the ball just stopped at the initial point. I already check many times of my code, but I can't find what's wrong with it. Here is my code below:

# Pong Version 2
# Display the ball and both paddles, with the ball bouncing from the window edges. 
# The ball bounce off the paddles. It go through the back of paddles. 
# The paddles do not move, but score is updated.
# The game ends when a score is 11 or until the player closes the window.

import pygame, random

def main():
   # initialize all pygame modules (some need initialization)
   pygame.init()
   # create a pygame display window
   pygame.display.set_mode((1000, 800))
   # set the title of the display window
   pygame.display.set_caption('Pong')
   # get the display surface
   w_surface = pygame.display.get_surface() 
   # create a game object
   game = Game(w_surface)
   #init text
   pygame.font.init()
   # start the main game loop by calling the play method on the game object
   game.play() 
   # quit pygame and clean up the pygame window
   pygame.quit() 

class Game:
   # An object in this class represents a complete game.

   def __init__(self, surface):
      # Initialize a Game.
      # - self is the Game to initialize
      # - surface is the display window surface object

      # === objects that are part of every game that we will discuss
      self.surface = surface
      self.bg_color = pygame.Color('black')

      self.FPS = 60
      self.game_Clock = pygame.time.Clock()
      self.close_clicked = False
      self.continue_game = True

      self.num_board1 = '0'
      self.num_board2 = '0'
      # === game specific objects

      #ball elements
      #(ball_color,ball_radius,ball_center,ball_velocity,surface)
      self.ball = Ball('white', 10, [500, 400], [10,20], self.surface)

      #rectangle elements
      #(rect_left_top,rect_width_height,rect_surface,rect_color)
      self.paddle1 = Rect((150,350),(10,100),self.surface,'white')
      self.paddle2 = Rect((840,350),(10,100),self.surface,'white')

      #board elements
      #(name,size,content,color,center,screen)
      #board size is (57,104)
      self.board1 = Board("",150,self.num_board1,(100,100,100),(10,10),self.surface)
      self.board2 = Board("",150,self.num_board2,(100,100,100),(933,10),self.surface)            

   def play(self):
      # Play the game until the player presses the close box.
      # - self is the Game that should be continued or not.
      while not self.close_clicked:  # until player clicks close box
         # play frame
         self.handle_events()
         self.draw()            
         if self.continue_game:
            self.update()
            self.decide_continue()
         self.game_Clock.tick(self.FPS) # run at most with FPS Frames Per Second 

   def handle_events(self):
      # Handle each user event by changing the game state appropriately.
      # - self is the Game whose events will be handled
      events = pygame.event.get()
      for event in events:
         if event.type == pygame.QUIT:
            self.close_clicked = True

   def draw(self):
      # Draw all game objects.
      # - self is the Game to draw      

      self.surface.fill(self.bg_color) # clear the display surface first
      # Draw game elements ball
      self.ball.draw()
      # Draw game elements paddles
      self.paddle1.draw()
      self.paddle2.draw()
      # Draw game elements boards
      self.board1.draw()
      self.board2.draw()      
      pygame.display.update() # make the updated surface appear on the display

   def update(self):
      # Update the game objects.
      # - self is the Game to update
      self.ball.move()

   def decide_continue(self):
      # Check and remember if the game should continue
      # - self is the Game to check
      pass
      if self.num_board1 or self.num_board2 == '11':
         self.continue_game = False

class Ball:
   # An object in this class represents a ball that moves 
   def __init__(self, ball_color, ball_radius, ball_center, ball_velocity, surface):
      # Initialize a ball.
      # - self is the ball to initialize
      # - color is the pygame.Color of the ball
      # - center is a list containing the x and y int
      #   coords of the center of the ball
      # - radius is the int pixel radius of the ball
      # - velocity is a list containing the x and y components
      # - surface is the window's pygame.Surface object
      self.color = pygame.Color(ball_color)
      self.radius = ball_radius
      self.center = ball_center
      self.velocity = ball_velocity
      self.surface = surface

   def move(self):
      # Change the location of the ball by adding the corresponding 
      # speed values to the x and y coordinate of its center
      # - self is the ball
      size = self.surface.get_size() # size is a tuple (width,height)      
      for index in range(0,2):
         self.center[index] = self.center[index] + self.velocity[index]
         if self.center[index] < self.radius: # left or top
            self.velocity[index] = -self.velocity[index] # bounce the ball
         if self.center[index]+ self.radius > size[index]:# right of bottom
            self.velocity[index] = -self.velocity[index] # bounce the ball     

   def draw(self):
      # Draw the ball on the surface
      # - self is the ball
      pygame.draw.circle(self.surface, self.color, self.center, self.radius)


class Rect:
   def __init__(self,rect_left_top,rect_width_height,rect_surface,rect_color):
      #set elements
      # - rect_left_top is the distance from edge
      # - rect_width_height is width and height of the rectangle
      # - rect_surface is the surface of rectangle
      # - rect_color is color of the rectangle
      self.left_top = rect_left_top
      self.width_height = rect_width_height
      self.surface = rect_surface
      self.color = pygame.Color(rect_color)
      self.rect = (self.left_top,self.width_height)

   def draw(self): 
      # draw the rectangle
      pygame.draw.rect(self.surface,self.color,self.rect)  


class Board:
   def __init__(self,name,size,content,color,text_left_right,surface):
      # - name is the typeface of the text
      # - size is the size of the text
      # - content is the content fo the text 
      # - color is the color of text, it looks like (x,x,x), which is combined by three basic color)
      # - text_left_right is a the left and right distance from edge
      # - surface is a the display.set_mode, used to blit text
      self.name = name
      self.size = size
      self.content = content
      self.color = color
      self.text_left_right = text_left_right
      self.surface = surface

   def draw(self):
      #to show the text
      font = pygame.font.SysFont(self.name,self.size)
      text = font.render(self.content,True,self.color)
      self.surface.blit(text,self.text_left_right)

main()
2 Answers

The problem with decide_continue method.

When I remove call of decide_continue from play method ball start moving:

   def play(self):
      # Play the game until the player presses the close box.
      # - self is the Game that should be continued or not.
      while not self.close_clicked:  # until player clicks close box
         # play frame
         self.handle_events()
         self.draw()
         if self.continue_game:
            self.update()

         self.game_Clock.tick(self.FPS) # run at most with FPS Frames Per Second

So the problem with decide_continue method. You should review it.

Going by the test done by Yurii (see other answer), since you didn't mention which change you had made before the program didn't work properly anymore.

decide_continue(self) has the following if-clause:

if self.num_board1 or self.num_board2 == '11':

This means it evaluates whether self.num_board1 is equivalent to True (i.e., not False, 0, empty string and the like), which is probably always the case, or it compares self.num_board2 to the string '11'.

Important note: the string '0', the initial value for the boards, does not evaluate to False: it's not an empty string, nor an integer 0.

Because of the first condition, this if-statement will practically always evaluate in being true.

You probably want:

if self.num_board1 == '11' or self.num_board2 == '11':

or something like that. You should also consider whether you want a '11' string, or that this should be a number (integer) instead, given that you call the variable num_board.

Further, since no manipulations with num_board1/2 appear to be done, it's value will likely never change from the initial value '0', in which case it'll, at this moment, never be equal to '11'.

Related