gpio input translated to command events
This commit is contained in:
parent
ac9c5cdf4c
commit
f0b77551b6
60
OPEN-GAME
60
OPEN-GAME
|
@ -1,42 +1,38 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from os import environ, execvp, chdir, getcwd
|
import sys, os
|
||||||
from os.path import exists, join, dirname
|
|
||||||
from sys import version_info, argv
|
|
||||||
|
|
||||||
def can_import(module_name):
|
def ignore_sighup():
|
||||||
try:
|
"""
|
||||||
__import__(module_name)
|
Ignore hangup signal (that is thrown when launching from systemd?).
|
||||||
except ImportError:
|
Taken from https://stackoverflow.com/questions/57205271/how-to-display-pygame-framebuffer-using-systemd-service
|
||||||
return False
|
"""
|
||||||
else:
|
import signal
|
||||||
return True
|
def handler(signum, frame):
|
||||||
|
pass
|
||||||
|
signal.signal(signal.SIGHUP, handler)
|
||||||
|
|
||||||
def is_python_3():
|
# Change directory to the directory of the program launching the script (usually this script "OPEN-GAME").
|
||||||
return version_info[0] >= 3
|
if "--go-to-dir" in sys.argv:
|
||||||
|
os.chdir(os.path.dirname(sys.argv[0]))
|
||||||
|
|
||||||
def is_current_version(file_name):
|
# Use the KMS video driver. This works for newer versions of Raspberry Pi with the KMS overlay
|
||||||
version = map(int, file_name.replace("python", "").split("."))
|
# enabled, SDL 2, and Pygame 2.
|
||||||
return version == list(version_info)[:2]
|
if "--kms" in sys.argv:
|
||||||
|
os.putenv("SDL_VIDEODRIVER", "kmsdrm")
|
||||||
|
|
||||||
def launch_alternative(alternatives):
|
# Use the framebuffer display. This only works with Pygame 1.9.6 (and SDL 1.2).
|
||||||
for alternative in alternatives:
|
if "--fb" in sys.argv:
|
||||||
if not is_current_version(alternative):
|
os.putenv("SDL_VIDEODRIVER", "fbcon")
|
||||||
for root in environ["PATH"].split(":"):
|
os.putenv("SDL_FBDEV", "/dev/fb0")
|
||||||
if exists(join(root, alternative)):
|
|
||||||
execvp(alternative, [alternative] + argv)
|
|
||||||
|
|
||||||
def move_to_executable():
|
# Ignore hangup signal. This may be necessary when launching from systemd.
|
||||||
chdir(dirname(argv[0]))
|
if "--ignore-hangup" in sys.argv:
|
||||||
|
ignore_sighup()
|
||||||
|
|
||||||
if is_python_3():
|
# Import GPIO library if requested
|
||||||
launch_alternative(["python2", "python2.7", "python2.6"])
|
if "--gpio" in sys.argv:
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
if not can_import("pygame"):
|
|
||||||
launch_alternative(["python2.7", "python2.6"])
|
|
||||||
|
|
||||||
if "--go-to-dir" in argv:
|
|
||||||
move_to_executable()
|
|
||||||
|
|
||||||
from electric_sieve.ElectricSieve import ElectricSieve
|
from electric_sieve.ElectricSieve import ElectricSieve
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import os
|
|
||||||
from os import environ, execvp, chdir, getcwd
|
|
||||||
from os.path import exists, join, dirname
|
|
||||||
from sys import version_info, argv
|
|
||||||
|
|
||||||
def can_import(module_name):
|
|
||||||
try:
|
|
||||||
__import__(module_name)
|
|
||||||
except ImportError:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def is_python_3():
|
|
||||||
return version_info[0] >= 3
|
|
||||||
|
|
||||||
def is_current_version(file_name):
|
|
||||||
version = map(int, file_name.replace("python", "").split("."))
|
|
||||||
return version == list(version_info)[:2]
|
|
||||||
|
|
||||||
def launch_alternative(alternatives):
|
|
||||||
for alternative in alternatives:
|
|
||||||
if not is_current_version(alternative):
|
|
||||||
for root in environ["PATH"].split(":"):
|
|
||||||
if exists(join(root, alternative)):
|
|
||||||
execvp(alternative, [alternative] + argv)
|
|
||||||
|
|
||||||
def move_to_executable():
|
|
||||||
chdir(dirname(argv[0]))
|
|
||||||
|
|
||||||
if is_python_3():
|
|
||||||
launch_alternative(["python2", "python2.7", "python2.6"])
|
|
||||||
|
|
||||||
if not can_import("pygame"):
|
|
||||||
launch_alternative(["python2.7", "python2.6"])
|
|
||||||
|
|
||||||
if "--go-to-dir" in argv:
|
|
||||||
move_to_executable()
|
|
||||||
|
|
||||||
from electric_sieve.ElectricSieve import ElectricSieve
|
|
||||||
|
|
||||||
os.putenv("SDL_FBDEV", "/dev/fb0")
|
|
||||||
os.putenv("SDL_VIDEODRIVER", "fbcon")
|
|
||||||
os.putenv("SDL_NOMOUSE", "1")
|
|
||||||
ElectricSieve().run()
|
|
|
@ -1,26 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import sys, os
|
|
||||||
|
|
||||||
def ignore_sighup():
|
|
||||||
"""
|
|
||||||
Ignore hangup signal (that is thrown when launching from systemd?).
|
|
||||||
Taken from https://stackoverflow.com/questions/57205271/how-to-display-pygame-framebuffer-using-systemd-service
|
|
||||||
"""
|
|
||||||
import signal
|
|
||||||
def handler(signum, frame):
|
|
||||||
pass
|
|
||||||
signal.signal(signal.SIGHUP, handler)
|
|
||||||
|
|
||||||
# Change directory to the directory of the program launching the script (usually this script "OPEN-GAME").
|
|
||||||
if "--go-to-dir" in sys.argv:
|
|
||||||
os.chdir(os.path.dirname(sys.argv[0]))
|
|
||||||
|
|
||||||
# Use the KMS video driver. This works for newer versions of Raspberry Pi with the KMS overlay
|
|
||||||
# enabled, SDL 2, and Pygame 2.
|
|
||||||
os.putenv("SDL_VIDEODRIVER", "kmsdrm")
|
|
||||||
# ignore_sighup()
|
|
||||||
|
|
||||||
from electric_sieve.ElectricSieve import ElectricSieve
|
|
||||||
|
|
||||||
ElectricSieve().run()
|
|
19
README.md
19
README.md
|
@ -1,12 +1,12 @@
|
||||||
Electric Sieve
|
Electric Sieve
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Avoid touching the triangles with the rods. Chain successes to send acid deeper into the Earth.
|
Avoid touching the triangles with the rods
|
||||||
|
|
||||||
Controls
|
Controls
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* L/R - Scroll sieve
|
* Left/Right - Scroll sieve
|
||||||
* Down - Increase fall speed
|
* Down - Increase fall speed
|
||||||
* F11 - Full screen
|
* F11 - Full screen
|
||||||
|
|
||||||
|
@ -20,4 +20,17 @@ Running
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* Windows - double-click "scale-sieve" EXE
|
* Windows - double-click "scale-sieve" EXE
|
||||||
* Linux/Mac - run "./scale-sieve" on the command line
|
* Linux/Mac - run `./OPEN-GAME` on the command line
|
||||||
|
|
||||||
|
Raspberry Pi
|
||||||
|
------------
|
||||||
|
|
||||||
|
Add `--gpio` to the command line to read input from buttons wired to the Raspberry Pi (the buttons should be wired to GPIO 17 and 27).
|
||||||
|
|
||||||
|
Headless
|
||||||
|
--------
|
||||||
|
|
||||||
|
If running on Linux without X-Windows (for example, Raspberry Pi Lite OS), there are two options for launching
|
||||||
|
|
||||||
|
* add `--kms` to the command line if the newer KMS driver and Pygame 2 are being used
|
||||||
|
* add `--fb` to use the framebuffer if using Pygame 1
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
from random import randint, randrange, choice
|
from random import randint, randrange, choice
|
||||||
from time import time
|
from time import time
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
import RPi.GPIO as GPIO
|
|
||||||
|
|
||||||
from pygame import Surface, PixelArray, Rect
|
from pygame import Surface, PixelArray, Rect
|
||||||
from pygame.draw import aalines, polygon
|
from pygame.draw import aalines, polygon
|
||||||
|
@ -25,12 +25,19 @@ class ElectricSieve(Game):
|
||||||
PIN_LED_DOWN = 23
|
PIN_LED_DOWN = 23
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.initialize_gpio()
|
if self.gpio_enabled():
|
||||||
|
self.initialize_gpio()
|
||||||
Game.__init__(self)
|
Game.__init__(self)
|
||||||
self.background = Surface(self.display.screen.get_size())
|
self.background = Surface(self.display.screen.get_size())
|
||||||
self.background.fill((255, 80, 190))
|
self.background.fill((255, 80, 190))
|
||||||
self.title.activate()
|
self.title.activate()
|
||||||
|
|
||||||
|
def gpio_enabled(self):
|
||||||
|
"""
|
||||||
|
@return True if GPIO mode was requested at launch, False otherwise
|
||||||
|
"""
|
||||||
|
return "--gpio" in sys.argv
|
||||||
|
|
||||||
def initialize_gpio(self):
|
def initialize_gpio(self):
|
||||||
"""
|
"""
|
||||||
Set pin numbering mode to GPIO, initialize all buttons to input pullup.
|
Set pin numbering mode to GPIO, initialize all buttons to input pullup.
|
||||||
|
@ -38,9 +45,25 @@ class ElectricSieve(Game):
|
||||||
# Use GPIO numbering
|
# Use GPIO numbering
|
||||||
GPIO.setmode(GPIO.BCM)
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
|
||||||
# Set all button pins to pullup
|
# Set button pins to pullup and attach to each a callback that runs on press or release
|
||||||
for pin in self.PIN_BUTTON_UP, self.PIN_BUTTON_DOWN:
|
for pin in self.PIN_BUTTON_UP, self.PIN_BUTTON_DOWN:
|
||||||
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
||||||
|
GPIO.add_event_detect(pin, GPIO.BOTH, self.gpio_input)
|
||||||
|
|
||||||
|
def gpio_input(self, pin):
|
||||||
|
"""
|
||||||
|
Translate GPIO input into PGFW commands, so Raspberry Pi wired controllers be used for input. The pin will be checked for a low
|
||||||
|
signal, meaning the pin has been connected to ground, which is translated to a button press. If the low signal is not detected, it
|
||||||
|
is translated to a button release. Usually called as a callback by `GPIO.add_event_detect` but can be called directly.
|
||||||
|
|
||||||
|
@param pin Raspberry Pi pin number as read by the RPi.GPIO library
|
||||||
|
"""
|
||||||
|
cancel = not (GPIO.input(pin) == GPIO.LOW)
|
||||||
|
if pin == ElectricSieve.PIN_BUTTON_UP:
|
||||||
|
self.input.post_command("left", cancel=cancel)
|
||||||
|
elif pin == ElectricSieve.PIN_BUTTON_DOWN:
|
||||||
|
self.input.post_command("right", cancel=cancel)
|
||||||
|
self.input.post_any_command(id=pin, cancel=cancel)
|
||||||
|
|
||||||
def set_children(self):
|
def set_children(self):
|
||||||
Game.set_children(self)
|
Game.set_children(self)
|
||||||
|
@ -131,8 +154,6 @@ class Strip(Sprite):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
Sprite.__init__(self, parent)
|
Sprite.__init__(self, parent)
|
||||||
GPIO.add_event_detect(ElectricSieve.PIN_BUTTON_UP, GPIO.BOTH, self.respond)
|
|
||||||
GPIO.add_event_detect(ElectricSieve.PIN_BUTTON_DOWN, GPIO.BOTH, self.respond)
|
|
||||||
self.deactivate()
|
self.deactivate()
|
||||||
self.display_surface = self.get_display_surface()
|
self.display_surface = self.get_display_surface()
|
||||||
self.delegate = self.get_game().delegate
|
self.delegate = self.get_game().delegate
|
||||||
|
@ -151,30 +172,17 @@ class Strip(Sprite):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def respond(self, event):
|
def respond(self, event):
|
||||||
if type(event) == int:
|
"""
|
||||||
pressed = "pressed" if GPIO.input(event) == GPIO.LOW else "released"
|
Translate input events into movement of the sieve object. This function is usually set as a callback, but it can be called directly.
|
||||||
print(f"pin {event} {pressed}")
|
|
||||||
|
@param event `pygame.event.Event` with input
|
||||||
|
"""
|
||||||
if self.active:
|
if self.active:
|
||||||
move = False
|
compare = self.delegate.compare
|
||||||
if type(event) == int:
|
if compare(event, "left") or compare(event, "left", True):
|
||||||
if event == ElectricSieve.PIN_BUTTON_UP:
|
self.hshifts[self.LEFT].active = not event.cancel
|
||||||
direction = self.LEFT
|
elif compare(event, "right") or compare(event, "right", True):
|
||||||
move = True
|
self.hshifts[self.RIGHT].active = not event.cancel
|
||||||
elif event == ElectricSieve.PIN_BUTTON_DOWN:
|
|
||||||
direction = self.RIGHT
|
|
||||||
move = True
|
|
||||||
active = GPIO.input(event) == GPIO.LOW
|
|
||||||
else:
|
|
||||||
compare = self.delegate.compare
|
|
||||||
if compare(event, "left") or compare(event, "left", True):
|
|
||||||
direction = self.LEFT
|
|
||||||
move = True
|
|
||||||
elif compare(event, "right") or compare(event, "right", True):
|
|
||||||
direction = self.RIGHT
|
|
||||||
move = True
|
|
||||||
active = not event.cancel
|
|
||||||
if move:
|
|
||||||
self.hshifts[direction].active = active
|
|
||||||
|
|
||||||
def activate(self):
|
def activate(self):
|
||||||
self.active = True
|
self.active = True
|
||||||
|
|
Loading…
Reference in New Issue