Search code examples
python-3.xfiletextpygamepong

How to display text onto a pygame screen from a text file?


I'm attempting to display instructions for a game from a text file in a pygame screen. At this point, I have coded this:

def instructions():
    screen.fill(TEAL)
    with open("pongInstructions.txt", encoding = 'utf-8') as f:
        for line in f:
            instructText = instructionsFont.render(line, True, WHITE)
            screen.blit(instructText, ((400 - (instructText.get_width()/2)),(300 - (instructText.get_height()/2))))
            pygame.display.update()

When I call upon the instructions function, nothing happens at all. Does anybody have an idea as to why? Any help is greatly appreciated!

EDIT:

#Imports and Initialize Pygame Screen
import pygame
import sys
import time
import random
import codecs

pygame.init()
screenSize = (800,600)
screen = pygame.display.set_mode((screenSize),0)
pygame.display.set_caption("Tasnim's Pong")

instructionsFile = [line.strip('\n')
    for line in open('pongInstructions.txt', 'r', encoding = 'utf-8').readlines()]
font = pygame.font.SysFont("americantypewriter", 16)

def instructions(screen):
    screen.fill(TEAL)
    for n, line in enumerate(instructionsFile):
        text = font.render(line, 1, WHITE)
        text_rect = text.get_rect()
        text_rect.centerx = screenSize[0]//2
        text_rect.centery = n*25 + 50
        screen.blit(text, text_rect)
        pygame.display.update()

#Define Colours
WHITE = (255,255,255)
BLUE = (0,0,255)
BLACK = (0,0,0)
GRAY = (128, 128, 128)
MAROON = (128, 0, 0)
NAVYBLUE = (0, 0, 128)
OLIVE = (128, 128, 0)
PURPLE = (128, 0, 128)
TEAL = (0,128,128)
PINK = (226,132,164)
MUTEDBLUE = (155,182,203)
PLUM = (221,160,221)

#All Fonts
startscreenTitleFont =  pygame.font.SysFont("americantypewriter", 120)
startscreenPlayerChoiceFont = pygame.font.SysFont("americantypewriter", 60)
startscreenQuitFont = ("americantypewriter", 60)
startscreenCreditsFont = ("americantypewriter", 60)
instructionsFont = pygame.font.SysFont("americantypewriter",60)
quitFont = pygame.font.SysFont("americantypewriter",60)
maingameP1ScoreFont = pygame.font.SysFont("americantypewriter",70)
maingameP2ScoreFont = pygame.font.SysFont("americantypewriter",70)
maingamePlayerOneFont = pygame.font.SysFont("americantypewriter",50)
maingamescoreFont  = pygame.font.SysFont("americantypewriter",25, bold = True)
winnerFont = pygame.font.SysFont("americantypewriter",25)

instructionsFile = [line.strip('\n')
    for line in open('pongInstructions.txt', 'r', encoding = 'utf-8').readlines()]
font = pygame.font.SysFont("americantypewriter", 16)



#Introduction Screen
def startscreen():
    go = True
    choice = 1

    screen.fill(MUTEDBLUE)

    pygame.display.update()
    pongTitle = startscreenTitleFont.render("Pong", True, WHITE)
    screen.blit(pongTitle,((400 - (pongTitle.get_width()/2)),0))

    playerchoiceTitle = startscreenPlayerChoiceFont.render("Two Player Game", True, WHITE)
    screen.blit(playerchoiceTitle, ((400 - (playerchoiceTitle.get_width()/2)),160))

    playerchoice2Title = startscreenPlayerChoiceFont.render("One Player Game", True, WHITE)
    screen.blit(playerchoice2Title, ((400 - (playerchoice2Title.get_width()/2)),275))

    instructionsTitle = instructionsFont.render("How To Play", True, WHITE)
    screen.blit(instructionsTitle, ((400 - (instructionsTitle.get_width()/2)),390))

    quitgameTitle = quitFont.render("Quit", True, WHITE)
    screen.blit(quitgameTitle, ((400 - (quitgameTitle.get_width()/2)),495))


    pygame.display.update()

