2019-09-10 16:35:08 +02:00
|
|
|
#!/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()
|
|
|
|
|
|
|
|
# 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()
|
|
|
|
|
2019-09-10 16:38:31 +02:00
|
|
|
# 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)
|
|
|
|
|
|
|
|
# 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)
|
|
|
|
|
2019-09-10 16:46:49 +02:00
|
|
|
# font colors
|
|
|
|
pygame_font_main_color = pygame_color_black
|
|
|
|
|
2019-09-10 16:35:08 +02:00
|
|
|
# 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
|
2019-09-10 16:46:49 +02:00
|
|
|
led_red = 0
|
|
|
|
led_green = 0
|
|
|
|
led_blue = 0
|
2019-09-10 16:35:08 +02:00
|
|
|
|
|
|
|
############################################
|
|
|
|
########## 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
|
2019-09-10 16:48:00 +02:00
|
|
|
game_just_started = True
|
2019-09-10 16:35:08 +02:00
|
|
|
|
|
|
|
############################################
|
|
|
|
########## END OF INITIALISATION ###########
|
|
|
|
############################################
|
|
|
|
|
|
|
|
############################################
|
|
|
|
######### START OF MAIN GAME LOOP ##########
|
|
|
|
############################################
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
2019-09-10 16:46:49 +02:00
|
|
|
clear_screen()
|
2019-09-10 16:35:08 +02:00
|
|
|
handle_events()
|
|
|
|
|
|
|
|
if game_running == False:
|
2019-09-10 16:46:49 +02:00
|
|
|
|
|
|
|
if game_just_started == True:
|
|
|
|
print("New game starting")
|
|
|
|
change_led_colour(10,140,10)
|
|
|
|
game_just_started = False
|
|
|
|
|
2019-09-10 16:35:08 +02:00
|
|
|
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()
|
2019-09-10 16:46:49 +02:00
|
|
|
|
2019-09-10 16:35:08 +02:00
|
|
|
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)
|
|
|
|
|
2019-09-10 16:46:49 +02:00
|
|
|
# nach dem spiel ist vor dem spiel
|
|
|
|
game_just_started = True
|
2019-09-10 16:35:08 +02:00
|
|
|
clear_screen()
|
|
|
|
|
|
|
|
pygame.display.update()
|
|
|
|
pygame_clock.tick(pygame_fps)
|
|
|
|
|
|
|
|
############################################
|
|
|
|
########## END OF MAIN GAME LOOP ###########
|
|
|
|
############################################
|
|
|
|
|