first part for phy simluation #34
@ -15,7 +15,7 @@ import traceback
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Callable, Dict, List, TYPE_CHECKING
|
from typing import Callable, Dict, List, TYPE_CHECKING, Optional
|
||||||
|
|
||||||
# third function
|
# third function
|
||||||
import rtoml
|
import rtoml
|
||||||
@ -23,6 +23,7 @@ import pyglet
|
|||||||
# from pyglet import gl
|
# from pyglet import gl
|
||||||
# from pyglet.gl import glClearColor
|
# from pyglet.gl import glClearColor
|
||||||
# from pyglet.libs.win32 import _user32
|
# from pyglet.libs.win32 import _user32
|
||||||
|
from pyglet.graphics import Group, Batch
|
||||||
from pyglet.window import Window
|
from pyglet.window import Window
|
||||||
from pyglet.window import key, mouse
|
from pyglet.window import key, mouse
|
||||||
|
|
||||||
@ -37,10 +38,10 @@ from Difficult_Rocket.utils.translate import tr
|
|||||||
from Difficult_Rocket.runtime import DR_runtime
|
from Difficult_Rocket.runtime import DR_runtime
|
||||||
from Difficult_Rocket.api.screen import BaseScreen
|
from Difficult_Rocket.api.screen import BaseScreen
|
||||||
from Difficult_Rocket.utils.thread import new_thread
|
from Difficult_Rocket.utils.thread import new_thread
|
||||||
|
from Difficult_Rocket.client.screen import DRDEBUGScreen
|
||||||
from Difficult_Rocket.client.fps.fps_log import FpsLogger
|
from Difficult_Rocket.client.fps.fps_log import FpsLogger
|
||||||
from Difficult_Rocket.client.guis.widgets import InputBox
|
from Difficult_Rocket.client.guis.widgets import InputBox
|
||||||
from Difficult_Rocket.exception.language import LanguageNotFound
|
from Difficult_Rocket.exception.language import LanguageNotFound
|
||||||
from Difficult_Rocket.client.screen import DRScreen, DRDEBUGScreen
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger('client')
|
logger = logging.getLogger('client')
|
||||||
@ -122,7 +123,36 @@ def pyglet_load_fonts_folder(folder) -> None:
|
|||||||
pyglet_load_fonts_folder(os.path.join(folder, obj))
|
pyglet_load_fonts_folder(os.path.join(folder, obj))
|
||||||
|
|
||||||
|
|
||||||
|
def _call_back(call_back: Callable) -> Callable:
|
||||||
|
"""
|
||||||
|
>>> def call_back():
|
||||||
|
>>> pass
|
||||||
|
>>> @_call_back(call_back)
|
||||||
|
>>> def on_draw(self):
|
||||||
|
>>> pass
|
||||||
|
用于在调用窗口函数后调用指定函数 的装饰器
|
||||||
|
:param call_back: 需要调用的函数
|
||||||
|
:return: 包装后的函数
|
||||||
|
"""
|
||||||
|
def wrapper(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def warp(self: "ClientWindow", *args, **kwargs):
|
||||||
|
result = func(self, *args, **kwargs)
|
||||||
|
call_back(self)
|
||||||
|
return result
|
||||||
|
return warp
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def _call_screen_after(func: Callable) -> Callable:
|
def _call_screen_after(func: Callable) -> Callable:
|
||||||
|
"""
|
||||||
|
>>> @_call_screen_after
|
||||||
|
>>> def on_draw(self):
|
||||||
|
>>> pass
|
||||||
|
用于在调用窗口函数后调用子窗口函数 的装饰器
|
||||||
|
:param func: 需要包装的函数
|
||||||
|
:return: 包装后的函数
|
||||||
|
"""
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def warped(self: "ClientWindow", *args, **kwargs):
|
def warped(self: "ClientWindow", *args, **kwargs):
|
||||||
result = func(self, *args, **kwargs)
|
result = func(self, *args, **kwargs)
|
||||||
@ -141,6 +171,14 @@ def _call_screen_after(func: Callable) -> Callable:
|
|||||||
|
|
||||||
|
|
||||||
def _call_screen_before(func: Callable) -> Callable:
|
def _call_screen_before(func: Callable) -> Callable:
|
||||||
|
"""
|
||||||
|
>>> @_call_screen_before
|
||||||
|
>>> def on_draw(self):
|
||||||
|
>>> pass
|
||||||
|
用于在调用窗口函数前调用子窗口函数 的装饰器
|
||||||
|
:param func: 需要包装的函数
|
||||||
|
:return: 包装后的函数
|
||||||
|
"""
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def warped(self: "ClientWindow", *args, **kwargs):
|
def warped(self: "ClientWindow", *args, **kwargs):
|
||||||
for title, a_screen in self.screen_list.items():
|
for title, a_screen in self.screen_list.items():
|
||||||
@ -185,8 +223,9 @@ class ClientWindow(Window):
|
|||||||
self.SPF = Decimal('1') / self.FPS
|
self.SPF = Decimal('1') / self.FPS
|
||||||
self.fps_log = FpsLogger(stable_fps=int(self.FPS))
|
self.fps_log = FpsLogger(stable_fps=int(self.FPS))
|
||||||
# batch
|
# batch
|
||||||
self.part_batch = pyglet.graphics.Batch()
|
self.part_batch = Batch()
|
||||||
self.label_batch = pyglet.graphics.Batch()
|
self.label_batch = Batch()
|
||||||
|
self.main_group = Group(0)
|
||||||
# frame
|
# frame
|
||||||
self.frame = pyglet.gui.Frame(self, order=20)
|
self.frame = pyglet.gui.Frame(self, order=20)
|
||||||
self.M_frame = pyglet.gui.MovableFrame(self, modifier=key.LCTRL)
|
self.M_frame = pyglet.gui.MovableFrame(self, modifier=key.LCTRL)
|
||||||
@ -194,9 +233,10 @@ class ClientWindow(Window):
|
|||||||
# setup
|
# setup
|
||||||
self.setup()
|
self.setup()
|
||||||
# 命令显示
|
# 命令显示
|
||||||
self.command_group = pyglet.graphics.Group(0)
|
self.command_batch = Batch()
|
||||||
|
self.command_group = Group(1, parent=self.main_group)
|
||||||
self.input_box = InputBox(x=50, y=30, width=300,
|
self.input_box = InputBox(x=50, y=30, width=300,
|
||||||
batch=self.label_batch, text='') # 实例化
|
batch=self.command_batch, text='') # 实例化
|
||||||
self.input_box.push_handlers(self)
|
self.input_box.push_handlers(self)
|
||||||
self.input_box.set_handler('on_commit', self.on_input)
|
self.input_box.set_handler('on_commit', self.on_input)
|
||||||
self.set_handlers(self.input_box)
|
self.set_handlers(self.input_box)
|
||||||
@ -215,9 +255,7 @@ class ClientWindow(Window):
|
|||||||
def setup(self):
|
def setup(self):
|
||||||
self.set_icon(pyglet.image.load('./textures/icon.png'))
|
self.set_icon(pyglet.image.load('./textures/icon.png'))
|
||||||
self.load_fonts()
|
self.load_fonts()
|
||||||
# TODO 读取配置文件,加载不同的屏幕,解耦
|
|
||||||
self.screen_list['DR_debug'] = DRDEBUGScreen(self)
|
self.screen_list['DR_debug'] = DRDEBUGScreen(self)
|
||||||
self.screen_list['DR_main'] = DRScreen(self)
|
|
||||||
self.game.dispatch_event('on_client_start', game=self.game, client=self)
|
self.game.dispatch_event('on_client_start', game=self.game, client=self)
|
||||||
|
|
||||||
def load_fonts(self) -> None:
|
def load_fonts(self) -> None:
|
||||||
@ -264,6 +302,10 @@ class ClientWindow(Window):
|
|||||||
now_FPS = pyglet.clock.get_frequency()
|
now_FPS = pyglet.clock.get_frequency()
|
||||||
self.fps_log.update_tick(now_FPS, decimal_tick)
|
self.fps_log.update_tick(now_FPS, decimal_tick)
|
||||||
|
|
||||||
|
def on_command_draw(self):
|
||||||
|
self.command_batch.draw()
|
||||||
|
|
||||||
|
@_call_back(on_command_draw)
|
||||||
@_call_screen_after
|
@_call_screen_after
|
||||||
def on_draw(self, *dt):
|
def on_draw(self, *dt):
|
||||||
while command := self.game.console.get_command():
|
while command := self.game.console.get_command():
|
||||||
@ -306,10 +348,15 @@ class ClientWindow(Window):
|
|||||||
self.on_command(command_text)
|
self.on_command(command_text)
|
||||||
self.input_box.value = ''
|
self.input_box.value = ''
|
||||||
|
|
||||||
|
def new_command(self):
|
||||||
|
self.game.console.new_command()
|
||||||
|
|
||||||
|
@_call_back(new_command)
|
||||||
@_call_screen_after
|
@_call_screen_after
|
||||||
def on_command(self, command: line.CommandText):
|
def on_command(self, command: line.CommandText):
|
||||||
print(command.find('/'))
|
command.text = command.text.rstrip('\n')
|
||||||
self.logger.info(tr().window.command.text().format(command))
|
self.logger.info(tr().window.command.text().format(command))
|
||||||
|
command.find('/')
|
||||||
if command.find('stop'):
|
if command.find('stop'):
|
||||||
# self.dispatch_event('on_exit')
|
# self.dispatch_event('on_exit')
|
||||||
print("command stop!")
|
print("command stop!")
|
||||||
@ -335,8 +382,9 @@ class ClientWindow(Window):
|
|||||||
except LanguageNotFound:
|
except LanguageNotFound:
|
||||||
self.logger.info(tr().language_available().format(os.listdir('./configs/lang')))
|
self.logger.info(tr().language_available().format(os.listdir('./configs/lang')))
|
||||||
self.save_info()
|
self.save_info()
|
||||||
|
elif command.find('mods'):
|
||||||
# self.command_tree.parse(command.plain_command)
|
for mod in self.game.mod_module:
|
||||||
|
self.logger.info(f"mod: {mod.name} id: {mod.mod_id} version: {mod.version}")
|
||||||
|
|
||||||
@_call_screen_after
|
@_call_screen_after
|
||||||
def on_message(self, message: line.CommandText):
|
def on_message(self, message: line.CommandText):
|
||||||
|
@ -7,24 +7,17 @@
|
|||||||
import typing
|
import typing
|
||||||
|
|
||||||
from pyglet.text import Label
|
from pyglet.text import Label
|
||||||
from pyglet.graphics import Batch, Group
|
|
||||||
from pyglet.clock import get_frequency
|
from pyglet.clock import get_frequency
|
||||||
|
from pyglet.graphics import Batch, Group
|
||||||
|
|
||||||
# Difficult Rocket function
|
# Difficult Rocket function
|
||||||
from Difficult_Rocket.api.types import Fonts
|
from Difficult_Rocket.api.types import Fonts
|
||||||
# from Difficult_Rocket.utils import translate
|
|
||||||
from Difficult_Rocket.api.screen import BaseScreen
|
from Difficult_Rocket.api.screen import BaseScreen
|
||||||
# from Difficult_Rocket.command.tree import CommandTree
|
|
||||||
|
|
||||||
if typing.TYPE_CHECKING:
|
if typing.TYPE_CHECKING:
|
||||||
from Difficult_Rocket.client import ClientWindow
|
from Difficult_Rocket.client import ClientWindow
|
||||||
|
|
||||||
|
|
||||||
class DRScreen(BaseScreen):
|
|
||||||
def __init__(self, main_window: "ClientWindow"):
|
|
||||||
super().__init__(main_window)
|
|
||||||
|
|
||||||
|
|
||||||
class DRDEBUGScreen(BaseScreen):
|
class DRDEBUGScreen(BaseScreen):
|
||||||
def __init__(self, main_window: "ClientWindow"):
|
def __init__(self, main_window: "ClientWindow"):
|
||||||
super().__init__(main_window)
|
super().__init__(main_window)
|
||||||
@ -55,4 +48,3 @@ class DRDEBUGScreen(BaseScreen):
|
|||||||
|
|
||||||
def on_draw(self, *dt, window: "ClientWindow"):
|
def on_draw(self, *dt, window: "ClientWindow"):
|
||||||
self.main_batch.draw()
|
self.main_batch.draw()
|
||||||
# print(self.window_pointer.try_if_runs)
|
|
||||||
|
@ -44,9 +44,12 @@ class CommandText:
|
|||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
def find(self, text: str) -> bool:
|
def find(self, text: str) -> bool:
|
||||||
|
startswith = self.text.startswith(text)
|
||||||
|
if startswith:
|
||||||
find = self.text.find(text)
|
find = self.text.find(text)
|
||||||
if find != -1:
|
if find != -1:
|
||||||
self.text = self.text[find + len(text):]
|
if not len(text) == len(self.text):
|
||||||
|
self.text = self.text[find + len(text):] if not self.text[find+len(text)] == ' ' else self.text[find + len(text) + 1:]
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -65,6 +65,9 @@ class Console(Options):
|
|||||||
def get_command(self) -> Optional[str]:
|
def get_command(self) -> Optional[str]:
|
||||||
return self.caches.pop(0) if self.caches else None
|
return self.caches.pop(0) if self.caches else None
|
||||||
|
|
||||||
|
def new_command(self) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Game(Options):
|
class Game(Options):
|
||||||
name = 'MainGame'
|
name = 'MainGame'
|
||||||
|
@ -16,20 +16,19 @@ import sys
|
|||||||
import time
|
import time
|
||||||
import math
|
import math
|
||||||
import json
|
import json
|
||||||
|
import rtoml
|
||||||
import logging
|
import logging
|
||||||
import configparser
|
import configparser
|
||||||
|
|
||||||
from typing import Union
|
from pathlib import Path
|
||||||
|
from typing import Union, Optional
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
import rtoml
|
|
||||||
|
|
||||||
from defusedxml.ElementTree import parse
|
from defusedxml.ElementTree import parse
|
||||||
|
|
||||||
from Difficult_Rocket.exception.unsupport import NoMoreJson5
|
from Difficult_Rocket.exception.unsupport import NoMoreJson5
|
||||||
|
|
||||||
# logger
|
# logger
|
||||||
tools_logger = logging.getLogger('part-tools')
|
tools_logger = logging.getLogger('tools')
|
||||||
"""
|
"""
|
||||||
file configs
|
file configs
|
||||||
"""
|
"""
|
||||||
@ -39,10 +38,12 @@ file_error = {FileNotFoundError: 'no {filetype} file was founded!:\n file name:
|
|||||||
Exception: 'get some {error_type} when read {filetype} file {filename}! \n file type: {} \n file name: {} \n stack: {stack}'}
|
Exception: 'get some {error_type} when read {filetype} file {filename}! \n file type: {} \n file name: {} \n stack: {stack}'}
|
||||||
|
|
||||||
|
|
||||||
def load_file(file_name: str,
|
def load_file(file_name: Union[str, Path],
|
||||||
stack: Union[str, list, dict, None] = None,
|
stack: Optional[Union[str, list, dict]] = None,
|
||||||
raise_error: bool = True,
|
raise_error: Optional[bool] = True,
|
||||||
encoding: str = 'utf-8') -> Union[dict, ElementTree.ElementTree]:
|
encoding: Optional[str] = 'utf-8') -> Union[dict, ElementTree.ElementTree]:
|
||||||
|
if isinstance(file_name, Path):
|
||||||
|
file_name = str(file_name)
|
||||||
f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式)
|
f_type = file_name[file_name.rfind('.') + 1:] # 从最后一个.到末尾 (截取文件格式)
|
||||||
get_file = NotImplementedError('解析失败,请检查文件类型/文件内容/文件是否存在!')
|
get_file = NotImplementedError('解析失败,请检查文件类型/文件内容/文件是否存在!')
|
||||||
try:
|
try:
|
||||||
|
@ -14,6 +14,7 @@ gitee: @shenjackyuanjie
|
|||||||
import os
|
import os
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Union, Tuple, Any, List, Dict, Hashable, Optional
|
from typing import Union, Tuple, Any, List, Dict, Hashable, Optional
|
||||||
|
|
||||||
@ -153,15 +154,16 @@ class Tr:
|
|||||||
GOOD
|
GOOD
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, language: str = None, config: Optional[TranslateConfig] = None):
|
def __init__(self, language: str = None, config: Optional[TranslateConfig] = None, lang_path: Optional[Path] = None):
|
||||||
"""
|
"""
|
||||||
诶嘿,我抄的MCDR
|
诶嘿,我抄的MCDR
|
||||||
:param language: Tr 所使用的的语言
|
:param language: Tr 所使用的的语言
|
||||||
:param config: 配置
|
:param config: 配置
|
||||||
"""
|
"""
|
||||||
self.language_name = language if language is not None else DR_runtime.language
|
self.language_name = language if language is not None else DR_runtime.language
|
||||||
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(f'configs/lang/{self.language_name}.toml')
|
self.language_path = lang_path if lang_path is not None else Path('configs/lang')
|
||||||
self.default_translate: Dict = tools.load_file(f'configs/lang/{DR_status.default_language}.toml')
|
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(self.language_path / f'{self.language_name}.toml')
|
||||||
|
self.default_translate: Dict = tools.load_file(f'{self.language_path}/{DR_status.default_language}.toml')
|
||||||
self.default_config = config.set('source', self) if config is not None else TranslateConfig(source=self)
|
self.default_config = config.set('source', self) if config is not None else TranslateConfig(source=self)
|
||||||
self.translates_cache = Translates(value=self.translates, config=self.default_config.copy())
|
self.translates_cache = Translates(value=self.translates, config=self.default_config.copy())
|
||||||
|
|
||||||
@ -185,11 +187,11 @@ class Tr:
|
|||||||
if lang == ' ' or lang == '':
|
if lang == ' ' or lang == '':
|
||||||
raise LanguageNotFound('Can not be empty')
|
raise LanguageNotFound('Can not be empty')
|
||||||
lang = lang or self.language_name
|
lang = lang or self.language_name
|
||||||
if not os.path.exists(f'./configs/lang/{lang}.toml'):
|
if not os.path.exists(f'{self.language_path}/{lang}.toml'):
|
||||||
print(f"lang: {os.path.exists(f'./configs/lang/{lang}.toml')} language = {lang} {self.language_name=}")
|
print(f"lang: {os.path.exists(f'{self.language_path}/{lang}.toml')} language = {lang} {self.language_name=}")
|
||||||
raise LanguageNotFound(lang)
|
raise LanguageNotFound(lang)
|
||||||
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(f'configs/lang/{lang}.toml')
|
self.translates: Dict[str, Union[str, Dict]] = tools.load_file(f'{self.language_path}/{lang}.toml')
|
||||||
self.default_translate: Dict = tools.load_file(f'configs/lang/{DR_runtime.default_language}.toml')
|
self.default_translate: Dict = tools.load_file(f'{self.language_path}/{DR_runtime.default_language}.toml')
|
||||||
self.translates_cache = Translates(value=self.translates, config=self.default_config.copy())
|
self.translates_cache = Translates(value=self.translates, config=self.default_config.copy())
|
||||||
self.language_name = lang
|
self.language_name = lang
|
||||||
DR_runtime.language = self.language_name
|
DR_runtime.language = self.language_name
|
||||||
|
@ -75,14 +75,3 @@ input = "console"
|
|||||||
window = "window"
|
window = "window"
|
||||||
command = "in game commands"
|
command = "in game commands"
|
||||||
require_DR_rs = "require DR_rs module"
|
require_DR_rs = "require DR_rs module"
|
||||||
|
|
||||||
[client.sr1_render]
|
|
||||||
setup.start = "SR1 Renderer start loading"
|
|
||||||
setup.use_time = "SR1 Renderer loading has used: {} second"
|
|
||||||
xml.loading = "Loading XML file: {}"
|
|
||||||
xml.load_done = "XML file loaded"
|
|
||||||
xml.load_time = "XML file loading has used: {} second"
|
|
||||||
ship.load = "Loading ship: {}"
|
|
||||||
ship.load_time = "Ship loading has used: {} second"
|
|
||||||
ship.info = "Ship info:\n- Parts: {}\n- Weight: {}"
|
|
||||||
ship.render.done = "Ship render done"
|
|
||||||
|
@ -75,15 +75,3 @@ input = "控制台"
|
|||||||
window = "窗口"
|
window = "窗口"
|
||||||
command = "游戏内命令行"
|
command = "游戏内命令行"
|
||||||
require_DR_rs = "需要 DR_rs 模块"
|
require_DR_rs = "需要 DR_rs 模块"
|
||||||
|
|
||||||
[client.sr1_render]
|
|
||||||
setup.start = "SR1 渲染器开始载入"
|
|
||||||
setup.use_time = "SR1 渲染器载入消耗时间: {} 秒"
|
|
||||||
xml.loading = "正在加载XML文件: {}"
|
|
||||||
xml.load_done = "XML 文件加载完成"
|
|
||||||
xml.load_time = "XML 文件加载消耗时间: {} 秒"
|
|
||||||
ship.load = "正在加载飞船: {}"
|
|
||||||
ship.load_time = "飞船加载消耗时间: {} 秒"
|
|
||||||
#ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}\n- 文件大小: {}"
|
|
||||||
ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}"
|
|
||||||
ship.render.done = "飞船渲染完成"
|
|
||||||
|
@ -7,8 +7,8 @@ fonts_folder = "libs/fonts"
|
|||||||
|
|
||||||
[window]
|
[window]
|
||||||
style = "None"
|
style = "None"
|
||||||
width = 1021
|
width = 1041
|
||||||
height = 1078
|
height = 1050
|
||||||
visible = true
|
visible = true
|
||||||
gui_scale = 1
|
gui_scale = 1
|
||||||
caption = "Difficult Rocket v{DR_version}"
|
caption = "Difficult Rocket v{DR_version}"
|
||||||
|
@ -3,7 +3,24 @@
|
|||||||
|
|
||||||
- 最新版本号
|
- 最新版本号
|
||||||
- DR game: 0.2.0.0
|
- DR game: 0.2.0.0
|
||||||
- DR rs: 0.2.10.1
|
- DR rs: 0.2.11.0
|
||||||
|
|
||||||
|
## DR game 0.1.2.0
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 现在渲染飞船的时候不会再显示那个白色框了
|
||||||
|
- 改为一个彩色的框
|
||||||
|
- Now, the ship will not be displayed in the white box
|
||||||
|
- Change to a colored box
|
||||||
|
|
||||||
|
## DR rs 0.2.11.0
|
||||||
|
|
||||||
|
### 添加
|
||||||
|
|
||||||
|
- `Python::data::PySR1Ship`
|
||||||
|
- `get_part_box(&self, part_id: i64) -> Option<(f64, f64), (f64, f64)>`
|
||||||
|
- 用于获取对应 id 的实际碰撞箱
|
||||||
|
|
||||||
## DR game 0.2.0.0
|
## DR game 0.2.0.0
|
||||||
|
|
||||||
|
@ -11,6 +11,21 @@
|
|||||||
- issue #33 (https://github.com/shenjackyuanjie/Difficult-Rocket/issues/33)
|
- issue #33 (https://github.com/shenjackyuanjie/Difficult-Rocket/issues/33)
|
||||||
- 修复了实际上并不会加载 `.otf` 格式的字体文件的问题
|
- 修复了实际上并不会加载 `.otf` 格式的字体文件的问题
|
||||||
|
|
||||||
|
### 修改
|
||||||
|
|
||||||
|
- 现在输入命令之后不会输出一个 `True`/`False` 了
|
||||||
|
- (实际上是用来检测命令是不是用 `/` 开头的)
|
||||||
|
- Now, the command will not output a `True`/`False`
|
||||||
|
- (Actually used to detect whether the command starts with `/`)
|
||||||
|
- `CommandText`
|
||||||
|
- `find`
|
||||||
|
- 现在会先用 `str.startswith` 检测是否以要求的字符串开头
|
||||||
|
- 实际上就是丐版 `re.match`
|
||||||
|
- 并且会在匹配上之后 如果匹配内容后面第一个字符是空格 则会截取掉空格
|
||||||
|
- Now, it will first use `str.startswith` to detect whether it starts with the required string
|
||||||
|
- Actually a poor version of `re.match`
|
||||||
|
- And after matching, if the first character after the matching content is a space, the space will be intercepted
|
||||||
|
|
||||||
## DR sdk 0.8.3.0
|
## DR sdk 0.8.3.0
|
||||||
|
|
||||||
### 删除
|
### 删除
|
||||||
|
@ -121,9 +121,11 @@ if TYPE_CHECKING:
|
|||||||
@property
|
@property
|
||||||
def img_pos(self) -> Tuple[int, int, int, int]: ...
|
def img_pos(self) -> Tuple[int, int, int, int]: ...
|
||||||
""" -x -y +x +y 左下右上 """
|
""" -x -y +x +y 左下右上 """
|
||||||
|
def get_part_box(self, part_id: int) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]: ...
|
||||||
|
|
||||||
class Console_rs:
|
class Console_rs:
|
||||||
def __init__(self) -> None: ...
|
def __init__(self) -> None: ...
|
||||||
def start(self) -> None: ...
|
def start(self) -> None: ...
|
||||||
def stop(self) -> bool: ...
|
def stop(self) -> bool: ...
|
||||||
def get_command(self) -> Optional[str]: ...
|
def get_command(self) -> Optional[str]: ...
|
||||||
|
def new_command(self) -> bool: ...
|
||||||
|
29
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
29
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
@ -13,9 +13,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.2"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
@ -84,14 +84,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.9.14"
|
version = "0.9.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
|
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"memoffset",
|
"memoffset 0.9.0",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -107,9 +107,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.15"
|
version = "0.8.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@ -167,9 +167,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.18"
|
version = "0.4.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
|
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matrixmultiply"
|
name = "matrixmultiply"
|
||||||
@ -190,6 +190,15 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nalgebra"
|
name = "nalgebra"
|
||||||
version = "0.32.2"
|
version = "0.32.2"
|
||||||
@ -348,7 +357,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"indoc",
|
"indoc",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset 0.8.0",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pyo3-build-config",
|
"pyo3-build-config",
|
||||||
"pyo3-ffi",
|
"pyo3-ffi",
|
||||||
|
@ -12,7 +12,7 @@ package_path = 'Difficult_Rocket_rs'
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='Difficult_Rocket_rs',
|
name='Difficult_Rocket_rs',
|
||||||
version="0.2.10.1",
|
version="0.2.11.0",
|
||||||
author='shenjackyuanjie',
|
author='shenjackyuanjie',
|
||||||
author_email='3695888@qq.com',
|
author_email='3695888@qq.com',
|
||||||
rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs",
|
rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs",
|
||||||
|
@ -12,6 +12,7 @@ mod python;
|
|||||||
mod render;
|
mod render;
|
||||||
mod simulator;
|
mod simulator;
|
||||||
mod sr1_data;
|
mod sr1_data;
|
||||||
|
mod translate;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
@ -26,7 +27,7 @@ enum LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn get_version_str() -> String { "0.2.10.1".to_string() }
|
fn get_version_str() -> String { "0.2.11.0".to_string() }
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
||||||
@ -42,7 +43,6 @@ fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
|||||||
fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_function(wrap_pyfunction!(get_version_str, m)?)?;
|
m.add_function(wrap_pyfunction!(get_version_str, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(test_call, m)?)?;
|
m.add_function(wrap_pyfunction!(test_call, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(simulator::simulation, m)?)?;
|
|
||||||
m.add_function(wrap_pyfunction!(sr1_data::part_list::read_part_list_py, m)?)?;
|
m.add_function(wrap_pyfunction!(sr1_data::part_list::read_part_list_py, m)?)?;
|
||||||
m.add_function(wrap_pyfunction!(sr1_data::ship::py_raw_ship_from_file, m)?)?;
|
m.add_function(wrap_pyfunction!(sr1_data::ship::py_raw_ship_from_file, m)?)?;
|
||||||
m.add_class::<render::camera::CameraRs>()?;
|
m.add_class::<render::camera::CameraRs>()?;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
/// 插件加载
|
/// 插件加载
|
||||||
///
|
///
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub mod plugin_trait {
|
pub mod plugin_trait {
|
||||||
pub struct ModInfo {
|
pub struct ModInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -12,6 +12,7 @@ pub mod data {
|
|||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::sr1_data::part_list::RawPartList;
|
use crate::sr1_data::part_list::RawPartList;
|
||||||
|
use crate::types::math::{Point2D, Rotatable};
|
||||||
use crate::types::sr1::{get_max_box, SR1PartData, SR1PartListTrait};
|
use crate::types::sr1::{get_max_box, SR1PartData, SR1PartListTrait};
|
||||||
use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship};
|
use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship};
|
||||||
|
|
||||||
@ -142,96 +143,35 @@ pub mod data {
|
|||||||
}
|
}
|
||||||
parts
|
parts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_part_box(&self, part_id: i64) -> Option<((f64, f64), (f64, f64))> {
|
||||||
|
let part_data = self.ship.parts.iter().find(|&x| x.id == part_id);
|
||||||
|
if let Some(part_data) = part_data {
|
||||||
|
let part_type = self.part_list.get_part_type(part_data.part_type_id.clone()).unwrap();
|
||||||
|
// rotate
|
||||||
|
let radius = part_data.angle;
|
||||||
|
let ((x1, y1), (x2, y2)) = part_type.get_box();
|
||||||
|
let mut p1 = Point2D::new(x1, y1);
|
||||||
|
let mut p2 = Point2D::new(x2, y2);
|
||||||
|
p1.rotate_radius_mut(radius);
|
||||||
|
p2.rotate_radius_mut(radius);
|
||||||
|
// transform
|
||||||
|
p1.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||||
|
p2.add_mut(part_data.x * 2.0, part_data.y * 2.0);
|
||||||
|
return Some(((p1.x, p1.y), (p2.x, p2.y)));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod translate {
|
pub mod translate {
|
||||||
use pyo3::prelude::*;
|
use crate::translate;
|
||||||
use pyo3::types::PyDict;
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[pyo3(name = "TranslateConfig_rs")]
|
|
||||||
#[pyo3(text_signature = "(language, raise_error = False, replace_normal = False, add_error = False, is_result = False, keep_get = False)")]
|
|
||||||
pub struct PyTranslateConfig {
|
|
||||||
pub raise_error: bool,
|
|
||||||
pub replace_normal: bool,
|
|
||||||
pub add_error: bool,
|
|
||||||
pub is_result: bool,
|
|
||||||
pub keep_get: bool,
|
|
||||||
pub language: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pymethods]
|
|
||||||
impl PyTranslateConfig {
|
|
||||||
#[new]
|
|
||||||
fn new(py_: Python, raise_error: bool, replace_normal: bool, language: Option<String>) -> Self {
|
|
||||||
let dr_runtime = PyModule::import(py_, "Difficult_Rocket").unwrap().get_item("DR_runtime").unwrap();
|
|
||||||
let default_language = dr_runtime.get_item("language").unwrap().extract::<String>().unwrap();
|
|
||||||
Self {
|
|
||||||
raise_error,
|
|
||||||
replace_normal,
|
|
||||||
add_error: false,
|
|
||||||
is_result: false,
|
|
||||||
keep_get: false,
|
|
||||||
language: language.unwrap_or(default_language),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn set(&self, py_: Python, item: String, value: BoolString) -> &Self {
|
|
||||||
// match item.as_str() {
|
|
||||||
// "raise_error" => self,
|
|
||||||
// _ => self,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
pub struct PyTranslate {
|
|
||||||
pub data: Py<PyAny>,
|
|
||||||
pub get_list: Vec<(String, bool)>,
|
|
||||||
pub config: PyTranslateConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pymethods]
|
|
||||||
impl PyTranslate {
|
|
||||||
#[new]
|
|
||||||
fn py_new(py_: Python, data: &PyAny) -> Self {
|
|
||||||
let _ = data.is_instance_of::<PyDict>();
|
|
||||||
Self {
|
|
||||||
data: data.into_py(py_),
|
|
||||||
get_list: Vec::new(),
|
|
||||||
config: PyTranslateConfig::new(py_, false, false, None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod physics {
|
|
||||||
use pyo3::prelude::*;
|
|
||||||
|
|
||||||
use crate::simulator::interface::PhysicsSpace;
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[pyo3(name = "PhysicsSpace_rs")]
|
|
||||||
pub struct PyPhysicsSpace {
|
|
||||||
pub space: PhysicsSpace,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pymethods]
|
|
||||||
impl PyPhysicsSpace {
|
|
||||||
#[new]
|
|
||||||
fn new(gravity: (f64, f64)) -> Self {
|
|
||||||
Self {
|
|
||||||
space: PhysicsSpace::new(gravity),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tick_space(&mut self) { self.space.tick_space() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod console {
|
pub mod console {
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
use std::io::{self, Write};
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[pyo3(name = "Console_rs")]
|
#[pyo3(name = "Console_rs")]
|
||||||
@ -255,7 +195,7 @@ pub mod console {
|
|||||||
let (stop_sender, stop_receiver) = std::sync::mpsc::channel();
|
let (stop_sender, stop_receiver) = std::sync::mpsc::channel();
|
||||||
let (keyboard_input_sender, keyboard_input_receiver) = std::sync::mpsc::channel();
|
let (keyboard_input_sender, keyboard_input_receiver) = std::sync::mpsc::channel();
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let std_in = std::io::stdin();
|
let std_in = io::stdin();
|
||||||
loop {
|
loop {
|
||||||
if let Ok(()) = stop_receiver.try_recv() {
|
if let Ok(()) = stop_receiver.try_recv() {
|
||||||
break;
|
break;
|
||||||
@ -265,9 +205,10 @@ pub mod console {
|
|||||||
if !input.is_empty() {
|
if !input.is_empty() {
|
||||||
keyboard_input_sender.send(input).unwrap();
|
keyboard_input_sender.send(input).unwrap();
|
||||||
}
|
}
|
||||||
print!(">>");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
print!("rs>");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
self.stop_sender = Some(stop_sender);
|
self.stop_sender = Some(stop_sender);
|
||||||
self.keyboard_input_receiver = Some(keyboard_input_receiver);
|
self.keyboard_input_receiver = Some(keyboard_input_receiver);
|
||||||
}
|
}
|
||||||
@ -280,6 +221,12 @@ pub mod console {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_command(&self) -> bool {
|
||||||
|
print!("rs>");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn get_command(&self) -> Option<String> {
|
fn get_command(&self) -> Option<String> {
|
||||||
// 获取输入
|
// 获取输入
|
||||||
if let Some(receiver) = &self.keyboard_input_receiver {
|
if let Some(receiver) = &self.keyboard_input_receiver {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use rapier2d_f64::prelude::*;
|
use rapier2d_f64::prelude::*;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
#[pyo3(name = "simulation")]
|
#[pyo3(name = "simulation")]
|
||||||
pub fn simulation() -> () {
|
pub fn simulation() -> () {
|
||||||
@ -63,73 +64,8 @@ pub fn simulation() -> () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod interface {
|
#[allow(unused)]
|
||||||
|
pub mod python {
|
||||||
|
use pyo3::prelude::*;
|
||||||
use rapier2d_f64::prelude::*;
|
use rapier2d_f64::prelude::*;
|
||||||
|
|
||||||
pub struct PhysicsSpace {
|
|
||||||
pub rigid_body_set: RigidBodySet,
|
|
||||||
pub collider_set: ColliderSet,
|
|
||||||
pub gravity: Vector<f64>,
|
|
||||||
pub integration_parameters: IntegrationParameters,
|
|
||||||
pub physics_pipeline: PhysicsPipeline,
|
|
||||||
pub island_manager: IslandManager,
|
|
||||||
pub broad_phase: BroadPhase,
|
|
||||||
pub narrow_phase: NarrowPhase,
|
|
||||||
pub impulse_joint_set: ImpulseJointSet,
|
|
||||||
pub multibody_joint_set: MultibodyJointSet,
|
|
||||||
pub ccd_solver: CCDSolver,
|
|
||||||
pub physics_hooks: (),
|
|
||||||
pub event_handler: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhysicsSpace {
|
|
||||||
pub fn new(gravity: (f64, f64)) -> Self {
|
|
||||||
let rigid_body_set = RigidBodySet::new();
|
|
||||||
let collider_set = ColliderSet::new();
|
|
||||||
let gravity = vector![gravity.0, gravity.1];
|
|
||||||
let integration_parameters = IntegrationParameters::default();
|
|
||||||
let physics_pipeline = PhysicsPipeline::new();
|
|
||||||
let island_manager = IslandManager::new();
|
|
||||||
let broad_phase = BroadPhase::new();
|
|
||||||
let narrow_phase = NarrowPhase::new();
|
|
||||||
let impulse_joint_set = ImpulseJointSet::new();
|
|
||||||
let multibody_joint_set = MultibodyJointSet::new();
|
|
||||||
let ccd_solver = CCDSolver::new();
|
|
||||||
let physics_hooks = ();
|
|
||||||
let event_handler = ();
|
|
||||||
Self {
|
|
||||||
rigid_body_set,
|
|
||||||
collider_set,
|
|
||||||
gravity,
|
|
||||||
integration_parameters,
|
|
||||||
physics_pipeline,
|
|
||||||
island_manager,
|
|
||||||
broad_phase,
|
|
||||||
narrow_phase,
|
|
||||||
impulse_joint_set,
|
|
||||||
multibody_joint_set,
|
|
||||||
ccd_solver,
|
|
||||||
physics_hooks,
|
|
||||||
event_handler,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tick_space(&mut self) {
|
|
||||||
self.physics_pipeline.step(
|
|
||||||
&self.gravity,
|
|
||||||
&self.integration_parameters,
|
|
||||||
&mut self.island_manager,
|
|
||||||
&mut self.broad_phase,
|
|
||||||
&mut self.narrow_phase,
|
|
||||||
&mut self.rigid_body_set,
|
|
||||||
&mut self.collider_set,
|
|
||||||
&mut self.impulse_joint_set,
|
|
||||||
&mut self.multibody_joint_set,
|
|
||||||
&mut self.ccd_solver,
|
|
||||||
None,
|
|
||||||
&self.physics_hooks,
|
|
||||||
&self.event_handler,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
16
mods/dr_game/Difficult_Rocket_rs/src/src/translate.rs
Normal file
16
mods/dr_game/Difficult_Rocket_rs/src/src/translate.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* -------------------------------
|
||||||
|
* Difficult Rocket
|
||||||
|
* Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
|
||||||
|
* All rights reserved
|
||||||
|
* -------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
type TranslateMapper = HashMap<String, HashMap<String, HashMap<String, String>>>;
|
||||||
|
|
||||||
|
pub struct Translater {
|
||||||
|
pub data: TranslateMapper,
|
||||||
|
pub language: String,
|
||||||
|
}
|
@ -197,9 +197,13 @@ pub mod sr1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SR1PartType {
|
impl SR1PartType {
|
||||||
pub fn get_box(&self) -> (f64, f64, f64, f64) {
|
pub fn get_box(&self) -> ((f64, f64), (f64, f64)) {
|
||||||
let x = self.width as f64 / 2.0;
|
// -x, -y, x, y
|
||||||
(-x, 0.0, x, self.height as f64)
|
// 居中
|
||||||
|
(
|
||||||
|
(-(self.width as f64 / 2.0), -(self.height as f64 / 2.0)),
|
||||||
|
(self.width as f64 / 2.0, self.height as f64 / 2.0),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,14 +781,14 @@ pub mod sr1 {
|
|||||||
let mut max_box = (0_f64, 0_f64, 0_f64, 0_f64);
|
let mut max_box = (0_f64, 0_f64, 0_f64, 0_f64);
|
||||||
for part in parts.iter() {
|
for part in parts.iter() {
|
||||||
let part_type = part_list.get_part_type(part.part_type_id.clone()).unwrap();
|
let part_type = part_list.get_part_type(part.part_type_id.clone()).unwrap();
|
||||||
let (x1, y1, x2, y2) = part_type.get_box();
|
let ((x1, y1), (x2, y2)) = part_type.get_box();
|
||||||
// rotate
|
// rotate
|
||||||
let mut p1 = Point2D::new(x1, y1);
|
let mut p1 = Point2D::new(x1, y1);
|
||||||
let mut p2 = Point2D::new(x2, y2);
|
let mut p2 = Point2D::new(x2, y2);
|
||||||
p1.rotate_radius_mut(part.angle);
|
p1.rotate_radius_mut(part.angle);
|
||||||
p2.rotate_radius_mut(part.angle);
|
p2.rotate_radius_mut(part.angle);
|
||||||
let p1 = p1.add(part.x, part.y);
|
let p1 = p1.add(part.x * 2.0, part.y * 2.0);
|
||||||
let p2 = p2.add(part.x, part.y);
|
let p2 = p2.add(part.x * 2.0, part.y * 2.0);
|
||||||
let (x1, y1, x2, y2) = (p1.x, p1.y, p2.x, p2.y);
|
let (x1, y1, x2, y2) = (p1.x, p1.y, p2.x, p2.y);
|
||||||
// get max box
|
// get max box
|
||||||
max_box.0 = max_box.0.min(x1).min(part.x);
|
max_box.0 = max_box.0.min(x1).min(part.x);
|
||||||
@ -835,6 +839,12 @@ pub mod math {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add(&self, x: f64, y: f64) -> Self { Point2D::new(self.x + x, self.y + y) }
|
pub fn add(&self, x: f64, y: f64) -> Self { Point2D::new(self.x + x, self.y + y) }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn add_mut(&mut self, x: f64, y: f64) -> () {
|
||||||
|
self.x += x;
|
||||||
|
self.y += y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rotatable for Point2D {
|
impl Rotatable for Point2D {
|
||||||
|
@ -17,7 +17,7 @@ from Difficult_Rocket.api.mod import ModInfo
|
|||||||
from Difficult_Rocket.client import ClientWindow
|
from Difficult_Rocket.client import ClientWindow
|
||||||
from Difficult_Rocket.api.types import Options, Version
|
from Difficult_Rocket.api.types import Options, Version
|
||||||
|
|
||||||
DR_rust_version = Version("0.2.10.1") # DR_mod 的 Rust 编写部分的兼容版本
|
DR_rust_version = Version("0.2.11.0") # DR_mod 的 Rust 编写部分的兼容版本
|
||||||
|
|
||||||
logger = logging.getLogger('client.dr_game')
|
logger = logging.getLogger('client.dr_game')
|
||||||
|
|
||||||
|
@ -22,3 +22,6 @@ class RustConsole(Console):
|
|||||||
|
|
||||||
def get_command(self) -> str:
|
def get_command(self) -> str:
|
||||||
return self.console.get_command()
|
return self.console.get_command()
|
||||||
|
|
||||||
|
def new_command(self) -> None:
|
||||||
|
self.console.new_command()
|
||||||
|
12
mods/dr_game/lang/en-us.toml
Normal file
12
mods/dr_game/lang/en-us.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[mod.info]
|
||||||
|
setup.start = "SR1 Renderer start loading"
|
||||||
|
setup.use_time = "SR1 Renderer loading has used: {} second"
|
||||||
|
|
||||||
|
[sr1.ship]
|
||||||
|
xml.loading = "Loading XML file: {}"
|
||||||
|
xml.load_done = "XML file loaded"
|
||||||
|
xml.load_time = "XML file loading has used: {} second"
|
||||||
|
ship.load = "Loading ship: {}"
|
||||||
|
ship.load_time = "Ship loading has used: {} second"
|
||||||
|
ship.info = "Ship info:\n- Parts: {}\n- Weight: {}"
|
||||||
|
ship.render.done = "Ship render done"
|
13
mods/dr_game/lang/zh-CN.toml
Normal file
13
mods/dr_game/lang/zh-CN.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[mod.info]
|
||||||
|
setup.start = "SR1 渲染器开始载入"
|
||||||
|
setup.use_time = "SR1 渲染器载入消耗时间: {} 秒"
|
||||||
|
|
||||||
|
[sr1.ship]
|
||||||
|
xml.loading = "正在加载XML文件: {}"
|
||||||
|
xml.load_done = "XML 文件加载完成"
|
||||||
|
xml.load_time = "XML 文件加载消耗时间: {} 秒"
|
||||||
|
ship.load = "正在加载飞船: {}"
|
||||||
|
ship.load_time = "飞船加载消耗时间: {} 秒"
|
||||||
|
#ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}\n- 文件大小: {}"
|
||||||
|
ship.info = "飞船信息:\n- 部件数量: {}\n- 部件重量: {}"
|
||||||
|
ship.render.done = "飞船渲染完成"
|
@ -9,26 +9,24 @@ import time
|
|||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
# from xml.etree import ElementTree
|
|
||||||
|
from pathlib import Path
|
||||||
from xml.etree.ElementTree import Element
|
from xml.etree.ElementTree import Element
|
||||||
from typing import List, TYPE_CHECKING, Union, Dict, Optional, Generator
|
from typing import List, TYPE_CHECKING, Union, Dict, Optional, Generator
|
||||||
|
|
||||||
# third party package
|
|
||||||
from defusedxml.ElementTree import parse
|
from defusedxml.ElementTree import parse
|
||||||
|
|
||||||
# pyglet
|
|
||||||
from pyglet.math import Vec4
|
from pyglet.math import Vec4
|
||||||
from pyglet.text import Label
|
from pyglet.text import Label
|
||||||
from pyglet.shapes import Line, Rectangle
|
|
||||||
from pyglet.sprite import Sprite
|
from pyglet.sprite import Sprite
|
||||||
# from pyglet.image import Texture
|
# from pyglet.image import Texture
|
||||||
from pyglet.graphics import Batch, Group
|
from pyglet.graphics import Batch, Group
|
||||||
|
from pyglet.shapes import Line, Rectangle
|
||||||
|
|
||||||
from . import DR_mod_runtime
|
from . import DR_mod_runtime
|
||||||
|
|
||||||
# Difficult Rocket
|
# Difficult Rocket
|
||||||
from Difficult_Rocket import DR_status
|
from Difficult_Rocket import DR_status
|
||||||
from Difficult_Rocket.utils.translate import tr
|
from Difficult_Rocket.utils.translate import Tr
|
||||||
from Difficult_Rocket.api.types import Fonts, Options
|
from Difficult_Rocket.api.types import Fonts, Options
|
||||||
from Difficult_Rocket.command.line import CommandText
|
from Difficult_Rocket.command.line import CommandText
|
||||||
from Difficult_Rocket.client.screen import BaseScreen
|
from Difficult_Rocket.client.screen import BaseScreen
|
||||||
@ -41,6 +39,7 @@ if DR_mod_runtime.use_DR_rust:
|
|||||||
from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs, SR1Ship_rs
|
from .Difficult_Rocket_rs import CenterCamera_rs, SR1PartList_rs, SR1Ship_rs
|
||||||
|
|
||||||
logger = logging.getLogger('client.dr_game_sr1_ship')
|
logger = logging.getLogger('client.dr_game_sr1_ship')
|
||||||
|
sr_tr = Tr(lang_path=Path('./mods/dr_game/lang'))
|
||||||
|
|
||||||
|
|
||||||
def get_sr1_part(part_xml: Element) -> Optional[SR1PartData]:
|
def get_sr1_part(part_xml: Element) -> Optional[SR1PartData]:
|
||||||
@ -88,7 +87,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
def __init__(self,
|
def __init__(self,
|
||||||
main_window: "ClientWindow"):
|
main_window: "ClientWindow"):
|
||||||
super().__init__(main_window)
|
super().__init__(main_window)
|
||||||
logger.info(tr().client.sr1_render.setup.start())
|
logger.info(sr_tr().mod.info.setup.start())
|
||||||
load_start_time = time.time_ns()
|
load_start_time = time.time_ns()
|
||||||
self.rendered = False
|
self.rendered = False
|
||||||
self.focus = True
|
self.focus = True
|
||||||
@ -124,15 +123,16 @@ class SR1ShipRender(BaseScreen):
|
|||||||
self.part_box_batch = Batch()
|
self.part_box_batch = Batch()
|
||||||
self.part_batch = Batch()
|
self.part_batch = Batch()
|
||||||
self.part_group = Group()
|
self.part_group = Group()
|
||||||
self.debug_label = Label(x=20, y=main_window.height - 20, font_size=DR_status.std_font_size,
|
self.debug_label = Label(x=20, y=main_window.height - 100, font_size=DR_status.std_font_size,
|
||||||
text='SR1 render!', font_name=Fonts.微软等宽无线,
|
text='SR1 render!', font_name=Fonts.微软等宽无线,
|
||||||
width=main_window.width - 20, height=20,
|
width=main_window.width - 20, height=20,
|
||||||
anchor_x='left', anchor_y='top')
|
anchor_x='left', anchor_y='top')
|
||||||
self.part_data: Dict[int, SR1PartData] = {}
|
self.part_data: Dict[int, SR1PartData] = {}
|
||||||
self.parts_sprite: Dict[int, Sprite] = {}
|
self.parts_sprite: Dict[int, Sprite] = {}
|
||||||
self.part_box_dict: Dict[int, Rectangle] = {}
|
self.part_box_dict: Dict[int, Rectangle] = {}
|
||||||
|
self.part_line_box: Dict[int, List[Line]] = {}
|
||||||
load_end_time = time.time_ns()
|
load_end_time = time.time_ns()
|
||||||
logger.info(tr().client.sr1_render.setup.use_time().format(
|
logger.info(sr_tr().mod.info.setup.use_time().format(
|
||||||
(load_end_time - load_start_time) / 1000000000))
|
(load_end_time - load_start_time) / 1000000000))
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
self.camera_rs = CenterCamera_rs(main_window,
|
self.camera_rs = CenterCamera_rs(main_window,
|
||||||
@ -143,7 +143,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
def load_xml(self, file_path: str) -> bool:
|
def load_xml(self, file_path: str) -> bool:
|
||||||
try:
|
try:
|
||||||
start_time = time.time_ns()
|
start_time = time.time_ns()
|
||||||
logger.info(tr().client.sr1_render.xml.loading().format(file_path))
|
logger.info(sr_tr().sr1.ship.xml.loading().format(file_path))
|
||||||
cache_doc = parse(file_path)
|
cache_doc = parse(file_path)
|
||||||
self.xml_doc = cache_doc
|
self.xml_doc = cache_doc
|
||||||
self.xml_root = self.xml_doc.getroot()
|
self.xml_root = self.xml_doc.getroot()
|
||||||
@ -155,8 +155,8 @@ class SR1ShipRender(BaseScreen):
|
|||||||
print(self.rust_ship.img_pos)
|
print(self.rust_ship.img_pos)
|
||||||
except Exception:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
logger.info(tr().client.sr1_render.xml.load_done())
|
logger.info(sr_tr().sr1.ship.xml.load_done())
|
||||||
logger.info(tr().client.sr1_render.xml.load_time().format(
|
logger.info(sr_tr().sr1.ship.xml.load_time().format(
|
||||||
(time.time_ns() - start_time) / 1000000000))
|
(time.time_ns() - start_time) / 1000000000))
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -191,19 +191,26 @@ class SR1ShipRender(BaseScreen):
|
|||||||
cache_sprite.y = cache_sprite.y - cache_sprite.scale_y / 2
|
cache_sprite.y = cache_sprite.y - cache_sprite.scale_y / 2
|
||||||
self.parts_sprite[part.id] = cache_sprite
|
self.parts_sprite[part.id] = cache_sprite
|
||||||
|
|
||||||
part_width = 100
|
|
||||||
part_height = 100
|
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
part_type = self.part_list_rs.get_part_type(part.p_type)
|
part_debug_box = self.rust_ship.get_part_box(part.id)
|
||||||
if part_type is not None:
|
if part_debug_box:
|
||||||
part_width = part_type.width * 15
|
# 线框
|
||||||
part_height = part_type.height * 15
|
part_line_box = []
|
||||||
part_box = Rectangle(x=render_x, y=render_y,
|
width = 4
|
||||||
width=part_width, height=part_height,
|
color = (random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255), random.randrange(100, 200))
|
||||||
batch=self.part_box_batch, group=self.part_group)
|
part_line_box.append(Line(x=part_debug_box[0][0] * 30, y=part_debug_box[0][1] * 30,
|
||||||
part_box.rotation = SR1Rotation.get_rotation(part.angle)
|
x2=part_debug_box[0][0] * 30, y2=part_debug_box[1][1] * 30,
|
||||||
part_box.opacity = 50
|
batch=self.part_box_batch, width=width, color=color))
|
||||||
self.part_box_dict[part.id] = part_box
|
part_line_box.append(Line(x=part_debug_box[0][0] * 30, y=part_debug_box[1][1] * 30,
|
||||||
|
x2=part_debug_box[1][0] * 30, y2=part_debug_box[1][1] * 30,
|
||||||
|
batch=self.part_box_batch, width=width, color=color))
|
||||||
|
part_line_box.append(Line(x=part_debug_box[1][0] * 30, y=part_debug_box[1][1] * 30,
|
||||||
|
x2=part_debug_box[1][0] * 30, y2=part_debug_box[0][1] * 30,
|
||||||
|
batch=self.part_box_batch, width=width, color=color))
|
||||||
|
part_line_box.append(Line(x=part_debug_box[1][0] * 30, y=part_debug_box[0][1] * 30,
|
||||||
|
x2=part_debug_box[0][0] * 30, y2=part_debug_box[0][1] * 30,
|
||||||
|
batch=self.part_box_batch, width=width, color=color))
|
||||||
|
self.part_line_box[part.id] = part_line_box
|
||||||
# if not part_render: # 如果不渲染(渲染有毛病)
|
# if not part_render: # 如果不渲染(渲染有毛病)
|
||||||
# self.parts_sprite[part.id].visible = False
|
# self.parts_sprite[part.id].visible = False
|
||||||
count += 1
|
count += 1
|
||||||
@ -216,10 +223,11 @@ class SR1ShipRender(BaseScreen):
|
|||||||
def render_ship(self):
|
def render_ship(self):
|
||||||
if self.textures is None:
|
if self.textures is None:
|
||||||
self.load_textures()
|
self.load_textures()
|
||||||
logger.info(tr().client.sr1_render.ship.load().format(self.xml_name))
|
logger.info(sr_tr().sr1.ship.ship.load().format(self.xml_name))
|
||||||
start_time = time.perf_counter_ns()
|
start_time = time.perf_counter_ns()
|
||||||
self.part_data: Dict[int, SR1PartData] = {}
|
self.part_data: Dict[int, SR1PartData] = {}
|
||||||
self.parts_sprite: Dict[int, Sprite] = {}
|
self.parts_sprite: Dict[int, Sprite] = {}
|
||||||
|
self.part_line_box = {}
|
||||||
self.camera_rs.zoom = 1.0
|
self.camera_rs.zoom = 1.0
|
||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
self.camera_rs.dx = 0
|
self.camera_rs.dx = 0
|
||||||
@ -243,10 +251,10 @@ class SR1ShipRender(BaseScreen):
|
|||||||
if DR_mod_runtime.use_DR_rust:
|
if DR_mod_runtime.use_DR_rust:
|
||||||
for part in self.part_data:
|
for part in self.part_data:
|
||||||
full_mass += self.part_list_rs.get_part_type(self.part_data[part].p_type).mass * 500
|
full_mass += self.part_list_rs.get_part_type(self.part_data[part].p_type).mass * 500
|
||||||
logger.info(tr().client.sr1_render.ship.load_time().format(
|
logger.info(sr_tr().sr1.ship.ship.load_time().format(
|
||||||
(time.perf_counter_ns() - start_time) / 1000000000))
|
(time.perf_counter_ns() - start_time) / 1000000000))
|
||||||
logger.info(tr().client.sr1_render.ship.info().format(
|
logger.info(sr_tr().sr1.ship.ship.info().format(
|
||||||
len(self.part_data), f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else tr().game.require_DR_rs()))
|
len(self.part_data), f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else sr_tr().game.require_DR_rs()))
|
||||||
self.rendered = True
|
self.rendered = True
|
||||||
|
|
||||||
def update_parts(self) -> bool:
|
def update_parts(self) -> bool:
|
||||||
@ -269,7 +277,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
next(self.gen_draw)
|
next(self.gen_draw)
|
||||||
except GeneratorExit:
|
except GeneratorExit:
|
||||||
self.drawing = False
|
self.drawing = False
|
||||||
logger.info(tr().client.sr1_render.ship.render.done())
|
logger.info(sr_tr().sr1.ship.ship.render.done())
|
||||||
|
|
||||||
if self.need_update_parts:
|
if self.need_update_parts:
|
||||||
self.update_parts()
|
self.update_parts()
|
||||||
@ -292,6 +300,7 @@ class SR1ShipRender(BaseScreen):
|
|||||||
self.debug_mouse_delta_line.draw()
|
self.debug_mouse_delta_line.draw()
|
||||||
|
|
||||||
def on_resize(self, width: int, height: int, window: "ClientWindow"):
|
def on_resize(self, width: int, height: int, window: "ClientWindow"):
|
||||||
|
self.debug_label.y = height - 100
|
||||||
if not self.rendered:
|
if not self.rendered:
|
||||||
return
|
return
|
||||||
self.debug_line.x = width / 2
|
self.debug_line.x = width / 2
|
||||||
@ -348,22 +357,26 @@ class SR1ShipRender(BaseScreen):
|
|||||||
self.need_draw = True
|
self.need_draw = True
|
||||||
print('应该渲染飞船的')
|
print('应该渲染飞船的')
|
||||||
elif command.find('debug'):
|
elif command.find('debug'):
|
||||||
print('sr ?')
|
|
||||||
if command.find('delta'):
|
if command.find('delta'):
|
||||||
SR1ShipRender_Option.debug_d_pos = not SR1ShipRender_Option.debug_mouse_d_pos
|
# SR1ShipRender_Option.debug_d_pos = not SR1ShipRender_Option.debug_mouse_d_pos
|
||||||
self.debug_line.visible = SR1ShipRender_Option.debug_d_pos
|
self.debug_line.visible = not self.debug_line.visible
|
||||||
self.debug_d_pos_label.visible = SR1ShipRender_Option.debug_d_pos
|
self.debug_d_pos_label.visible = not self.debug_d_pos_label.visible
|
||||||
# print('sr1 delta')
|
SR1ShipRender_Option.debug_d_pos = self.debug_line.visible
|
||||||
|
logger.debug('sr1 delta')
|
||||||
elif command.find('mouse'):
|
elif command.find('mouse'):
|
||||||
if command.find('delta'):
|
if command.find('delta'):
|
||||||
SR1ShipRender_Option.debug_mouse_pos = not SR1ShipRender_Option.debug_mouse_pos
|
SR1ShipRender_Option.debug_mouse_pos = not SR1ShipRender_Option.debug_mouse_pos
|
||||||
self.debug_mouse_line.visible = SR1ShipRender_Option.debug_mouse_pos
|
self.debug_mouse_line.visible = SR1ShipRender_Option.debug_mouse_pos
|
||||||
self.debug_mouse_label.visible = SR1ShipRender_Option.debug_mouse_pos
|
self.debug_mouse_label.visible = SR1ShipRender_Option.debug_mouse_pos
|
||||||
# print('sr1 mouse delta')
|
logger.debug(f'sr1 mouse delta {SR1ShipRender_Option.debug_mouse_pos}')
|
||||||
else:
|
else:
|
||||||
SR1ShipRender_Option.debug_mouse_d_pos = not SR1ShipRender_Option.debug_mouse_d_pos
|
self.debug_mouse_delta_line.visible = not self.debug_mouse_delta_line.visible
|
||||||
self.debug_mouse_delta_line.visible = SR1ShipRender_Option.debug_mouse_d_pos
|
SR1ShipRender_Option.debug_mouse_d_pos = self.debug_mouse_delta_line.visible
|
||||||
# print('sr1 mouse')
|
logger.debug(f'sr1 mouse {SR1ShipRender_Option.debug_mouse_d_pos}')
|
||||||
|
elif command.find('ship'):
|
||||||
|
if self.rendered:
|
||||||
|
for index, sprite in self.parts_sprite.items():
|
||||||
|
sprite.visible = not sprite.visible
|
||||||
|
|
||||||
elif command.find('get_buf'):
|
elif command.find('get_buf'):
|
||||||
|
|
||||||
@ -390,7 +403,6 @@ class SR1ShipRender(BaseScreen):
|
|||||||
return
|
return
|
||||||
img_box = self.rust_ship.img_pos
|
img_box = self.rust_ship.img_pos
|
||||||
img_size = (img_box[2] - img_box[0] + 1000, img_box[3] - img_box[1] + 1000)
|
img_size = (img_box[2] - img_box[0] + 1000, img_box[3] - img_box[1] + 1000)
|
||||||
# img_center = (abs(img_box[0]), abs(img_box[1]))
|
|
||||||
# 中心点是左上角坐标
|
# 中心点是左上角坐标
|
||||||
img_center = (abs(img_box[0]), abs(img_box[3]))
|
img_center = (abs(img_box[0]), abs(img_box[3]))
|
||||||
print(f"img_box: {img_box} img_size: {img_size} img_center: {img_center}")
|
print(f"img_box: {img_box} img_size: {img_size} img_center: {img_center}")
|
||||||
@ -400,23 +412,6 @@ class SR1ShipRender(BaseScreen):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print('PIL not found')
|
print('PIL not found')
|
||||||
return
|
return
|
||||||
min_x = 0
|
|
||||||
min_y = 0
|
|
||||||
max_x = 0
|
|
||||||
max_y = 0
|
|
||||||
for part, sprite in self.parts_sprite.items():
|
|
||||||
sprite_img = sprite.image
|
|
||||||
print(f"sprite_img: {sprite_img} {sprite_img.width} {sprite_img.height}")
|
|
||||||
# 碰撞箱是居中的
|
|
||||||
# -x, -y, +x, +y
|
|
||||||
part_data = self.part_data[part]
|
|
||||||
bound_box = [-sprite_img.width / 2 + part_data.x, -sprite_img.height / 2 + part_data.y,
|
|
||||||
sprite_img.width / 2 + part_data.x, sprite_img.height / 2 + part_data.y]
|
|
||||||
min_x = min(min_x, bound_box[0])
|
|
||||||
min_y = min(min_y, bound_box[1])
|
|
||||||
max_x = max(max_x, bound_box[2])
|
|
||||||
max_y = max(max_y, bound_box[3])
|
|
||||||
print(f"min_x: {min_x} min_y: {min_y} max_x: {max_x} max_y: {max_y}")
|
|
||||||
img = Image.new('RGBA', img_size)
|
img = Image.new('RGBA', img_size)
|
||||||
for part, sprite in self.parts_sprite.items():
|
for part, sprite in self.parts_sprite.items():
|
||||||
sprite_img = sprite.image
|
sprite_img = sprite.image
|
||||||
|
Loading…
Reference in New Issue
Block a user