#Choices for Introduction Screen
    while go:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                go = False

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    if choice != 1:
                        choice = choice - 1
                elif event.key == pygame.K_DOWN:
                    if choice != 4:
                        choice = choice + 1

                elif event.key == pygame.K_RETURN:
                    if choice == 1:
                        playTwoPlayer()
                    elif choice == 2:
                        playOnePlayer()                        
                    elif choice == 3:
                        instructions()
                    elif choice == 4:
                        quitGame()

        if choice == 1:
            screen.fill(MUTEDBLUE)

            pongTitle = startscreenTitleFont.render("Pong", True, WHITE)
            screen.blit(pongTitle,((400 - (pongTitle.get_width()/2)),0))

            playerchoiceTitle = startscreenPlayerChoiceFont.render("Two Player Game", True, NAVYBLUE)
            screen.blit(playerchoiceTitle, ((400 - (playerchoiceTitle.get_width()/2)),160))

            playerchoice2Title = startscreenPlayerChoiceFont.render("One Player Game", True, WHITE)
            screen.blit(playerchoice2Title, ((400 - (playerchoice2Title.get_width()/2)),275))

            instructionsTitle = instructionsFont.render("How To Play", True, WHITE)
            screen.blit(instructionsTitle, ((400 - (instructionsTitle.get_width()/2)),390))

            quitgameTitle = quitFont.render("Quit", True, WHITE)
            screen.blit(quitgameTitle, ((400 - (quitgameTitle.get_width()/2)),495))

        elif choice == 2:
            screen.fill(MUTEDBLUE)

            pongTitle = startscreenTitleFont.render("Pong", True, WHITE)
            screen.blit(pongTitle,((400 - (pongTitle.get_width()/2)),0))

            playerchoiceTitle = startscreenPlayerChoiceFont.render("Two Player Game", True, WHITE)
            screen.blit(playerchoiceTitle, ((400 - (playerchoiceTitle.get_width()/2)),160))

            playerchoice2Title = startscreenPlayerChoiceFont.render("One Player Game", True, NAVYBLUE)
            screen.blit(playerchoice2Title, ((400 - (playerchoice2Title.get_width()/2)),275))

            instructionsTitle = instructionsFont.render("How To Play", True, WHITE)
            screen.blit(instructionsTitle, ((400 - (instructionsTitle.get_width()/2)),390))

            quitgameTitle = quitFont.render("Quit", True, WHITE)
            screen.blit(quitgameTitle, ((400 - (quitgameTitle.get_width()/2)),495))

        elif choice == 3:
            screen.fill(MUTEDBLUE)

            pongTitle = startscreenTitleFont.render("Pong", True, WHITE)
            screen.blit(pongTitle,((400 - (pongTitle.get_width()/2)),0))

            playerchoiceTitle = startscreenPlayerChoiceFont.render("Two Player Game", True, WHITE)
            screen.blit(playerchoiceTitle, ((400 - (playerchoiceTitle.get_width()/2)),160))

            playerchoice2Title = startscreenPlayerChoiceFont.render("One Player Game", True, WHITE)
            screen.blit(playerchoice2Title, ((400 - (playerchoice2Title.get_width()/2)),275))

            instructionsTitle = instructionsFont.render("How To Play", True, NAVYBLUE)
            screen.blit(instructionsTitle, ((400 - (instructionsTitle.get_width()/2)),390))

            quitgameTitle = quitFont.render("Quit", True, WHITE)
            screen.blit(quitgameTitle, ((400 - (quitgameTitle.get_width()/2)),495))

        if choice == 4:
            screen.fill(MUTEDBLUE)

            pongTitle = startscreenTitleFont.render("Pong", True, WHITE)
            screen.blit(pongTitle,((400 - (pongTitle.get_width()/2)),0))

            playerchoiceTitle = startscreenPlayerChoiceFont.render("Two Player Game", True, WHITE)
            screen.blit(playerchoiceTitle, ((400 - (playerchoiceTitle.get_width()/2)),160))

            playerchoice2Title = startscreenPlayerChoiceFont.render("One Player Game", True, WHITE)
            screen.blit(playerchoice2Title, ((400 - (playerchoice2Title.get_width()/2)),275))

            instructionsTitle = instructionsFont.render("How To Play", True, WHITE)
            screen.blit(instructionsTitle, ((400 - (instructionsTitle.get_width()/2)),390))

            quitgameTitle = quitFont.render("Quit", True, NAVYBLUE)
            screen.blit(quitgameTitle, ((400 - (quitgameTitle.get_width()/2)),495))

            pygame.display.update()

        pygame.display.update()

