diff --git a/Difficult_Rocket/__init__.py b/Difficult_Rocket/__init__.py index bad2a2e..ab6aab9 100644 --- a/Difficult_Rocket/__init__.py +++ b/Difficult_Rocket/__init__.py @@ -38,11 +38,12 @@ class DR_option(Options): use_cProfile: bool = False use_local_logging: bool = False report_translate_no_found: bool = True + use_muitprocess: bool = False # tests playing: bool = False debugging: bool = False - crash_report_test: bool = True + crash_report_test: bool = False # window option gui_scale: int = 1 # default 1 2 -> 2x 3 -> 3x @@ -58,7 +59,8 @@ class _DR_runtime(Options): DR_long_version: int = long_version # run status - start_time_ns: int = None + running: bool = False + start_time_ns: int = None client_setup_cause_ns: int = None server_setup_cause_ns: int = None diff --git a/Difficult_Rocket/api/screen.py b/Difficult_Rocket/api/screen.py new file mode 100644 index 0000000..37487eb --- /dev/null +++ b/Difficult_Rocket/api/screen.py @@ -0,0 +1,430 @@ +# ------------------------------- +# Difficult Rocket +# Copyright © 2021-2022 by shenjackyuanjie 3695888@qq.com +# All rights reserved +# ------------------------------- + + +import typing +from typing import List + +# from pyglet.window import Window +from pyglet.event import EventDispatcher + +# Difficult Rocket function + + +if typing.TYPE_CHECKING: + from Difficult_Rocket.client import ClientWindow + + +class BaseScreen(EventDispatcher): + """ + DR 的 页面API + """ + + def __init__(self, main_window: "ClientWindow"): + super().__init__() + self.window_pointer = main_window + + if typing.TYPE_CHECKING: + def on_key_press(self, symbol: int, modifiers: int): + """一个键盘按键被按下 + :param: + `symbol` : int + 按下按键的标识符 + `modifiers` : int + 每一位(二进制)表示一个修饰键的启用情况 + """ + + def on_key_release(self, symbol: int, modifiers: int): + """一个键盘按键被松开 + :param: + `symbol` : int + 放下按键的标识符 + `modifiers` : int + 每一位(二进制)表示一个修饰键的启用情况 + """ + + def on_text(self, text: str): + """用户输入了一个字符 + + Typically this is called after :py:meth:`~pyglet.window.Window.on_key_press` and before + :py:meth:`~pyglet.window.Window.on_key_release`, but may also be called multiple times if the key + is held down (key repeating); or called without key presses if + another input method was used (e.g., a pen input). + + You should always use this method for interpreting text, as the + key symbols often have complex mappings to their unicode + representation which this event takes care of. + + :param: + `text` : unicode + 用户输入的 unicode 编码的内容 + + """ + + def on_text_motion(self, motion: int): + """The user moved the text input cursor. + + Typically this is called after :py:meth:`~pyglet.window.Window.on_key_press` and before + :py:meth:`~pyglet.window.Window.on_key_release`, but may also be called multiple times if the key + is help down (key repeating). + + You should always use this method for moving the text input cursor + (caret), as different platforms have different default keyboard + mappings, and key repeats are handled correctly. + + The values that `motion` can take are defined in + :py:mod:`pyglet.window.key`: + + * MOTION_UP + * MOTION_RIGHT + * MOTION_DOWN + * MOTION_LEFT + * MOTION_NEXT_WORD + * MOTION_PREVIOUS_WORD + * MOTION_BEGINNING_OF_LINE + * MOTION_END_OF_LINE + * MOTION_NEXT_PAGE + * MOTION_PREVIOUS_PAGE + * MOTION_BEGINNING_OF_FILE + * MOTION_END_OF_FILE + * MOTION_BACKSPACE + * MOTION_DELETE + + :param: + `motion` : int + The direction of motion; see remarks. + + """ + + def on_text_motion_select(self, motion: int): + """The user moved the text input cursor while extending the + selection. + + Typically this is called after :py:meth:`~pyglet.window.Window.on_key_press` and before + :py:meth:`~pyglet.window.Window.on_key_release`, but may also be called multiple times if the key + is help down (key repeating). + + You should always use this method for responding to text selection + events rather than the raw :py:meth:`~pyglet.window.Window.on_key_press`, as different platforms + have different default keyboard mappings, and key repeats are + handled correctly. + + The values that `motion` can take are defined in :py:mod:`pyglet.window.key`: + + * MOTION_UP + * MOTION_RIGHT + * MOTION_DOWN + * MOTION_LEFT + * MOTION_NEXT_WORD + * MOTION_PREVIOUS_WORD + * MOTION_BEGINNING_OF_LINE + * MOTION_END_OF_LINE + * MOTION_NEXT_PAGE + * MOTION_PREVIOUS_PAGE + * MOTION_BEGINNING_OF_FILE + * MOTION_END_OF_FILE + + :param: + `motion` : int + The direction of selection motion; see remarks. + + """ + + def on_mouse_motion(self, x: int, y: int, dx: int, dy: int): + """The mouse was moved with no buttons held down. + + :param: + `x` : int + Distance in pixels from the left edge of the window. + `y` : int + Distance in pixels from the bottom edge of the window. + `dx` : int + Relative X position from the previous mouse position. + `dy` : int + Relative Y position from the previous mouse position. + + """ + + def on_mouse_drag(self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int): + """The mouse was moved with one or more mouse buttons pressed. + + This event will continue to be fired even if the mouse leaves + the window, so long as the drag buttons are continuously held down. + + :param: + `x` : int + Distance in pixels from the left edge of the window. + `y` : int + Distance in pixels from the bottom edge of the window. + `dx` : int + Relative X position from the previous mouse position. + `dy` : int + Relative Y position from the previous mouse position. + `buttons` : int + Bitwise combination of the mouse buttons currently pressed. + `modifiers` : int + Bitwise combination of any keyboard modifiers currently + active. + + """ + + def on_mouse_press(self, x: int, y: int, button: int, modifiers: int): + """A mouse button was pressed (and held down). + + :param: + `x` : int + Distance in pixels from the left edge of the window. + `y` : int + Distance in pixels from the bottom edge of the window. + `button` : int + The mouse button that was pressed. + `modifiers` : int + Bitwise combination of any keyboard modifiers currently + active. + + """ + + def on_mouse_release(self, x: int, y: int, button: int, modifiers: int): + """A mouse button was released. + + :param: + `x` : int + Distance in pixels from the left edge of the window. + `y` : int + Distance in pixels from the bottom edge of the window. + `button` : int + The mouse button that was released. + `modifiers` : int + Bitwise combination of any keyboard modifiers currently + active. + + """ + + def on_mouse_scroll(self, x: int, y: int, scroll_x: int, scroll_y: int): + """The mouse wheel was scrolled. + + Note that most mice have only a vertical scroll wheel, so + `scroll_x` is usually 0. An exception to this is the Apple Mighty + Mouse, which has a mouse ball in place of the wheel which allows + both `scroll_x` and `scroll_y` movement. + + :param: + `x` : int + Distance in pixels from the left edge of the window. + `y` : int + Distance in pixels from the bottom edge of the window. + `scroll_x` : float + Amount of movement on the horizontal axis. + `scroll_y` : float + Amount of movement on the vertical axis. + """ + + def on_close(self): + """The user attempted to close the window. + + This event can be triggered by clicking on the "X" control box in + the window title bar, or by some other platform-dependent manner. + + The default handler sets `has_exit` to ``True``. In pyglet 1.1, if + `pyglet.app.event_loop` is being used, `close` is also called, + closing the window immediately. + """ + + def on_mouse_enter(self, x: int, y: int): + """The mouse was moved into the window. + + This event will not be triggered if the mouse is currently being + dragged. + + :param: + `x` : int + Distance in pixels from the left edge of the window. + `y` : int + Distance in pixels from the bottom edge of the window. + """ + + def on_mouse_leave(self, x: int, y: int): + """The mouse was moved outside of the window. + + This event will not be triggered if the mouse is currently being + dragged. Note that the coordinates of the mouse pointer will be + outside of the window rectangle. + + :param: + `x` : int + Distance in pixels from the left edge of the window. + `y` : int + Distance in pixels from the bottom edge of the window. + """ + + def on_expose(self): + """A portion of the window needs to be redrawn. + + This event is triggered when the window first appears, and any time + the contents of the window is invalidated due to another window + obscuring it. + + There is no way to determine which portion of the window needs + redrawing. Note that the use of this method is becoming + increasingly uncommon, as newer window managers composite windows + automatically and keep a backing store of the window contents. + """ + + def on_resize(self, width: int, height: int): + """The window was resized. + + The window will have the GL context when this event is dispatched; + there is no need to call `switch_to` in this handler. + + :param: + `width` : int + The new width of the window, in pixels. + `height` : int + The new height of the window, in pixels. + """ + + def on_move(self, x: int, y: int): + """The window was moved. + + :param: + `x` : int + Distance from the left edge of the screen to the left edge + of the window. + `y` : int + Distance from the top edge of the screen to the top edge of + the window. Note that this is one of few methods in pyglet + which use a Y-down coordinate system. + """ + + def on_activate(self): + """The window was activated. + + This event can be triggered by clicking on the title bar, bringing + it to the foreground; or by some platform-specific method. + + When a window is "active" it has the keyboard focus. + """ + + def on_deactivate(self): + """The window was deactivated. + + This event can be triggered by clicking on another application + window. When a window is deactivated it no longer has the + keyboard focus. + """ + + def on_show(self): + """The window was shown. + + This event is triggered when a window is restored after being + minimised, hidden, or after being displayed for the first time. + """ + + def on_hide(self): + """The window was hidden. + + This event is triggered when a window is minimised + or hidden by the user. + """ + + def on_context_lost(self): + """The window's GL context was lost. + + When the context is lost no more GL methods can be called until it + is recreated. This is a rare event, triggered perhaps by the user + switching to an incompatible video mode. When it occurs, an + application will need to reload all objects (display lists, texture + objects, shaders) as well as restore the GL state. + """ + + def on_context_state_lost(self): + """The state of the window's GL context was lost. + + pyglet may sometimes need to recreate the window's GL context if + the window is moved to another video device, or between fullscreen + or windowed mode. In this case it will try to share the objects + (display lists, texture objects, shaders) between the old and new + contexts. If this is possible, only the current state of the GL + context is lost, and the application should simply restore state. + """ + + def on_file_drop(self, x: int, y: int, paths: List[str]): + """File(s) were dropped into the window, will return the position of the cursor and + a list of paths to the files that were dropped. + """ + + def on_draw(self): + """The window contents must be redrawn. + + The `EventLoop` will dispatch this event when the window + should be redrawn. This will happen during idle time after + any window events and after any scheduled functions were called. + + The window will already have the GL context, so there is no + need to call `switch_to`. The window's `flip` method will + be called after this event, so your event handler should not. + + You should make no assumptions about the window contents when + this event is triggered; a resize or expose event may have + invalidated the framebuffer since the last time it was drawn. + """ + + def on_refresh(self): + """The window contents must be redrawn. + + The `EventLoop` will dispatch this event when the window + should be redrawn. + + The window will already have the GL context, so there is no + need to call `switch_to`. The window's `flip` method will + be called after this event, so your event handler should not. + + You should make no assumptions about the window contents when + this event is triggered; a resize or expose event may have + invalidated the framebuffer since the last time it was drawn. + + """ + + def on_command(self, command): + """ + + :param command: + :return: + """ + + def on_message(self, message): + """ + + :param message: + :return: + """ + + +BaseScreen.register_event_type('on_key_press') +BaseScreen.register_event_type('on_key_release') +BaseScreen.register_event_type('on_text') +BaseScreen.register_event_type('on_text_motion') +BaseScreen.register_event_type('on_text_motion_select') +BaseScreen.register_event_type('on_mouse_motion') +BaseScreen.register_event_type('on_mouse_drag') +BaseScreen.register_event_type('on_mouse_press') +BaseScreen.register_event_type('on_mouse_release') +BaseScreen.register_event_type('on_mouse_scroll') +BaseScreen.register_event_type('on_mouse_enter') +BaseScreen.register_event_type('on_mouse_leave') +BaseScreen.register_event_type('on_close') +BaseScreen.register_event_type('on_expose') +BaseScreen.register_event_type('on_resize') +BaseScreen.register_event_type('on_move') +BaseScreen.register_event_type('on_activate') +BaseScreen.register_event_type('on_deactivate') +BaseScreen.register_event_type('on_show') +BaseScreen.register_event_type('on_hide') +BaseScreen.register_event_type('on_context_lost') +BaseScreen.register_event_type('on_context_state_lost') +BaseScreen.register_event_type('on_file_drop') +BaseScreen.register_event_type('on_draw') +BaseScreen.register_event_type('on_refresh') diff --git a/Difficult_Rocket/client/__init__.py b/Difficult_Rocket/client/__init__.py index 0cf97d7..3d786a9 100644 --- a/Difficult_Rocket/client/__init__.py +++ b/Difficult_Rocket/client/__init__.py @@ -10,14 +10,15 @@ mail: 3695888@qq.com github: @shenjackyuanjie gitee: @shenjackyuanjie """ - +import inspect # system function import os import time import logging +import functools import traceback -from typing import List, Union +from typing import List, Callable, Union from decimal import Decimal # third function @@ -30,11 +31,10 @@ from pyglet.window import Window from pyglet.window import key, mouse # Difficult_Rocket function -from Difficult_Rocket import Options, DR_runtime +from Difficult_Rocket import DR_runtime from Difficult_Rocket.command import line, tree from Difficult_Rocket.utils.translate import tr -from Difficult_Rocket.client.screen import DRScreen -from Difficult_Rocket.client.screen import DRDEBUGScreen +from Difficult_Rocket.client.screen import BaseScreen, DRScreen, DRDEBUGScreen from Difficult_Rocket.utils import tools, translate from Difficult_Rocket.utils.new_thread import new_thread from Difficult_Rocket.client.fps.fps_log import FpsLogger @@ -54,7 +54,8 @@ class Client: self.process_name = 'Client process' self.process_pid = os.getpid() self.net_mode = net_mode - self.caption = tools.name_handler(self.config['window']['caption'], {'version': self.config['runtime']['version']}) + self.caption = tools.name_handler(self.config['window']['caption'], + {'version': self.config['runtime']['version']}) self.window = ClientWindow(net_mode=self.net_mode, width=int(self.config['window']['width']), height=int(self.config['window']['height']), @@ -83,8 +84,30 @@ def pyglet_load_fonts_folder(folder) -> None: pyglet_load_fonts_folder(os.path.join(folder, obj)) -# class _DR_Client_option(Options): -# ... +def _call_screen_after(func: Callable) -> Callable: + @functools.wraps(func) + def warped(self, *args, **kwargs): + result = func(self, *args, **kwargs) + for a_screen in self.screen_list: + if hasattr(a_screen, func.__name__): + getattr(a_screen, func.__name__)(*args, **kwargs) + return result + + warped.__signature__ = inspect.signature(func) + return warped + + +def _call_screen_before(func: Callable) -> Callable: + @functools.wraps(func) + def warped(self, *args, **kwargs): + for a_screen in self.screen_list: + if hasattr(a_screen, func.__name__): + getattr(a_screen, func.__name__)(*args, **kwargs) + result = func(self, *args, **kwargs) + return result + + warped.__signature__ = inspect.signature(func) + return warped class ClientWindow(Window): @@ -117,7 +140,6 @@ class ClientWindow(Window): # frame self.frame = pyglet.gui.Frame(self, order=20) self.M_frame = pyglet.gui.MovableFrame(self, modifier=key.LCTRL) - # self.DRscreen = DRScreen(self) self.screen_list = [] # setup self.setup() @@ -128,13 +150,6 @@ class ClientWindow(Window): batch=self.label_batch) # 实例化 self.push_handlers(self.input_box) self.input_box.enabled = True - # fps显示 - self.fps_label = pyglet.text.Label(x=10, y=self.height - 10, - width=self.width - 20, height=20, - anchor_x='left', anchor_y='top', - font_name=translate.微软等宽无线, font_size=20, - multiline=True, - batch=self.label_batch, group=self.command_group) # 设置刷新率 pyglet.clock.schedule_interval(self.draw_update, float(self.SPF)) # 完成设置后的信息输出 @@ -149,7 +164,6 @@ class ClientWindow(Window): def setup(self): self.load_fonts() - from Difficult_Rocket.client.screen import DRDEBUGScreen, DRScreen, BaseScreen self.screen_list: List[BaseScreen] self.screen_list.append(DRDEBUGScreen(self)) self.screen_list.append(DRScreen(self)) @@ -197,38 +211,39 @@ class ClientWindow(Window): draws and some event """ + @_call_screen_after def draw_update(self, tick: float): decimal_tick = Decimal(str(tick)[:10]) - self.FPS_update(decimal_tick) - - def FPS_update(self, tick: Decimal): now_FPS = pyglet.clock.get_frequency() - self.fps_log.update_tick(now_FPS, tick) - - self.fps_label.text = f'FPS: {self.fps_log.fps: >5.1f}({self.fps_log.middle_fps: >5.1f})[{now_FPS: >.7f}]\n {self.fps_log.max_fps: >7.1f} {self.fps_log.min_fps:>5.1f}' + self.fps_log.update_tick(now_FPS, decimal_tick) + @_call_screen_after def on_draw(self, *dt): # self.logger.debug('on_draw call dt: {}'.format(dt)) pyglet.gl.glClearColor(0.1, 0, 0, 0.0) self.clear() self.draw_batch() + @_call_screen_after def on_resize(self, width: int, height: int): super().on_resize(width, height) - self.fps_label.y = height - 10 + @_call_screen_after def on_refresh(self, dt): ... + @_call_screen_after def on_show(self): # HWND_TOPMOST = -1 # _user32.SetWindowPos(self._hwnd, HWND_TOPMOST, 0, 0, self.width, self.height, 0) ... + @_call_screen_after def on_hide(self): # self.set_location(*self.get_location()) print('on hide!') + @_call_screen_after def draw_batch(self): self.part_batch.draw() self.label_batch.draw() @@ -237,11 +252,12 @@ class ClientWindow(Window): command line event """ + @_call_screen_after def on_command(self, command: line.CommandText): self.logger.info(tr.lang('window', 'command.text').format(command)) if command.match('stop'): - self.dispatch_event('on_exit') - # platform_event_loop.stop() + # self.dispatch_event('on_exit') + pyglet.app.platform_event_loop.stop() self.dispatch_event('on_close', 'command') # source = command elif command.match('fps'): if command.match('log'): @@ -253,9 +269,11 @@ class ClientWindow(Window): self.logger.info(self.fps_log.min_fps) self.command.push_line(self.fps_log.min_fps, block_line=True) elif command.match('default'): - self.set_size(int(self.main_config['window_default']['width']), int(self.main_config['window_default']['height'])) + self.set_size(int(self.main_config['window_default']['width']), + int(self.main_config['window_default']['height'])) self.command_tree.parse(command.plain_command) + @_call_screen_after def on_message(self, message: line.CommandLine.text): self.logger.info(tr.lang('window', 'message.text').format(message)) @@ -263,31 +281,51 @@ class ClientWindow(Window): keyboard and mouse input """ - def activate(self): + @_call_screen_after + def on_activate(self): super().activate() + @_call_screen_after + def on_deactivate(self): + ... + + @_call_screen_after def on_mouse_motion(self, x, y, dx, dy) -> None: pass + @_call_screen_after def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers) -> None: pass + @_call_screen_after def on_mouse_press(self, x, y, button, modifiers) -> None: - self.logger.debug(tr.lang('window', 'mouse.press').format([x, y], tr.lang('window', 'mouse.{}'.format(mouse.buttons_string(button))))) + self.logger.debug(tr.lang('window', 'mouse.press').format([x, y], tr.lang('window', 'mouse.{}'.format( + mouse.buttons_string(button))))) + @_call_screen_after def on_mouse_release(self, x, y, button, modifiers) -> None: - self.logger.debug(tr.lang('window', 'mouse.release').format([x, y], tr.lang('window', 'mouse.{}'.format(mouse.buttons_string(button))))) + self.logger.debug(tr.lang('window', 'mouse.release').format([x, y], tr.lang('window', 'mouse.{}'.format( + mouse.buttons_string(button))))) + @_call_screen_after def on_key_press(self, symbol, modifiers) -> None: if symbol == key.ESCAPE and not (modifiers & ~(key.MOD_NUMLOCK | key.MOD_CAPSLOCK | key.MOD_SCROLLLOCK)): self.dispatch_event('on_close') - self.logger.debug(tr.lang('window', 'key.press').format(key.symbol_string(symbol), key.modifiers_string(modifiers))) + self.logger.debug( + tr.lang('window', 'key.press').format(key.symbol_string(symbol), key.modifiers_string(modifiers))) + @_call_screen_after def on_key_release(self, symbol, modifiers) -> None: - self.logger.debug(tr.lang('window', 'key.release').format(key.symbol_string(symbol), key.modifiers_string(modifiers))) + self.logger.debug( + tr.lang('window', 'key.release').format(key.symbol_string(symbol), key.modifiers_string(modifiers))) + @_call_screen_after + def on_file_drop(self, x, y, paths): + ... + + @_call_screen_after def on_text(self, text): if text == '\r': self.logger.debug(tr.lang('window', 'text.new_line')) @@ -296,18 +334,22 @@ class ClientWindow(Window): if text == 't': self.input_box.enabled = True + @_call_screen_after def on_text_motion(self, motion): motion_string = key.motion_string(motion) self.logger.debug(tr.lang('window', 'text.motion').format(motion_string)) + @_call_screen_after def on_text_motion_select(self, motion): motion_string = key.motion_string(motion) self.logger.debug(tr.lang('window', 'text.motion_select').format(motion_string)) + @_call_screen_before def on_close(self, source: str = 'window') -> None: self.logger.info(tr.lang('window', 'game.stop_get').format(tr.lang('window', f'game.{source}_stop'))) self.logger.info(tr.lang('window', 'game.stop')) self.fps_log.check_list = False + DR_runtime.running = False if self.run_input: self.run_input = False self.save_info() diff --git a/Difficult_Rocket/client/render/sr1_ship.py b/Difficult_Rocket/client/render/sr1_ship.py index 50d4925..48d4e60 100644 --- a/Difficult_Rocket/client/render/sr1_ship.py +++ b/Difficult_Rocket/client/render/sr1_ship.py @@ -5,8 +5,32 @@ # ------------------------------- # third party package -from defusedxml.ElementTree import parse +from defusedxml.ElementTree import DefusedXMLParser + +# pyglet +from pyglet.graphics import Batch +from pyglet.resource import texture # Difficult Rocket -from Difficult_Rocket.client.screen import BaseScreen +from client.screen import BaseScreen +from Difficult_Rocket.client import ClientWindow + +class SR1ShipRender(BaseScreen): + """用于渲染 sr1 船的类""" + + def __init__(self, x: float, y: float, + scale: float, + xml_doc: DefusedXMLParser, + main_window: "ClientWindow"): + super().__init__(main_window) + self.x, self.y = x, y + self.scale = scale + self.xml_doc = xml_doc + self.part_batch = Batch() + + def on_draw(self): + ... + + def on_command(self, command): + ... diff --git a/Difficult_Rocket/client/screen.py b/Difficult_Rocket/client/screen.py index e7bf3ec..30785a3 100644 --- a/Difficult_Rocket/client/screen.py +++ b/Difficult_Rocket/client/screen.py @@ -6,412 +6,19 @@ import typing -from pyglet.window import Window -from pyglet.event import EventDispatcher +from pyglet.text import Label +from pyglet.graphics import Batch, Group +from pyglet.clock import get_frequency # Difficult Rocket function +from Difficult_Rocket.utils import translate +from Difficult_Rocket.api.screen import BaseScreen from Difficult_Rocket.command.tree import CommandTree - if typing.TYPE_CHECKING: from Difficult_Rocket.client import ClientWindow -class BaseScreen(EventDispatcher): - """ - DR 的 页面API - """ - def __init__(self, main_window: "ClientWindow"): - super().__init__() - self.window_pointer = main_window - - def on_key_press(self, symbol, modifiers): - """一个键盘按键被按下 - :param: - `symbol` : int - 按下按键的标识符 - `modifiers` : int - 每一位(二进制)表示一个修饰键的启用情况 - """ - - def on_key_release(self, symbol, modifiers): - """一个键盘按键被松开 - :param: - `symbol` : int - 放下按键的标识符 - `modifiers` : int - 每一位(二进制)表示一个修饰键的启用情况 - """ - - def on_text(self, text): - """用户输入了一个字符 - - Typically this is called after :py:meth:`~pyglet.window.Window.on_key_press` and before - :py:meth:`~pyglet.window.Window.on_key_release`, but may also be called multiple times if the key - is held down (key repeating); or called without key presses if - another input method was used (e.g., a pen input). - - You should always use this method for interpreting text, as the - key symbols often have complex mappings to their unicode - representation which this event takes care of. - - :param: - `text` : unicode - 用户输入的 unicode 编码的内容 - - """ - - def on_text_motion(self, motion): - """The user moved the text input cursor. - - Typically this is called after :py:meth:`~pyglet.window.Window.on_key_press` and before - :py:meth:`~pyglet.window.Window.on_key_release`, but may also be called multiple times if the key - is help down (key repeating). - - You should always use this method for moving the text input cursor - (caret), as different platforms have different default keyboard - mappings, and key repeats are handled correctly. - - The values that `motion` can take are defined in - :py:mod:`pyglet.window.key`: - - * MOTION_UP - * MOTION_RIGHT - * MOTION_DOWN - * MOTION_LEFT - * MOTION_NEXT_WORD - * MOTION_PREVIOUS_WORD - * MOTION_BEGINNING_OF_LINE - * MOTION_END_OF_LINE - * MOTION_NEXT_PAGE - * MOTION_PREVIOUS_PAGE - * MOTION_BEGINNING_OF_FILE - * MOTION_END_OF_FILE - * MOTION_BACKSPACE - * MOTION_DELETE - - :param: - `motion` : int - The direction of motion; see remarks. - - """ - - def on_text_motion_select(self, motion): - """The user moved the text input cursor while extending the - selection. - - Typically this is called after :py:meth:`~pyglet.window.Window.on_key_press` and before - :py:meth:`~pyglet.window.Window.on_key_release`, but may also be called multiple times if the key - is help down (key repeating). - - You should always use this method for responding to text selection - events rather than the raw :py:meth:`~pyglet.window.Window.on_key_press`, as different platforms - have different default keyboard mappings, and key repeats are - handled correctly. - - The values that `motion` can take are defined in :py:mod:`pyglet.window.key`: - - * MOTION_UP - * MOTION_RIGHT - * MOTION_DOWN - * MOTION_LEFT - * MOTION_NEXT_WORD - * MOTION_PREVIOUS_WORD - * MOTION_BEGINNING_OF_LINE - * MOTION_END_OF_LINE - * MOTION_NEXT_PAGE - * MOTION_PREVIOUS_PAGE - * MOTION_BEGINNING_OF_FILE - * MOTION_END_OF_FILE - - :param: - `motion` : int - The direction of selection motion; see remarks. - - """ - - def on_mouse_motion(self, x, y, dx, dy): - """The mouse was moved with no buttons held down. - - :param: - `x` : int - Distance in pixels from the left edge of the window. - `y` : int - Distance in pixels from the bottom edge of the window. - `dx` : int - Relative X position from the previous mouse position. - `dy` : int - Relative Y position from the previous mouse position. - - """ - - def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): - """The mouse was moved with one or more mouse buttons pressed. - - This event will continue to be fired even if the mouse leaves - the window, so long as the drag buttons are continuously held down. - - :param: - `x` : int - Distance in pixels from the left edge of the window. - `y` : int - Distance in pixels from the bottom edge of the window. - `dx` : int - Relative X position from the previous mouse position. - `dy` : int - Relative Y position from the previous mouse position. - `buttons` : int - Bitwise combination of the mouse buttons currently pressed. - `modifiers` : int - Bitwise combination of any keyboard modifiers currently - active. - - """ - - def on_mouse_press(self, x, y, button, modifiers): - """A mouse button was pressed (and held down). - - :param: - `x` : int - Distance in pixels from the left edge of the window. - `y` : int - Distance in pixels from the bottom edge of the window. - `button` : int - The mouse button that was pressed. - `modifiers` : int - Bitwise combination of any keyboard modifiers currently - active. - - """ - - def on_mouse_release(self, x, y, button, modifiers): - """A mouse button was released. - - :param: - `x` : int - Distance in pixels from the left edge of the window. - `y` : int - Distance in pixels from the bottom edge of the window. - `button` : int - The mouse button that was released. - `modifiers` : int - Bitwise combination of any keyboard modifiers currently - active. - - """ - - def on_mouse_scroll(self, x, y, scroll_x, scroll_y): - """The mouse wheel was scrolled. - - Note that most mice have only a vertical scroll wheel, so - `scroll_x` is usually 0. An exception to this is the Apple Mighty - Mouse, which has a mouse ball in place of the wheel which allows - both `scroll_x` and `scroll_y` movement. - - :param: - `x` : int - Distance in pixels from the left edge of the window. - `y` : int - Distance in pixels from the bottom edge of the window. - `scroll_x` : float - Amount of movement on the horizontal axis. - `scroll_y` : float - Amount of movement on the vertical axis. - """ - - def on_close(self): - """The user attempted to close the window. - - This event can be triggered by clicking on the "X" control box in - the window title bar, or by some other platform-dependent manner. - - The default handler sets `has_exit` to ``True``. In pyglet 1.1, if - `pyglet.app.event_loop` is being used, `close` is also called, - closing the window immediately. - """ - - def on_mouse_enter(self, x, y): - """The mouse was moved into the window. - - This event will not be triggered if the mouse is currently being - dragged. - - :param: - `x` : int - Distance in pixels from the left edge of the window. - `y` : int - Distance in pixels from the bottom edge of the window. - """ - - def on_mouse_leave(self, x, y): - """The mouse was moved outside of the window. - - This event will not be triggered if the mouse is currently being - dragged. Note that the coordinates of the mouse pointer will be - outside of the window rectangle. - - :param: - `x` : int - Distance in pixels from the left edge of the window. - `y` : int - Distance in pixels from the bottom edge of the window. - """ - - def on_expose(self): - """A portion of the window needs to be redrawn. - - This event is triggered when the window first appears, and any time - the contents of the window is invalidated due to another window - obscuring it. - - There is no way to determine which portion of the window needs - redrawing. Note that the use of this method is becoming - increasingly uncommon, as newer window managers composite windows - automatically and keep a backing store of the window contents. - """ - - def on_resize(self, width, height): - """The window was resized. - - The window will have the GL context when this event is dispatched; - there is no need to call `switch_to` in this handler. - - :param: - `width` : int - The new width of the window, in pixels. - `height` : int - The new height of the window, in pixels. - """ - - def on_move(self, x, y): - """The window was moved. - - :param: - `x` : int - Distance from the left edge of the screen to the left edge - of the window. - `y` : int - Distance from the top edge of the screen to the top edge of - the window. Note that this is one of few methods in pyglet - which use a Y-down coordinate system. - """ - - def on_activate(self): - """The window was activated. - - This event can be triggered by clicking on the title bar, bringing - it to the foreground; or by some platform-specific method. - - When a window is "active" it has the keyboard focus. - """ - - def on_deactivate(self): - """The window was deactivated. - - This event can be triggered by clicking on another application - window. When a window is deactivated it no longer has the - keyboard focus. - """ - - def on_show(self): - """The window was shown. - - This event is triggered when a window is restored after being - minimised, hidden, or after being displayed for the first time. - """ - - def on_hide(self): - """The window was hidden. - - This event is triggered when a window is minimised - or hidden by the user. - """ - - def on_context_lost(self): - """The window's GL context was lost. - - When the context is lost no more GL methods can be called until it - is recreated. This is a rare event, triggered perhaps by the user - switching to an incompatible video mode. When it occurs, an - application will need to reload all objects (display lists, texture - objects, shaders) as well as restore the GL state. - """ - - def on_context_state_lost(self): - """The state of the window's GL context was lost. - - pyglet may sometimes need to recreate the window's GL context if - the window is moved to another video device, or between fullscreen - or windowed mode. In this case it will try to share the objects - (display lists, texture objects, shaders) between the old and new - contexts. If this is possible, only the current state of the GL - context is lost, and the application should simply restore state. - """ - - def on_file_drop(self, x, y, paths): - """File(s) were dropped into the window, will return the position of the cursor and - a list of paths to the files that were dropped. - """ - - def on_draw(self, dt): - """The window contents must be redrawn. - - The `EventLoop` will dispatch this event when the window - should be redrawn. This will happen during idle time after - any window events and after any scheduled functions were called. - - The window will already have the GL context, so there is no - need to call `switch_to`. The window's `flip` method will - be called after this event, so your event handler should not. - - You should make no assumptions about the window contents when - this event is triggered; a resize or expose event may have - invalidated the framebuffer since the last time it was drawn. - """ - - def on_refresh(self, dt): - """The window contents must be redrawn. - - The `EventLoop` will dispatch this event when the window - should be redrawn. - - The window will already have the GL context, so there is no - need to call `switch_to`. The window's `flip` method will - be called after this event, so your event handler should not. - - You should make no assumptions about the window contents when - this event is triggered; a resize or expose event may have - invalidated the framebuffer since the last time it was drawn. - """ - - -BaseScreen.register_event_type('on_key_press') -BaseScreen.register_event_type('on_key_release') -BaseScreen.register_event_type('on_text') -BaseScreen.register_event_type('on_text_motion') -BaseScreen.register_event_type('on_text_motion_select') -BaseScreen.register_event_type('on_mouse_motion') -BaseScreen.register_event_type('on_mouse_drag') -BaseScreen.register_event_type('on_mouse_press') -BaseScreen.register_event_type('on_mouse_release') -BaseScreen.register_event_type('on_mouse_scroll') -BaseScreen.register_event_type('on_mouse_enter') -BaseScreen.register_event_type('on_mouse_leave') -BaseScreen.register_event_type('on_close') -BaseScreen.register_event_type('on_expose') -BaseScreen.register_event_type('on_resize') -BaseScreen.register_event_type('on_move') -BaseScreen.register_event_type('on_activate') -BaseScreen.register_event_type('on_deactivate') -BaseScreen.register_event_type('on_show') -BaseScreen.register_event_type('on_hide') -BaseScreen.register_event_type('on_context_lost') -BaseScreen.register_event_type('on_context_state_lost') -BaseScreen.register_event_type('on_file_drop') -BaseScreen.register_event_type('on_draw') -BaseScreen.register_event_type('on_refresh') - - class DRScreen(BaseScreen): def __init__(self, main_window: "ClientWindow"): super().__init__(main_window) @@ -420,3 +27,29 @@ class DRScreen(BaseScreen): class DRDEBUGScreen(BaseScreen): def __init__(self, main_window: "ClientWindow"): super().__init__(main_window) + self.main_batch = Batch() + self.main_group = Group(order=1) + self.fps_label = Label(x=10, y=main_window.height - 10, + width=main_window.width - 20, height=20, + anchor_x='left', anchor_y='top', + font_name=translate.微软等宽无线, font_size=20, + multiline=True, + batch=self.main_batch, group=self.main_group) + self.fps_label.text = "11111114514" + + def draw_update(self, tick: float): + self.update_label() + + def update_label(self): + now_FPS = get_frequency() + self.fps_label.text = f'FPS: {self.window_pointer.fps_log.fps: >5.1f}(' \ + f'{self.window_pointer.fps_log.middle_fps: >5.1f})[{now_FPS: >.7f}]\n ' \ + f'{self.window_pointer.fps_log.max_fps: >7.1f} ' \ + f'{self.window_pointer.fps_log.min_fps:>5.1f}' + + def on_resize(self, width, height): + self.fps_label.y = height - 10 + + def on_draw(self, *dt): + self.main_batch.draw() + # print(self.window_pointer.try_if_runs) diff --git a/Difficult_Rocket/main.py b/Difficult_Rocket/main.py index c68bba0..a2af438 100644 --- a/Difficult_Rocket/main.py +++ b/Difficult_Rocket/main.py @@ -22,7 +22,7 @@ if __name__ == '__main__': # been start will not run this sys.path.append('/bin/libs') sys.path.append('/bin') -from Difficult_Rocket import client, DR_option +from Difficult_Rocket import client, server, DR_option from Difficult_Rocket.utils import tools from Difficult_Rocket.utils.translate import tr @@ -56,6 +56,7 @@ class Game: def setup(self) -> None: self.client = client.Client(net_mode='local') + self.server = server.Server(net_mode='local') def python_version_check(self) -> None: # best 3.8+ and write at 3.8.10 self.logger.info('{} {}'.format(tr['main']['version.now_on'], self.on_python_v)) @@ -68,8 +69,8 @@ class Game: # @new_thread('main') def _start(self): - threaded = False - if threaded: + self.server.run() + if DR_option.use_muitprocess: try: game_process = multiprocessing.Process(target=self.client.start(), name='pyglet app') game_process.start() diff --git a/Difficult_Rocket/utils/translate.py b/Difficult_Rocket/utils/translate.py index 76d5ce3..f245d6f 100644 --- a/Difficult_Rocket/utils/translate.py +++ b/Difficult_Rocket/utils/translate.py @@ -25,10 +25,11 @@ class Translates: def __init__(self, value: Union[Dict[str, Any], list, tuple, str], raise_error: bool = False, - get_list: list = None, + get_list: List[str] = None, + error_get_list: List[str] = None, final: bool = False): """ - 一个用于 + 一个用于翻译的东西 :param value: 翻译键节点 :param raise_error: 是否抛出错误 :param get_list: 尝试获取的列表 @@ -37,19 +38,23 @@ class Translates: self.value: Union[Dict[str, Any], list, tuple] = value self.raise_error = raise_error self.get_list = get_list or [] + self.error_get_list = error_get_list or [] self.final = final - def __getitem__(self, item: Union[str, int, Hashable]) -> Union["Translates", str]: + def __getitem__(self, item: Union[str, int, Hashable]) -> Union["Translates", str, int]: """ 一坨答辩 :param item: 取用的内容/小天才 :return: """ cache_get_list = self.get_list.copy() + cache_error_get_list = self.error_get_list.copy() cache_get_list.append(item) try: cache = self.value[item] + cache_get_list.append(item) except (KeyError, TypeError): + # 出现问题 if DR_option.report_translate_no_found: frame = inspect.currentframe() last_frame = frame.f_back @@ -58,15 +63,17 @@ class Translates: call_info = f'Translate Not Found at {last_frame.f_code.co_name} by {".".join(cache_get_list)} at:' \ f'{last_frame.f_code.co_filename}:{last_frame.f_lineno}' print(call_info) - - if not self.raise_error: - return Translates(value='.'.join(cache_get_list), raise_error=False, final=True) - else: + # 如果不抛出错误 + if self.raise_error: raise TranslateKeyNotFound(item_names=cache_get_list) from None - if self.final: - return self + cache_error_get_list.append(item) + if self.final: # 如果已经是翻译结果 + return Translates(value='.'.join(cache_get_list), raise_error=False, final=True, error_get_list=cache_error_get_list) else: - return Translates(value=cache, raise_error=self.raise_error, get_list=cache_get_list) + if self.final: + return self + else: + return Translates(value=cache, raise_error=self.raise_error, get_list=cache_get_list) def __getattr__(self, item: Union[str, Hashable]) -> Union["Translates"]: if hasattr(object, item): @@ -74,7 +81,7 @@ class Translates: return self.__getitem__(item) def __str__(self): - if self.final: + if self.final: # 如果是字符串 return f'{self.value}.{".".join(self.get_list)}' return str(self.value) diff --git a/configs/local_logger.toml b/configs/local_logger.toml index e8dadb3..114bfc5 100644 --- a/configs/local_logger.toml +++ b/configs/local_logger.toml @@ -42,7 +42,7 @@ logger_version = '1.0.0' [Formatter] -main_format = '[{long_time}] [{logger_name}] {level} | {file_name}:{code_line} | {message}' +main_format = '[{long_time}] [{logger_name}] {level} | {file_name}:{code_line} | {marker} | {message}' file_name = 'no frame' code_line = 'no frame' short_time = '%Y-%m-%d %H-%M-%S' diff --git a/configs/main.toml b/configs/main.toml index f7ca655..d31e97d 100644 --- a/configs/main.toml +++ b/configs/main.toml @@ -8,8 +8,8 @@ fonts_folder = "libs/fonts" [window] style = "None" -width = 907 -height = 570 +width = 1219 +height = 835 visible = true gui_scale = 1 caption = "Difficult Rocket {version}"