2

I know this is a lot of code but I really need help making it so as long as a user keeps playing (not getting to a sys.quit) the high score saves and can be shown with the highscore func. Ive been working for hours and cant figure this part out. Please and sorry for so much code. Also open to any ways to make it run better or smoother.

import pygame, sys, random
from time import *
from pygame import *
from pygame.locals import *
scores=[]
name=[]
def playagain():
    print "Would you like to play again?"
    global playername
    choice=raw_input("Or do you want to see the current high scores: ")
    choice1=choice.lower()
    if choice=='yes' or choice=='y':
        playername=raw_input('Name:  ')
        main_loop(random.randint(3.0,6.0))
    elif choice=='high scores' or choice=='hs':
        highscores()
    elif choice=='no' or choice=='n' or choice=='goodbye' or choice=='bye' or choice=='exit' or choice=='quit':
        pygame.quit()
        sys.exit()       
def highscores():
    pygame.init()
    windowSurface = pygame.display.set_mode((500, 400), 0, 32)
    pygame.display.set_caption('Tic-toc!')
    WHITE = (255, 255, 255)
    BLUE = (0, 0, 255)
    RED=(255, 0, 0)
    GREEN=(0,255,0)
    basicFont = pygame.font.SysFont(None, 48)    
    global finaltime
    global scores
    global name
    global playername
    font = pygame.font.Font(None, 35)  # load the default font, size 50
    color = (255, 50, 0)
    if finaltime<=.01:
        finaltime=0.00
        scores.append(str(finaltime))
    else:
        scores.append(str(finaltime+.01))
    name.append(str(playername))            
    for i in range(len(scores)):
        score = scores[i]
        name= name[i]
        nameimage = font.render(name, True, color)
        namerect = nameimage.get_rect()
        namerect.left, namerect.y = 40, 100 + (i*(namerect.height + 20))
        windowSurface.blit(nameimage,namerect)
        scoreimage = font.render(score, True, color)
        scorerect = scoreimage.get_rect()
        scorerect.right, scorerect.y = 480, namerect.y
        windowSurface.blit(scoreimage, scorerect)
        for d in range(namerect.right + 25, scorerect.left-10, 25):
            pygame.draw.rect(scoreimage, color, pygame.Rect(d, scorerect.centery, 5, 5))
    pygame.display.update()
    sleep(7)
    pygame.quit()
    playagain()
def main_loop(timer):
    global playername
    playername=raw_input('Name:  ')
    global finaltime
    pygame.init()
    windowSurface = pygame.display.set_mode((500, 400), 0, 32)
    pygame.display.set_caption('Tic-toc!')
    WHITE = (255, 255, 255)
    BLUE = (0, 0, 255)
    RED=(255, 0, 0)
    GREEN=(0,255,0)
    basicFont = pygame.font.SysFont(None, 48)
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
        timer-=.01
        if timer<=0.0099:
            timernew=0.00
            timer=0.00
            textnew=basicFont.render('0.00', True, WHITE, RED)
            textRectnew = textnew.get_rect()
            textRectnew.centerx = windowSurface.get_rect().centerx
            textRectnew.centery = windowSurface.get_rect().centery
            windowSurface.blit(textnew, textRect)
            pygame.display.update()
            break
        button1,button2,button3=pygame.mouse.get_pressed()
        text = basicFont.render(str(timer), True, WHITE, BLUE)
        textRect = text.get_rect()
        textRect.centerx = windowSurface.get_rect().centerx
        textRect.centery = windowSurface.get_rect().centery
        x,y=pygame.mouse.get_pos()
        if (x > textRect.left) and (x < textRect.right) and (y > textRect.top) and (y < textRect.bottom) and button1==1:
            text=basicFont.render(str(timer), True, WHITE, BLUE)
            finaltime=timer
            break
        sleep(.01)
        windowSurface.blit(text, textRect)
        pygame.display.update()
    pygame.quit()
    playagain()
    return
main_loop(random.randint(3.0,6.0))
Zack Tarr
  • 851
  • 1
  • 8
  • 28
  • what have you tried? If you want to save high scores to a file ... What's wrong if you just save them? – sleepsort Dec 21 '12 at 05:45
  • well i have tried that, originally it was my plan so that it always saved but I could not figure out how to save more than one line of code. If someone could show me how and where to add the code I would greatly appreciate it. – Zack Tarr Dec 21 '12 at 05:51
  • Also I would still like it to display the scores on the screen. – Zack Tarr Dec 21 '12 at 06:00
  • i would advise to divide all this code into more functions, since it is really hard to read. Second this, don't use globals, you can pass the necessary things in the parameters. – Bartlomiej Lewandowski Dec 21 '12 at 09:55
  • 1
    one more thing, you can delete import pygame, since you are already importing it this way: from pygame import * – Bartlomiej Lewandowski Dec 21 '12 at 09:59

1 Answers1

2

I did some simple modifications to your code. Have a look at the comments I added. This should give you a good starting point.

import pygame, sys, random

from time import *
from pygame import *
from pygame.locals import *

