From 6412bbd26f32d709de21bd5c2ba07dccd12703de Mon Sep 17 00:00:00 2001 From: Patrick Tschuchnig Date: Tue, 10 Sep 2019 16:35:08 +0200 Subject: [PATCH] first general code revision, unstable and untested. restructured the definitions, changed the game to a tick-based system, changed game loop to have a game state instead of being a strict script based state machine, lots of small changes. changed naming convention from camel case to underscore-spaced. unified naming convention. changed variable naming to reflect what the variable is used by. --- gametest_rev1.py | 471 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 471 insertions(+) create mode 100644 gametest_rev1.py diff --git a/gametest_rev1.py b/gametest_rev1.py new file mode 100644 index 0000000..6064ed5 --- /dev/null +++ b/gametest_rev1.py @@ -0,0 +1,471 @@ +#!/usr/bin/env python +#coding=utf-8 + +############################################ +############# START OF IMPORTS ############# +############################################ + + +import pygame, signal, sys, time, os, RPi.GPIO as GPIO +from PIL import Image +from pygame.locals import * + +############################################ +############## END OF IMPORTS ############## +############################################ + +############################################ +########### START OF DEFINITIONS ########### +############################################ + +# base pygame settings +pygame_fps = 30 #frames per second setting +pygame_clock = pygame.time.Clock() + +# colors +pygame_color_green = pygame.Color(42, 217, 13) +pygame_color_black = pygame.Color(0, 0, 0) +pygame_color_white = pygame.Color(255, 255, 255) +pygame_color_yellow = pygame.Color(255, 215, 0) +pygame_color_grey = pygame.Color(196, 202, 206) +pygame_color_brown = pygame.Color(177, 86, 15) + +# fonts +pygame_font_1 = pygame.font.Font('freesansbold.ttf', 90) +pygame_font_2 = pygame.font.Font('freesansbold.ttf', 65) +pygame_font_3 = pygame.font.Font('freesansbold.ttf', 45) + +# font colors +pygame_font_main_color = pygame_color_black + +# GPIO for Buttons +pin_start = 32 +pin_error = 31 +pin_shutdown = 3 + +# GPIO for LED +pin_red = 22 +pin_green = 18 +pin_blue = 16 + +# other constants +time_per_error = 5 # every time the wire is touched, some time is added as penalty. + +# screen settings +screen_size_x = 1920 +screen_size_y = 1080 + +# name length for highscores +max_name_length = 10 + +# preset highscores +hs1_name = "Fritz" +hs2_name = "Bernd" +hs3_name = "Max" +hs1_time = 100 +hs2_time = 200 +hs3_time = 300 + +############################################ +############ END OF DEFINITIONS ############ +############################################ + +############################################ +####### START OF PRE-INITIALISATION ######## +############################################ + +# here goes stuff that is requires by functions +# so they can be properly defined + +# initialise the game +pygame.init() + +# initialise gpio +GPIO.setmode(GPIO.BOARD) +GPIO.setup(pin_start, GPIO.IN) +GPIO.setup(pin_error, GPIO.IN) +GPIO.setup(pin_shutdown, GPIO.IN) + +# predefinition of led variables, for use in functions +led_red = "" +led_green = "" +led_blue = "" + + +############################################ +########## END OF INITIALISATION ########### +############################################ + +############################################ +###### START OF FUNCTION DEFINITIONS ####### +############################################ + +def get_image_width(filepath): + return ((Image.open(filepath).size)[0]) + +def get_image_height(filepath): + return ((Image.open(filepath).size)[1]) + +def signal_handler(sig, frame): + # signal handler, later called to interpret + # ctrl+c as "quit" rather than "abort" + print('Programm exiting') + exit_application() + +def led_init(): + # initialises the LED pins + # mind that the pins for the LEDs are pullup by default, + # which is on purpose, since this causes the LED strip to + # be turned off when the program isnt running or their state + # is undefined + + # set the led pins to be outputs + # careful: these pins dont drive the + # led strip themselves, but rather 3 + # n-channel mosfets, type IRLZ34N + global led_red,led_green,led_blue + GPIO.setup(pin_red, GPIO.OUT) + GPIO.setup(pin_green, GPIO.OUT) + GPIO.setup(pin_blue, GPIO.OUT) + + # set the pwm frequency to 100 + # if you experience strobing, try changing + # the number + led_red = GPIO.PWM(pin_red, 100) + led_blue = GPIO.PWM(pin_blue, 100) + led_green = GPIO.PWM(pin_green, 100) + + # start pwm generation with a duty cycle of 0 + led_green.start(0) + led_blue.start(0) + led_red.start(0) + +def change_green(amount): + # takes an input from 0 to 255 and converts it to Duty Cycle + # to be used by change_led_colour + global led_green + factor = 100/255 + led_green.ChangeDutyCycle(amount*factor) + +def change_blue(amount): + # takes an input from 0 to 255 and converts it to Duty Cycle + # to be used by change_led_colour + global led_blue + factor = 100/255 + led_blue.ChangeDutyCycle(amount*factor) + +def change_red(amount): + # takes an input from 0 to 255 and converts it to Duty Cycle + # to be used by change_led_colour + global led_red + factor = 100/255 + led_red.ChangeDutyCycle(amount*factor) + +def change_led_colour(red_amount,green_amount,blue_amount): + # sets an RGB value for the led strip. + if red_amount < 0 or red_amount > 255 or green_amount < 0 or green_amount > 255 or blue_amount < 0 or blue_amount > 255: + led_alert() + return false + change_red(red_amount) + change_blue(blue_amount) + change_green(green_amount) + +def change_led_speed(colour, speed): + # changes the speed of the LED pwm + global led_red,led_green,led_blue + + if colour == "red": + led_red.ChangeDutyCycle(speed) + elif colour == "green": + led_green.ChangeDutyCycle(speed) + elif colour == "blue": + led_blue.ChangeDutyCycle(speed) + else: + return false + +def led_alert(): + # stops the running program for 10 seconds + # causes the red LED to flash + # use as error message + # + # !!!!untested!!!! + # + change_led_colour(100, 0, 0) + change_led_speed(red, 1) + for i in range(1,10): + time.sleep(1) + change_led_colour(100, 100, 100) + change_led_speed(red, 100) + +def toggle_fullscreen(): + screen = pygame.display.get_surface() + tmp = screen.convert() + caption = pygame.display.get_caption() + cursor = pygame.mouse.get_cursor() # Duoas 16-04-2007 + + w,h = screen.get_width(),screen.get_height() + flags = screen.get_flags() + bits = screen.get_bitsize() + + pygame.display.quit() + pygame.display.init() + + screen = pygame.display.set_mode((w,h),flags^FULLSCREEN,bits) + screen.blit(tmp,(0,0)) + pygame.display.set_caption(*caption) + + pygame.key.set_mods(0) # HACK: work-a-round for a SDL bug?? + + pygame.mouse.set_cursor( *cursor ) # Duoas 16-04-2007 + return screen + +def clear_screen(): + print("filled screen") + screen.fill(pygame_color_white) + return + +def handle_events(): + for event in pygame.event.get(): + if event.type == KEYDOWN and event.key == K_ESCAPE: + exit_application() + elif event.type == KEYDOWN and event.key == K_q: + shutdown_raspberry() + return + +def exit_application(): + pygame.quit() + GPIO.cleanup() + sys.exit() + return + +def shutdown_raspberry(): + pygame.quit() + GPIO.cleanup() + os.system("sudo shutdown -h now") + return + +def enter_name(): + clear_screen() + print('text entry started') + name = '' + while True: + clear_screen() + + highscore_surface = pygame_font_1.render('High Score!', True, pygame_font_main_color) + highscore_rectangle = highscore_surface.get_rect() + highscore_rectangle.topleft = (700, 210) + + screen.blit(highscore_surface, highscore_rectangle) + + + textbox_surface = pygame_font_2.render('Enter name: ' + str(name), True, pygame_font_main_color) + textbox_rectangle = textbox_surface.get_rect() + textbox_rectangle.topleft = (700, 350) + screen.blit(textbox_surface, textbox_rectangle) + pygame.display.flip() + for event in pygame.event.get(): + if len(name) < max_name_length: + if event.type == KEYDOWN: + if event.key == pygame.K_BACKSPACE: + name = name[:-1] + elif event.key == pygame.K_RETURN: + clear_screen() + return name + else: + name += event.unicode + elif event.key == pygame.K_BACKSPACE: + name = name[:-1] + + elif event.type == KEYDOWN and event.key == pygame.K_RETURN: + clear_screen() + return name + clear_screen() + name = 'Error' + return name + +def check_highscores(time): + global hs1_time, hs2_time, hs3_time, hs1_name, hs2_name, hs3_name + if time <= hs1_time: + print ('new high score:'+str(time)) + # make the second the third + hs3_time = hs2_time + hs3_name = hs2_name + + # make the first the second + hs2_time = hs1_time + hs2_name = hs1_name + + # new high score + hs1_time = time + hs1_name = enter_name() + return + elif time <= hs2_time: + print ('new second:'+str(time)) + + # make the second the third + hs3_time = hs2_time + hs3_name = hs2_name + + # new second time + hs2_time = time + hs2_name = enter_name() + return + elif time <= hs3_time: + print ('new third:'+str(time)) + hs3_time = time + hs3_name = enter_name() + return + else: + return + +############################################ +####### END OF FUNCTION DEFINITIONS ######## +############################################ + +############################################ +######### START OF INITIALISATION ########## +############################################ + +# signal handing setup for controlled exit via ctrl+c +signal.signal(signal.SIGINT, signal_handler) + +# hide mouse from screen +pygame.mouse.set_visible(False) + +# start fullscreen mode with defined screen geometrics +screen = pygame.display.set_mode((screen_size_x, screen_size_y), pygame.FULLSCREEN) +#pygame.display.set_caption('Heisser Draht') # not required for fullscreen application + +# currently unused because its not needed +#screen = toggle_fullscreen() + +# define image variables +img_itlablogo = 'img/itlablogo.png' +img_itlablogo_image = pygame.image.load(img_itlablogo) +img_itlablogo_imagex = get_image_width(img_itlablogo) +img_itlablogo_imagey = get_image_height(img_itlablogo) + +# initialise led strip +led_init() + +game_running = False + +############################################ +########## END OF INITIALISATION ########### +############################################ + +############################################ +######### START OF MAIN GAME LOOP ########## +############################################ + +while True: + + handle_events() + + if game_running == False: + clear_screen() + print("New game starting") + change_led_colour(10,140,10) + time_surface = 0 + errors_surface = 0 + time_rectangle = 0 + errors_rectangle = 0 + + header_surface = pygame_font_1.render('Dr' + u'ü' + 'cken Sie Start!', True, pygame_font_main_color) + header_rectangle = header_surface.get_rect() + header_rectangle.topleft = (560, 250) + + highscore_header_surface = pygame_font_2.render('Highscores:', True, pygame_font_main_color) + highscore_header_rectangle = highscore_header_surface.get_rect() + highscore_header_rectangle = (770, 410) + + score1_surface = pygame_font_3.render(hs1_name + ": " + str(hs1_time) + 's', True, pygame_color_yellow) + score1_rectangle = score1_surface.get_rect() + score1_rectangle.topleft = (820, 540) + + score2_surface = pygame_font_3.render(hs2_name + ": " + str(hs2_time) + 's', True, pygame_color_grey) + score2_rectangle = score2_surface.get_rect() + score2_rectangle.topleft = (820, 630) + + score3_surface = pygame_font_3.render(hs3_name + ": " + str(hs3_time) + 's', True, pygame_color_brown) + score3_rectangle = score3_surface.get_rect() + score3_rectangle.topleft = (820, 720) + + pygame.draw.rect(screen,pygame_color_black, (500, 200, (screen_size_x-500*2), (screen_size_y-200*2)), 5) + + screen.blit(header_surface, header_rectangle) + screen.blit(highscore_header_surface, highscore_header_rectangle) + screen.blit(score1_surface, score1_rectangle) + screen.blit(score2_surface, score2_rectangle) + screen.blit(score3_surface, score3_rectangle) + screen.blit(img_itlablogo_image, (screen_size_x-img_itlablogo_imagex-20, screen_size_y-img_itlablogo_imagey-20)) + + pygame.display.flip() + + if GPIO.input(pin_start) == True and game_running == False: #wait for the user to press start button + game_running = True + errors = 0 + error_added = False + + header_surface = pygame_font_1.render('Spiel l' + u'ä' + 'uft!', True, pygame_font_main_color) + + start_time = int(time.time()) + + change_led_colour(10,10,100) + + if game_running == True: # game running + print("Game running normally") + + if GPIO.input(pin_error) == True: + if error_added == False: + errors += 1 + int_time = int(time.time()) - start_time + errors * time_per_error + error_added = True + else: + error_added = False + + int_time = int(time.time()) - start_time + + time_surface = pygame_font_2.render('Zeit: ' + str(int_time) + 's', True, pygame_font_main_color) + time_rectangle = time_surface.get_rect() + time_rectangle.topleft = (640, 480) + + errors_surface = pygame_font_2.render('Fehler: ' + str(errors), True, pygame_font_main_color) + errors_rectangle = errors_surface.get_rect() + errors_rectangle.topleft = (640, 560) + + clear_screen() + screen.blit(errors_surface, errors_rectangle) #errors + screen.blit(time_surface, time_rectangle) #time + screen.blit(header_surface, header_rectangle) #header + + pygame.display.flip() + + if GPIO.input(pin_start) != True: + + change_led_colour(100,10,10) + + print("Game ended because start pin wasnt true") + + check_highscores(int_time) + + clear_screen() + header_surface = pygame_font_1.render('Game over!', True, pygame_font_main_color) + + screen.blit(errors_surface, errors_rectangle) #errors + screen.blit(time_surface, time_rectangle) #time + screen.blit(header_surface, header_rectangle) #header + + pygame.display.flip() + + time.sleep(10) + + clear_screen() + + pygame.display.update() + pygame_clock.tick(pygame_fps) + +############################################ +########## END OF MAIN GAME LOOP ########### +############################################ +