Created
July 20, 2025 02:01
-
-
Save EncodeTheCode/a455349f5bb10084d760717b221ecbfb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import glfw | |
from OpenGL.GL import * | |
import time | |
# Configuration | |
INITIAL_WINDOW_WIDTH = 800 | |
INITIAL_WINDOW_HEIGHT = 600 | |
CROSSHAIR_COLOR = (0.2, 1.0, 0.2, 1.0) # Syphon Filter green RGBA | |
# Ghost settings | |
GHOST_LIFETIME = 0.5 # seconds before a ghost fully fades | |
GHOST_SPAWN_INTERVAL = 0.1 # seconds between ghost spawns | |
MAX_GHOSTS = 50 # cap total ghosts in list | |
MAX_GHOST_DISTANCE = 150 # pixels: only draw ghosts within this distance | |
# Crosshair geometry (all in pixels) | |
CENTER_HALF = 5 # half-length of central crosshair | |
BOX_GAP = 8 # gap between center cross and box | |
BOX_EXT = 30 # half-size of outer box from edge of gap | |
LINE_THICKNESS = 2 | |
# Dynamic state | |
mouse_x, mouse_y = INITIAL_WINDOW_WIDTH/2, INITIAL_WINDOW_HEIGHT/2 | |
ghosts = [] # list of (x, y, timestamp) | |
window_width = INITIAL_WINDOW_WIDTH | |
window_height = INITIAL_WINDOW_HEIGHT | |
last_spawn_time = 0.0 | |
def mouse_move_callback(window, xpos, ypos): | |
global mouse_x, mouse_y | |
mouse_x = xpos | |
mouse_y = window_height - ypos | |
def window_size_callback(window, width, height): | |
global window_width, window_height | |
window_width, window_height = width, height | |
glViewport(0, 0, width, height) | |
glMatrixMode(GL_PROJECTION) | |
glLoadIdentity() | |
glOrtho(0, width, 0, height, -1, 1) | |
glMatrixMode(GL_MODELVIEW) | |
glLoadIdentity() | |
def init_window(): | |
if not glfw.init(): | |
raise Exception("glfw cannot be initialized!") | |
glfw.window_hint(glfw.RESIZABLE, glfw.TRUE) | |
window = glfw.create_window( | |
INITIAL_WINDOW_WIDTH, | |
INITIAL_WINDOW_HEIGHT, | |
"Crosshair Ghost Trails", | |
None, None | |
) | |
if not window: | |
glfw.terminate() | |
raise Exception("glfw window cannot be created!") | |
glfw.make_context_current(window) | |
glfw.set_cursor_pos_callback(window, mouse_move_callback) | |
glfw.set_window_size_callback(window, window_size_callback) | |
fb_w, fb_h = glfw.get_framebuffer_size(window) | |
window_size_callback(window, fb_w, fb_h) | |
glEnable(GL_BLEND) | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) | |
return window | |
def draw_crosshair(x, y, color): | |
"""Draws a Syphon Filter style box crosshair centered at (x,y).""" | |
r, g, b, a = color | |
glColor4f(r, g, b, a) | |
glLineWidth(LINE_THICKNESS) | |
half_center = CENTER_HALF | |
half_box = CENTER_HALF + BOX_GAP + BOX_EXT | |
gap_extent = CENTER_HALF + BOX_GAP | |
# central crosshair | |
glBegin(GL_LINES) | |
glVertex2f(x - half_center, y) | |
glVertex2f(x + half_center, y) | |
glVertex2f(x, y - half_center) | |
glVertex2f(x, y + half_center) | |
glEnd() | |
# outer box segments | |
glBegin(GL_LINES) | |
# top horizontal | |
glVertex2f(x - half_box, y + half_box) | |
glVertex2f(x + half_box, y + half_box) | |
# bottom horizontal | |
glVertex2f(x - half_box, y - half_box) | |
glVertex2f(x + half_box, y - half_box) | |
# left vertical (two segments leaving gap at middle) | |
glVertex2f(x - half_box, y + half_box) | |
glVertex2f(x - half_box, y + gap_extent) | |
glVertex2f(x - half_box, y - gap_extent) | |
glVertex2f(x - half_box, y - half_box) | |
# right vertical | |
glVertex2f(x + half_box, y + half_box) | |
glVertex2f(x + half_box, y + gap_extent) | |
glVertex2f(x + half_box, y - gap_extent) | |
glVertex2f(x + half_box, y - half_box) | |
glEnd() | |
def main(): | |
global last_spawn_time | |
window = init_window() | |
while not glfw.window_should_close(window): | |
glClear(GL_COLOR_BUFFER_BIT) | |
now = time.time() | |
# spawn a new ghost at live position, controlled by interval | |
if now - last_spawn_time >= GHOST_SPAWN_INTERVAL: | |
ghosts.append((mouse_x, mouse_y, now)) | |
last_spawn_time = now | |
if len(ghosts) > MAX_GHOSTS: | |
ghosts.pop(0) | |
# draw and prune ghosts | |
alive = [] | |
max_dist_sq = MAX_GHOST_DISTANCE * MAX_GHOST_DISTANCE | |
for gx, gy, ts in ghosts: | |
age = now - ts | |
if age < GHOST_LIFETIME: | |
dx = gx - mouse_x | |
dy = gy - mouse_y | |
if dx*dx + dy*dy <= max_dist_sq: | |
alpha = a = CROSSHAIR_COLOR[3] * (1 - age / GHOST_LIFETIME) | |
draw_crosshair(gx, gy, | |
(CROSSHAIR_COLOR[0], | |
CROSSHAIR_COLOR[1], | |
CROSSHAIR_COLOR[2], | |
alpha)) | |
alive.append((gx, gy, ts)) | |
ghosts[:] = alive | |
# draw live crosshair on top | |
draw_crosshair(mouse_x, mouse_y, CROSSHAIR_COLOR) | |
glfw.swap_buffers(window) | |
glfw.poll_events() | |
glfw.terminate() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment