Skip to content

Commit f79fb96

Browse files
committed
Refactor Memory game as well
1 parent 97602fe commit f79fb96

1 file changed

Lines changed: 62 additions & 70 deletions

File tree

  • Metro/Metro_RP2350_Memory/memory_game

Metro/Metro_RP2350_Memory/memory_game/code.py

Lines changed: 62 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import terminalio
2121
import usb.core
2222
from adafruit_fruitjam.peripherals import request_display_config
23+
from adafruit_usb_host_mouse import find_and_init_boot_mouse, find_and_init_report_mouse
2324
import adafruit_usb_host_descriptors
2425
from adafruit_pathlib import Path
2526

@@ -223,6 +224,20 @@ def update_score_text():
223224
# add the game over group to the main group
224225
main_group.append(game_over_group)
225226

227+
# add the Exit Game button to game screen
228+
exit_game = TextBox(
229+
terminalio.FONT,
230+
text="Exit",
231+
color=0xFFFFFF,
232+
background_color=0xFF0000,
233+
width=30,
234+
height=15,
235+
align=TextBox.ALIGN_CENTER,
236+
)
237+
exit_game.x = display.width - 30
238+
exit_game.y = display.height - 15
239+
main_group.append(exit_game)
240+
226241
# create score label for each player
227242
for i in range(2):
228243
# create a new label to hold score
@@ -268,78 +283,46 @@ def update_score_text():
268283
# add it to the main group
269284
main_group.append(title_screen_tg)
270285

271-
# load the mouse bitmap
272-
mouse_bmp = OnDiskBitmap("mouse_cursor.bmp")
273-
274-
# make the background pink pixels transparent
275-
mouse_bmp.pixel_shader.make_transparent(0)
276-
277-
# create a TileGrid for the mouse
278-
mouse_tg = TileGrid(mouse_bmp, pixel_shader=mouse_bmp.pixel_shader)
279-
280-
# place it in the center of the display
281-
mouse_tg.x = display.width // 2
282-
mouse_tg.y = display.height // 2
283-
284-
# add the mouse to the main group
285-
main_group.append(mouse_tg)
286-
287286
# variable for the mouse USB device instance
288287
mouse = None
289288

290289
# wait a second for USB devices to be ready
291290
time.sleep(1)
292291

293-
mouse_interface_index, mouse_endpoint_address = None, None
294-
mouse = None
295-
296292
# scan for connected USB devices
297-
for device in usb.core.find(find_all=True):
298-
# print information about the found devices
299-
print(f"{device.idVendor:04x}:{device.idProduct:04x}")
300-
print(device.manufacturer, device.product)
301-
print(device.serial_number)
302-
mouse_interface_index, mouse_endpoint_address = (
303-
adafruit_usb_host_descriptors.find_boot_mouse_endpoint(device))
304-
305-
if mouse_interface_index is not None and mouse_endpoint_address is not None:
306-
mouse = device
307-
print(
308-
f"mouse interface: {mouse_interface_index} "
309-
+ f"endpoint_address: {hex(mouse_endpoint_address)}"
310-
)
311-
312-
break
293+
mouse_ptr = find_and_init_boot_mouse("mouse_cursor.bmp")
294+
if mouse_ptr is None:
295+
mouse_ptr = find_and_init_report_mouse("mouse_cursor.bmp")
296+
sensitivity = 1
297+
if mouse_ptr is None:
298+
print("No mouse found.")
299+
mouse = mouse_ptr.device
313300

301+
mouse_tg = mouse_ptr.tilegrid
314302

315-
mouse_was_attached = None
316-
if mouse is not None:
317-
# detach the kernel driver if needed
318-
if mouse.is_kernel_driver_active(0):
319-
mouse_was_attached = True
320-
mouse.detach_kernel_driver(0)
321-
else:
322-
mouse_was_attached = False
303+
# place it in the center of the display
304+
mouse_tg.x = display.width // 2
305+
mouse_tg.y = display.height // 2
323306

324-
# set configuration on the mouse so we can use it
325-
mouse.set_configuration()
307+
# add the mouse to the main group
308+
main_group.append(mouse_tg)
326309

327310
def atexit_callback():
328311
"""
329312
re-attach USB devices to kernel if needed.
330313
:return:
331314
"""
332315
print("inside atexit callback")
333-
if mouse_was_attached and not mouse.is_kernel_driver_active(0):
334-
mouse.attach_kernel_driver(0)
335-
316+
if mouse is not None:
317+
if mouse_ptr.was_attached and not mouse_ptr.device.is_kernel_driver_active(0):
318+
mouse.attach_kernel_driver(0)
319+
# The keyboard buffer seems to have data left over from when it was detached
320+
# This clears it before the next process starts
321+
while supervisor.runtime.serial_bytes_available:
322+
sys.stdin.read(1)
336323