# define colors at top level of the script
WHITE = (255, 255, 255)
BLUE  = (0  ,   0, 255)
RED   = (255,   0,   0)
GREEN = (0  , 255,   0)

# keep track of highscores
scores = []

def get_window_and_font():
    """Returns a tuple of a font and the surface of a newly created window"""
    pygame.init()
    pygame.display.set_caption('Tic-toc!')
    return pygame.font.SysFont(None, 48), pygame.display.set_mode((500, 400), 0, 32)

def playagain():
    """Returns if the player wants to play again"""
    print "Would you like to (p)lay again or (n)ot?"
    choice = raw_input("Or do you want to see the current (h)igh scores: ").lower()
    # use 'in' to check choices of fewer code
    if choice in ('yes', 'y', 'p', 'play', 'again'):
        return True
    elif choice in ('high scores', 'hs', 'h'):
        highscores()
        return True
    elif choice in ('no', 'n', 'goodbye', 'bye', 'exit', 'quit'):
        return False
    else:
        playagain()

def highscores():
    basicFont, windowSurface = get_window_and_font()

    # use enumerate to get the index of the sorted elements in our highscores
    # highscores are sorted by score, descending
    for i, (name, score) in enumerate(sorted(scores, key=lambda x: -x[1])):
        # use list comprehension to create a nice color effect in highscore :-)
        color = tuple([max(0, 255-i*x) for x in (15, 25, 40)])
        nameimage = basicFont.render(name, True, color)
        namerect = nameimage.get_rect()
        namerect.left, namerect.y = 40, 10 + (i*(namerect.height + 10))
        windowSurface.blit(nameimage,namerect)
        scoreimage = basicFont.render(str(score), True, color)
        scorerect = scoreimage.get_rect()
        scorerect.right, scorerect.y = 480, namerect.y
        windowSurface.blit(scoreimage, scorerect)
        for d in range(namerect.right + 25, scorerect.left-10, 25):
            pygame.draw.rect(scoreimage, color, pygame.Rect(d, scorerect.centery, 5, 5))

    pygame.display.update()
    # just check for MOUSEBUTTONUP and QUIT, using the filter argument of .get()
    while not any(pygame.event.get((MOUSEBUTTONUP, QUIT))):
        sleep(0.1)
    pygame.quit()

def play_game():
    """this function handles a round of the game and returns the playername and his score"""
    timer = random.randint(3.0,6.0)
    playername = raw_input('Name:  ')
    finaltime = 0
    basicFont, windowSurface = get_window_and_font()
    # keep running while no QUIT event is in the queue
    while not any(pygame.event.get(QUIT)):
        # clear the screen every tick
        windowSurface.fill((0,0,0))
        timer -= .01
        if timer <= 0.0099:
            textnew  = basicFont.render('0.00', True, WHITE, RED)
            textRectnew = textnew.get_rect()
            textRectnew.centerx = windowSurface.get_rect().centerx
            textRectnew.centery = windowSurface.get_rect().centery
            windowSurface.blit(textnew, textRect)
            pygame.display.update()
            break

        # we are only interested in button1, so discard the rest
        button1, _, _ = pygame.mouse.get_pressed()
        text = basicFont.render(str(timer), True, WHITE, BLUE)
        textRect = text.get_rect()
        textRect.centerx = windowSurface.get_rect().centerx
        textRect.centery = windowSurface.get_rect().centery

        # use collidepoint to check if mouse is above the rect
        # you could also use the MOUSEBUTTONUP event instead of mouse.get_pos()
        if button1 == 1 and textRect.collidepoint(pygame.mouse.get_pos()):
            text = basicFont.render(str(timer), True, WHITE, BLUE)
            finaltime = timer
            break

        sleep(.01)
        windowSurface.blit(text, textRect)
        pygame.display.update()

    pygame.quit()

    return playername, finaltime

def main():
    keep_playing = True
    while keep_playing:
        # play_game returns the playername and his score
        # store that in our highscore list
        scores.append((play_game()))
        # keep playing if the player wants to
        keep_playing = playagain()

# good habit to use the __name__ magic variable
if __name__ == '__main__':
    main()

You don't need global at all.

I think it is a little bit strange to close and reopen windows to switch between pygame and CLI, but I keeped that part of your code intact while moving the relevant code to its own function get_window_and_font.

You probably want to divide your game into different scenes later, like title screen, name entry screen, gameplay screen and highscore screen, but this beyond the scope of this answer.

sloth
  • 99,095
  • 21
  • 171
  • 219
  • isn't import pygame not needed when you import it with from? – Bartlomiej Lewandowski Dec 21 '12 at 10:54
  • I didn't change the `import` statements of the original code, but I would suggest keeping only `import pygame` and removing `from pygame import *` and `from pygame.locals import *` and then use `pygame.QUIT` instead just `QUIT` etc. – sloth Dec 21 '12 at 11:00
  • Thank you so much for this! This code will allow me to do exactly what I want and be able to understand it for further use. But one question, how does the last part work and why is it a good habit? – Zack Tarr Dec 21 '12 at 17:43
  • `I think it is a little bit strange to close and reopen...` was a good decision, I find. – Wolf Dec 30 '14 at 21:26