@ElFiniberto: Anmerkungen zum Quelltext: `random` wird importiert, aber nirgends verwendet.
In `script_unload()` sollte man auch den Timer für `start` entfernen, denn wenn man Timer entfernen muss, dann ja auch wenn das innerhalb der Zeit aufgerufen wird, die gewartet wird bis `start()` das erste mal aufgerufen wird.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).
Namen sollten keine kryptischen Abkürzungen enthalten. Was soll `dvd` bedeuten?
`time.time()` ist hier nicht wirklich geeignet, da sollte `time.monotonic()` verwendet werden.
Warum heisst `update_text()` so wie es heisst? Wo wird denn dort Text aktualisiert‽
``global`` hat in sauberen Programmen nichts zu suchen. Das die OBS-API keine Methoden für Rückrufe erlaubt ist äusserst hässlich.
Man kann da fast die Hälfte der globalen Variablen einsparen wenn man X und X nicht getrennt speichert, sondern sich eine Klasse dafür schreibt.
Wenn `scene` zuverlässig wieder freigegeben werden soll, sollte man das mit einem ``finally`` absichern.
Die Zeichenkette "cangr" wird zweimal verwendet. Sollte die beide male das gleiche Bedeuten, dann sollte man das als Konstante definieren.
Man verwendet kein nacktes ``except:`` ohne konkrete Ausnahmen. Das behandelt *alle* Ausnahmen, auch welche mit denen man gar nicht rechnet, verschluckt also hier auch alle möglichen Fehler, die man so nicht finden kann.
Das zusammenstückeln von Zeichenketten und Werten mittels ``+`` und `str()` ist eher BASIC als Python. Dafür gibt es die `format()`-Methode auf Zeichenketten und f-Zeichenkettenliterale.
Ungetestet:
Code: Alles auswählen
import time
import obspython as S
import pyautogui
WIDTH, HEIGHT = 1920, 1080
MARGIN = 32
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __repr__(self):
return f"{self.__class__.__name__}({self.x!r}, {self.y!r})"
def __eq__(self, other):
return self.as_tuple() == other.as_tuple()
def __neq__(self, other):
return not self == other
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Point(self.x - other.x, self.y - other.y)
def min(self, other):
return Point(min(self.x, other.x), min(self.y, other.y))
def as_tuple(self):
return (self.x, self.y)
def as_vec2(self):
result = S.vec2()
result.x, result.y = self.as_tuple()
return result
SPEED = Point(3, 3)
dvd_position = Point(144, 128)
speed = SPEED
last_position = Point()
last_move_timestamp = time.monotonic()
is_cursor = False
def update_position():
global dvd_position, speed, is_cursor, last_position, last_move_timestamp
scene = S.obs_get_scene_by_name("Wall")
try:
scene_item = S.obs_scene_find_source(scene, "cangr")
if scene_item:
position = Point(*pyautogui.position())
if (
position != last_position
and position.x > MARGIN
and position.y > MARGIN
):
last_position = position
last_move_timestamp = time.monotonic()
# print(f"{speed=}, {position=}, {last_position=}")
if (
position.x >= WIDTH
or time.monotonic() - last_move_timestamp > 3
):
if is_cursor:
dvd_position = last_position.min(
Point(WIDTH - MARGIN, HEIGHT - MARGIN)
)
speed = SPEED
if not MARGIN <= dvd_position.x < WIDTH - MARGIN:
speed.x = -speed.x
if not MARGIN <= dvd_position.y < HEIGHT - MARGIN:
speed.y = -speed.y
dvd_position += speed
position = dvd_position
# print("new position:", position)
is_cursor = False
else:
is_cursor = True
S.obs_sceneitem_set_pos(
scene_item, (position - Point(MARGIN, MARGIN)).as_vec2()
)
finally:
S.obs_scene_release(scene)
def start():
S.timer_add(update_position, 17)
S.timer_remove(start)
def script_description():
return "cangr"
def script_load(_settings):
S.timer_add(start, 3000)
def script_unload():
S.timer_remove(start)
S.timer_remove(update_position)