#Two Player Game
def playTwoPlayer():
    screen.fill(MUTEDBLUE)
    play = True
    startballSPACE = True

#Two Player Game- Set Variables
    playeroneScore = 0
    playertwoScore = 0

    ballx = 400
    bally = 350
    balldx = 0
    balldy = 0
    xOne = 775
    yOne = 275 
    xTwo = 0
    yTwo = 275
    dyOne = 0
    dyTwo = 0
    heightPaddleoneandtwo = 150
    paddleheight = 150

    go = True
    while go:

        if playeroneScore == 3:
            winnerPlayerOne()

        if playertwoScore == 3:
            winnerPlayerTwo()

        balldxdir = random.choice([-5,5])
        balldydir = random.choice([-5,5])

        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                quitGame()

            elif event.type == pygame.KEYDOWN:

 #Controls for player one- Up and Down key               
                if event.key == pygame.K_UP:
                    dyOne = -10
                    directiony = 3
                elif event.key == pygame.K_DOWN:
                    dyOne = 10
                    directiony = 4

 #Controls for player two- W and S key 
                elif event.key == pygame.K_w:
                    dyTwo = -10
                    directionyTWO = 2
                elif event.key == pygame.K_s:
                    dyTwo = 10
                    directionyTWO = 1
#Controls to quit
                elif event.key == pygame.K_q:
                    startscreen()

#Controls to start game (press space bar)
                elif startballSPACE == True:
                    if event.key == pygame.K_SPACE:
                        play = True
                        balldx = balldxdir
                        balldy = balldydir
                        startballSPACE = False

            if event.type == pygame.KEYUP:

                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    dyOne = 0
                    directiony = 0

                elif event.key == pygame.K_w or event.key == pygame.K_s: 
                    dyTwo = 0
                    directionyTWO = 0

        screen.fill(MUTEDBLUE)

#Paddle Positioning
        yOne = yOne + dyOne
        yTwo =yTwo + dyTwo

#Screen Top and Bottom Collision Check       
        if yOne > (600 - heightPaddleoneandtwo) and directiony == 4:
            dyOne = 0
            yOne = (600 - heightPaddleoneandtwo)

        if yOne < 100 and directiony == 3:
            dyOne = 0
            yOne = 100

        if yTwo > (600 - heightPaddleoneandtwo) and directionyTWO == 1:
            dyTwo = 0
            yTwo = (600 - heightPaddleoneandtwo)

        if yTwo < 100 and directionyTWO == 2:
            dyTwo = 0
            yTwo = 100

#Makes Ball Bounce in opposite direction
        if play == True:
            if ballx == xOne and bally <= (yOne + heightPaddleoneandtwo) and bally >= yOne:
                balldx = -balldx

#Makes Paddle Shorter on collisions with ball (makes game tougher)
                if heightPaddleoneandtwo >= 10:
                    heightPaddleoneandtwo = heightPaddleoneandtwo - 7
                else:                   
                    heightPaddleoneandtwo = heightPaddleoneandtwo

