diff --git a/game/events.py b/game/events.py new file mode 100644 index 0000000..fe212f0 --- /dev/null +++ b/game/events.py @@ -0,0 +1,54 @@ +# Copyright (C) 2022 RozK +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from engine import ( + buffer, + EVENT_FOCUS_IN, EVENT_FOCUS_OUT, + EVENT_KEY_PRESS, EVENT_KEY_RELEASE, + EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE, + EVENT_MOTION, + Event, create_events, destroy_events, consume_events) + +_max_type = max( + EVENT_FOCUS_IN, EVENT_FOCUS_OUT, + EVENT_KEY_PRESS, EVENT_KEY_RELEASE, + EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE, + EVENT_MOTION) + +_max_events = 64 + +class Events: + __slots__ = '_display', '_events', '_buffer', '_handlers' + + def __init__(self, display): + self._display = display + self._events = create_events(display) + self._buffer = buffer(Event, _max_events) + self._handlers = [[] for _ in range(_max_type + 1)] + + def __del__(self): + destroy_events(self._display, self._events) + + def register(self, type, handler): + assert type <= _max_type + self._handlers[type].append(handler) + + def update(self): + nevents = consume_events(self._events, self._buffer, _max_events) + if nevents: + for event in self._buffer[:nevents]: + data = event.data + for handler in self._handlers[event.type]: + handler(data) diff --git a/game/keyboard.py b/game/keyboard.py new file mode 100644 index 0000000..729df97 --- /dev/null +++ b/game/keyboard.py @@ -0,0 +1,27 @@ +# Copyright (C) 2022 RozK +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from engine import EVENT_KEY_PRESS + +class Keyboard: + __slots__ = 'quit' + + def __init__(self, events): + self.quit = False + events.register(EVENT_KEY_PRESS, self.key_press_handler) + + def key_press_handler(self, data): + if data.key.character == 'q': + self.quit = True diff --git a/game/mouse.py b/game/mouse.py new file mode 100644 index 0000000..acedbf4 --- /dev/null +++ b/game/mouse.py @@ -0,0 +1,52 @@ +# Copyright (C) 2022 RozK +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from engine import ( + EVENT_BUTTON_PRESS, EVENT_BUTTON_RELEASE, EVENT_MOTION, BUTTON_LEFT, BUTTON_WHEEL_UP, BUTTON_WHEEL_DOWN) + +class Mouse: + __slots__ = 'buttons', 'wheel', 'wheel_min', 'position', 'drag' + + def __init__(self, events, wheel = 0, wheel_min = None): + self.buttons = 0 + self.wheel = wheel + self.wheel_min = wheel_min + self.position = None + self.drag = (0, 0) + events.register(EVENT_BUTTON_PRESS, self.button_press_handler) + events.register(EVENT_BUTTON_RELEASE, self.button_release_handler) + events.register(EVENT_MOTION, self.motion_handler) + + def button_press_handler(self, data): + button = data.button.index + self.buttons |= 1 << button + if button == BUTTON_WHEEL_UP: + self.wheel -= 1 + if self.wheel_min is not None and self.wheel < self.wheel_min: + self.wheel = self.wheel_min + elif button == BUTTON_WHEEL_DOWN: + self.wheel += 1 + + def button_release_handler(self, data): + self.buttons &= ~(1 << data.button.index) + + def motion_handler(self, data): + new_x = data.motion.x + new_y = data.motion.y + if self.position and (self.buttons & (1 << BUTTON_LEFT)): + prev_x, prev_y = self.position + prev_dx, prev_dy = self.drag + self.drag = (prev_dx + (new_x - prev_x), prev_dy + (new_y - prev_y)) + self.position = (new_x, new_y)