Add virtual cursor for controller support

This commit is contained in:
csd4ni3l
2025-06-24 21:41:21 +02:00
parent 1672f35211
commit ffcf12552a
5 changed files with 63 additions and 7 deletions

View File

@@ -1,4 +1,10 @@
The Roboto Black font used in this project is licensed under the Open Font License. Read assets/fonts/OFL.txt for more information. The cursor used for virtual controller support is from the Pixel UI pack
by Kenney Vleugels for Kenney (www.kenney.nl)
with help by Lynn Evers (Twitter: @EversLynn)
Licensed (Creative Commons Zero, CC0) https://creativecommons.org/publicdomain/zero/1.0/
The Roboto Black font used in this project is licensed under the Open Font License.
Read assets/fonts/OFL.txt for more information.
Huge Thanks to Python for being the programming language used in this game. Huge Thanks to Python for being the programming language used in this game.
https://www.python.org/ https://www.python.org/

BIN
assets/graphics/cursor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

View File

@@ -2,7 +2,7 @@ import arcade, arcade.gui, pyglet, json
from game.shader import create_iter_calc_shader from game.shader import create_iter_calc_shader
from utils.constants import button_style, initial_real_imag from utils.constants import button_style, initial_real_imag
from utils.preload import button_texture, button_hovered_texture from utils.preload import button_texture, button_hovered_texture, cursor_texture
class IterFractalViewer(arcade.gui.UIView): class IterFractalViewer(arcade.gui.UIView):
def __init__(self, pypresence_client, fractal_name: str): def __init__(self, pypresence_client, fractal_name: str):
@@ -20,9 +20,14 @@ class IterFractalViewer(arcade.gui.UIView):
self.zoom = 1.0 self.zoom = 1.0
self.zoom_start_position = () self.zoom_start_position = ()
self.zoom_rect = None self.zoom_rect = None
self.has_controller = False
self.dragging_with_controller = False
def on_show_view(self): def on_show_view(self):
super().on_show_view() super().on_show_view()
self.window.on_stick_motion = self.on_stick_motion
self.window.on_button_press = self.on_button_press
self.window.on_button_release = self.on_button_release
self.shader_program, self.fractal_image = create_iter_calc_shader( self.shader_program, self.fractal_image = create_iter_calc_shader(
self.fractal_name, self.fractal_name,
@@ -57,6 +62,29 @@ class IterFractalViewer(arcade.gui.UIView):
self.back_button.on_click = lambda event: self.main_exit() self.back_button.on_click = lambda event: self.main_exit()
self.anchor.add(self.back_button, anchor_x="left", anchor_y="top", align_x=5, align_y=-5) self.anchor.add(self.back_button, anchor_x="left", anchor_y="top", align_x=5, align_y=-5)
if self.window.get_controllers():
self.sprite_list = arcade.SpriteList()
self.cursor_sprite = arcade.Sprite(cursor_texture)
self.sprite_list.append(self.cursor_sprite)
self.has_controller = True
def on_button_press(self, controller, button_name):
if button_name == "a" and self.has_controller:
self.zoom_start_position = self.cursor_sprite.center_x, self.cursor_sprite.center_y
self.dragging_with_controller = True
def on_button_release(self, controller, button_name):
if button_name == "a" and self.dragging_with_controller:
self.dragging_with_controller = False
self.on_mouse_release(self.cursor_sprite.center_x, self.cursor_sprite.center_y, None, None)
def on_stick_motion(self, controller, name, vector):
if name == "leftstick":
self.cursor_sprite.center_x += vector.x * 5
self.cursor_sprite.center_y += vector.y * 5
if self.dragging_with_controller:
self.on_mouse_drag(self.cursor_sprite.center_x, self.cursor_sprite.center_y, 0, 0, None, None)
def create_image(self): def create_image(self):
with self.shader_program: with self.shader_program:
self.shader_program['u_maxIter'] = int(self.max_iter) self.shader_program['u_maxIter'] = int(self.max_iter)
@@ -71,7 +99,7 @@ class IterFractalViewer(arcade.gui.UIView):
self.zoom = 1 self.zoom = 1
self.zoom_label.text = f"Zoom: {self.zoom:.4f}" self.zoom_label.text = f"Zoom: {self.zoom:.2f}"
self.zoom_start_position = None self.zoom_start_position = None
self.zoom_rect = None self.zoom_rect = None
@@ -80,7 +108,7 @@ class IterFractalViewer(arcade.gui.UIView):
self.pypresence_client.update( self.pypresence_client.update(
state=f'Viewing {self.fractal_name.replace("_", " ").capitalize()}', state=f'Viewing {self.fractal_name.replace("_", " ").capitalize()}',
details=f'Zoom: {self.zoom:.4f}\nMax Iterations: {self.max_iter}', details=f'Zoom: {self.zoom:.2f}\nMax Iterations: {self.max_iter}',
start=self.pypresence_client.start_time start=self.pypresence_client.start_time
) )
@@ -152,5 +180,8 @@ class IterFractalViewer(arcade.gui.UIView):
self.fractal_sprite.draw() self.fractal_sprite.draw()
self.ui.draw() self.ui.draw()
if self.has_controller:
self.sprite_list.draw()
if self.zoom_rect: if self.zoom_rect:
arcade.draw_rect_outline(self.zoom_rect, color=arcade.color.GRAY) arcade.draw_rect_outline(self.zoom_rect, color=arcade.color.GRAY)

View File

@@ -2,7 +2,7 @@ import arcade, arcade.gui, pyglet, json
from game.shader import create_sierpinsky_carpet_shader from game.shader import create_sierpinsky_carpet_shader
from utils.constants import button_style from utils.constants import button_style
from utils.preload import button_texture, button_hovered_texture from utils.preload import button_texture, button_hovered_texture, cursor_texture
class SierpinskyCarpetViewer(arcade.gui.UIView): class SierpinskyCarpetViewer(arcade.gui.UIView):
def __init__(self, pypresence_client): def __init__(self, pypresence_client):
@@ -16,6 +16,9 @@ class SierpinskyCarpetViewer(arcade.gui.UIView):
self.depth = self.settings_dict.get("sierpinsky_depth", 10) self.depth = self.settings_dict.get("sierpinsky_depth", 10)
self.zoom = 1.0 self.zoom = 1.0
self.click_center = (self.width / 2, self.height / 2) self.click_center = (self.width / 2, self.height / 2)
self.has_controller = False
self.window.on_stick_motion = self.on_stick_motion
def on_show_view(self): def on_show_view(self):
super().on_show_view() super().on_show_view()
@@ -30,6 +33,17 @@ class SierpinskyCarpetViewer(arcade.gui.UIView):
self.setup_ui() self.setup_ui()
if self.window.get_controllers():
self.sprite_list = arcade.SpriteList()
self.cursor_sprite = arcade.Sprite(cursor_texture)
self.sprite_list.append(self.cursor_sprite)
self.has_controller = True
def on_stick_motion(self, controller, name, vector):
if name == "leftstick":
self.cursor_sprite.center_x += vector.x * 5
self.cursor_sprite.center_y += vector.y * 5
def main_exit(self): def main_exit(self):
from menus.main import Main from menus.main import Main
self.window.show_view(Main(self.pypresence_client)) self.window.show_view(Main(self.pypresence_client))
@@ -53,8 +67,6 @@ class SierpinskyCarpetViewer(arcade.gui.UIView):
self.shader_program.dispatch(self.sierpinsky_carpet_image.width, self.sierpinsky_carpet_image.height, 1, barrier=pyglet.gl.GL_ALL_BARRIER_BITS) self.shader_program.dispatch(self.sierpinsky_carpet_image.width, self.sierpinsky_carpet_image.height, 1, barrier=pyglet.gl.GL_ALL_BARRIER_BITS)
def on_mouse_press(self, x: int, y: int, button: int, modifiers: int) -> bool | None: def on_mouse_press(self, x: int, y: int, button: int, modifiers: int) -> bool | None:
super().on_mouse_press(x, y, button, modifiers)
if button == arcade.MOUSE_BUTTON_LEFT: if button == arcade.MOUSE_BUTTON_LEFT:
zoom = self.settings_dict.get("sierpinsky_zoom_increase", 2) zoom = self.settings_dict.get("sierpinsky_zoom_increase", 2)
elif button == arcade.MOUSE_BUTTON_RIGHT: elif button == arcade.MOUSE_BUTTON_RIGHT:
@@ -72,7 +84,13 @@ class SierpinskyCarpetViewer(arcade.gui.UIView):
self.pypresence_client.update(state='Viewing Sierpinsky Carpet', details=f'Zoom: {self.zoom}\nDepth: {self.depth}', start=self.pypresence_client.start_time) self.pypresence_client.update(state='Viewing Sierpinsky Carpet', details=f'Zoom: {self.zoom}\nDepth: {self.depth}', start=self.pypresence_client.start_time)
def on_button_press(self, controller, name):
if name == "a":
self.on_mouse_press(self.cursor_sprite.left, self.cursor_sprite.bottom, arcade.MOUSE_BUTTON_LEFT, 0)
def on_draw(self): def on_draw(self):
self.window.clear() self.window.clear()
self.sierpinsky_carpet_sprite.draw() self.sierpinsky_carpet_sprite.draw()
self.ui.draw() self.ui.draw()
if self.has_controller:
self.sprite_list.draw()

View File

@@ -2,3 +2,4 @@ import arcade.gui, arcade
button_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button.png")) button_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button.png"))
button_hovered_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button_hovered.png")) button_hovered_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button_hovered.png"))
cursor_texture = arcade.load_texture("assets/graphics/cursor.png")