forked from KenYu910645/MapleStoryAutoLevelUp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKeyBoardListener.py
More file actions
147 lines (123 loc) · 4.02 KB
/
KeyBoardListener.py
File metadata and controls
147 lines (123 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
'''
KeyBoardListener
'''
# Standard Import
import threading
import time
import pyautogui
import pygetwindow as gw
from pynput import keyboard
# Local import
from logger import logger
pyautogui.PAUSE = 0 # remove delay
class KeyBoardListener():
'''
KeyBoardListener
'''
def __init__(self, cfg):
self.cfg = cfg
self.t_last_run = time.time()
self.is_enable = True
self.window_title = cfg["game_window"]["title"]
self.debounce_interval = 1 # second
self.is_need_screen_shot = False
self.is_need_toggle = False
self.fps = 0
self.fps_limit = 30
self.key_pressing = [] # record the key pressed by user
self.is_pressed_func_key = [False]*12 # 'F1', 'F2', .... 'F12'
# Timer
self.t_func_key = [0]*12 # 'F1', 'F2', .... 'F12'
# Keys
self.movement_keys = {
keyboard.Key.up: "up",
keyboard.Key.down: "down",
keyboard.Key.left: "left",
keyboard.Key.right: "right",
keyboard.Key.space: "space"
}
self.func_keys = {
getattr(keyboard.Key, f"f{i+1}"): i for i in range(12)
}
# Start keyboard control thread
threading.Thread(target=self.run, daemon=True).start()
listener = keyboard.Listener(on_press=self.on_press,
on_release=self.on_release)
listener.start()
def on_release(self, key):
'''
Handle key release events and update key_pressing list.
'''
try:
# Regular keys (like 'a', '1', etc.)
k = key.char.lower()
except AttributeError:
k = self.movement_keys.get(key, None)
# Remove the key from key_pressing list if it's in there
if k in self.key_pressing:
self.key_pressing.remove(k)
def on_press(self, key):
'''
Handle key press events.
'''
try:
# Regular character keys (e.g., 'a', 'w', '1')
k = key.char.lower()
except AttributeError:
# Handle F1, F2, F3, ... F12
if key in self.func_keys:
idx = self.func_keys[key]
if time.time() - self.t_func_key[idx] > self.debounce_interval:
self.is_pressed_func_key[idx] = True
self.t_func_key[idx] = time.time()
k = self.movement_keys.get(key, None)
if k and k not in self.key_pressing:
self.key_pressing.append(k)
def toggle_enable(self):
'''
toggle_enable
'''
# self.is_enable = not self.is_enable
logger.info(f"Player pressed F1, is_enable:{self.is_enable}")
def disable(self):
'''
disable keyboard controlller
'''
self.is_enable = False
def enable(self):
'''
enable keyboard controlller
'''
self.is_enable = True
def is_game_window_active(self):
'''
Check if the game window is currently the active (foreground) window.
Returns:
- True
- False
'''
active_window = gw.getActiveWindow()
return active_window is not None and self.window_title in active_window.title
def limit_fps(self):
'''
Limit FPS
'''
# If the loop finished early, sleep to maintain target FPS
target_duration = 1.0 / self.fps_limit # seconds per frame
frame_duration = time.time() - self.t_last_run
if frame_duration < target_duration:
time.sleep(target_duration - frame_duration)
# Update FPS
self.fps = round(1.0 / (time.time() - self.t_last_run))
self.t_last_run = time.time()
# logger.info(f"FPS = {self.fps}")
def run(self):
'''
run
'''
while True:
# Check if game window is active
if not self.is_enable or not self.is_game_window_active():
self.limit_fps()
continue
self.limit_fps()