#Makes Ball Bounce in opposite direction            
            elif bally >= 580:
                balldy = -balldy
            elif ballx == (xTwo + 25) and bally <= (yTwo + heightPaddleoneandtwo) and bally >= yTwo:
                balldx = -balldx

#Makes Paddle Shorter on collisions with ball (makes game tougher)
                if heightPaddleoneandtwo >= 10:
                    heightPaddleoneandtwo = heightPaddleoneandtwo - 7
                else:
                    heightPaddleoneandtwo = heightPaddleoneandtwo

            elif bally <= 110:
                balldy = -balldy

            elif ballx<0 or ballx>800:

#Adds score if ball passes paddle                
                 if ballx>800:
                      playeroneScore = playeroneScore + 1
                      startballSPACE = True
                 elif ballx < 0:
                      startballSPACE = True
                      playertwoScore = playertwoScore + 1
                 ballx = 400
                 bally = 350
                 balldx = 0
                 balldy = 0
                 yOne = 275
                 y2Two = 275
                 heightPaddleoneandtwo = 150
                 play = False

            ballx = ballx + balldx
            bally = bally - balldy

#Draw all screen components
        pygame.draw.rect(screen, WHITE,(xOne, yOne, 25, heightPaddleoneandtwo),0)
        pygame.draw.rect(screen, WHITE,(xTwo, yTwo, 25, heightPaddleoneandtwo),0)

        pygame.draw.circle (screen, WHITE, (ballx,bally), 10, 0)

        textScore = maingamescoreFont.render("Score", True, WHITE)
        screen.blit(textScore, (((800/2)-(textScore.get_width()/2),0)))

        textPlayeroneScore = maingameP1ScoreFont.render(str(playeroneScore), True, WHITE)
        screen.blit(textPlayeroneScore, (0,0))

        textPlayertwoScore = maingameP2ScoreFont.render(str(playertwoScore), True, WHITE)
        screen.blit(textPlayertwoScore, ((800 - textPlayertwoScore.get_width()),0))

        pygame.draw.rect (screen, WHITE, (0,90,800,10),0)

        pygame.draw.rect (screen, WHITE, (395,112,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,162,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,212,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,262,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,312,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,362,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,412,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,462,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,512,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,562,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,612,10,25),0)

        pygame.draw.rect (screen, WHITE, (45,0,3,100),0)
        pygame.draw.rect (screen, WHITE, (752,0,3,100),0)

        playerOneText = maingamePlayerOneFont.render("Player 1", True, WHITE)
        playerTwoText = maingamePlayerOneFont.render("Player 2", True, WHITE)
        screen.blit(playerOneText, (70,15))
        screen.blit(playerTwoText, (525,15))

        pygame.display.update()

def instructions():
    screen.fill(TEAL)
    for n, line in enumerate(instructionsFile):
        text = font.render(line, 1, WHITE)
        text_rect = text.get_rect()
        text_rect.centerx = screenSize[0]//2
        text_rect.centery = n*25 + 50
        screen.blit(text, text_rect)
        pygame.display.update()

def winnerPlayerOne():
    screen.fill(TEAL)
    winnerP1Message = winnerFont.render("Congrats Player 1. You Win! Press 'c' to continue", True, WHITE)
    screen.blit(winnerP1Message, ((400 - (winnerP1Message.get_width()/2)),(300 - (winnerP1Message.get_height()/2))))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quitGame()               
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_c:
                startscreen()

def winnerPlayerTwo():
    screen.fill(TEAL)
    winnerP2Message = winnerFont.render("Congrats Player 2. You Win! Press 'c' to continue", True, WHITE)
    screen.blit(winnerP2Message, ((400 - (winnerP2Message.get_width()/2)),(300 - (winnerP2Message.get_height()/2))))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quitGame()               
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_c:
                startscreen()

def CPUwinner():
    screen.fill(TEAL)
    computerWinner = winnerFont.render("Better luck next time... The computer has won! Press 'c' to continue", True, WHITE)
    screen.blit(computerWinner, ((400 - (computerWinner.get_width()/2)),(300 - (computerWinner.get_height()/2))))
    pygame.display.update()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quitGame()               
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_c:
                startscreen()

def quitGame():
    pygame.quit()
    sys.exit()

def playOnePlayer():
    screen.fill(MUTEDBLUE)
    play = True
    startballSPACE = True

#One Player Game- Set Variables
    playeroneScore = 0
    playertwoScore = 0

    ballx = 400
    bally = 350
    balldx = 0
    balldy = 0
    xOne = 775
    yOne = 275 
    xTwo = 0
    yTwo = 275
    dyOne = 0
    dyTwo = 0
    heightPaddleoneandtwo = 150
    paddleheight = 150

    go = True
    while go:

        if playeroneScore == 3:
            winnerPlayerOne()

        if playertwoScore == 3:
            CPUwinner()

        balldxdir = random.choice([-5,5])
        balldydir = random.choice([-5,5])

        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                quitGame()

            elif event.type == pygame.KEYDOWN:

 #Controls for player one- Up and Down key               
                if event.key == pygame.K_UP:
                    dyTwo = -10
                    directiony = 3
                elif event.key == pygame.K_DOWN:
                    dyTwo = 10
                    directiony = 4

#Controls to quit
                elif event.key == pygame.K_q:
                    startscreen()

#Controls to start game (press space bar)
                elif startballSPACE == True:
                    if event.key == pygame.K_SPACE:
                        play = True
                        balldx = balldxdir
                        balldy = balldydir
                        startballSPACE = False

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    dyTwo = 0
                    directionyTWO = 0

        screen.fill(MUTEDBLUE)

#Paddle Positioning
        yTwo = yTwo + dyTwo
        yOne = bally - (heightPaddleoneandtwo/2)

#Screen Top and Bottom Collision Check       
        if yOne > (600 - heightPaddleoneandtwo):
            dyOne = 0
            yOne = (600 - heightPaddleoneandtwo)

        if yOne < 100:
            dyOne = 0
            yOne = 100

        if yTwo > (600 - heightPaddleoneandtwo) and directiony == 4:
            dyTwo = 0
            yTwo = (600 - heightPaddleoneandtwo)

        if yTwo < 100 and directiony == 3:
            dyTwo = 0
            yTwo = 100

#Makes Ball Bounce in opposite direction
        if play == True:
            if ballx == xOne and bally <= (yOne + heightPaddleoneandtwo) and bally >= yOne:
                balldx = -balldx

#Makes Paddle Shorter on collisions with ball (makes game tougher)
                if heightPaddleoneandtwo >= 10:
                    heightPaddleoneandtwo = heightPaddleoneandtwo - 7
                else:                   
                    heightPaddleoneandtwo = heightPaddleoneandtwo                    

#Makes Ball Bounce in opposite direction                        
            elif bally >= 580:
                balldy = -balldy

            elif ballx == (xTwo + 25) and bally <= (yTwo + heightPaddleoneandtwo) and bally >= yTwo:
                balldx = -balldx

#Makes Paddle Shorter on collisions with ball (makes game tougher)                
                if heightPaddleoneandtwo >= 10:
                    heightPaddleoneandtwo = heightPaddleoneandtwo - 7
                else:
                    heightPaddleoneandtwo = heightPaddleoneandtwo

            elif bally <= 110:
                balldy = -balldy

            elif ballx<0 or ballx>800:

#Adds score if ball passes paddle                
                 if ballx>800:
                      playeroneScore = playeroneScore + 1
                      startballSPACE = True
                 elif ballx < 0:
                      startballSPACE = True
                      playertwoScore = playertwoScore + 1
                 ballx = 400
                 bally = 350
                 balldx = 0
                 balldy = 0
                 yOne = 275
                 y2Two = 275
                 heightPaddleoneandtwo = 150
                 play = False

            ballx = ballx + balldx
            bally = bally - balldy


