Video version of the code
This commit is contained in:
		
							
								
								
									
										2
									
								
								bounce_c/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								bounce_c/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +0,0 @@ | ||||
| *.exe | ||||
| *.pdb | ||||
| @@ -1,72 +0,0 @@ | ||||
| from ctypes import POINTER, WINFUNCTYPE, byref, windll | ||||
| from ctypes.wintypes import BOOL, HWND, INT, LPARAM, LPPOINT, POINT | ||||
| import time | ||||
| import math | ||||
|  | ||||
| user32 = windll.user32 | ||||
| gdi32 = windll.gdi32 | ||||
|  | ||||
| user32.GetSystemMetrics.argtypes = [INT] | ||||
|  | ||||
| user32.GetCursorPos.argtypes = [LPPOINT] | ||||
| user32.SetCursorPos.argtypes = [INT, INT] | ||||
|  | ||||
| CB_ENUM_WINDOWS = WINFUNCTYPE(BOOL, HWND, LPARAM) | ||||
|  | ||||
| def get_mouse() -> tuple[int, int]: | ||||
|     point = POINT() | ||||
|     user32.GetCursorPos(byref(point)) | ||||
|     x, y = point.x, point.y | ||||
|     return x, y | ||||
|  | ||||
| def get_resolution() -> tuple[int, int]: | ||||
|     SM_CXSCREEN = 0 | ||||
|     SM_CYSCREEN = 1 | ||||
|  | ||||
|     return ( | ||||
|         user32.GetSystemMetrics(SM_CXSCREEN), | ||||
|         user32.GetSystemMetrics(SM_CYSCREEN) | ||||
|     ) | ||||
|  | ||||
| def set_mouse(x: int, y: int): | ||||
|     user32.SetCursorPos(x, y) | ||||
|  | ||||
|  | ||||
| class MouseBody(object): | ||||
|     def __init__(self): | ||||
|         self._last_mouse = None | ||||
|         self.velocity = 0.0 | ||||
|      | ||||
|     def update(self): | ||||
|         mouse_x, mouse_y = get_mouse() | ||||
|         if self._last_mouse: | ||||
|             last_x, last_y = self._last_mouse | ||||
|             dx = mouse_x - last_x | ||||
|             dy = mouse_y - last_y | ||||
|             dist = math.sqrt(dx * dx + dy * dy) | ||||
|  | ||||
|             # if they move the mouse they can fight it | ||||
|             # (but they have to move it a lot) | ||||
|             self.velocity *= 1.0 - min(dist / 64, 1.0) | ||||
|  | ||||
|         _, res_y = get_resolution() | ||||
|         self.velocity += 1 | ||||
|  | ||||
|         new_y = int(mouse_y + self.velocity) | ||||
|  | ||||
|         if new_y > res_y: | ||||
|             # simulate an inelastic collision | ||||
|             self.velocity = -self.velocity * 0.75 | ||||
|             new_y = int(new_y + self.velocity) | ||||
|  | ||||
|         set_mouse(mouse_x, new_y) | ||||
|         self._last_mouse = (mouse_x, new_y) | ||||
|  | ||||
| def main(): | ||||
|     body = MouseBody() | ||||
|     while True: | ||||
|         time.sleep(1/120.0) | ||||
|         body.update() | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
| @@ -2,48 +2,36 @@ | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <windows.h> | ||||
| #include <time.h> | ||||
| 
 | ||||
| #define MAX_WINDOWS 1024 | ||||
| 
 | ||||
| // resolution
 | ||||
| // == globals ==
 | ||||
