Skip to content

Commit 98a81c3

Browse files
authored
Added Settings Menu für Input Config
Added a Settings Menu for defining all buttons
1 parent c2d61cb commit 98a81c3

File tree

1 file changed

+215
-60
lines changed

1 file changed

+215
-60
lines changed

ThumbCommander/ThumbCommander.py

Lines changed: 215 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@
1313
# Overclock. It doesn't seem to run above 250MHz
1414
freq(266_000_000)
1515

16-
from thumbyButton import buttonA, buttonB, buttonU, buttonD, buttonL, buttonR, dpadPressed
16+
from thumbyButton import buttonA, buttonB, buttonU, buttonD, buttonL, buttonR, dpadPressed, inputJustPressed
1717
from thumbyHardware import reset
1818
from random import randint, randrange, choice
1919
from time import sleep
2020
from utime import ticks_us, ticks_diff
2121
from math import sin, pi, cos, exp
2222
from array import array
2323
from gc import collect
24+
import json
2425

2526
WIDTH = const(72)
2627
HEIGHT = const(40)
@@ -93,6 +94,30 @@
9394
0,0,0,0,0,0,0,0,0,0,0,1,2,6,15,30,24,32,96,96,224,192,128,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,192,128,128,192,224,208,240,224,224,224,112,112,56,46,14,15,7,3,1,0,0,0,0,0,0,0,0,0,0,0,
9495
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,3,3,3,6,4,4,4,6,6,6,6,6,7,7,7,3,1,1,3,2,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
9596

97+
#DEFAULT_KEYS = array('A', #FIRE
98+
# 'B', #SHIFT
99+
# 'L', #MOVE_LEFT
100+
# 'R', #MOVE_RIGHT
101+
# 'D', #MOVE_UP
102+
# 'U', #MOVE_DOWN
103+
# 'U', #AFTERBURNER
104+
# 'D', #BREAK
105+
# 'R', #TARGET_NEXT
106+
# 'L') #TARGET_PREV
107+
108+
DEFAULT_KEYS = {
109+
"FIRE": "A",
110+
"SHIFT": "B",
111+
"MOVE_LEFT": "L",
112+
"MOVE_RIGHT": "R",
113+
"MOVE_UP": "D",
114+
"MOVE_DOWN": "U",
115+
"AFTERBURNER": "U",
116+
"BREAK": "D",
117+
"TARGET_NEXT": "R",
118+
"TARGET_PREV": "L"
119+
}
120+
96121
def copySprite(obj:Sprite):
97122
newSprite = Sprite(obj.width, obj.height,(bytearray(obj.bitmapByteCount), bytearray(obj.bitmapByteCount)),0,0,obj.key,obj.mirrorX,obj.mirrorY)
98123
newSprite.setFrame(obj.currentFrame)
@@ -215,20 +240,6 @@ def qsort(inlist):
215240

216241
@micropython.native
217242
def apply_physics(damping: int, desired_vel: int, initial_vel: int, t: int) -> int:
218-
"""
219-
Apply physics calculations independent of frame rate.
220-
221-
Args:
222-
damping: Damping factor. Zero means instant velocity change
223-
desired_vel: Target velocity
224-
initial_vel: Starting velocity
225-
t: Elapsed time since last call
226-
227-
Returns:
228-
tuple containing:
229-
- new_vel: Current velocity
230-
"""
231-
232243
if damping < MIN_DAMPING:
233244
return desired_vel, (desired_vel * t) >> 16
234245
else:
@@ -248,7 +259,39 @@ def apply_physics(damping: int, desired_vel: int, initial_vel: int, t: int) -> i
248259
def getSprite(z, shape):
249260
OBJECTS[shape].setScale(fpdiv((71<<16)-abs(z), 60<<16))
250261
return OBJECTS[shape]
251-
262+
263+
def button_exists(button_name):
264+
try:
265+
for part in button_name:
266+
if not "button" + part in globals():
267+
return False
268+
return True
269+
except:
270+
return False
271+
272+
def load_keymaps():
273+
try:
274+
with open(loc + "keymap.json", "r") as f:
275+
loaded_keys = json.loads(f.read())
276+
complete_keys = DEFAULT_KEYS.copy()
277+
for key, value in loaded_keys.items():
278+
if button_exists(value):
279+
complete_keys[key] = value
280+
return complete_keys
281+
except:
282+
return DEFAULT_KEYS.copy()
283+
284+
def save_keymaps(keymap):
285+
try:
286+
with open(loc + "keymap.json", "w") as f:
287+
f.write(json.dumps(keymap))
288+
except:
289+
pass
290+
291+
292+
# Global variable to store key mappings
293+
KEYMAPS = load_keymaps()
294+
252295
class Stars:
253296
def __init__(self, num:int, scale_pos:int=4, stable=80):
254297
stars = array('O', [None] * num)
@@ -674,8 +717,8 @@ def move_me(self, enemies):
674717
if (ta > 250000):
675718
self.afterburner_time = 0
676719
player_target_speed = 1<<16
677-
if buttonB.pressed():
678-
if buttonR.justPressed():
720+
if getattr(globals()["button"+KEYMAPS["SHIFT"]], "pressed")():
721+
if getattr(globals()["button"+KEYMAPS["TARGET_NEXT"]], "justPressed")():
679722
if enemies:
680723
for i in range(len(enemies)):
681724
e = enemies[i]
@@ -686,7 +729,7 @@ def move_me(self, enemies):
686729
break
687730
else:
688731
if enemies[0] != None: enemies[0][8] = 1
689-
elif buttonL.justPressed():
732+
elif getattr(globals()["button"+KEYMAPS["TARGET_PREV"]], "justPressed")():
690733
if enemies:
691734
for i in range(len(enemies) -1, -1, -1):
692735
e = enemies[i]
@@ -697,60 +740,31 @@ def move_me(self, enemies):
697740
break
698741
else:
699742
if enemies[0] != None: enemies[len(enemies) -1][8] = 1
700-
elif buttonU.justPressed() and (self.afterburner_time == 0):
701-
player_target_speed = 7<<16;
743+
elif getattr(globals()["button"+KEYMAPS["AFTERBURNER"]], "justPressed")() and (self.afterburner_time == 0):
744+
player_target_speed = 5<<16;
702745
self.afterburner_time = new_time
703-
elif buttonD.justPressed():
746+
elif getattr(globals()["button"+KEYMAPS["BREAK"]], "justPressed")():
704747
player_speed = 1<<16
705-
elif buttonR.pressed():
748+
elif getattr(globals()["button"+KEYMAPS["MOVE_RIGHT"]], "pressed")():
706749
player_angle[0] -= 1<<16
707750
player_angle[2] = -3
708751
self.cockpit_sprite.x = SHIP_X-1
709-
elif buttonL.pressed():
752+
elif getattr(globals()["button"+KEYMAPS["MOVE_LEFT"]], "pressed")():
710753
player_angle[0] += 1<<16
711754
player_angle[2] = 3
712755
self.cockpit_sprite.x = SHIP_X+1
713-
elif buttonU.pressed():
756+
elif getattr(globals()["button"+KEYMAPS["MOVE_DOWN"]], "pressed")():
714757
player_angle[1] -= 1<<16
715758
self.cockpit_sprite.y = SHIP_Y-1
716-
elif buttonD.pressed():
759+
elif getattr(globals()["button"+KEYMAPS["MOVE_UP"]], "pressed")():
717760
player_angle[1] += 1<<16
718761
self.cockpit_sprite.y = SHIP_Y+1
719-
elif buttonA.justPressed():
762+
elif getattr(globals()["button"+KEYMAPS["FIRE"]], "justPressed")():
720763
if (self.laser_energy > 0):
721764
self.laser.append(Laser(player_angle[0], player_angle[1]))
722765
self.target_sprite = Sprite(7,7,(targetactive,targetactiveSHD),CENTER_X-3, CENTER_Y-3,0)
723766
self.fire_couter += 20
724767
self.laser_energy -= 1
725-
#elif buttonB.justPressed():
726-
# if enemies:
727-
# for i in range(len(enemies)):
728-
# e = enemies[i]
729-
# if e[8] == 1:
730-
# e[8] = 0
731-
# if (i+1) < len(enemies): enemies[i+1][8] = 1
732-
# else: hudShip = None
733-
# break
734-
# else:
735-
# if enemies[0] != None: enemies[0][8] = 1
736-
737-
738-
#else:
739-
# delta_x = sign(player_angle[0])
740-
# player_angle[0] -= delta_x<<16
741-
# self.cockpit_sprite.x = SHIP_X-delta_x
742-
# delta_y = sign(player_angle[1])
743-
# player_angle[1] -= delta_y<<16
744-
# self.cockpit_sprite.y = SHIP_Y-delta_y
745-
# if delta_x > 0:
746-
# player_angle[2] = -3
747-
# elif delta_x < 0:
748-
# player_angle[2] = +3
749-
# else:
750-
# player_angle[2] = 0
751-
# self.cockpit_sprite.x = SHIP_X
752-
# if (player_angle[1] == 0):
753-
# self.cockpit_sprite.y = SHIP_Y
754768
else:
755769
player_angle[2] = 0
756770
self.cockpit_sprite.x = SHIP_X
@@ -770,6 +784,7 @@ def move_me(self, enemies):
770784
if player_angle[1] > 2162688: player_angle[1] = 2162688
771785

