Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
gottadiveintopython committed Nov 17, 2023
1 parent ce0b49b commit 8a4f605
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 54 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@

## Tested on

- CPython 3.9 + Kivy 2.2.1
- CPython 3.10 + Kivy 2.2.1
- CPython 3.11 + Kivy 2.2.1
- CPython 3.10 + pygame-ce 2.3.2
- CPython 3.11 + pygame-ce 2.3.2
34 changes: 34 additions & 0 deletions investigation/using_Timer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

def main():
import pygame
from pygame.constants import QUIT, K_ESCAPE, KEYDOWN

from asyncpygame import Timer

timer = Timer()
timer.schedule_interval(print, 3000)

screen = pygame.display.set_mode((600, 500))
clock = pygame.Clock()
pygame.display.set_caption("Trying out the Timer")


pygame_event_get = pygame.event.get
clock_tick = clock.tick
running = True
while running:
for event in pygame_event_get():
event_type = event.type
if event_type == QUIT:
running = False
elif event_type == KEYDOWN and event.key == K_ESCAPE:
running = False

dt = clock_tick(10)
timer.progress(dt)

pygame.quit()


if __name__ == "__main__":
main()
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ classifiers=[
'License :: OSI Approved :: MIT License',
'Intended Audience :: Developers',
'Programming Language :: Python',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Software Development :: Libraries',
Expand All @@ -24,7 +23,7 @@ packages = [
]

[tool.poetry.dependencies]
python = "^3.9"
python = "^3.10"
asyncgui = "~0.6"

[tool.poetry.group.dev.dependencies]
Expand Down
66 changes: 24 additions & 42 deletions src/asyncpygame/_timer.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import types
from typing import TypeAlias, Any
from collections.abc import Callable
from collections.abc import Callable, Awaitable
from dataclasses import dataclass


ms: TypeAlias = int # milli seconds
TimeUnit: TypeAlias = int # can be any numeric type


@dataclass()
@dataclass(slots=True)
class TimerEvent:
_deadline: ms = 0
_last_tick: ms = 0
_func: Callable[[ms], Any] = None
_interval: ms = 0
_deadline: TimeUnit
_last_tick: TimeUnit
_func: Callable[[TimeUnit], Any]
_interval: TimeUnit | None
_cancelled: bool = False

def cancel(self):
Expand All @@ -21,60 +22,41 @@ def cancel(self):
class Timer:
def __init__(self):
self._cur_time = 0
self._events_once: list[TimerEvent] = []
self._events_interval: list[TimerEvent] = []
self._tmp: list[TimerEvent] = []
self._events: list[TimerEvent] = []
self._tmp: list[TimerEvent] = [] # double buffering

@property
def current_time(self) -> ms:
def current_time(self) -> TimeUnit:
return self._cur_time

def progress(self, delta_time):
self._cur_time += delta_time
cur_time = self._cur_time

# schedule_once
events = self._events_once
tmp = self._tmp
self._events_once = tmp
tmp_append = tmp.append
for event in events:
self._events, self._tmp = self._tmp, self._events
events_append = self._events.append
for event in self._tmp:
if event._cancelled:
continue
if event._deadline > cur_time:
tmp_append(event)
events_append(event)
continue
event._func(cur_time - event._last_tick)
tmp = events
tmp.clear()

# schedule_interval
events = self._events_interval
self._events_interval = tmp
tmp_append = tmp.append
for event in events:
if event._cancelled:
continue
if event._deadline > cur_time:
tmp_append(event)
continue
if event._func(cur_time - event._last_tick) is False:
if event._func(cur_time - event._last_tick) is False or event._interval is None:
continue
event._deadline += event._interval
event._last_tick = cur_time
tmp_append(event)
events.clear()

self._tmp = tmp
events_append(event)
self._tmp.clear()
assert self._tmp is not self._events

def schedule_once(self, func: Callable, delay: ms) -> TimerEvent:
def schedule_once(self, func: Callable, delay: TimeUnit) -> TimerEvent:
cur_time = self._cur_time
event = TimerEvent(cur_time + delay, cur_time, func)
self._events_once.append(event)
event = TimerEvent(cur_time + delay, cur_time, func, None)
self._events.append(event)
return event

def schedule_interval(self, func: Callable, interval: ms) -> TimerEvent:
def schedule_interval(self, func: Callable, interval: TimeUnit) -> TimerEvent:
cur_time = self._cur_time
event = TimerEvent(cur_time + interval, cur_time, func, interval)
self._events_interval.append(event)
self._events.append(event)
return event
26 changes: 19 additions & 7 deletions tests/test_timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,27 @@ def test_schedule_interval_cancel():
dt_list = []
func = dt_list.append

timer.schedule_interval(func, 100)
assert dt_list == []
timer.progress(50)
e = timer.schedule_interval(func, 100)
assert dt_list == []
timer.progress(50)
timer.progress(100)
assert dt_list == [100, ]
timer.progress(50)
e.cancel()
timer.progress(100)
assert dt_list == [100, ]


def test_schedule_interval_cancel_by_returning_false():
from asyncpygame import Timer
timer = Timer()
dt_list = []

def func(dt):
dt_list.append(dt)
return False

timer.schedule_interval(func, 100)
assert dt_list == []
timer.progress(100)
assert dt_list == [100, 150, ]
assert dt_list == [100, ]
timer.progress(100)
assert dt_list == [100, 150, 100]
assert dt_list == [100, ]

0 comments on commit 8a4f605

Please sign in to comment.