#Draw all screen components
        pygame.draw.rect(screen, WHITE,(xOne, yOne, 25, heightPaddleoneandtwo),0)
        pygame.draw.rect(screen, WHITE,(xTwo, yTwo, 25, heightPaddleoneandtwo),0)

        pygame.draw.circle (screen, WHITE, (ballx,bally), 10, 0)

        textScore = maingamescoreFont.render("Score", True, WHITE)
        screen.blit(textScore, (((800/2)-(textScore.get_width()/2),0)))

        textPlayeroneScore = maingameP1ScoreFont.render(str(playeroneScore), True, WHITE)
        screen.blit(textPlayeroneScore, (0,0))

        textPlayertwoScore = maingameP2ScoreFont.render(str(playertwoScore), True, WHITE)
        screen.blit(textPlayertwoScore, ((800 - textPlayertwoScore.get_width()),0))

        pygame.draw.rect (screen, WHITE, (0,90,800,10),0)

        pygame.draw.rect (screen, WHITE, (395,112,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,162,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,212,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,262,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,312,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,362,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,412,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,462,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,512,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,562,10,25),0)
        pygame.draw.rect (screen, WHITE, (395,612,10,25),0)

        pygame.draw.rect (screen, WHITE, (45,0,3,100),0)
        pygame.draw.rect (screen, WHITE, (752,0,3,100),0)

        playerOneText = maingamePlayerOneFont.render("Player 1", True, WHITE)
        playerTwoText = maingamePlayerOneFont.render("CPU", True, WHITE)
        screen.blit(playerOneText, (70,15))
        screen.blit(playerTwoText, (630,15))

        pygame.display.update()

startscreen()

Solution

  • You're almost there, but screen.blit needs a rectangle object alongside your textsprite, this object is used to define the size, and location of the sprite. Furthermore you need to give each line it's own either x or y coordinate (or else they'll all be drawn on top of eachother) a way to solve this is to use for n, line in enumerate(f) this will give you an index value for each line, called n. if use enumerate and remove your current screen.blit statement and replace it with this block it should work:

        text_rect = instructText.get_rect()
        text_rect.centerx = SCREENSIZE[0]//2
        text_rect.centery = n*25 + 50
        screen.blit(text, text_rect)
    

    Here you get a rect object for the text sprite by calling it's get_rect() method, then set its center x coordinate to be the center of the screen (I use a contant to hold screen size), then set it's center y coordinate to be 25 * the lines placement in the array + 50 pixels of padding, and lastly draw it to the screen with screen.blit(text, text_rect)

    I made a working example using a custom font, you can see it here

    In a previous project I've also made an object for tasks such as this, you're welcome to use, or copy it if you want, you can find it here

    Anyways, I hope it helped, happy coding.

    EDIT:

    Just took at at your code, and from what I can see your code currently does nothing :) You define your desired behaviour in the sartscreen() function but never call the function and thus nothing happens, this is your primary isssue, fortunatly it's an easy solve, just call the function at the bottom of your document like so startscreen(screen)

    But wait? You'll notice that i've added the screen object to this function call, this is because you need to hand your function a reference of the screen object, otherwise it doesn't know "which" screen object your talking about, you need to do this with any function that uses the screen object, however you also need to tell your function to expect an argument, so when you define your startscreen function, and instruction function as well, you need to add the screen object as well like so def startscreen(screen): and def instructions(screen): now your functions know what you're talking about when calling screen.fill(COLOR) and screen.blit(text, text_rect)

    Other than that it's only a matter of small details, but after applying those two changes your menu seemed to work for me on python 3.5, however I recommend that you take a look at the Clock object as well for limiting your framerate (otherwise the game will run super fast on fast computers)