337324
atexit.register(atexit_callback)
338325

339-
# Buffer to hold data read from the mouse
340-
# Boot mice have 4 byte reports
341-
buf = array.array("b", [0] * 4)
342-
343326
# timestamp in the future to wait until before
344327
# awarding points for a pair, or flipping cards
345328
# back over and changing turns
@@ -352,36 +335,40 @@ def atexit_callback():
352335
waiting_to_reset = False
353336

354337
# main loop
338+
last_left_button_state = None
339+
left_button_pressed = False
355340
while True:
356341
# timestamp of the current time
357342
now = ticks_ms()
358343

359344
# attempt mouse read
360-
try:
361-
# try to read data from the mouse, small timeout so the code will move on
362-
# quickly if there is no data
363-
data_len = mouse.read(mouse_endpoint_address, buf, timeout=20)
345+
buttons = mouse_ptr.update()
346+
347+
# Extract button states
348+
if buttons is None or last_left_button_state is None:
349+
current_left_button_state = 0
350+
else:
351+
current_left_button_state = 1 if 'left' in buttons else 0
364352

365-
# if there was data, then update the mouse cursor on the display
366-
# using min and max to keep it within the bounds of the display
367-
mouse_tg.x = max(0, min(display.width - 1, mouse_tg.x + buf[1] // 2))
368-
mouse_tg.y = max(0, min(display.height - 1, mouse_tg.y + buf[2] // 2))
353+
# Detect button presses
354+
if current_left_button_state == 1 and last_left_button_state == 0:
355+
left_button_pressed = True
356+
elif current_left_button_state == 0 and last_left_button_state == 1:
357+
left_button_pressed = False
369358

370-
# timeout error is raised if no data was read within the allotted timeout
371-
except usb.core.USBTimeoutError:
372-
# no problem, just go on
373-
pass
359+
# Update button states
360+
last_left_button_state = current_left_button_state
374361

375362
# if the current state is title screen
376363
if CUR_STATE == STATE_TITLE:
377364
# if the left mouse button was clicked
378-
if buf[0] & (1 << 0) != 0:
365+
if left_button_pressed:
379366
# change the current state to playing
380367
CUR_STATE = STATE_PLAYING
381368
# hide the title screen
382369
title_screen_tg.hidden = True
383370
# change the mouse cursor color to match the current player
384-
mouse_bmp.pixel_shader[2] = colors[current_turn_index]
371+
mouse_tg.pixel_shader[2] = colors[current_turn_index]
385372

386373
# if the current state is playing
387374
elif CUR_STATE == STATE_PLAYING:
@@ -455,15 +442,20 @@ def atexit_callback():
455442
current_player_lbl.color = colors[current_turn_index]
456443

457444
# update the color of the mouse cursor
458-
mouse_bmp.pixel_shader[2] = colors[current_turn_index]
445+
mouse_tg.pixel_shader[2] = colors[current_turn_index]
459446

460447
# empty out the cards flipped this turn list
461448
cards_flipped_this_turn = []
462449

463450
# ignore any clicks while the code is waiting to take reset cards
464451
if now >= WAIT_UNTIL:
465452
# left btn pressed
466-
if buf[0] & (1 << 0) != 0:
453+
if left_button_pressed:
454+
# if the mouse point is within the exit button
455+
if (mouse_tg.x >= display.width - 30 and
456+
mouse_tg.y >= display.height - 15):
457+
# restart back to code.py
458+
supervisor.reload()
467459

468460
# loop over all cards
469461
for card_index, card in enumerate(card_tgs):
@@ -491,7 +483,7 @@ def atexit_callback():
491483
# if the current state is gameover
492484
elif CUR_STATE == STATE_GAMEOVER:
493485
# left btn pressed
494-
if buf[0] & (1 << 0) != 0:
486+
if left_button_pressed:
495487
# get the coordinates of the mouse cursor point
496488
coords = (mouse_tg.x, mouse_tg.y, 0)
497489

@@ -500,7 +492,7 @@ def atexit_callback():
500492
if play_again_btn.contains(coords):
501493
# set next code file to this one
502494
supervisor.set_next_code_file(__file__,
503-
working_directory=Path(__file__).parent.absolute())
495+
working_directory=Path(__file__).parent.absolute())
504496
# reload
505497
supervisor.reload()
506498

0 commit comments

Comments
 (0)