| uint32_t res_y; | ||||
| void globals_init() { | ||||
| void globals_update() { | ||||
|     res_y = GetSystemMetrics(SM_CYSCREEN); | ||||
| } | ||||
| 
 | ||||
| // bodies
 | ||||
| // == bodies ==
 | ||||
| typedef struct body_t { | ||||
|     int32_t last_x; | ||||
|     int32_t last_y; | ||||
|     float offset_x; | ||||
|     float offset_y; | ||||
|     float velocity; | ||||
| } body_t; | ||||
| 
 | ||||
| void body_init(body_t* body) { | ||||
|     body->last_x = -1; | ||||
|     body->last_y = -1; | ||||
|     body->offset_x = 0.5; | ||||
|     body->offset_y = 0.5; | ||||
|     body->velocity = 0.0; | ||||
| } | ||||
| 
 | ||||
| void body_update(body_t* body, int32_t x, int32_t y, int32_t* x_new, int32_t* y_new) { | ||||
|     if (body->last_x != -1 && body->last_y != -1) { | ||||
|         int32_t dx = x - body->last_x; | ||||
|         int32_t dy = y - body->last_y; | ||||
|         double dist = sqrt((double) dx * dx + dy * dy); | ||||
|         body->velocity *= 1.0 - min(dist / 128, 1.0); | ||||
|     } | ||||
| void body_update(body_t* body, int32_t *y_ptr) { | ||||
|     int32_t y = *y_ptr; | ||||
| 
 | ||||
|     float float_x = x + body->offset_x; | ||||
|     float float_y = y + body->offset_y; | ||||
|     for (uint8_t step = 0; step < 100; step += 1) { | ||||
|     float y_float = y + body->offset_y; | ||||
| 
 | ||||
|     for (size_t step = 0; step < 100; step++) { | ||||
|         body->velocity += 0.0002; | ||||
|         y_float += body->velocity; | ||||
| 
 | ||||
|         float_y += body->velocity; | ||||
|         if (float_y > res_y && body->velocity > 0) { | ||||
|         if (y_float > res_y && body->velocity > 0) { | ||||
|             body->velocity = -body->velocity * 0.75; | ||||
|             if (-body->velocity < 0.05) { | ||||
|                 body->velocity = 0; | ||||
| @@ -51,12 +39,9 @@ void body_update(body_t* body, int32_t x, int32_t y, int32_t* x_new, int32_t* y_ | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     *x_new = (int) float_x; | ||||
|     *y_new = (int) float_y; | ||||
|     body->last_x = *x_new; | ||||
|     body->last_y = *y_new; | ||||
|     body->offset_x = float_x - *x_new; | ||||
|     body->offset_y = float_y - *y_new; | ||||
|     *y_ptr = min((int) y_float, res_y); | ||||
| 
 | ||||
|     body->offset_y = y_float - *y_ptr; | ||||
| } | ||||
| 
 | ||||
| // == mouse ==
 | ||||
| @@ -73,9 +58,9 @@ void mouse_init() { | ||||
| void mouse_update() { | ||||
|     POINT xy; | ||||
|     GetCursorPos(&xy); | ||||
|     int32_t new_x, new_y; | ||||
|     body_update(&mouse_body.body, xy.x, xy.y, &new_x, &new_y); | ||||
|     SetCursorPos(new_x, new_y); | ||||
|     int32_t x = xy.x, y = xy.y; | ||||
|     body_update(&mouse_body.body, &y); | ||||
|     SetCursorPos(x, y); | ||||
| } | ||||
| 
 | ||||
| // == window ==
 | ||||
| @@ -97,12 +82,9 @@ void window_init() { | ||||
| } | ||||
| 
 | ||||
| BOOL CALLBACK window_handle_enum(HWND window, LPARAM _) { | ||||
|     if (_n_new_windows >= MAX_WINDOWS) { | ||||
|         return 0; | ||||
|     } | ||||
|     if (!IsWindowVisible(window)) { | ||||
|         return 1; | ||||
|     } | ||||
|     if (_n_new_windows >= MAX_WINDOWS) { return 0; } | ||||
|     if (!IsWindowVisible(window)) { return 1; } | ||||
| 
 | ||||
|     window_body_t new; | ||||
|     new.window = window; | ||||
|     body_init(&new.body); | ||||
| @@ -119,7 +101,6 @@ BOOL CALLBACK window_handle_enum(HWND window, LPARAM _) { | ||||
| void window_enumerate() { | ||||
|     EnumWindows(window_handle_enum, 0); | ||||
| 
 | ||||
|     // do the swap
 | ||||
|     window_body_t* tmp_windows = windows; | ||||
| 
 | ||||
|     n_windows = _n_new_windows; | ||||
| @@ -138,22 +119,28 @@ void window_update() { | ||||
|         int32_t x = rect.left; | ||||
|         int32_t y = rect.bottom; | ||||
| 
 | ||||
|         body_update(&windows[i].body, x, y, &x, &y); | ||||
|         body_update(&windows[i].body, &y); | ||||
| 
 | ||||
|         int32_t height = rect.bottom - rect.top; | ||||
|         uint32_t flags = SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER | SWP_ASYNCWINDOWPOS; | ||||
|         SetWindowPos(windows[i].window, 0, x, y - height, -1, -1, flags); | ||||
|         SetWindowPos( | ||||
|             windows[i].window, 0,  | ||||
|             x, y - height, | ||||
|             -1, -1, | ||||
|             SWP_NOACTIVATE | SWP_NOSIZE | | ||||
|             SWP_NOZORDER | SWP_ASYNCWINDOWPOS | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // == main ==
 | ||||
| int main() { | ||||
|     globals_init(); | ||||
| 
 | ||||
|     mouse_init(); | ||||
|     window_init(); | ||||
| 
 | ||||
|     while (1) { | ||||
|         // mouse_update();
 | ||||
|         globals_update(); | ||||
| 
 | ||||
|         mouse_update(); | ||||
|         window_update(); | ||||
| 
 | ||||
|         Sleep(1000/120); | ||||
							
								
								
									
										
											BIN
										
									
								
								c/bounce.exe
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								c/bounce.exe
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								c/bounce.pdb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								c/bounce.pdb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										88
									
								
								main.py.old
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								main.py.old
									
									
									
									
									
								
							| @@ -1,88 +0,0 @@ | ||||
| from ctypes import POINTER, WINFUNCTYPE, WinError, create_unicode_buffer, get_last_error, windll | ||||
| from ctypes.wintypes import BOOL, DWORD, HBRUSH, HDC, HINSTANCE, HMENU, HWND, LPARAM, LPCWSTR, LPVOID, LPWSTR, INT, RECT | ||||
| import time | ||||
|  | ||||
| user32 = windll.user32 | ||||
| gdi32 = windll.gdi32 | ||||
|  | ||||
| CB_ENUM_WINDOWS = WINFUNCTYPE(BOOL, HWND, LPARAM) | ||||
|  | ||||
| # thanks: https://stackoverflow.com/questions/37501191/how-to-get-windows-window-names-with-ctypes-in-python | ||||
| def check_zero(result, func, args): | ||||
|     if not result: | ||||
|         err = get_last_error() | ||||
|         if err: | ||||
|             raise WinError(err) | ||||
|     return args | ||||
|  | ||||
| user32.CreateWindowExW.argtypes = [ | ||||
|     DWORD, LPCWSTR, LPCWSTR, DWORD, | ||||
|     INT, INT, INT, INT,  | ||||
|     HWND, HMENU, HINSTANCE, LPVOID | ||||
| ] | ||||
| user32.CreateWindowExW.errcheck = check_zero | ||||
|  | ||||
| user32.FillRect.argtypes = [HDC, POINTER(RECT), HBRUSH] | ||||
|  | ||||
| user32.GetWindowDC.argtypes = [HWND] | ||||
| user32.GetWindowDC.errcheck = check_zero | ||||
|  | ||||
| user32.GetWindowTextLengthW.argtypes = [HWND] | ||||
| user32.GetWindowTextLengthW.errcheck = check_zero | ||||
|  | ||||
| user32.GetWindowTextW.argtypes = [HWND, LPWSTR, INT] | ||||
| user32.GetWindowTextW.errcheck = check_zero | ||||
|  | ||||
| def find_all_windows(): | ||||
|     windows = [] | ||||
|  | ||||
|     @CB_ENUM_WINDOWS | ||||
|     def _handle_window(hwnd, lparam): | ||||
|         # +1: make room for the null  | ||||
|         length = user32.GetWindowTextLengthW(hwnd) + 1 | ||||
|         buffer = create_unicode_buffer(length) | ||||
|         user32.GetWindowTextW(hwnd, buffer, length) | ||||
|         windows.append((hwnd, buffer.value)) | ||||
|         return True | ||||
|  | ||||
|     user32.EnumWindows(_handle_window, 0) | ||||
|     return windows | ||||
|  | ||||
| def fix_window(window): | ||||
|     """ | ||||
|     hdc = user32.GetWindowDC(window) | ||||
|     rect = RECT(0, 0, 10000, 10000) | ||||
|     brush = gdi32.CreateSolidBrush(0x00FF0000) | ||||
|     user32.FillRect(hdc, rect, brush) | ||||
|     gdi32.DeleteObject(brush) | ||||
|     print(window) | ||||
|     """ | ||||
|     classname = create_unicode_buffer("overlapper\x00") | ||||
|     windowname = create_unicode_buffer("overlapper\x00") | ||||
|     window = user32.CreateWindowExW( | ||||
|         0x08000000 |  # WS_EX_NOACTIVATE | ||||
|         0x8 |  # WS_EX_TOPMOST | ||||
|         0x0, # 0x20,  # WS_EX_TRANSPARENT | ||||
|         classname, | ||||
|         windowname, | ||||
|         0x10000000,  # WS_VISIBLE | ||||
|         0, 0, 128, 128,  # x y w h | ||||
|         None, None, | ||||
|         None, None | ||||
|     ) | ||||
|     user32.ShowWindow(window, 5)  # SW_SHOW | ||||
|  | ||||
| def fix_step(): | ||||
|     windows = find_all_windows() | ||||
|     for window_id, window_name in windows: | ||||
|         if window_name.endswith("Visual Studio Code"): | ||||
|             fix_window(window_id) | ||||
|  | ||||
| def main(): | ||||
|     fix_step() | ||||
|  | ||||
|     while True: | ||||
|         time.sleep(1) | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
| @@ -2,16 +2,14 @@ from abc import ABC, abstractmethod | ||||
| from ctypes import WINFUNCTYPE, byref, windll | ||||
| from ctypes.wintypes import BOOL, HWND, INT, LPARAM, LPPOINT, LPRECT, POINT, RECT | ||||
| import time | ||||
| import math | ||||
| 
 | ||||
| user32 = windll.user32 | ||||
| gdi32 = windll.gdi32 | ||||
| 
 | ||||
| user32.GetSystemMetrics.argtypes = [INT] | ||||
| 
 | ||||
| user32.GetCursorPos.argtypes = [LPPOINT] | ||||
| user32.SetCursorPos.argtypes = [INT, INT] | ||||
| 
 | ||||
| user32.GetSystemMetrics.argtypes = [INT] | ||||
| 
 | ||||
| CB_ENUM_WINDOWS = WINFUNCTYPE(BOOL, HWND, LPARAM) | ||||
| 
 | ||||
| user32.EnumWindows.argtypes = [CB_ENUM_WINDOWS, LPARAM] | ||||
| @@ -20,13 +18,18 @@ user32.GetWindowRect.argtypes = [HWND, LPRECT] | ||||
| user32.SetWindowPos.argtypes = [HWND, INT, INT, INT, INT, INT, INT] | ||||
| user32.IsWindowVisible.argtypes = [HWND] | ||||
| 
 | ||||
| def get_resolution_y() -> int: | ||||
|     SM_CYSCREEN = 1 | ||||
|     return user32.GetSystemMetrics(SM_CYSCREEN) | ||||
| 
 | ||||
| 
 | ||||
| class BouncyObject(ABC): | ||||
|     @abstractmethod | ||||
|     def get_position(self) -> tuple[int, int]: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     @abstractmethod | ||||
|     def set_position(self, xy: tuple[int, int]): | ||||
|     def set_position(self, xy: tuple[int, int]) -> None: | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
| 
 | ||||
| @@ -50,10 +53,9 @@ class Window(BouncyObject): | ||||
|         user32.GetWindowRect(self._handle, byref(rect)) | ||||
|         return (rect.left, rect.bottom) | ||||
| 
 | ||||
|     def set_position(self, xy: tuple[int, int]): | ||||
|     def set_position(self, xy: tuple[int, int]) -> None: | ||||
|         rect = RECT() | ||||
|         user32.GetWindowRect(self._handle, byref(rect)) | ||||
|         width = rect.right - rect.left | ||||
|         height = rect.bottom - rect.top | ||||
|         x, y = xy | ||||
|         user32.SetWindowPos( | ||||
| @@ -61,15 +63,41 @@ class Window(BouncyObject): | ||||
|             0x0010 |  # SWP_NOACTIVATE | ||||
|             0x0001 |  # SWP_NOSIZE | ||||
|             0x0004 |  # SWP_NOZORDER | ||||
|             0x4000  # SWP_ASYNCWINDOWPOS | ||||
|             0x4000    # SWP_ASYNCWINDOWPOS | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class Body(object): | ||||
|     def __init__(self, controlled_object: BouncyObject): | ||||
|         self._last_offset: tuple[float, float] = (0.5, 0.5) | ||||
|         self._velocity = 0.0 | ||||
|         self._controlled_object = controlled_object | ||||
| 
 | ||||
|     def update(self, res_y: int) -> None: | ||||
|         x, y = self._controlled_object.get_position() | ||||
|         ox, oy = self._last_offset | ||||
|         x += ox | ||||
|         y += oy | ||||
| 
 | ||||
|         for _ in range(100): | ||||
|             self._velocity += 0.0002 | ||||
|             y += self._velocity | ||||
| 
 | ||||
|             if y > res_y and self._velocity > 0: | ||||
|                 self._velocity = -self._velocity * 0.75 | ||||
|                 if abs(self._velocity) < 0.05: | ||||
|                     self._velocity = 0 | ||||
| 
 | ||||
|         x_int, y_int = int(x), min(int(y), res_y) | ||||
|         self._controlled_object.set_position((x_int, y_int)) | ||||
|         self._last_offset = x - x_int, y - y_int | ||||
| 
 | ||||
| 
 | ||||
| def enumerate_windows() -> list[int]: | ||||
|     windows: list[int] = [] | ||||
| 
 | ||||
|     @CB_ENUM_WINDOWS | ||||
|     def _handle_window(hwnd, lparam): | ||||
|     def _handle_window(hwnd: int, _lparam: int): | ||||
|         if user32.IsWindowVisible(hwnd): | ||||
|             windows.append(hwnd) | ||||
|         return True | ||||
| @@ -78,61 +106,19 @@ def enumerate_windows() -> list[int]: | ||||
|     return windows | ||||
| 
 | ||||
| 
 | ||||
| def get_resolution_y() -> int: | ||||
|     SM_CYSCREEN = 1 | ||||
|     return user32.GetSystemMetrics(SM_CYSCREEN) | ||||
| 
 | ||||
| 
 | ||||
| class Body(object): | ||||
|     def __init__(self, controlled_object: BouncyObject): | ||||
|         self._last_xy: tuple[int, int] | None =None | ||||
|         self._last_offset: tuple[float, float] = (0.5, 0.5) | ||||
|         self._velocity = 0.0 | ||||
|         self._controlled_object = controlled_object | ||||
|      | ||||
|     def update(self, res_y): | ||||
|         x, y = self._controlled_object.get_position() | ||||
|         ox, oy = self._last_offset | ||||
|         x += ox | ||||
|         y += oy | ||||
| 
 | ||||
|         if self._last_xy: | ||||
|             last_x, last_y = self._last_xy | ||||
|             dx = x - last_x | ||||
|             dy = y - last_y | ||||
|             dist = math.sqrt(dx * dx + dy * dy) | ||||
| 
 | ||||
|             # if they move the mouse they can fight it | ||||
|             # (but they have to move it a lot) | ||||
|             self._velocity *= 1.0 - min(dist / 128, 1.0) | ||||
| 
 | ||||
|         for _ in range(100): | ||||
|             self._velocity += 0.0002 | ||||
| 
 | ||||
|             y += self._velocity | ||||
|             if y > res_y and self._velocity > 0: | ||||
|                 self._velocity = -self._velocity * 0.75 | ||||
|                 if abs(self._velocity) < 0.05: | ||||
|                     self._velocity = 0 | ||||
| 
 | ||||
|         self._controlled_object.set_position((int(x), int(y))) | ||||
|         self._last_xy = (int(x), int(y)) | ||||
|         self._last_offset = (x % 1, y % 1) | ||||
| 
 | ||||
| 
 | ||||
| class Bodies(object): | ||||
|     def __init__(self): | ||||
|         self._mouse = Body(Mouse()) | ||||
|         self._windows = {} | ||||
| 
 | ||||
|     def update_list(self): | ||||
|         windows2 = {} | ||||
|     def enumerate(self): | ||||
|         windows_2 = {} | ||||
|         for i in enumerate_windows(): | ||||
|             if existing := self._windows.get(i): | ||||
|                 windows2[i] = existing | ||||
|                 windows_2[i] = existing | ||||
|             else: | ||||
|                 windows2[i] = Body(Window(i)) | ||||
|         self._windows = windows2 | ||||
|                 windows_2[i] = Body(Window(i)) | ||||
|         self._windows = windows_2 | ||||
| 
 | ||||
|     def get(self) -> list[Body]: | ||||
|         return [self._mouse, *self._windows.values()] | ||||
| @@ -143,11 +129,13 @@ def main(): | ||||
| 
 | ||||
|     while True: | ||||
|         res_y = get_resolution_y() | ||||
|         bodies.update_list() | ||||
|         print(len(bodies.get())); | ||||
|         bodies.enumerate() | ||||
| 
 | ||||
|         for b in bodies.get(): | ||||
|             b.update(res_y) | ||||
|         time.sleep(1/120.0) | ||||
| 
 | ||||
|         time.sleep(1.0/120.0) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|     main() | ||||
		Reference in New Issue
	
	Block a user