| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import platform
- import sys
- import customtkinter as ctk
- from PIL import Image, ImageTk
- import time
- import threading
- import tkinter as tk
- import dobluetooth
- import math
- # If on Windows, allow STA for Bleak
- if platform.system() == "Windows":
- try:
- from bleak.backends.winrt.util import allow_sta
- allow_sta()
- except ImportError:
- pass
- # UI setup
- ctk.set_appearance_mode("System")
- ctk.set_default_color_theme("blue")
- app = ctk.CTk()
- app.geometry("1440x1024")
- canvas = ctk.CTkCanvas(app, width=250, height=250, highlightthickness=0)
- canvas.config(background="white")
- canvas.place(x=0, y=0)
- # Score variables
- currentScore = tk.DoubleVar()
- currentScore.set(0)
- names = []
- scores = []
- highestScore = 100
- highScoreName = ""
- punch_on = False
- # Punch control
- def startPunch():
- global punch_on
- punch_on = True
- print("STARTED PUNCH")
- def stopPunch():
- global punch_on, highestScore
- punch_on = False
- print("STOPPED PUNCH")
- if currentScore.get() > highestScore:
- highestScore = currentScore.get()
- try:
- with open("scores.txt", "w") as f: # Fixed mode from "rw" to "w"
- f.write(f"{highestScore} {highScoreName}")
- except Exception as e:
- print("Error writing to file:", e)
- scores.append(highestScore)
- names.append(highScoreName)
- def resetPunch():
- global currentScore
- currentScore.set(0)
- print("reset punch")
- dinger = ctk.CTkLabel(width=40, height=30, text="", fg_color="gray77", master=app)
- dinger.place(x=1405, y=900)
- # Leaderboard & UI setup
- def placeLeaderboard():
- canvas.create_rectangle(0, 0, 500, 500, fill="grey20", width=2)
- intx = 0
- inty = 60
- for i in range(len(names)):
- label1 = ctk.CTkLabel(width=124, height=39, text_color="white", text=names[i], font=("Arial", 15), master=app)
- label1.place(x=intx, y=inty)
- label2 = ctk.CTkLabel(width=124, height=39, text_color="white", text=scores[i], font=("Arial", 15), master=app)
- label2.place(x=intx + 125, y=inty)
- inty += 40
- ctk.CTkLabel(width=249, height=39, text_color="white", text="Leaderboard", font=("Arial", 50), master=app).place(x=0, y=0)
- ctk.CTkButton(width=0, height=150, text="START", fg_color="green", corner_radius=50, font=("Arial", 50),
- text_color="gray99", master=app, command=startPunch).place(x=50, y=300)
- ctk.CTkButton(width=0, height=150, text="STOP", fg_color="orange2", corner_radius=50, font=("Arial", 50),
- text_color="gray99", master=app, command=stopPunch).place(x=50, y=500)
- ctk.CTkButton(width=0, height=150, text="RESET", fg_color="red1", corner_radius=50, font=("Arial", 50),
- text_color="gray99", master=app, command=resetPunch).place(x=50, y=700)
- ctk.CTkLabel(width=50, height=20, text_color="white", text="Current Score", font=("Arial", 50), master=app).place(x=350, y=20)
- ctk.CTkLabel(width=50, height=20, text_color="white", textvariable=currentScore, font=("Arial", 50), master=app).place(x=500, y=100)
- nameEntry = ctk.CTkEntry(width=300, height=50, master=app, font=("Arial", 50))
- nameEntry.place(x=370, y=200)
- ctk.CTkButton(width=50, height=50, text="ENTER", fg_color="green", font=("Arial", 20),
- text_color="gray99", master=app).place(x=670, y=205)
- image = Image.open("./BellDrawing.png")
- photo = ImageTk.PhotoImage(image)
- ctk.CTkLabel(image=photo, text="", width=10, master=app).place(x=800, y=0)
- # BLE thread setup
- def ble_thread_func():
- import asyncio
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
- loop.run_until_complete(dobluetooth.getData())
- def start_ble_thread():
- thread = threading.Thread(target=ble_thread_func, daemon=True)
- thread.start()
- def update_dinger_position():
- global dinger
- score = currentScore.get()
- # Example logic: map score (0–100) to y-position (900 to 300)
- # You can adjust the ranges to suit your needs
- max_score = 100
- min_y = 300
- max_y = 900
- # Clamp score between 0 and max_score
- score = min(max(score, 0), max_score)
- # Calculate the new y position
- new_y = max_y - int((score / max_score) * (max_y - min_y))
- # Move the label
- dinger.place_configure(y=new_y)
- # Call this again after a short delay
- app.after(100, update_dinger_position)
- # Data processing loop in background thread
- def data_loop():
- last_data = None
- last_value = 0.00
- while True:
- bledata = dobluetooth.getDataArr()
- if punch_on:
- if last_data == None:
- last_data = bledata
- current_x_accel = bledata[3]
- current_y_accel = bledata[4]
- last_x_accel = last_data[3]
- last_y_accel = last_data[4]
- value = math.sqrt((current_x_accel - last_y_accel)**2 + ((current_y_accel - last_y_accel)**2))/4
- print(value)
- if(value < 0.26):
- pass
- else:
- if(last_value - value > 10.00):
- app.after(0, lambda val=value: currentScore.set(currentScore.get() + int(val)))
- else:
- if(value - last_value > 10.00):
- if(value == last_value):
- app.after(0, lambda val=value: currentScore.set(currentScore.get() + int(val*10)))
- else:
- app.after(0, lambda val=value: currentScore.set(currentScore.get() + int(val)))
- else:
- app.after(0, lambda val=value: currentScore.set(currentScore.get() + int(val*25)))
- app.after(0, update_dinger_position)
- last_data = bledata
- last_value = value
- time.sleep(0.1)
- def start_data_loop_thread():
- thread = threading.Thread(target=data_loop, daemon=True)
- thread.start()
- # Run UI setup
- placeLeaderboard()
- # Start threads after UI initializes
- app.after(500, start_ble_thread)
- app.after(1000, start_data_loop_thread)
- app.mainloop()
|