Compare commits
34 Commits
rpi-dev-me
...
d8775fb1a9
Author | SHA1 | Date | |
---|---|---|---|
d8775fb1a9 | |||
4045930bd9 | |||
d322949b5a | |||
b97d54f49d | |||
65365adc3d | |||
f56f775541 | |||
509efa7e23 | |||
327f6cadee | |||
a8674f073e | |||
eff7f2c893 | |||
adfece1a32 | |||
07aae2b075 | |||
bba0af4946 | |||
dd621dbe7a | |||
bbf549c024 | |||
ca9406aab8 | |||
535aa993a5 | |||
4e14204392 | |||
7b8898b77b | |||
da5bacf950 | |||
fd7e1b7492 | |||
bbe97f0de7 | |||
296b6df4a0 | |||
2ffd9bd929 | |||
6f6eaa3c6d | |||
d66d56630d | |||
7073bbb73c | |||
f1c83ade97 | |||
787c1cc252 | |||
36487cad9e | |||
2987bfa7ed | |||
44986e62c0 | |||
6d28f0827f | |||
c25b021501 |
10
README.md
10
README.md
@@ -1,11 +1,11 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
Pocket Friends is a game where you raise your own little pocket friend! These pocket friends, called bloops, are great little companions to have! You can feed them, play with them, and watch them grow up!
|
Pocket Friends is a game where you raise your own little pocket friend! These pocket friends, called bloops, are great little companions to have! You can feed them, play with them, and watch them grow up!
|
||||||
|
|
||||||
~~You can download the latest release of Pocket Friends on the [releases page.](https://github.com/nickedyer/pocket-friends/releases)~~
|
~~You can download the latest release of Pocket Friends on the [releases page.](https://gitea.citruxx.com/ndyer/pocket-friends/releases)~~
|
||||||
There are currently no releases of the game. To install the current version on GitHub, follow the instructions below.
|
There are currently no releases of the game. To install the current version on GitHub, follow the instructions below.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -13,13 +13,13 @@ There are currently no releases of the game. To install the current version on G
|
|||||||
## Installing From Source
|
## Installing From Source
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
- Python 3.6 or greater
|
- Python 3.10 or greater
|
||||||
- Pip
|
- Pip
|
||||||
- Git
|
- Git
|
||||||
|
|
||||||
All you need to do to install Pocket Friends is install it with pip and you're good to go!
|
All you need to do to install Pocket Friends is install it with pip and you're good to go!
|
||||||
|
|
||||||
`pip install git+https://github.com/nickedyer/pocket-friends.git`
|
`pip install git+https://gitea.citruxx.com/ndyer/pocket-friends.git`
|
||||||
|
|
||||||
Now that the game is installed, just run it like you would any other Python program.
|
Now that the game is installed, just run it like you would any other Python program.
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ If you wish to build this version of Pocket Friends for Windows, you will need t
|
|||||||
requirements as to install it to your system from source. After you have done that,
|
requirements as to install it to your system from source. After you have done that,
|
||||||
issue the following:
|
issue the following:
|
||||||
```
|
```
|
||||||
git clone https://github.com/nickedyer/pocket-friends.git
|
git clone https://gitea.citruxx.com/ndyer/pocket-friends.git
|
||||||
cd pocket-friends
|
cd pocket-friends
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
pip install pyinstaller
|
pip install pyinstaller
|
||||||
|
@@ -1 +1,4 @@
|
|||||||
|
"""Pocket Friends is a game where you raise your own little pocket friend! These pocket friends, called bloops,
|
||||||
|
are great little companions to have! You can feed them, play with them, and watch them grow up!"""
|
||||||
|
|
||||||
__version__ = 'dev_0.0.3'
|
__version__ = 'dev_0.0.3'
|
||||||
|
@@ -2,11 +2,10 @@
|
|||||||
Launch script for Pocket Friends.
|
Launch script for Pocket Friends.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
|
||||||
import pygame
|
import pygame
|
||||||
import sys
|
import sys
|
||||||
from pocket_friends.game_files.game import main as game_main
|
from pathlib import Path
|
||||||
from pocket_friends.development.dev_menu import main as dev_menu_main
|
import pocket_friends.game_files.game as game
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
enable_dev = False
|
enable_dev = False
|
||||||
@@ -14,16 +13,11 @@ if __name__ == '__main__':
|
|||||||
# enable dev mode if --dev argument is passed
|
# enable dev mode if --dev argument is passed
|
||||||
if len(sys.argv) > 0:
|
if len(sys.argv) > 0:
|
||||||
for args in sys.argv:
|
for args in sys.argv:
|
||||||
if args == '--dev':
|
|
||||||
enable_dev = True
|
|
||||||
if args == '--delete-save':
|
if args == '--delete-save':
|
||||||
save_dir = os.path.join(Path.home(), '.pocket_friends')
|
save_dir = os.path.join(Path.home(), '.pocket_friends')
|
||||||
os.remove(save_dir + '/save.json')
|
os.remove(save_dir + '/save.json')
|
||||||
|
|
||||||
if not enable_dev:
|
game.main()
|
||||||
game_main()
|
|
||||||
else:
|
|
||||||
dev_menu_main()
|
|
||||||
|
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
Module to test the GPIO input on the Raspberry Pi.
|
Module to test the GPIO input on the Raspberry Pi.
|
||||||
"""
|
"""
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from ..hardware.gpio_handler import Constants, GPIOHandler
|
from pocket_friends.game_files.io.gpio_handler import Constants, GPIOHandler
|
||||||
|
|
||||||
|
|
||||||
def button_test():
|
def button_test():
|
||||||
|
@@ -8,13 +8,13 @@ import pygame
|
|||||||
import time
|
import time
|
||||||
from .button_test import button_test
|
from .button_test import button_test
|
||||||
from .menus import Menu
|
from .menus import Menu
|
||||||
from ..hardware.gpio_handler import GPIOHandler, Constants
|
from pocket_friends.game_files.io.gpio_handler import GPIOHandler, Constants
|
||||||
|
|
||||||
try:
|
try:
|
||||||
importlib.util.find_spec('RPi.GPIO')
|
importlib.util.find_spec('RPi.GPIO')
|
||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import pocket_friends.development.FakeGPIO as GPIO
|
import pocket_friends.game_files.io.fake_gpio as GPIO
|
||||||
|
|
||||||
# Global variable to keep track of the current menu.
|
# Global variable to keep track of the current menu.
|
||||||
menu = 'main'
|
menu = 'main'
|
||||||
|
1
pocket_friends/game_files/elements/__init__.py
Normal file
1
pocket_friends/game_files/elements/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
"""Sub-module for use in the game. Helps with the drawing of various objects such as sprites and text boxes."""
|
272
pocket_friends/game_files/elements/sprites.py
Normal file
272
pocket_friends/game_files/elements/sprites.py
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
import pygame
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class SpriteSheet:
|
||||||
|
"""
|
||||||
|
Class to be used by sprites in order to give them a texture and an animation.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
images (list) List of all the sprites in the animation separated from the sprite sheet.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, sprite_sheet, texture_json):
|
||||||
|
"""
|
||||||
|
Creates a sprite sheet given a sprite image and its corresponding JSON file.
|
||||||
|
Args:
|
||||||
|
sprite_sheet (str): The path of the sprite sheet image component.
|
||||||
|
texture_json (str): The path of the sprite sheet JSON component, contains the number of frames in the
|
||||||
|
sprite sheet, and the width and height of an individual sprite from the sprite sheet.
|
||||||
|
"""
|
||||||
|
# Load in whole sprite sheet as one image.
|
||||||
|
sprite_sheet = pygame.image.load(sprite_sheet).convert_alpha()
|
||||||
|
self.images = []
|
||||||
|
print(type(self.images))
|
||||||
|
|
||||||
|
# Get the sprite sheet json file.
|
||||||
|
with open(texture_json, 'r') as json_file:
|
||||||
|
img_attrib = json.load(json_file)
|
||||||
|
json_file.close()
|
||||||
|
|
||||||
|
# Count for how many images have been added in the image list
|
||||||
|
image_count = 0
|
||||||
|
|
||||||
|
# Get the sprite size as a tuple
|
||||||
|
sprite_size = img_attrib['width'], img_attrib['height']
|
||||||
|
|
||||||
|
# Iterate through every image location on the sprite sheet given the sprite size
|
||||||
|
for i in range(sprite_sheet.get_size()[1] // sprite_size[1]):
|
||||||
|
i *= sprite_size[1]
|
||||||
|
for j in range(sprite_sheet.get_size()[0] // sprite_size[0]):
|
||||||
|
j *= sprite_size[0]
|
||||||
|
|
||||||
|
# Create a new transparent surface
|
||||||
|
sprite = pygame.Surface(sprite_size, pygame.SRCALPHA)
|
||||||
|
# Blit the sprite onto the image
|
||||||
|
sprite.blit(sprite_sheet, (0, 0), (j, i, sprite_size[0], sprite_size[1]))
|
||||||
|
# Add the image to the list of images
|
||||||
|
self.images.append(sprite)
|
||||||
|
|
||||||
|
image_count += 1
|
||||||
|
|
||||||
|
# Break the loop if the specified number of frames has been reached.
|
||||||
|
if image_count >= img_attrib['frames']:
|
||||||
|
break
|
||||||
|
if image_count >= img_attrib['frames']:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
class SelectionEgg(pygame.sprite.Sprite):
|
||||||
|
"""
|
||||||
|
Sprite to render the egg on the egg selection screen.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
egg_color (str): The color of the egg (also its name).
|
||||||
|
description (str): The description of the egg to be displayed when selected.
|
||||||
|
contentedness (int): How likely the egg is to stay happy, ranges from 0-5.
|
||||||
|
metabolism (int): How quickly the egg will get hungry, ranges from 0-5.
|
||||||
|
rect (pygame.Rect): Pygame rectangle used to position the egg on screen.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, egg_color, resources_dir):
|
||||||
|
"""
|
||||||
|
Creates a SelectionEgg object given an egg color and a resource location.
|
||||||
|
Args:
|
||||||
|
egg_color (str): The color egg that should be rendered.
|
||||||
|
resources_dir (str): The path of the resources directory.
|
||||||
|
"""
|
||||||
|
pygame.sprite.Sprite.__init__(self)
|
||||||
|
|
||||||
|
self.egg_color = egg_color
|
||||||
|
|
||||||
|
# Loads the JSON file of the egg to read in data.
|
||||||
|
with open(resources_dir + '/data/bloop_info/{0}.json'.format(egg_color), 'r') as save_file:
|
||||||
|
json_file = json.load(save_file)
|
||||||
|
save_file.close()
|
||||||
|
|
||||||
|
# Gets the description off the egg from the JSON file.
|
||||||
|
self.description = json_file.get('description')
|
||||||
|
self.contentedness = json_file.get('contentedness')
|
||||||
|
self.metabolism = json_file.get('metabolism')
|
||||||
|
|
||||||
|
# Load the egg from the given color and get the bounding rectangle for the image.
|
||||||
|
sprite_sheet = SpriteSheet(resources_dir + '/images/bloops/{0}/egg.png'.format(self.egg_color),
|
||||||
|
resources_dir + '/images/bloops/{0}/egg.json'.format(self.egg_color))
|
||||||
|
self._images = sprite_sheet.images
|
||||||
|
|
||||||
|
# Get the rectangle from the first image in the list
|
||||||
|
self.rect = self._images[0].get_rect()
|
||||||
|
print(type(self.rect))
|
||||||
|
self._index = 0
|
||||||
|
self.image = self._images[self._index]
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""
|
||||||
|
Update the sprite to the next animation frame.
|
||||||
|
"""
|
||||||
|
# Animate the sprite
|
||||||
|
self._index = (self._index + 1) % len(self._images)
|
||||||
|
self.image = self._images[self._index]
|
||||||
|
|
||||||
|
|
||||||
|
class InfoText:
|
||||||
|
"""
|
||||||
|
Class for drawing large amounts of text on the screen at a time
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, resources_dir, game_res, text='Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
|
||||||
|
'Nam commodo tempor aliquet. Suspendisse placerat accumsan'
|
||||||
|
' neque, nec volutpat nunc porta ut.'):
|
||||||
|
|
||||||
|
self.font = pygame.font.Font(resources_dir + '/fonts/5Pts5.ttf', 10)
|
||||||
|
self.text = [] # Text broken up into a list according to how it will fit on screen.
|
||||||
|
self.max_lines = 6 # Max number of lines to be shown on screen at a time.
|
||||||
|
self.offset = 0
|
||||||
|
self.game_res = game_res
|
||||||
|
|
||||||
|
# Arrow icons to indicate scrolling
|
||||||
|
self.up_arrow = pygame.image.load(resources_dir + '/images/gui/up_arrow.png').convert_alpha()
|
||||||
|
self.down_arrow = pygame.image.load(resources_dir + '/images/gui/down_arrow.png').convert_alpha()
|
||||||
|
|
||||||
|
raw_text = text # Copy the text to a different variable to be cut up.
|
||||||
|
|
||||||
|
margins = 4.5
|
||||||
|
max_line_width = self.game_res - (margins * 2) # The maximum pixel width that drawn text can be.
|
||||||
|
cut_chars = '.,! ' # Characters that will be considered "cuts" aka when a line break can occur.
|
||||||
|
|
||||||
|
# Prevents freezing if the end of the string does not end in a cut character
|
||||||
|
# Will fix eventually more elegantly
|
||||||
|
if raw_text[-1:] not in cut_chars:
|
||||||
|
raw_text += ' '
|
||||||
|
|
||||||
|
# Calculating line breaks.
|
||||||
|
while len(raw_text) > 0:
|
||||||
|
index = 0
|
||||||
|
test_text = '' # Chunk of text to pseudo-render and test the width of.
|
||||||
|
|
||||||
|
# Loops until the testing text has reached the size limit.
|
||||||
|
while True:
|
||||||
|
|
||||||
|
# Break if the current index is larger than the remaining text.
|
||||||
|
if index + 1 > len(raw_text):
|
||||||
|
index -= 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# Add one character to the testing text from the raw text.
|
||||||
|
test_text += raw_text[index]
|
||||||
|
# Get the width of the pseudo-rendered text.
|
||||||
|
text_width = self.font.size(test_text)[0]
|
||||||
|
|
||||||
|
# Break if the text is larger than the defined max width.
|
||||||
|
if text_width > max_line_width:
|
||||||
|
break
|
||||||
|
index += 1
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Gets the chunk of text to be added to the list.
|
||||||
|
text_chunk = raw_text[0:index + 1]
|
||||||
|
# Determines if the chunk of text has any break characters.
|
||||||
|
has_breaks = any(cut_chars in text_chunk for cut_chars in cut_chars)
|
||||||
|
|
||||||
|
# If the text has break characters, start with the last character and go backwards until
|
||||||
|
# one has been found, decreasing the index each time.
|
||||||
|
if has_breaks:
|
||||||
|
while raw_text[index] not in cut_chars:
|
||||||
|
index -= 1
|
||||||
|
text_chunk = raw_text[0:index + 1]
|
||||||
|
# If there are no break characters in the chunk, simply decrease the index by one and insert
|
||||||
|
# a dash at the end of the line to indicate the word continues.
|
||||||
|
else:
|
||||||
|
index -= 1
|
||||||
|
text_chunk = raw_text[0:index + 1]
|
||||||
|
text_chunk += '-'
|
||||||
|
|
||||||
|
# Append the text chunk to the list of text to draw.
|
||||||
|
self.text.append(text_chunk)
|
||||||
|
|
||||||
|
# Cut the text to repeat the process with the new cut string.
|
||||||
|
raw_text = raw_text[index + 1:]
|
||||||
|
|
||||||
|
def draw(self, surface):
|
||||||
|
"""
|
||||||
|
Draws the text on a given surface.
|
||||||
|
:param surface: The surface for the text to be drawn on.
|
||||||
|
"""
|
||||||
|
# Constants to help draw the text
|
||||||
|
line_separation = 7
|
||||||
|
left_margin = 3
|
||||||
|
top_margin = 25
|
||||||
|
bottom_margin = 10
|
||||||
|
|
||||||
|
# Draw the lines on the screen
|
||||||
|
for i in range(min(len(self.text), self.max_lines)):
|
||||||
|
text = self.font.render(self.text[i + self.offset], False, (64, 64, 64))
|
||||||
|
surface.blit(text, (left_margin, top_margin + (i * line_separation)))
|
||||||
|
|
||||||
|
# Draw the arrows if there is more text than is on screen.
|
||||||
|
if self.offset != 0:
|
||||||
|
surface.blit(self.up_arrow, ((self.game_res / 2) - (self.up_arrow.get_rect().width / 2), top_margin - 3))
|
||||||
|
if len(self.text) - (self.offset + 1) >= self.max_lines:
|
||||||
|
surface.blit(self.down_arrow,
|
||||||
|
((self.game_res / 2) - (self.down_arrow.get_rect().width / 2), self.game_res - bottom_margin))
|
||||||
|
|
||||||
|
def scroll_down(self):
|
||||||
|
"""
|
||||||
|
Scrolls the text on the screen down.
|
||||||
|
"""
|
||||||
|
# Ensures that the offset cannot be too big as to try to render non-existent lines.
|
||||||
|
if len(self.text) - (self.offset + 1) >= self.max_lines:
|
||||||
|
self.offset += 1
|
||||||
|
|
||||||
|
def scroll_up(self):
|
||||||
|
"""
|
||||||
|
Scrolls the text on the screen up.
|
||||||
|
"""
|
||||||
|
if self.offset > 0: # Ensures a non-zero offset is not possible.
|
||||||
|
self.offset -= 1
|
||||||
|
|
||||||
|
|
||||||
|
class EggInfo:
|
||||||
|
"""
|
||||||
|
Class to draw the contentedness and metabolism value off the egg on the info screen.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, resources_dir, contentedness, metabolism, location):
|
||||||
|
self.contentedness = contentedness
|
||||||
|
self.metabolism = metabolism
|
||||||
|
self.x = location[0]
|
||||||
|
self.y = location[1]
|
||||||
|
|
||||||
|
# Create a new surface to blit onto the other surface
|
||||||
|
self.surface = pygame.Surface((44, 15), pygame.SRCALPHA)
|
||||||
|
|
||||||
|
# Blit the two indicator icons on screen
|
||||||
|
smiley = pygame.image.load(resources_dir + '/images/gui/smiley.png').convert_alpha()
|
||||||
|
self.surface.blit(smiley, (0, 0))
|
||||||
|
apple = pygame.image.load(resources_dir + '/images/gui/apple.png').convert_alpha()
|
||||||
|
self.surface.blit(apple, (1, 9))
|
||||||
|
|
||||||
|
# Draw 5 stars. If the value of the contentedness is less than the current star, make it a blank star.
|
||||||
|
for i in range(5):
|
||||||
|
if i < self.contentedness:
|
||||||
|
star = pygame.image.load(resources_dir + '/images/gui/star.png').convert_alpha()
|
||||||
|
else:
|
||||||
|
star = pygame.image.load(resources_dir + '/images/gui/blank_star.png').convert_alpha()
|
||||||
|
self.surface.blit(star, (11 + (i * 6), 1))
|
||||||
|
|
||||||
|
# Draw 5 stars. If the value of the metabolism is less than the current star, make it a blank star.
|
||||||
|
for i in range(5):
|
||||||
|
if i < self.metabolism:
|
||||||
|
star = pygame.image.load(resources_dir + '/images/gui/star.png').convert_alpha()
|
||||||
|
else:
|
||||||
|
star = pygame.image.load(resources_dir + '/images/gui/blank_star.png').convert_alpha()
|
||||||
|
self.surface.blit(star, (11 + (i * 6), 10))
|
||||||
|
|
||||||
|
def draw(self, surface):
|
||||||
|
"""
|
||||||
|
Draw the info icons on a given surface.
|
||||||
|
:param surface: the surface to draw the icons on.
|
||||||
|
"""
|
||||||
|
# Blit the info onto the given surface.
|
||||||
|
surface.blit(self.surface, (self.x, self.y))
|
File diff suppressed because it is too large
Load Diff
2
pocket_friends/game_files/io/__init__.py
Normal file
2
pocket_friends/game_files/io/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
"""Sub-package for handling all I/O operations including keyboard input (GPIO input when connected to a Raspberry Pi)
|
||||||
|
and save data reading and writing."""
|
55
pocket_friends/game_files/io/data.py
Normal file
55
pocket_friends/game_files/io/data.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import pocket_friends
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class SaveData:
|
||||||
|
"""
|
||||||
|
Class used to read and write save data for the game
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
attributes (dict): Dictionary containing all the attributes to read and write from a save file.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Constructs the object with all starting values.
|
||||||
|
"""
|
||||||
|
# Attributes that are saved to a file to recover upon startup.
|
||||||
|
self.attributes = {
|
||||||
|
'version': pocket_friends.__version__,
|
||||||
|
'time_elapsed': 0,
|
||||||
|
'bloop': '',
|
||||||
|
'age': 0,
|
||||||
|
'health': 0,
|
||||||
|
'hunger': 0,
|
||||||
|
'happiness': 0,
|
||||||
|
'care_counter': 0,
|
||||||
|
'missed_care': 0,
|
||||||
|
'adult': 0,
|
||||||
|
'evolution_stage': '',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Frame counter
|
||||||
|
self.frames_passed = 0
|
||||||
|
|
||||||
|
def write_save(self):
|
||||||
|
"""
|
||||||
|
Writes attributes of the save object to "save.json" file.
|
||||||
|
"""
|
||||||
|
with open(save_dir + '/save.json', 'w') as save_file:
|
||||||
|
json.dump(self.attributes, save_file)
|
||||||
|
save_file.close()
|
||||||
|
|
||||||
|
def read_save(self):
|
||||||
|
"""
|
||||||
|
Reads from "save.json" and inserts into the save object's attributes dictionary. Creates file if it does not
|
||||||
|
exist.
|
||||||
|
"""
|
||||||
|
# Open up the save file and read it into self.attributes.
|
||||||
|
try:
|
||||||
|
with open(save_dir + '/save.json', 'r') as save_file:
|
||||||
|
self.attributes = json.load(save_file)
|
||||||
|
save_file.close()
|
||||||
|
|
||||||
|
# If there is no save file, write one with the defaults.
|
||||||
|
except FileNotFoundError:
|
||||||
|
self.write_save()
|
@@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
Module used to fake the RPi.GPIO module so that
|
Dummy module that contains empty functions and variables that exist in RPi.GPIO. This module is to be imported
|
||||||
the hardware can be run without the actual hardware.
|
if importing RPi.GPIO fails.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Constants used by RPi.GPIO
|
# Constants used by RPi.GPIO
|
||||||
@@ -12,7 +12,11 @@ FALLING = 0
|
|||||||
def setmode(new_mode):
|
def setmode(new_mode):
|
||||||
"""
|
"""
|
||||||
Fake setmode function.
|
Fake setmode function.
|
||||||
:param new_mode:
|
Args:
|
||||||
|
new_mode:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -20,10 +24,14 @@ def setmode(new_mode):
|
|||||||
def setup(channel, mode, initial=None, pull_up_down=None):
|
def setup(channel, mode, initial=None, pull_up_down=None):
|
||||||
"""
|
"""
|
||||||
Fake setup function.
|
Fake setup function.
|
||||||
:param channel:
|
Args:
|
||||||
:param mode:
|
channel:
|
||||||
:param initial:
|
mode:
|
||||||
:param pull_up_down:
|
initial:
|
||||||
|
pull_up_down:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -31,10 +39,14 @@ def setup(channel, mode, initial=None, pull_up_down=None):
|
|||||||
def add_event_detect(channel, edge_type, callback=None, bouncetime=0):
|
def add_event_detect(channel, edge_type, callback=None, bouncetime=0):
|
||||||
"""
|
"""
|
||||||
Fake function to add a non-existent event detect.
|
Fake function to add a non-existent event detect.
|
||||||
:param channel:
|
Args:
|
||||||
:param edge_type:
|
channel:
|
||||||
:param callback:
|
edge_type:
|
||||||
:param bouncetime:
|
callback:
|
||||||
|
bouncetime:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -42,8 +54,11 @@ def add_event_detect(channel, edge_type, callback=None, bouncetime=0):
|
|||||||
def event_detected(channel):
|
def event_detected(channel):
|
||||||
"""
|
"""
|
||||||
Fake function to detect an event. Always returns false.
|
Fake function to detect an event. Always returns false.
|
||||||
:param channel:
|
Args:
|
||||||
:return:
|
channel:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -51,6 +66,10 @@ def event_detected(channel):
|
|||||||
def cleanup(channel=None):
|
def cleanup(channel=None):
|
||||||
"""
|
"""
|
||||||
Fake cleanup function.
|
Fake cleanup function.
|
||||||
:param channel:
|
Args:
|
||||||
|
channel:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
65
pocket_friends/game_files/io/gpio_handler.py
Normal file
65
pocket_friends/game_files/io/gpio_handler.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
"""Handle inputs from the GPIO pins on the Raspberry Pi and converting them to events to be used in other places (
|
||||||
|
pygame, etc.)"""
|
||||||
|
import importlib.util
|
||||||
|
|
||||||
|
# If the RPi.GPIO module is not found (aka the program is not running on a Pi), import the fake
|
||||||
|
# GPIO module instead to prevent a crash.
|
||||||
|
|
||||||
|
ON_HARDWARE = None # Flag to tell other methods if the program is running on hardware or not
|
||||||
|
|
||||||
|
try:
|
||||||
|
importlib.util.find_spec('RPi.GPIO')
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
|
ON_HARDWARE = True
|
||||||
|
except ImportError:
|
||||||
|
import pocket_friends.game_files.io.fake_gpio as GPIO
|
||||||
|
ON_HARDWARE = False
|
||||||
|
|
||||||
|
# Dictionary of all the buttons used and what their corresponding GPIO codes are
|
||||||
|
BUTTONS = {
|
||||||
|
'a': 31, # A button
|
||||||
|
'b': 29, # B button
|
||||||
|
'j_i': 7, # Joystick in
|
||||||
|
'j_u': 11, # Joystick up
|
||||||
|
'j_d': 15, # Joystick down
|
||||||
|
'j_l': 13, # Joystick left
|
||||||
|
'j_r': 16 # Joystick right
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
"""Prime the GPIO pins for reading the inputs of the buttons."""
|
||||||
|
GPIO.setmode(GPIO.BOARD)
|
||||||
|
|
||||||
|
GPIO.setup(BUTTONS.get('a'), GPIO.IN)
|
||||||
|
GPIO.setup(BUTTONS.get('b'), GPIO.IN)
|
||||||
|
GPIO.setup(BUTTONS.get('j_i'), GPIO.IN)
|
||||||
|
GPIO.setup(BUTTONS.get('j_u'), GPIO.IN)
|
||||||
|
GPIO.setup(BUTTONS.get('j_d'), GPIO.IN)
|
||||||
|
GPIO.setup(BUTTONS.get('j_l'), GPIO.IN)
|
||||||
|
GPIO.setup(BUTTONS.get('j_r'), GPIO.IN)
|
||||||
|
|
||||||
|
GPIO.add_event_detect(BUTTONS.get('a'), GPIO.FALLING)
|
||||||
|
GPIO.add_event_detect(BUTTONS.get('b'), GPIO.FALLING)
|
||||||
|
GPIO.add_event_detect(BUTTONS.get('j_i'), GPIO.FALLING)
|
||||||
|
GPIO.add_event_detect(BUTTONS.get('j_u'), GPIO.FALLING)
|
||||||
|
GPIO.add_event_detect(BUTTONS.get('j_d'), GPIO.FALLING)
|
||||||
|
GPIO.add_event_detect(BUTTONS.get('j_l'), GPIO.FALLING)
|
||||||
|
GPIO.add_event_detect(BUTTONS.get('j_r'), GPIO.FALLING)
|
||||||
|
|
||||||
|
|
||||||
|
def teardown():
|
||||||
|
"""Clean up the GPIO handler."""
|
||||||
|
GPIO.cleanup()
|
||||||
|
|
||||||
|
|
||||||
|
def get_press(button):
|
||||||
|
"""
|
||||||
|
Checks if a given button code has been pressed and returns a bool depending on the state.
|
||||||
|
Args:
|
||||||
|
button: button to be detected
|
||||||
|
|
||||||
|
Returns: True if the button is has been pressed, False otherwise
|
||||||
|
|
||||||
|
"""
|
||||||
|
return GPIO.event_detected(button)
|
81
pocket_friends/game_files/io/input_handler.py
Normal file
81
pocket_friends/game_files/io/input_handler.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import pygame
|
||||||
|
import pocket_friends.game_files.io.gpio_handler as gpio_handler
|
||||||
|
|
||||||
|
|
||||||
|
class InputHandler:
|
||||||
|
"""
|
||||||
|
Class that is implemented into surfaces in order to control the
|
||||||
|
pressing of buttons on both the real hardware and on a keyboard.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
clock (pygame.time.Clock): Pygame clock used for input time calculations.
|
||||||
|
last_input_tick (int): The tick that the last input was registered on.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, pygame_clock):
|
||||||
|
"""
|
||||||
|
Create a InputHandler object using a given Pygame clock.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pygame_clock (pygame.time.Clock): A pygame clock to use as the clock for input time calculations.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.clock = pygame_clock
|
||||||
|
self.last_input_tick = 0
|
||||||
|
|
||||||
|
def create_event(self, pressed_button):
|
||||||
|
"""
|
||||||
|
Create a pygame event given a GPIO code and post it to the pygame event handler.
|
||||||
|
Args:
|
||||||
|
pressed_button (int): The GPIO code to be registered and pressed.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Register a button click so long as the last button click happened no less than two frames ago
|
||||||
|
if pygame.time.get_ticks() - self.last_input_tick > self.clock.get_time() * 2 or not gpio_handler.ON_HARDWARE:
|
||||||
|
pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'key': pressed_button}))
|
||||||
|
pygame.event.post(pygame.event.Event(pygame.KEYUP, {'key': pressed_button}))
|
||||||
|
self.last_input_tick = pygame.time.get_ticks()
|
||||||
|
|
||||||
|
def handle_gpio(self):
|
||||||
|
"""
|
||||||
|
Handle GPIO events and create events for them.
|
||||||
|
"""
|
||||||
|
for pressed_button in gpio_handler.BUTTONS:
|
||||||
|
code = gpio_handler.BUTTONS.get(pressed_button)
|
||||||
|
|
||||||
|
# Check if a button has been pressed. If it has, create a pygame event for it.
|
||||||
|
if gpio_handler.get_press(code):
|
||||||
|
self.create_event(code)
|
||||||
|
|
||||||
|
def handle_keyboard(self):
|
||||||
|
"""Handle keyboard presses and generate corresponding GPIO codes to create events."""
|
||||||
|
|
||||||
|
# Checks if a corresponding keyboard key has been pressed. If it has, emulate a button press.
|
||||||
|
for keyboard_event in pygame.event.get():
|
||||||
|
if keyboard_event.type == pygame.QUIT:
|
||||||
|
running = False
|
||||||
|
if keyboard_event.type == pygame.KEYDOWN:
|
||||||
|
if keyboard_event.key == pygame.K_a:
|
||||||
|
self.create_event(gpio_handler.BUTTONS.get('a'))
|
||||||
|
if keyboard_event.key == pygame.K_b:
|
||||||
|
self.create_event(gpio_handler.BUTTONS.get('b'))
|
||||||
|
if keyboard_event.key == pygame.K_PERIOD:
|
||||||
|
self.create_event(gpio_handler.BUTTONS.get('j_i'))
|
||||||
|
if keyboard_event.key == pygame.K_RIGHT:
|
||||||
|
self.create_event(gpio_handler.BUTTONS.get('j_r'))
|
||||||
|
if keyboard_event.key == pygame.K_LEFT:
|
||||||
|
self.create_event(gpio_handler.BUTTONS.get('j_l'))
|
||||||
|
if keyboard_event.key == pygame.K_DOWN:
|
||||||
|
self.create_event(gpio_handler.BUTTONS.get('j_d'))
|
||||||
|
if keyboard_event.key == pygame.K_UP:
|
||||||
|
self.create_event(gpio_handler.BUTTONS.get('j_u'))
|
||||||
|
if keyboard_event.key == pygame.K_ESCAPE:
|
||||||
|
running = False
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""Run either the GPIO handler or the keyboard handler to check for input and create events."""
|
||||||
|
if gpio_handler.ON_HARDWARE:
|
||||||
|
self.handle_gpio()
|
||||||
|
else:
|
||||||
|
self.handle_keyboard()
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
147
pocket_friends/game_files/surfaces/egg_select.py
Normal file
147
pocket_friends/game_files/surfaces/egg_select.py
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import pygame
|
||||||
|
from ..elements import sprites
|
||||||
|
import pocket_friends.game_files.io.gpio_handler as gpio_handler
|
||||||
|
from ..io.input_handler import InputHandler
|
||||||
|
|
||||||
|
|
||||||
|
class Surface(pygame.Surface):
|
||||||
|
def __init__(self, window_size, resources_dir, game_fps, **kwargs):
|
||||||
|
super().__init__(window_size, pygame.SRCALPHA)
|
||||||
|
self.name = 'egg_select'
|
||||||
|
self.running = True
|
||||||
|
self.next_surface = None
|
||||||
|
self.resource_dir = resources_dir
|
||||||
|
self.clock = pygame.time.Clock()
|
||||||
|
self.game_fps = game_fps
|
||||||
|
self.input_handler = InputHandler(self.clock)
|
||||||
|
self.additional_args = {}
|
||||||
|
|
||||||
|
self.bg = pygame.image.load(self.resource_dir + '/images/bg.png').convert_alpha()
|
||||||
|
self.sprites = pygame.sprite.Group()
|
||||||
|
|
||||||
|
preselected_color = None
|
||||||
|
for key in kwargs.keys():
|
||||||
|
if key == 'selected_color':
|
||||||
|
preselected_color = kwargs.get(key)
|
||||||
|
|
||||||
|
egg_list = [
|
||||||
|
'dev_egg',
|
||||||
|
'blue',
|
||||||
|
'rainbow'
|
||||||
|
]
|
||||||
|
self.eggs = []
|
||||||
|
for egg in egg_list:
|
||||||
|
self.eggs.append(sprites.SelectionEgg(egg, self.resource_dir))
|
||||||
|
|
||||||
|
self.eggs_per_row = 3
|
||||||
|
distance_between_eggs = 36 / self.eggs_per_row
|
||||||
|
|
||||||
|
# Count the total rows.
|
||||||
|
self.total_rows = -(-len(self.eggs) // self.eggs_per_row)
|
||||||
|
distance_between_rows = 32 / self.eggs_per_row
|
||||||
|
|
||||||
|
# Determine the location of each egg.
|
||||||
|
for egg in self.eggs:
|
||||||
|
current_row = self.eggs.index(egg) // self.eggs_per_row
|
||||||
|
rows_after = self.total_rows - (current_row + 1)
|
||||||
|
egg_in_row = self.eggs.index(egg) % self.eggs_per_row
|
||||||
|
eggs_after = min(len(self.eggs) - (current_row * self.eggs_per_row), self.eggs_per_row) - (egg_in_row + 1)
|
||||||
|
|
||||||
|
x_offset = 32
|
||||||
|
y_offset = 30
|
||||||
|
|
||||||
|
# The x coordinate of an egg is determined by which egg in the row it is, and how many eggs
|
||||||
|
# are in that row. If there is only 1 egg in a row, it is in the middle of the screen. If
|
||||||
|
# there are two, they're on equal halves and so on.
|
||||||
|
x = x_offset - (eggs_after * distance_between_eggs) + (egg_in_row * distance_between_eggs)
|
||||||
|
y = y_offset - (rows_after * distance_between_rows) + (current_row * distance_between_rows)
|
||||||
|
|
||||||
|
egg.rect.x = x
|
||||||
|
egg.rect.y = y
|
||||||
|
|
||||||
|
# Add the egg to the sprite list.
|
||||||
|
self.sprites.add(egg)
|
||||||
|
|
||||||
|
self.selected_egg = 0
|
||||||
|
self.selected_color = ''
|
||||||
|
if preselected_color is not None:
|
||||||
|
self.selected_color = self.eggs[self.selected_egg].egg_color
|
||||||
|
for i in range(len(self.eggs)):
|
||||||
|
if self.eggs[i].egg_color == preselected_color:
|
||||||
|
self.selected_egg = i
|
||||||
|
|
||||||
|
def get_cursor_coords(self):
|
||||||
|
"""
|
||||||
|
Gets the coordinates of an egg on the selection screen by index and returns it as a tuple
|
||||||
|
:return: tuple of the coordinates of the selected egg
|
||||||
|
"""
|
||||||
|
cursor_x_offset = -2
|
||||||
|
cursor_y_offset = -2
|
||||||
|
|
||||||
|
return (self.eggs[self.selected_egg].rect.x + cursor_x_offset,
|
||||||
|
self.eggs[self.selected_egg].rect.y + cursor_y_offset)
|
||||||
|
|
||||||
|
def sel_left(self):
|
||||||
|
"""
|
||||||
|
Select the egg to the left with constraints.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.selected_egg % self.eggs_per_row != 0:
|
||||||
|
self.selected_egg -= 1
|
||||||
|
|
||||||
|
def sel_right(self):
|
||||||
|
"""
|
||||||
|
Select the egg to the right with constraints.
|
||||||
|
"""
|
||||||
|
|
||||||
|
row = self.selected_egg // self.eggs_per_row
|
||||||
|
eggs_in_row = min(len(self.eggs) - (row * self.eggs_per_row), self.eggs_per_row)
|
||||||
|
|
||||||
|
if self.selected_egg % self.eggs_per_row != eggs_in_row - 1:
|
||||||
|
self.selected_egg += 1
|
||||||
|
|
||||||
|
def sel_up(self):
|
||||||
|
"""
|
||||||
|
Select the egg above with constraints.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.selected_egg // self.eggs_per_row != 0:
|
||||||
|
self.selected_egg -= self.eggs_per_row
|
||||||
|
|
||||||
|
def sel_down(self):
|
||||||
|
"""
|
||||||
|
Select the egg below with constraints.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.selected_egg // self.eggs_per_row != self.total_rows - 1:
|
||||||
|
self.selected_egg += self.eggs_per_row
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.clock.tick(self.game_fps)
|
||||||
|
|
||||||
|
self.blit(self.bg, (0, 0))
|
||||||
|
self.sprites.update()
|
||||||
|
self.sprites.draw(self)
|
||||||
|
|
||||||
|
self.input_handler.update()
|
||||||
|
|
||||||
|
cursor = pygame.image.load(
|
||||||
|
self.resource_dir + '/images/gui/egg_selector.png').convert_alpha()
|
||||||
|
self.blit(cursor, self.get_cursor_coords())
|
||||||
|
|
||||||
|
self.selected_color = self.eggs[self.selected_egg].egg_color
|
||||||
|
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.KEYDOWN:
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('j_r'):
|
||||||
|
self.sel_right()
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('j_l'):
|
||||||
|
self.sel_left()
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('j_d'):
|
||||||
|
self.sel_down()
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('j_u'):
|
||||||
|
self.sel_up()
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('a'):
|
||||||
|
self.additional_args = {'selected_egg': self.selected_color}
|
||||||
|
self.next_surface = 'selection_info'
|
||||||
|
self.running = False
|
70
pocket_friends/game_files/surfaces/selection_info.py
Normal file
70
pocket_friends/game_files/surfaces/selection_info.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import pygame
|
||||||
|
from ..elements import sprites
|
||||||
|
import pocket_friends.game_files.io.gpio_handler as gpio_handler
|
||||||
|
from ..io.input_handler import InputHandler
|
||||||
|
|
||||||
|
|
||||||
|
class Surface(pygame.Surface):
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, window_size, resources_dir, game_fps, **kwargs):
|
||||||
|
"""
|
||||||
|
|
||||||
|
Args:
|
||||||
|
window_size:
|
||||||
|
resources_dir:
|
||||||
|
game_fps:
|
||||||
|
**kwargs:
|
||||||
|
"""
|
||||||
|
super().__init__(window_size, pygame.SRCALPHA)
|
||||||
|
self.name = 'selection_info'
|
||||||
|
self.running = True
|
||||||
|
self.next_surface = None
|
||||||
|
self.resource_dir = resources_dir
|
||||||
|
self.clock = pygame.time.Clock()
|
||||||
|
self.game_fps = game_fps
|
||||||
|
self.input_handler = InputHandler(self.clock)
|
||||||
|
self.additional_args = {}
|
||||||
|
|
||||||
|
self.bg = pygame.image.load(self.resource_dir + '/images/bg.png').convert_alpha()
|
||||||
|
self.sprites = pygame.sprite.Group()
|
||||||
|
|
||||||
|
self.selected_egg = None
|
||||||
|
for key in kwargs.keys():
|
||||||
|
if key == 'selected_egg':
|
||||||
|
self.selected_egg = kwargs.get(key)
|
||||||
|
|
||||||
|
egg = sprites.SelectionEgg(self.selected_egg, resources_dir)
|
||||||
|
egg.rect.x = 8
|
||||||
|
egg.rect.y = 3
|
||||||
|
self.sprites.add(egg)
|
||||||
|
|
||||||
|
self.info_text = sprites.InfoText(resources_dir, window_size[0], egg.description)
|
||||||
|
self.info_icons = sprites.EggInfo(resources_dir, egg.contentedness, egg.metabolism, (32, 4))
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.clock.tick(self.game_fps)
|
||||||
|
|
||||||
|
self.blit(self.bg, (0, 0))
|
||||||
|
self.sprites.update()
|
||||||
|
self.sprites.draw(self)
|
||||||
|
self.info_text.draw(self)
|
||||||
|
self.info_icons.draw(self)
|
||||||
|
|
||||||
|
self.input_handler.update()
|
||||||
|
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.KEYDOWN:
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('j_d'):
|
||||||
|
# Scroll down on the info screen.
|
||||||
|
self.info_text.scroll_down()
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('j_u'):
|
||||||
|
# Scroll up on the info screen.
|
||||||
|
self.info_text.scroll_up()
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('a'):
|
||||||
|
pass
|
||||||
|
if event.key == gpio_handler.BUTTONS.get('b'):
|
||||||
|
self.running = False
|
||||||
|
self.additional_args = {'selected_color': self.selected_egg}
|
||||||
|
self.next_surface = 'egg_select'
|
28
pocket_friends/game_files/surfaces/title.py
Normal file
28
pocket_friends/game_files/surfaces/title.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import pygame
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Surface(pygame.Surface):
|
||||||
|
def __init__(self, window_size, resources_dir, game_fps):
|
||||||
|
super().__init__(window_size, pygame.SRCALPHA)
|
||||||
|
self.name = 'title'
|
||||||
|
self.running = True
|
||||||
|
self.next_surface = None
|
||||||
|
self.clock = pygame.time.Clock()
|
||||||
|
self.additional_args = {}
|
||||||
|
|
||||||
|
self.bg = pygame.image.load(resources_dir + '/images/bg.png').convert_alpha()
|
||||||
|
self.title = pygame.image.load(resources_dir + '/images/title.png').convert_alpha()
|
||||||
|
self.frames = 1
|
||||||
|
self.game_fps = game_fps
|
||||||
|
self.delay = 1
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.clock.tick(self.game_fps)
|
||||||
|
self.blit(self.bg, (0, 0))
|
||||||
|
self.blit(self.title, (0, 0))
|
||||||
|
|
||||||
|
self.frames += 1
|
||||||
|
if self.frames > self.game_fps * self.delay:
|
||||||
|
self.next_surface = 'egg_select'
|
||||||
|
self.running = False
|
@@ -1,71 +0,0 @@
|
|||||||
"""
|
|
||||||
Module that helps with the handling of taking inputs from the GPIO pins on the Raspberry
|
|
||||||
Pi and converting them to events to be used in other places (pygame, etc.)
|
|
||||||
"""
|
|
||||||
import importlib.util
|
|
||||||
|
|
||||||
try:
|
|
||||||
importlib.util.find_spec('RPi.GPIO')
|
|
||||||
import RPi.GPIO as GPIO
|
|
||||||
except ImportError:
|
|
||||||
import pocket_friends.development.FakeGPIO as GPIO
|
|
||||||
|
|
||||||
|
|
||||||
class Constants:
|
|
||||||
"""
|
|
||||||
Contains the constants used by the HAT to read in buttons
|
|
||||||
"""
|
|
||||||
buttons = {
|
|
||||||
'a': 31, # A button
|
|
||||||
'b': 29, # B button
|
|
||||||
'j_i': 7, # Joystick in
|
|
||||||
'j_u': 11, # Joystick up
|
|
||||||
'j_d': 15, # Joystick down
|
|
||||||
'j_l': 13, # Joystick left
|
|
||||||
'j_r': 16 # Joystick right
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class GPIOHandler:
|
|
||||||
"""
|
|
||||||
Class to handle the GPIO inputs from the buttons.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def setup():
|
|
||||||
"""
|
|
||||||
Primes the GPIO pins for reading the inputs of the buttons.
|
|
||||||
"""
|
|
||||||
GPIO.setmode(GPIO.BOARD)
|
|
||||||
|
|
||||||
GPIO.setup(Constants.buttons.get('a'), GPIO.IN)
|
|
||||||
GPIO.setup(Constants.buttons.get('b'), GPIO.IN)
|
|
||||||
GPIO.setup(Constants.buttons.get('j_i'), GPIO.IN)
|
|
||||||
GPIO.setup(Constants.buttons.get('j_u'), GPIO.IN)
|
|
||||||
GPIO.setup(Constants.buttons.get('j_d'), GPIO.IN)
|
|
||||||
GPIO.setup(Constants.buttons.get('j_l'), GPIO.IN)
|
|
||||||
GPIO.setup(Constants.buttons.get('j_r'), GPIO.IN)
|
|
||||||
|
|
||||||
GPIO.add_event_detect(Constants.buttons.get('a'), GPIO.FALLING)
|
|
||||||
GPIO.add_event_detect(Constants.buttons.get('b'), GPIO.FALLING)
|
|
||||||
GPIO.add_event_detect(Constants.buttons.get('j_i'), GPIO.FALLING)
|
|
||||||
GPIO.add_event_detect(Constants.buttons.get('j_u'), GPIO.FALLING)
|
|
||||||
GPIO.add_event_detect(Constants.buttons.get('j_d'), GPIO.FALLING)
|
|
||||||
GPIO.add_event_detect(Constants.buttons.get('j_l'), GPIO.FALLING)
|
|
||||||
GPIO.add_event_detect(Constants.buttons.get('j_r'), GPIO.FALLING)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def teardown():
|
|
||||||
"""
|
|
||||||
Cleans up the GPIO handler.
|
|
||||||
"""
|
|
||||||
GPIO.cleanup()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_press(button):
|
|
||||||
"""
|
|
||||||
Returns true if a button has moved from not pressed to pressed.
|
|
||||||
:param button: button to be detected
|
|
||||||
:return: True if the button is has been pressed, False otherwise
|
|
||||||
"""
|
|
||||||
return GPIO.event_detected(button)
|
|
@@ -1 +1 @@
|
|||||||
pygame==1.9.4
|
pygame~=2.1.2
|
4
setup.py
4
setup.py
@@ -15,12 +15,12 @@ setuptools.setup(
|
|||||||
license='GNU GPL-3.0',
|
license='GNU GPL-3.0',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
url='https://github.com/nickedyer/pocket-friends',
|
url='https://gitea.citruxx.com/ndyer/pocket-friends',
|
||||||
packages=setuptools.find_packages(),
|
packages=setuptools.find_packages(),
|
||||||
# https://pypi.org/classifiers/
|
# https://pypi.org/classifiers/
|
||||||
classifiers=[
|
classifiers=[
|
||||||
],
|
],
|
||||||
install_requires=required,
|
install_requires=required,
|
||||||
python_requires='>=3.6',
|
python_requires='>=3.10',
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user