Apr-17-2017, 04:05 PM
(This post was last modified: Apr-17-2017, 04:05 PM by TerryRitchie.)
A simple little pong game I created using Pygame.
###################################################################################################### #                                                                                                   # #                 ,-.----.           ,-.----.                                                     # #                 \   / \          \   / \                                                    # #                 |  :   \         |  :   \                                                   # #                 |  | .\ :        |  | .\ :  ,---.       ,---,                             # #                 .  : |: |        .  : |: | '  ,'\  ,-+-. / | ,----._,.                 # #                 |  |  \ :   .--, |  |  \ : /  /  | ,--.'|'  | /  / ' /                 # #                 |  : .  / /_ ./| |  : .  /.  ; ,. :|  | ,"' ||  :    |                 # #                 ;  | |`-', ' , ' : ;  | |`-' '  | |: :|  | / | ||  | .\ .                 # #                 |  | ; /___/ \: | |  | ;   '  | .; :|  | | | |.  ; '; |                 # #                 :  ' |  . \ ' | :  ' |   |  :   ||  | | |/ '  .  . |                 # #                 :  : :   \ ;  : :  : :    \  \ / |  | |--'  `---`-'| |                 # #                 |  | :    \ \ ; |  | :     `----' |  |/      .'__/\_: |                 # #                 `---'.|     : \ \`---'.|             '---'       |  :   :   v1.0         # #                   `---`      \ ' ; `---`                           \  \ /                  # #                                `--`                                    `--`-'                   # #                                                                                                   # ###################################################################################################### # PyPong 1.0 # Terry Ritchie # 04/15/17 # ---------------------------------------------------------------------------------------------------- # - IMPORT LIBRARIES --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- import pygame              # pygame graphics engine import random              # random number library import os                  # operating system library import winsound            # windows sound library import sys                 # system functions from pygame.locals import * # pygame constants # ---------------------------------------------------------------------------------------------------- # - DEFINE CONSTANTS --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- SWIDTH = 768               # width of play screen SHEIGHT = 576              # height of play screen FPS = 480                  # frames per second of game play PSIZE = 10                 # width/height of puck PWIDTH = 10                # width of player paddles PHEIGHT = 60               # height of player paddles PSPEED = 480 // FPS        # speed of player paddles and puck POFFSET = 20               # paddle distance from edge of screen PLAYER1 = 0                # player one value PLAYER2 = 1                # player 2 value GAMEINPROGRESS = -1        # denotes game in progress WHITE = (255, 255, 255)    # define constant colors LGRAY = (192, 192, 192) GRAY = (128, 128, 128) BLACK = ( 0,  0,  0) # ---------------------------------------------------------------------------------------------------- # - DEFINE VARIABLES --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- pxdir = 0.0                # puck x direction vector pydir = 0.0                # puck y direction vector puckx = 0.0                # puck x coordinate location pucky = 0.0                # puck y coordinate location p1x = 0.0                  # player 1 x coordinate location p1y = 0.0                  # player 1 y coordinate location p2x = 0.0                  # player 2 x coordinate location p2y = 0.0                  # player 2 y coordinate location pscore = []                # player scores scoretext = []             # big numbers custom strings missed = 0                 # holds value of player that missed puck ai = False                 # True if playing the computer numplayers = 0             # number of human players font = 0                   # font used within game clock = 0                  # clock FPS timer screen = 0                 # window surface players_text = 0           # instruction texts spacebar_text = 0          player1_text = 0 # ---------------------------------------------------------------------------------------------------- # - DEFINE FUNCTIONS --------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- def Draw_Frame(): # draw the current play field                                          Draw_Frame() # ----------------------------------------------------------------------------------------------------    sx = 0     # x coordinate of score digits    sy = 50    # y coordinate of score digits    clr = 0    # color of score digits    screen.fill(BLACK)    pygame.draw.rect(screen, WHITE, (0, 19, SWIDTH, 10), 0)                # draw top and    pygame.draw.rect(screen, WHITE, (0, SHEIGHT - 29, SWIDTH, 10), 0)      # bottom lines    for y in range(40, SHEIGHT - 52, 30):                                  # draw dashed line        pygame.draw.rect(screen, GRAY, (SWIDTH // 2 - 5, y, 10, 15), 0)    for p in range(PLAYER1, PLAYER2 + 1):                                  # draw score digits        if p == 0:            sx = SWIDTH // 2 - 100        else:            sx = SWIDTH // 2 + 55        if pscore[p] == 9:            clr = WHITE        else:            clr = LGRAY        Draw_Digit(sx, sy, pscore[p], clr)    pygame.draw.rect(screen, WHITE, (p1x, p1y, PWIDTH, PHEIGHT), 0)        # draw paddles    pygame.draw.rect(screen, WHITE, (p2x, p2y, PWIDTH, PHEIGHT), 0)    if missed == GAMEINPROGRESS:                                           # if game in progress        pygame.draw.rect(screen, WHITE, (puckx, pucky, PSIZE, PSIZE), 0)   # draw puck        pygame.display.flip()                                              # and update screen        clock.tick(FPS) # ---------------------------------------------------------------------------------------------------- def Instructions(): # display game instructions to player                              Instructions() # ----------------------------------------------------------------------------------------------------    global ai, numplayers, pscore  # need to modify these globals    fcount = 0         # frame counter    blink = True       # show "press spacebar" when True    waiting = True     # wait for spacebar to be pressed    numplayers = 0     # number of human players    ready = 4          # countdown timer    player2_text = font.render("SELECT (1) OR (2) PLAYERS NOW", True, WHITE)    while ready > 0:        Play_Round()                               # draw frame        if waiting:            pygame.event.pump()                    # clear keyboard buffer            keys = pygame.key.get_pressed()        # get keys currently held down            if keys[K_SPACE] and numplayers:       # spacebar key                waiting = False                fcount = FPS * 3 + 1               # countdown sequence value            if keys[K_ESCAPE]:                     # ESC key                pygame.quit()                sys.exit()            if keys[K_1] and numplayers != 1:      # number 1 key                numplayers = 1                ai = True                          # computer will be player 2                winsound.Beep(440, 55)                winsound.Beep(880, 55)                player2_text = font.render("PLAYER 2: THE CPU HAS CONTROL", True, WHITE)            if keys[K_2] and numplayers != 2:      # number 2 key                numplayers = 2                ai = False                         # human will be player 2                winsound.Beep(440, 55)                winsound.Beep(880, 55)                player2_text = font.render("PLAYER 2: UP ARROW / DOWN ARROW", True, WHITE)            if numplayers > 0:                     # show blinking "press spacebar"                fcount += 1                if fcount == FPS:                    fcount = 0                    blink = not(blink)                if blink:                    screen.blit(spacebar_text, [(SWIDTH - 178) // 2, SHEIGHT - 17])            screen.blit(players_text, [(SWIDTH - 306) / 2, 2])            screen.blit(player1_text, [(SWIDTH // 2 - 197) // 2, (SHEIGHT - 18) // 2])            screen.blit(player2_text, [(SWIDTH // 2) + ((SWIDTH // 2) - 220) // 2, (SHEIGHT - 18) // 2])        else:                                      # countdown sequence            pscore[PLAYER1] = 0            pscore[PLAYER2] = 0            fcount -= 1            if fcount % FPS == 0:                  # keep track of each second elapsed                winsound.Beep(ready * 220, 55)                ready -= 1            Draw_Digit((SWIDTH - 45) // 2, (SHEIGHT - 75) //2, ready, WHITE)        pygame.display.flip()        clock.tick(FPS) # ---------------------------------------------------------------------------------------------------- def New_Game(): # new game initialization                                                  New_Game() # ----------------------------------------------------------------------------------------------------    global p1x, p1y, p2x, p2y, missed, ai, numplayers          # need to modify these globals    winsound.Beep(440, 55)                                     # intro sounds    winsound.Beep(880, 55)    missed = PLAYER2                                           # serve to player 2    ai = False                                                 # assume two human players    numplayers = 0    p1x = POFFSET                                              # reset paddle locations    p1y = SHEIGHT // 2 - PHEIGHT // 2    p2x = SWIDTH - POFFSET - PWIDTH    p2y = SHEIGHT // 2 - PHEIGHT // 2 # ---------------------------------------------------------------------------------------------------- def Reset_Round(): # resets the condition for the next round of play                    Reset_Round() # ----------------------------------------------------------------------------------------------------    global pxdir, pydir, puckx, pucky, missed                  # need to modify these globals    pucky = random.randrange(50, SHEIGHT - 50)                 # random puck y coordinate    pydir = ((random.random() - random.random()) / 2) * PSPEED # and vertical direction    if missed == PLAYER1:                                      # set puck heading toward player 1        pxdir = -0.5 * PSPEED        puckx = SWIDTH * .75    else:                                                      # set puck heading toward player 2        pxdir = 0.5 * PSPEED        puckx = SWIDTH * .25    missed = GAMEINPROGRESS                                    # put game back into play # ---------------------------------------------------------------------------------------------------- def Draw_Digit(dx, dy, d, c): # draw a large digit to the screen                         Draw_Digit() # ----------------------------------------------------------------------------------------------------    # dx = digit top left x coordinate    # dy = digit top left y coordinate    # d = digit (0 - 9)    # c = digit color    # The large digits are drawn as follows:    #    #             x    #         ---------    #         0  1  2    #       +---+---+---+     +---+---+---+  If there is a character (non-space) in the text a    #   | 0 | * | * | * |     | * | * | * |  square is drawn in that position. As the nested for    #   |  +---+---+---+     +---+---+---+  statements progress a number is drawn from the text    #   | 1 | * |  | * |     |  |  | * |  that describes where a square should be placed in    #   |  +---+---+---+     +---+---+---+  each row.    # y | 2 | * |  | * |     | * | * | * |    #   |  +---+---+---+     +---+---+---+    #   | 3 | * |  | * |     |  |  | * |    #   |  +---+---+---+     +---+---+---+    #   | 4 | * | * | * |     | * | * | * |    #   |  +---+---+---+     +---+---+---+    #    #     "0000 00 00 0000" "333 3333 3333"    #      |||---|||---|||   |||---|||---|||    # Row-> 0 1 2 3 4     0 1 2 3 4    p = -1                                     # current position in text string    for y in range(5):        for x in range(3):            p += 1                             # increment text position            if scoretext[d][0][p] != " ":      # if there is a character in text position draw square                pygame.draw.rect(screen, c, [dx + x * 15, dy + y * 15, 15, 15], 0) # ---------------------------------------------------------------------------------------------------- def Setup(): # creates the assets needed to play the game                                     Setup() # ----------------------------------------------------------------------------------------------------    global scoretext, font, players_text, spacebar_text, pscore, clock, screen # need to modify these    global player1_text    os.environ["SDL_VIDEO_CENTERED"] = "1"             # tell pygame to center the surface on desktop    pygame.init()                                      # start pygame engine    screen = pygame.display.set_mode((SWIDTH, SHEIGHT)) # create the surface window    pygame.display.set_caption("PyPong!")              # give window a caption    clock = pygame.time.Clock()                        # start clock routines    pscore.append([0])                                 # create player score list    pscore.append([0])    pscore[PLAYER1] = 0    pscore[PLAYER2] = 0    scoretext.append(["0000 00 00 0000"])              # create big number strings list    scoretext.append([" 1 1 1 1 1"])    scoretext.append(["222 22222 222"])    scoretext.append(["333 3333 3333"])    scoretext.append(["4 44 4444 4 4"])    scoretext.append(["5555 555 5555"])    scoretext.append(["6666 6666 6666"])    scoretext.append(["777 7 7 7 7"])    scoretext.append(["8888 88888 8888"])    scoretext.append(["9999 9999 9999"])    font = pygame.font.SysFont("Calibri", 16, False, False)    players_text = font.render("SELECT (1) or (2) PLAYERS NOW : ESC TO EXIT", True, WHITE)    spacebar_text = font.render("PRESS SPACEBAR TO PLAY", True, WHITE)    player1_text = font.render("PLAYER 1: W = UP / S = DOWN", True, WHITE) # ---------------------------------------------------------------------------------------------------- def Trajectory(playery): # calculates angle of puck trajectory                           Trajectory() # ----------------------------------------------------------------------------------------------------    # playery = player's y coordinate location    return (((pucky - playery) + PSIZE - (PHEIGHT + PSIZE) // 2) / ((PHEIGHT + PSIZE) / 2)) / 2 # ---------------------------------------------------------------------------------------------------- def sgn(n): # returns the sign of a number (-1, 0, or 1                                         sgn() # ----------------------------------------------------------------------------------------------------    # n = any numeric value       if n > 0:        return 1    elif n < 0:        return -1    else:        return 0 # ---------------------------------------------------------------------------------------------------- def Play_Round(): # plays a round of PyPong                                              Play_Round() # ----------------------------------------------------------------------------------------------------    global pxdir, pydir, puckx, pucky, p1x, p1y, p2x, p2y, pscore, missed, ai  # need to modify these    for event in pygame.event.get():                       # cycle through events        if event.type == pygame.QUIT:                      # leave game if window closed            pygame.quit()            sys.exit()    pygame.event.pump()                                    # clear keyboard buffer    keys = pygame.key.get_pressed()                        # key all keys currently pressed    if keys[K_ESCAPE]:                                     # ESC key        pygame.quit()        sys.exit()    if keys[K_w]:                                          # W key        p1y -= PSPEED    if keys[K_s]:                                          # S key        p1y += PSPEED    if ai:                                                 # computer controls player 2        v_speed = ((1 + random.random()) / (PSPEED * 2)) * PSPEED        if pxdir > 0:                                      # puck heading toward computer            puck_location = pucky - p2y - PHEIGHT // 2 + PSIZE // 2            if puck_location < 0:                p2y -= v_speed            elif puck_location > 0:                p2y += v_speed        else:                                              # puck heading toward player 1            if int(p2y) > SHEIGHT // 2 - PHEIGHT //2:                p2y -= v_speed            elif int(p2y) < SHEIGHT //2 - PHEIGHT //2:                p2y += v_speed    else:                                                  # human controls player 2        if keys[K_DOWN]:                                   # DOWN ARROW key            p2y += PSPEED        if keys[K_UP]:                                     # UP ARROW key            p2y -= PSPEED    if p1y <= 30:                                          # keep player 1 paddle within limits        p1y = 30    if p1y >= SHEIGHT - PHEIGHT - 30:        p1y = SHEIGHT - PHEIGHT - 30    if p2y <= 30:                                          # keep player 2 paddle within limits        p2y = 30    if p2y >= SHEIGHT - PHEIGHT - 30:        p2y = SHEIGHT - PHEIGHT - 30    if missed == GAMEINPROGRESS:                           # is there a game in progress?        puckx += pxdir                                     # update puck position        pucky += pydir        if pucky <= 30:                                    # keep puck in vertical limits            pucky = 30            pydir = -pydir            winsound.Beep(880, 55)        elif pucky >= SHEIGHT - PSIZE - 30:            pucky = SHEIGHT - PSIZE - 30            pydir = -pydir            winsound.Beep(880, 55)        if puckx <= p1x:                                   # player 1 missed puck            pscore[PLAYER2] += 1            missed = PLAYER1            winsound.Beep(220, 55)        elif puckx >= p2x + PWIDTH:                        # player 2 missed puck            pscore[PLAYER1] += 1            missed = PLAYER2            winsound.Beep(220, 55)        else:            if puckx <= p1x + PWIDTH:                        if pucky - p1y >= -PSIZE:                    if pucky - p1y <= PHEIGHT:             # player 1 hit puck                        puckx = p1x + PWIDTH                        pxdir = -pxdir + (.025 * PSPEED)                        pydir += Trajectory(p1y)           # update puck trajectory                        if abs(pydir) > PSPEED:                            pydir = sgn(pydir) * PSPEED                        winsound.Beep(440, 55)            if puckx + PSIZE >= p2x:                if pucky - p2y + PSIZE >= 0:                    if pucky - p2y <= PHEIGHT:             # player 2 hit puck                        puckx = p2x - PSIZE                        pxdir = -pxdir - (.025 * PSPEED)                        pydir += Trajectory(p2y)           # update puck trajectory                        if abs(pydir) > PSPEED:                            pydir = sgn(pydir) * PSPEED                        winsound.Beep(440, 55)    Draw_Frame()                                           # draw screen # ---------------------------------------------------------------------------------------------------- # - MAIN PROGRAM LOOP -------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------- Setup()                                                    # create game assets while True:                                                # loop forever    New_Game()                                             # set up a new game    Instructions()                                         # display instructions to player(s)    while pscore[PLAYER1] != 9 and pscore[PLAYER2] != 9:   # loop until one player scores 9        Reset_Round()                                      # set up a new round of play        while missed == GAMEINPROGRESS:                    # loop while a round in progress            Play_Round()                                   # play the round