renamed data directory to pocket_friends to avoid conflict
This commit is contained in:
56
pocket_friends/development/FakeGPIO.py
Normal file
56
pocket_friends/development/FakeGPIO.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
Module used to fake the RPi.GPIO module so that
|
||||
the game can be run without the actual hardware.
|
||||
"""
|
||||
|
||||
# Constants used by RPi.GPIO
|
||||
BOARD = 0
|
||||
IN = 0
|
||||
FALLING = 0
|
||||
|
||||
|
||||
def setmode(new_mode):
|
||||
"""
|
||||
Fake setmode function.
|
||||
:param new_mode:
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def setup(channel, mode, initial=None, pull_up_down=None):
|
||||
"""
|
||||
Fake setup function.
|
||||
:param channel:
|
||||
:param mode:
|
||||
:param initial:
|
||||
:param pull_up_down:
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def add_event_detect(channel, edge_type, callback=None, bouncetime=0):
|
||||
"""
|
||||
Fake function to add a non-existent event detect.
|
||||
:param channel:
|
||||
:param edge_type:
|
||||
:param callback:
|
||||
:param bouncetime:
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def event_detected(channel):
|
||||
"""
|
||||
Fake function to detect an event. Always returns false.
|
||||
:param channel:
|
||||
:return:
|
||||
"""
|
||||
return False
|
||||
|
||||
|
||||
def cleanup(channel=None):
|
||||
"""
|
||||
Fake cleanup function.
|
||||
:param channel:
|
||||
"""
|
||||
pass
|
1
pocket_friends/development/__init__.py
Normal file
1
pocket_friends/development/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Initializes all classes needed for the development environment, and faking GPIO inputs."""
|
50
pocket_friends/development/button_test.py
Normal file
50
pocket_friends/development/button_test.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
Module to test the GPIO input on the Raspberry Pi.
|
||||
"""
|
||||
from collections import deque
|
||||
from ..gpio_handler import Constants, GPIOHandler
|
||||
|
||||
|
||||
def button_test():
|
||||
"""
|
||||
GPIO button test. Checks for a GPIO input and prints it out, simple as that.
|
||||
"""
|
||||
running = True
|
||||
|
||||
# Exit code used to quit the button test.
|
||||
exit_code = deque()
|
||||
for button in ['j_d', 'j_d', 'j_u', 'j_u', 'j_d', 'j_d', 'j_u', 'j_u', 'a', 'a', 'b']:
|
||||
exit_code.append(button)
|
||||
|
||||
# Input log to check for quitting out of the button test.
|
||||
input_log = deque()
|
||||
|
||||
GPIOHandler.setup()
|
||||
|
||||
def log(pressed_button):
|
||||
"""
|
||||
Logs the pressed button into the input log.
|
||||
:param pressed_button:
|
||||
"""
|
||||
input_log.append(pressed_button)
|
||||
if len(input_log) > len(exit_code): # Don't let the input log exceed the length of the exit code.
|
||||
input_log.popleft()
|
||||
|
||||
def check_exit():
|
||||
"""
|
||||
Check if the input log and the exit code are the same. If they are, quit the button test.
|
||||
"""
|
||||
nonlocal running
|
||||
|
||||
if exit_code == input_log:
|
||||
running = False
|
||||
|
||||
while running:
|
||||
for button in Constants.buttons:
|
||||
code = Constants.buttons.get(button)
|
||||
if GPIOHandler.get_press(code): # If a button is pressed, print it out and do a quit check.
|
||||
print('event: {0}'.format(button))
|
||||
log(button)
|
||||
check_exit()
|
||||
|
||||
GPIOHandler.teardown()
|
154
pocket_friends/development/dev_menu.py
Normal file
154
pocket_friends/development/dev_menu.py
Normal file
@@ -0,0 +1,154 @@
|
||||
"""
|
||||
Development menu for the game on Raspberry Pi. NOTE: THIS DOES NOTHING ON A COMPUTER!
|
||||
"""
|
||||
import pocket_friends.game
|
||||
import importlib.util
|
||||
import os
|
||||
import pygame
|
||||
import time
|
||||
from .button_test import button_test
|
||||
from .menus import Menu
|
||||
from ..gpio_handler import GPIOHandler, Constants
|
||||
|
||||
dev_version = '0.0.1'
|
||||
|
||||
try:
|
||||
importlib.util.find_spec('RPi.GPIO')
|
||||
import RPi.GPIO as GPIO
|
||||
except ImportError:
|
||||
import pocket_friends.development.FakeGPIO as GPIO
|
||||
|
||||
# Global variable to keep track of the current menu.
|
||||
menu = 'main'
|
||||
|
||||
|
||||
def run_button_test():
|
||||
"""
|
||||
Runs the GPIO button test.
|
||||
"""
|
||||
GPIOHandler.teardown()
|
||||
button_test()
|
||||
GPIOHandler.setup()
|
||||
|
||||
|
||||
def clear_screen():
|
||||
"""
|
||||
Clears the screen.
|
||||
"""
|
||||
print("\n" * 20)
|
||||
|
||||
|
||||
def start_game():
|
||||
"""
|
||||
Cleans the GPIO and starts the game.
|
||||
"""
|
||||
GPIOHandler.teardown()
|
||||
pocket_friends.game.main()
|
||||
pygame.quit()
|
||||
GPIOHandler.setup()
|
||||
|
||||
|
||||
def quit_menu():
|
||||
"""
|
||||
Quits the menu.
|
||||
"""
|
||||
exit(0)
|
||||
|
||||
|
||||
def quit_with_error():
|
||||
"""
|
||||
Quits the menu with error code 3.
|
||||
"""
|
||||
exit(3)
|
||||
|
||||
|
||||
def change_menu(new_menu):
|
||||
"""
|
||||
Changes the global menu variable for the dev menu
|
||||
:param new_menu: the menu to change to
|
||||
"""
|
||||
global menu
|
||||
menu = new_menu
|
||||
clear_screen()
|
||||
print('...')
|
||||
time.sleep(0.75)
|
||||
|
||||
|
||||
def shutdown():
|
||||
"""
|
||||
Shuts down the linux system.
|
||||
"""
|
||||
os.system('sudo shutdown now')
|
||||
|
||||
|
||||
def restart():
|
||||
"""
|
||||
Restarts the linux system.
|
||||
"""
|
||||
os.system('sudo reboot')
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Starts the dev menu.
|
||||
"""
|
||||
|
||||
# The following defines all of the options in the various different menus.
|
||||
|
||||
main_menu = Menu('Pocket Friends Dev Menu {0}\nGame Version {1}'.format(dev_version, pocket_friends.game.version))
|
||||
main_menu.add_option(Menu.Option('Start Game', start_game))
|
||||
main_menu.add_option(Menu.Option('Button Test', run_button_test))
|
||||
main_menu.add_option(Menu.Option('Restart Dev Menu', quit_with_error))
|
||||
main_menu.add_option(Menu.Option('Shutdown Pi', change_menu, 'shutdown'))
|
||||
main_menu.add_option(Menu.Option('Restart Pi', change_menu, 'restart'))
|
||||
main_menu.add_option(Menu.Option('Quit Dev Menu', change_menu, 'quit'))
|
||||
|
||||
shutdown_confirm = Menu('Are you sure you want to shutdown?')
|
||||
shutdown_confirm.add_option(Menu.Option('No', change_menu, 'main'))
|
||||
shutdown_confirm.add_option(Menu.Option('Yes', shutdown))
|
||||
|
||||
restart_confirm = Menu('Are you sure you want to restart?')
|
||||
restart_confirm.add_option(Menu.Option('No', change_menu, 'main'))
|
||||
restart_confirm.add_option(Menu.Option('Yes', restart))
|
||||
|
||||
quit_confirm = Menu('Are you sure you want to exit?')
|
||||
quit_confirm.add_option(Menu.Option('No', change_menu, 'main'))
|
||||
quit_confirm.add_option(Menu.Option('Yes', quit_menu))
|
||||
|
||||
GPIOHandler.setup()
|
||||
|
||||
def menu_handler(current_menu):
|
||||
"""
|
||||
Draws the menu and handles the GPIO inputs
|
||||
:param current_menu: the current menu being drawn on the screen
|
||||
"""
|
||||
current_menu.draw_menu()
|
||||
|
||||
while True: # Main GPIO input loop
|
||||
|
||||
# Limits how often the program checks for a GPIO input. Eases CPU usage.
|
||||
time.sleep(0.125)
|
||||
|
||||
if GPIOHandler.get_press(Constants.buttons.get('j_d')):
|
||||
current_menu.select_next()
|
||||
break
|
||||
if GPIOHandler.get_press(Constants.buttons.get('j_u')):
|
||||
current_menu.select_prev()
|
||||
break
|
||||
if GPIOHandler.get_press(Constants.buttons.get('a')):
|
||||
current_menu.run_selection()
|
||||
break
|
||||
|
||||
while True: # Loop for drawing the menus.
|
||||
|
||||
while menu == 'main':
|
||||
menu_handler(main_menu)
|
||||
|
||||
while menu == 'shutdown':
|
||||
menu_handler(shutdown_confirm)
|
||||
|
||||
while menu == 'restart':
|
||||
menu_handler(restart_confirm)
|
||||
|
||||
while menu == 'quit':
|
||||
menu_handler(quit_confirm)
|
120
pocket_friends/development/menus.py
Normal file
120
pocket_friends/development/menus.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""
|
||||
Menu class to help with drawing menus on screen
|
||||
"""
|
||||
|
||||
|
||||
class Menu:
|
||||
"""
|
||||
Menu class. Creates a menu with text to display and options
|
||||
"""
|
||||
|
||||
def __init__(self, menu_text=''):
|
||||
self._menu_text = menu_text
|
||||
self._options = []
|
||||
self._selection = 0
|
||||
|
||||
def add_option(self, option):
|
||||
"""
|
||||
Adds an option to the menu. Only allows instances of Menu.Option
|
||||
:param option:
|
||||
"""
|
||||
if not isinstance(option, Menu.Option):
|
||||
raise TypeError('option must be an instance of Menu.Option')
|
||||
else:
|
||||
self._options.append(option)
|
||||
|
||||
def get_option(self, index):
|
||||
"""
|
||||
Gets an option object given the index of the option. Raises IndexError if given
|
||||
index is out of bounds.
|
||||
:param index: the index of the option
|
||||
:return: the option object
|
||||
"""
|
||||
try:
|
||||
return self._options[index]
|
||||
except IndexError as ex:
|
||||
raise IndexError('option index out of range') from ex
|
||||
|
||||
def select_next(self):
|
||||
"""
|
||||
Selects the next option in the list. Wraps around to the first option if
|
||||
the last option is currently selected.
|
||||
"""
|
||||
self._selection += 1
|
||||
if self._selection >= len(self._options):
|
||||
self._selection = 0
|
||||
|
||||
def select_prev(self):
|
||||
"""
|
||||
Selects the previous option in the list. Wraps around to the last option if
|
||||
the first option is currently selected.
|
||||
"""
|
||||
self._selection -= 1
|
||||
if self._selection < 0:
|
||||
if len(self._options) > 0:
|
||||
self._selection = len(self._options) - 1
|
||||
else:
|
||||
self._selection = 0
|
||||
|
||||
def run_selection(self, *args, **kwargs):
|
||||
"""
|
||||
Runs the function that the currently selected option object points to.
|
||||
:param args: arguments to be passed to the function
|
||||
:param kwargs: keyword arguments to be passed to the function
|
||||
"""
|
||||
try:
|
||||
return self._options[self._selection].run(*args, **kwargs)
|
||||
except IndexError as ex:
|
||||
raise Exception('menu has no options, cannot run a non-existent option') from ex
|
||||
|
||||
def draw_menu(self):
|
||||
"""
|
||||
Draws the menu on screen with a leading 20 blank lines.
|
||||
"""
|
||||
print('\n' * 20)
|
||||
|
||||
print(self._menu_text + '\n')
|
||||
|
||||
for option in self._options:
|
||||
selection_char = '>'
|
||||
|
||||
if self._options.index(option) != self._selection:
|
||||
selection_char = ' '
|
||||
|
||||
print('{0} {1}'.format(selection_char, option.get_text()))
|
||||
|
||||
class Option:
|
||||
"""
|
||||
Class that defines options for the Menu class.
|
||||
"""
|
||||
|
||||
def __init__(self, option_text='', function=None, *args, **kwargs):
|
||||
self._option_text = option_text
|
||||
self._function = function
|
||||
self._default_args = args
|
||||
self._default_kwargs = kwargs
|
||||
|
||||
def get_text(self):
|
||||
"""
|
||||
Returns the text to be displayed by the option
|
||||
:return: the option text
|
||||
"""
|
||||
return self._option_text
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
"""
|
||||
Runs the function that the option object points to. Returns None if
|
||||
there is no function or the given function is not valid.
|
||||
:param args: arguments to be passed to the function
|
||||
:param kwargs: keyword arguments to be passed to the function
|
||||
:return: the return value of the function (if any)
|
||||
"""
|
||||
if len(args) == 0:
|
||||
args = self._default_args
|
||||
if len(kwargs) == 0:
|
||||
kwargs = self._default_kwargs
|
||||
|
||||
try:
|
||||
return self._function(*args, **kwargs)
|
||||
except TypeError:
|
||||
return None
|
Reference in New Issue
Block a user