772786
player_speed = apply_physics(1<<16, player_target_speed, player_speed, t)
787+
inputJustPressed()
773788

774789

775790
class Laser:
@@ -874,27 +889,164 @@ def menu():
874889
display.drawText("Dog Fight",21,30,3)
875890
elif i==1:
876891
display.drawText("Dog Fight",21,20,1)
877-
display.drawText("Exit Game",21,30,3)
892+
display.drawText("Settings",21,30,3)
878893
elif i==2:
879-
display.drawText("Dog Fight",21,20,3)
894+
display.drawText("Settings",21,20,1)
895+
display.drawText("Exit Game",21,30,3)
896+
elif i==3:
897+
display.drawText("Settings",21,20,3)
880898
display.drawText("Exit Game",21,30,1)
881899
display.update()
882900
if buttonD.justPressed():
883901
i+=1
884-
if i > 2: i=2
902+
if i > 3: i=3
885903
rot = -5
886904
elif buttonU.justPressed():
887905
i+=-1
888906
if i < 0: i=0
889907
rot = 5
890908
return i
909+
910+
class SettingsMenu:
911+
def __init__(self):
912+
self.update_menu()
913+
self.selected = 0
914+
self.remapping = False
915+
self.current_remap = ""
916+
self.background = Stars(20, 4, 0)
917+
display.setFont("/lib/font3x5.bin", 3, 5, 1)
918+
# wait for button release
919+
inputJustPressed()
891920

921+
def update_menu(self):
922+
self.settings_items = [
923+
"FIRE: " + KEYMAPS["FIRE"],
924+
"SHIFT: " + KEYMAPS["SHIFT"],
925+
"MOVE LEFT: " + KEYMAPS["MOVE_LEFT"],
926+
"MOVE RIGHT: " + KEYMAPS["MOVE_RIGHT"],
927+
"MOVE UP: " + KEYMAPS["MOVE_UP"],
928+
"MOVE DOWN: " + KEYMAPS["MOVE_DOWN"],
929+
"AFTERBURNER: " + KEYMAPS["SHIFT"]+"+"+KEYMAPS["AFTERBURNER"],
930+
"BREAK: " + KEYMAPS["SHIFT"]+"+"+KEYMAPS["BREAK"],
931+
"TGT NEXT: " + KEYMAPS["SHIFT"]+"+"+KEYMAPS["TARGET_NEXT"],
932+
"TGT PREV: " + KEYMAPS["SHIFT"]+"+"+KEYMAPS["TARGET_PREV"],
933+
"RESET DEFAULTS",
934+
"BACK"
935+
]
936+
def run(self):
937+
global KEYMAPS
938+
display.setFPS(30)
939+
940+
while True:
941+
display.fill(0)
942+
self.background.run(0)
943+
944+
# Draw title
945+
display.drawText("SETTINGS", 22, 2, 1)
946+
display.drawLine(0, 9, 72, 9, 1)
947+
948+
# If in remapping mode
949+
if self.remapping:
950+
display.fill(0)
951+
# Draw title
952+
display.drawText("PRESS NEW KEY FOR:", 2, 2, 1)
953+
display.drawLine(0, 9, 72, 9, 1)
954+
display.drawText(self.current_remap, 16, 14, 3)
955+
display.update()
956+
957+
# Wait for a button press
958+
while not (buttonA.pressed() or buttonB.pressed() or dpadPressed()):
959+
pass
960+
961+
# Determine which button was pressed
962+
new_key = ""
963+
if buttonA.pressed(): new_key = "A"
964+
elif buttonB.pressed(): new_key = "B"
965+
elif buttonU.pressed(): new_key = "U"
966+
elif buttonD.pressed(): new_key = "D"
967+
elif buttonL.pressed(): new_key = "L"
968+
elif buttonR.pressed(): new_key = "R"
969+
970+
# Update mapping if valid
971+
if new_key != "":
972+
KEYMAPS[self.current_remap] = new_key
973+
self.update_menu()
974+
975+
# Wait for button release
976+
sleep(0.3)
977+
inputJustPressed()
978+
979+
self.remapping = False
980+
sleep(0.3)
981+
continue
982+
983+
# Draw menu items
984+
start_idx = max(0, min(self.selected - 2, len(self.settings_items) - 5))
985+
for i in range(start_idx, min(start_idx + 5, len(self.settings_items))):
986+
y_pos = 12 + (i - start_idx) * 6
987+
text_color = 1 if i == self.selected else 3
988+
display.drawText(self.settings_items[i], 4, y_pos, text_color)
989+
990+
# Draw scrollbar if needed
991+
if len(self.settings_items) > 5:
992+
scrollbar_height = min(35, 35 * 5 / len(self.settings_items))
993+
scrollbar_pos = 12 + (35 - scrollbar_height) * self.selected / (len(self.settings_items) - 1)
994+
display.drawFilledRectangle(70, int(scrollbar_pos), 2, int(scrollbar_height), 1)
995+
996+
display.update()
997+
998+
# Handle input
999+
if buttonU.justPressed():
1000+
self.selected = (self.selected - 1) % len(self.settings_items)
1001+
sleep(0.15)
1002+
elif buttonD.justPressed():
1003+
self.selected = (self.selected + 1) % len(self.settings_items)
1004+
sleep(0.15)
1005+
elif buttonA.justPressed():
1006+
# Handle selection
1007+
if self.selected < 10: # Key remapping options
1008+
self.remapping = True
1009+
if self.selected == 0:
1010+
self.current_remap = "FIRE"
1011+
elif self.selected == 1:
1012+
self.current_remap = "SHIFT"
1013+
elif self.selected == 2:
1014+
self.current_remap = "MOVE_LEFT"
1015+
elif self.selected == 3:
1016+
self.current_remap = "MOVE_RIGHT"
1017+
elif self.selected == 4:
1018+
self.current_remap = "MOVE_UP"
1019+
elif self.selected == 5:
1020+
self.current_remap = "MOVE_DOWN"
1021+
elif self.selected == 6:
1022+
self.current_remap = "AFTERBURNER"
1023+
elif self.selected == 7:
1024+
self.current_remap = "BREAK"
1025+
elif self.selected == 8:
1026+
self.current_remap = "TARGET_NEXT"
1027+
elif self.selected == 9:
1028+
self.current_remap = "TARGET_PREV"
1029+
elif self.selected == 10: # Reset defaults
1030+
for key in DEFAULT_KEYS:
1031+
KEYMAPS[key] = DEFAULT_KEYS[key]
1032+
# Update menu text
1033+
self.update_menu()
1034+
sleep(0.3)
1035+
elif self.selected == 11: # Back
1036+
save_keymaps(KEYMAPS)
1037+
return
1038+
sleep(0.15)
1039+
elif buttonB.justPressed():
1040+
# Go back
1041+
save_keymaps(KEYMAPS)
1042+
return
1043+
8921044
#Intro finished
8931045
Intro.finish()
8941046

8951047
while True:
8961048
lifes = 5
897-
player_speed = float2fp(1)
1049+
player_speed = player_target_speed = float2fp(1)
8981050
player_angle = [0, 0, 0]
8991051
score = 0
9001052
# Show the Menu
@@ -933,5 +1085,8 @@ def menu():
9331085
display.update()
9341086
die()
9351087
game_over()
1088+
elif (game == 2):
1089+
settings = SettingsMenu()
1090+
settings.run()
9361091
else:
9371092
reset()

0 commit comments

Comments
 (0)