Compare commits
No commits in common. "ad83def45e737aac0053e007de8db51b719dac1c" and "3629bcf163af342f6718eb3e09b3999075231d96" have entirely different histories.
ad83def45e
...
3629bcf163
@ -1,5 +1,3 @@
|
||||
<div style="text-align: center;">
|
||||
|
||||
# Difficult Rocket
|
||||
|
||||
中文 | [English](./docs/README-en.md)
|
||||
@ -121,8 +119,6 @@ setuptools-rust >= 1.6.0
|
||||
- [@Billchyi](https://github.com/Billchyi) : 文档矫正
|
||||
- [@MSDNicrosoft](https://github.com/MSDNicrosoft) : 优化代码
|
||||
|
||||
</div>
|
||||
|
||||
## 相关链接
|
||||
|
||||
## 关于分享协议
|
||||
|
@ -7,8 +7,8 @@ fonts_folder = "assets/fonts"
|
||||
|
||||
[window]
|
||||
style = "None"
|
||||
width = 1112
|
||||
height = 793
|
||||
width = 1301
|
||||
height = 970
|
||||
visible = true
|
||||
gui_scale = 1
|
||||
caption = "Difficult Rocket v{DR_version}"
|
||||
|
@ -2,31 +2,8 @@
|
||||
# DR game/DR rs 更新日志
|
||||
|
||||
- 最新版本号
|
||||
- DR game: 0.3.2.0
|
||||
- DR rs: 0.2.19.0
|
||||
|
||||
## 20230721 DR rs 0.2.19.0
|
||||
|
||||
### Add
|
||||
|
||||
- `PySR1Ship`
|
||||
- `as_list`
|
||||
|
||||
## 20230721 DR game 0.3.2.0
|
||||
|
||||
### BUG Fix
|
||||
|
||||
- [#46](https://github.com/shenjackyuanjie/Difficult-Rocket/issues/46)
|
||||
- 渲染偏移 bug
|
||||
|
||||
## 20230721 DR rs 0.2.18.0
|
||||
|
||||
### Add
|
||||
|
||||
- 导出了 export
|
||||
- `PySR1PartData`
|
||||
- `PySaveStatus`
|
||||
- `map_ptype_textures(part_type: str) -> str`
|
||||
- DR game: 0.3.1.3
|
||||
- DR rs: 0.2.17.0
|
||||
|
||||
## 20230721 DR rs 0.2.17.0
|
||||
|
||||
|
@ -9,81 +9,49 @@ from .lib import *
|
||||
from typing import TYPE_CHECKING, Dict, Tuple, Optional, List
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
def test_call(py_obj) -> bool:
|
||||
""" 这里展示的代码实际上就是实际的等效实现 """
|
||||
py_obj.draw()
|
||||
return True
|
||||
|
||||
def get_version_str() -> str: ...
|
||||
|
||||
def get_version_str() -> str:
|
||||
"""
|
||||
获取版本号
|
||||
:return: 版本号
|
||||
"""
|
||||
def part_list_read_test(file_name: Optional[str] = "./assets/builtin/PartList.xml") -> None: ...
|
||||
|
||||
def read_ship_test(path: Optional[str] = "./assets/builtin/dock1.xml") -> None: ...
|
||||
|
||||
|
||||
def part_list_read_test(file_name: Optional[str] = "./assets/builtin/PartList.xml") -> None:
|
||||
"""
|
||||
PartList 读取测试
|
||||
:param file_name:
|
||||
"""
|
||||
|
||||
|
||||
def read_ship_test(path: Optional[str] = "./assets/builtin/dock1.xml") -> None:
|
||||
"""
|
||||
飞船存档读取测试
|
||||
:param path:
|
||||
:return:
|
||||
"""
|
||||
|
||||
|
||||
def map_ptype_textures(part_type: str) -> str:
|
||||
"""
|
||||
获取零件的贴图 (写死的)
|
||||
:param part_type:
|
||||
:return:
|
||||
"""
|
||||
|
||||
|
||||
class SR1PartType_rs: # NOQA
|
||||
"""
|
||||
用于从 rust 中读取 SR1PartType
|
||||
class SR1PartType_rs:
|
||||
""" 用于从 rust 中读取 SR1PartType
|
||||
不能从 Python 端创建
|
||||
自带一些可从 Python 端读取的属性 (实际上就是一个接口)
|
||||
"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
""" 零件的名字 """
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
""" 零件的描述 """
|
||||
|
||||
@property
|
||||
def mass(self) -> float:
|
||||
""" 零件的质量 """
|
||||
|
||||
@property
|
||||
def width(self) -> int:
|
||||
""" 零件的宽度 """
|
||||
|
||||
@property
|
||||
def height(self) -> int:
|
||||
""" 零件的高度 """
|
||||
|
||||
@property
|
||||
def friction(self) -> float:
|
||||
""" 零件的摩擦系数 """
|
||||
|
||||
@property
|
||||
def hidden(self) -> bool:
|
||||
""" 零件是否隐藏 """
|
||||
|
||||
|
||||
class SR1PartList_rs: # NOQA
|
||||
class SR1PartList_rs:
|
||||
""" 用于从 rust 中读取 SR1PartList """
|
||||
|
||||
def __init__(self, file_name: Optional[str] = "./assets/builtin/PartList.xml",
|
||||
list_name: Optional[str] = 'NewPartList'): ...
|
||||
|
||||
@ -91,104 +59,63 @@ if TYPE_CHECKING:
|
||||
|
||||
def get_part_type(self, name: str) -> SR1PartType_rs: ...
|
||||
|
||||
|
||||
class SR1PartData_rs: # NOQA
|
||||
class SR1PartData_rs:
|
||||
""" 用于从 rust 中读取 SR1PartData (其实好像也没啥用哈)
|
||||
"""
|
||||
用于从 rust 中读取 SR1PartData (其实好像也没啥用哈)
|
||||
"""
|
||||
|
||||
@property
|
||||
def id(self) -> int: ...
|
||||
|
||||
@property
|
||||
def part_type_id(self) -> str: ...
|
||||
|
||||
@property
|
||||
def pos(self) -> Tuple[float, float]: ...
|
||||
|
||||
@property
|
||||
def x(self) -> float: ...
|
||||
|
||||
@property
|
||||
def y(self) -> float: ...
|
||||
|
||||
@property
|
||||
def activate(self) -> bool: ...
|
||||
|
||||
@property
|
||||
def angle(self) -> float: ...
|
||||
|
||||
@property
|
||||
def angle_r(self) -> float: ...
|
||||
|
||||
@property
|
||||
def angle_v(self) -> float: ...
|
||||
|
||||
@property
|
||||
def explode(self) -> bool: ...
|
||||
|
||||
@property
|
||||
def flip_x(self) -> bool: ...
|
||||
|
||||
@property
|
||||
def flip_y(self) -> bool: ...
|
||||
|
||||
|
||||
class SaveStatus_rs: # NOQA
|
||||
class SaveStatus_rs:
|
||||
def __init__(self, save_default: Optional[bool] = False) -> None: ...
|
||||
|
||||
|
||||
class SR1Ship_rs: # NOQA
|
||||
class SR1Ship_rs:
|
||||
""" 用于高效且省内存的读取 SR1Ship """
|
||||
|
||||
def __init__(self,
|
||||
file_path: Optional[str] = './assets/builtin/dock1.xml',
|
||||
part_list: Optional[SR1PartList_rs] = None,
|
||||
ship_name: Optional[str] = 'NewShip'): ...
|
||||
|
||||
@property
|
||||
def name(self) -> str: ...
|
||||
|
||||
@property
|
||||
def description(self) -> str: ...
|
||||
|
||||
@property
|
||||
def lift_off(self) -> bool: ...
|
||||
|
||||
@property
|
||||
def touch_ground(self) -> bool: ...
|
||||
|
||||
@property
|
||||
def mass(self) -> float:
|
||||
""" 获取整搜船的质量 """
|
||||
|
||||
def img_pos(self) -> Tuple[int, int, int, int]: ...
|
||||
""" -x -y +x +y 左下右上 """
|
||||
@property
|
||||
def img_pos(self) -> Tuple[int, int, int, int]:
|
||||
""" -x -y +x +y 左下右上 """
|
||||
|
||||
@property
|
||||
def connection(self) -> List[Tuple[int, int, int, int]]:
|
||||
"""获取所有连接信息"""
|
||||
|
||||
def get_part_box(self, part_id: int) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]:
|
||||
"""获取所有零件的盒子"""
|
||||
|
||||
def as_list(self) -> List[Tuple[SR1PartType_rs, SR1PartData_rs]]:
|
||||
"""用于返回一个包含所有已连接零件的列表"""
|
||||
|
||||
def connection(self) -> List[Tuple[int, int, int, int]]: ...
|
||||
"""获取所有连接信息"""
|
||||
def get_part_box(self, part_id: int) -> Optional[Tuple[Tuple[int, int], Tuple[int, int]]]: ...
|
||||
def as_dict(self) -> Dict[int, List[Tuple[SR1PartType_rs, SR1PartData_rs]]]:
|
||||
"""用于返回一个包含所有已连接零件的字典"""
|
||||
|
||||
def save(self, file_path: str, save_status: Optional[SaveStatus_rs] = None) -> None: ...
|
||||
|
||||
|
||||
class Console_rs: # NOQA
|
||||
class Console_rs:
|
||||
def __init__(self) -> None: ...
|
||||
|
||||
def start(self) -> None: ...
|
||||
|
||||
def stop(self) -> bool: ...
|
||||
|
||||
def get_command(self) -> Optional[str]: ...
|
||||
|
||||
def new_command(self) -> bool: ...
|
||||
|
2
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
2
mods/dr_game/Difficult_Rocket_rs/src/Cargo.lock
generated
@ -116,7 +116,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "difficult_rocket_rs"
|
||||
version = "0.2.19"
|
||||
version = "0.2.17"
|
||||
dependencies = [
|
||||
"pyo3",
|
||||
"quick-xml",
|
||||
|
@ -1,11 +1,8 @@
|
||||
[package]
|
||||
name = "difficult_rocket_rs"
|
||||
version = "0.2.19"
|
||||
version = "0.2.17"
|
||||
edition = "2021"
|
||||
license-file = '../../LICENSE'
|
||||
authors = [
|
||||
"shenjackyuanjie <3695888@qq.com>"
|
||||
]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -12,7 +12,7 @@ package_path = 'Difficult_Rocket_rs'
|
||||
|
||||
setup(
|
||||
name='Difficult_Rocket_rs',
|
||||
version="0.2.18.0",
|
||||
version="0.2.16.0",
|
||||
author='shenjackyuanjie',
|
||||
author_email='3695888@qq.com',
|
||||
rust_extensions=[RustExtension(target="Difficult_Rocket_rs.Difficult_Rocket_rs",
|
||||
|
@ -24,7 +24,7 @@ enum LoadState {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_version_str() -> String { "0.2.19.0".to_string() }
|
||||
fn get_version_str() -> String { "0.2.17.0".to_string() }
|
||||
|
||||
#[pyfunction]
|
||||
fn test_call(py_obj: &PyAny) -> PyResult<bool> {
|
||||
@ -43,12 +43,9 @@ fn module_init(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||
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!(python::data::load_and_save_test, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(python::data::py_map_ptype_textures, m)?)?;
|
||||
m.add_class::<python::data::PySR1Ship>()?;
|
||||
m.add_class::<python::data::PySR1PartList>()?;
|
||||
m.add_class::<python::data::PySR1PartType>()?;
|
||||
m.add_class::<python::data::PySR1PartData>()?;
|
||||
m.add_class::<python::data::PySaveStatus>()?;
|
||||
m.add_class::<python::console::PyConsole>()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -13,15 +13,10 @@ pub mod data {
|
||||
|
||||
use crate::sr1_data::part_list::RawPartList;
|
||||
use crate::types::math::{Point2D, Rotatable};
|
||||
use crate::types::sr1::{get_max_box, map_ptype_textures, SR1PartData, SR1PartListTrait};
|
||||
use crate::types::sr1::{get_max_box, SR1PartData, SR1PartListTrait};
|
||||
use crate::types::sr1::{IdType, SaveStatus};
|
||||
use crate::types::sr1::{SR1PartList, SR1PartType, SR1Ship};
|
||||
|
||||
#[pyfunction]
|
||||
#[pyo3(signature = (part_type))]
|
||||
#[pyo3(name = "map_ptype_textures")]
|
||||
pub fn py_map_ptype_textures(part_type: String) -> String { map_ptype_textures(part_type) }
|
||||
|
||||
#[pyclass]
|
||||
#[pyo3(name = "SaveStatus_rs")]
|
||||
#[derive(Clone, Debug)]
|
||||
@ -142,9 +137,6 @@ pub mod data {
|
||||
#[getter]
|
||||
fn get_angle(&self) -> f64 { self.data.angle }
|
||||
|
||||
#[getter]
|
||||
fn get_angle_r(&self) -> f64 { self.data.angle_degrees() }
|
||||
|
||||
#[getter]
|
||||
fn get_angle_v(&self) -> f64 { self.data.angle_v }
|
||||
|
||||
@ -229,20 +221,8 @@ pub mod data {
|
||||
connections
|
||||
}
|
||||
|
||||
fn as_list(&self) -> Vec<(PySR1PartType, PySR1PartData)> {
|
||||
let mut parts: Vec<(PySR1PartType, PySR1PartData)> = Vec::new();
|
||||
for part_data in self.ship.parts.iter() {
|
||||
if let Some(part_type) = self.part_list.get_part_type(&part_data.part_type_id) {
|
||||
let part_type = PySR1PartType::new(part_type.clone());
|
||||
let py_part_data = PySR1PartData::new(part_data.clone());
|
||||
parts.push((part_type, py_part_data));
|
||||
}
|
||||
}
|
||||
parts
|
||||
}
|
||||
|
||||
fn as_dict(&self) -> HashMap<IdType, Vec<(PySR1PartType, PySR1PartData)>> {
|
||||
let mut parts: HashMap<IdType, Vec<(PySR1PartType, PySR1PartData)>> = HashMap::new();
|
||||
fn as_dict(&self) -> HashMap<i64, Vec<(PySR1PartType, PySR1PartData)>> {
|
||||
let mut parts: HashMap<i64, Vec<(PySR1PartType, PySR1PartData)>> = HashMap::new();
|
||||
for part_data in self.ship.parts.iter() {
|
||||
if let Some(part_type) = self.part_list.get_part_type(&part_data.part_type_id) {
|
||||
let part_type = PySR1PartType::new(part_type.clone());
|
||||
|
@ -24,29 +24,6 @@ pub mod sr1 {
|
||||
pub type IdType = i64;
|
||||
pub type ConnectionsType = Vec<(Vec<SR1PartData>, Option<Vec<Connection>>)>;
|
||||
|
||||
#[inline]
|
||||
pub fn radians_map_to_degrees(angle: f64) -> f64 {
|
||||
// match angle {
|
||||
// 0.0 => 0.,
|
||||
// 1.570796 => 270.,
|
||||
// 3.141593 => 180.,
|
||||
// 4.712389 => 90.,
|
||||
// _ => {
|
||||
// angle.to_degrees()
|
||||
// }
|
||||
// }
|
||||
#[allow(clippy::approx_constant)]
|
||||
if angle == 1.570796 {
|
||||
270.
|
||||
} else if angle == 3.141593 {
|
||||
180.
|
||||
} else if angle == 4.712389 {
|
||||
90.
|
||||
} else {
|
||||
angle.to_degrees()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[inline]
|
||||
pub fn map_ptype_textures(ptype: String) -> String {
|
||||
@ -529,8 +506,6 @@ pub mod sr1 {
|
||||
}
|
||||
pos_box
|
||||
}
|
||||
|
||||
pub fn angle_degrees(&self) -> f64 { radians_map_to_degrees(self.angle) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -16,7 +16,7 @@ from Difficult_Rocket.api.mod import ModInfo
|
||||
from Difficult_Rocket.client import ClientWindow
|
||||
from Difficult_Rocket.api.types import Options, Version
|
||||
|
||||
DR_rust_version = Version("0.2.19.0") # DR_mod 的 Rust 编写部分的兼容版本
|
||||
DR_rust_version = Version("0.2.17.0") # DR_mod 的 Rust 编写部分的兼容版本
|
||||
|
||||
logger = logging.getLogger('client.dr_game')
|
||||
|
||||
@ -53,7 +53,7 @@ DR_mod_runtime = _DR_mod_runtime()
|
||||
class DR_mod(ModInfo): # NOQA
|
||||
mod_id = "difficult_rocket_mod"
|
||||
name = "Difficult Rocket mod"
|
||||
version = Version("0.3.2.0")
|
||||
version = Version("0.3.1.2")
|
||||
|
||||
writer = "shenjackyuanjie"
|
||||
link = "shenjack.top"
|
||||
@ -81,7 +81,7 @@ class DR_mod(ModInfo): # NOQA
|
||||
else:
|
||||
self.config.flush_option()
|
||||
logger.info("on_load")
|
||||
logger.info(f"\n{self.as_markdown()}")
|
||||
logger.info(self.as_markdown())
|
||||
return True
|
||||
|
||||
def on_client_start(self, game: Game, client: ClientWindow):
|
||||
|
@ -40,16 +40,38 @@ if TYPE_CHECKING:
|
||||
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
from .Difficult_Rocket_rs import (SR1PartList_rs,
|
||||
SR1Ship_rs,
|
||||
SR1PartData_rs,
|
||||
SR1PartType_rs,
|
||||
map_ptype_textures)
|
||||
SR1Ship_rs)
|
||||
|
||||
logger = logging.getLogger('client.dr_game_sr1_ship')
|
||||
logger.level = logging.DEBUG
|
||||
sr_tr = Tr(lang_path=Path(__file__).parent / 'lang')
|
||||
|
||||
|
||||
def get_sr1_part(part_xml: Element) -> Optional[SR1PartData]:
|
||||
if part_xml.tag != 'Part':
|
||||
return None
|
||||
# print(f"tag: {part.tag} attrib: {part.attrib}")
|
||||
part_id = int(part_xml.attrib.get('id'))
|
||||
part_type = part_xml.attrib.get('partType')
|
||||
part_x = float(part_xml.attrib.get('x'))
|
||||
part_y = float(part_xml.attrib.get('y'))
|
||||
part_activate = xml_bool(part_xml.attrib.get('activated'))
|
||||
part_angle = float(part_xml.attrib.get('angle'))
|
||||
part_angle_v = float(part_xml.attrib.get('angleV'))
|
||||
part_editor_angle = int(part_xml.attrib.get('editorAngle'))
|
||||
part_flip_x = xml_bool(part_xml.attrib.get('flippedX'))
|
||||
part_flip_y = xml_bool(part_xml.attrib.get('flippedY'))
|
||||
part_explode = xml_bool(part_xml.attrib.get('exploded'))
|
||||
if part_type not in SR1PartTexture.part_type_sprite:
|
||||
part_textures = None
|
||||
else:
|
||||
part_textures = SR1PartTexture.get_textures_from_type(part_type)
|
||||
return SR1PartData(x=part_x, y=part_y, id=part_id, p_type=part_type,
|
||||
active=part_activate, angle=part_angle, angle_v=part_angle_v,
|
||||
editor_angle=part_editor_angle, flip_x=part_flip_x,
|
||||
flip_y=part_flip_y, explode=part_explode, textures=part_textures)
|
||||
|
||||
|
||||
class SR1ShipRender_Option(Options): # NOQA
|
||||
# debug option
|
||||
debug_d_pos: bool = False
|
||||
@ -75,8 +97,6 @@ class SR1ShipRender(BaseScreen):
|
||||
self.render_option = SR1ShipRender_Option()
|
||||
self.dx = 0
|
||||
self.dy = 0
|
||||
self.width = main_window.width
|
||||
self.height = main_window.height
|
||||
|
||||
self.main_batch = Batch()
|
||||
self.part_group = Group(10, parent=main_window.main_group)
|
||||
@ -92,29 +112,32 @@ class SR1ShipRender(BaseScreen):
|
||||
self.render_d_label = Label('debug label NODATA', font_name=Fonts.微软等宽无线,
|
||||
x=main_window.width / 2, y=main_window.height / 2)
|
||||
self.render_d_label.visible = self.render_option.debug_d_pos
|
||||
self.camera = CenterCamera(main_window, min_zoom=(1 / 2) ** 10, max_zoom=10)
|
||||
|
||||
# Optional data
|
||||
self.textures: SR1Textures = SR1Textures()
|
||||
self.gen_draw: Optional[Generator] = None
|
||||
self.textures: Union[SR1Textures, None] = None
|
||||
self.xml_name: Optional[str] = None # 准备移除, 更换为基于 rust 的 xml 解析
|
||||
self.xml_doc: Optional[ElementTree] = None # 准备移除, 更换为基于 rust 的 xml 解析
|
||||
self.xml_root: Optional[Element] = None # 准备移除, 更换为基于 rust 的 xml 解析
|
||||
self.rust_ship: Optional[SR1Ship_rs] = None
|
||||
self.ship_name: Optional[str] = None
|
||||
|
||||
# List/Dict data
|
||||
self.parts_sprite: Dict[int, List[Sprite]] = {}
|
||||
self.part_data: Dict[int, SR1PartData] = {}
|
||||
self.parts_sprite: Dict[int, Sprite] = {}
|
||||
self.part_box_dict: Dict[int, Rectangle] = {}
|
||||
self.part_line_box: Dict[int, List[Line]] = {}
|
||||
self.part_line_list: List[Line] = []
|
||||
|
||||
|
||||
load_end_time = time.time_ns()
|
||||
logger.info(sr_tr().mod.info.setup.use_time().format((load_end_time - load_start_time) / 1000000000))
|
||||
self.camera = CenterCamera(main_window, min_zoom=(1 / 2) ** 10, max_zoom=10)
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
self.rust_parts = None
|
||||
self.part_list_rs = SR1PartList_rs('assets/builtin/PartList.xml', 'builtin_part_list')
|
||||
|
||||
self.load_xml('assets/builtin/dock1.xml')
|
||||
|
||||
load_end_time = time.time_ns()
|
||||
logger.info(sr_tr().mod.info.setup.use_time().format((load_end_time - load_start_time) / 1000000000))
|
||||
|
||||
def load_xml(self, file_path: str) -> bool:
|
||||
"""
|
||||
加载 xml 文件
|
||||
@ -124,7 +147,10 @@ class SR1ShipRender(BaseScreen):
|
||||
try:
|
||||
start_time = time.time_ns()
|
||||
logger.info(sr_tr().sr1.ship.xml.loading().format(file_path))
|
||||
self.ship_name = file_path.split('/')[-1].split('.')[0]
|
||||
cache_doc = parse(file_path)
|
||||
self.xml_doc = cache_doc
|
||||
self.xml_root = self.xml_doc.getroot()
|
||||
self.xml_name = file_path
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
self.rust_ship = SR1Ship_rs(file_path, self.part_list_rs, 'a_new_ship')
|
||||
logger.info(sr_tr().sr1.ship.xml.load_done())
|
||||
@ -135,34 +161,44 @@ class SR1ShipRender(BaseScreen):
|
||||
print(e)
|
||||
return False
|
||||
|
||||
def gen_sprite(self, each_count: int = 100) -> Generator:
|
||||
def load_textures(self):
|
||||
"""
|
||||
初始化纹理加载
|
||||
:return:
|
||||
"""
|
||||
self.textures = SR1Textures()
|
||||
|
||||
def gen_sprite(self, part_datas: Dict[int, SR1PartData], each_count: int = 100) -> Generator:
|
||||
"""
|
||||
生成 sprite
|
||||
通过生成器减少一次性渲染的压力
|
||||
:param part_datas: 所有的部件数据
|
||||
:param each_count: 每次生成的数量 (默认 100) (过大会导致卡顿)
|
||||
:return: 生成器
|
||||
"""
|
||||
count = 0
|
||||
self.drawing = True
|
||||
# rust 渲染
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
cache = self.rust_ship.as_dict()
|
||||
for p_id, parts in cache.items():
|
||||
p_id: int
|
||||
parts: List[Tuple[SR1PartType_rs, SR1PartData_rs]]
|
||||
part_group = Group(2, parent=self.part_group)
|
||||
batch = []
|
||||
for p_type, p_data in parts:
|
||||
part_sprite = Sprite(img=self.textures.get_texture(map_ptype_textures(p_data.part_type_id)),
|
||||
x=p_data.x * 60, y=p_data.y * 60, z=random.random(),
|
||||
batch=self.main_batch, group=part_group)
|
||||
part_sprite.rotation = p_data.angle_r
|
||||
part_sprite.scale_x = -1 if p_data.flip_x else 1
|
||||
part_sprite.scale_y = -1 if p_data.flip_y else 1
|
||||
for part_id, part in part_datas.items():
|
||||
# 下面就是调用 pyglet 去渲染的部分
|
||||
# render_scale = DR_status.gui_scale # 这个是 DR 的缩放比例 可以调节的
|
||||
# 在不缩放的情况下,XML的1个单位长度对应60个像素
|
||||
render_x = part.x * 60
|
||||
render_y = part.y * 60
|
||||
cache_sprite = Sprite(img=self.textures.get_texture(part.textures),
|
||||
x=render_x, y=render_y, z=random.random(),
|
||||
batch=self.main_batch, group=self.part_group)
|
||||
# 你得帮我换算一下 XML 里的 x y 和这里的屏幕像素的关系(OK
|
||||
# 旋转啥的不是大问题, 我找你要那个渲染代码就是要 x y 的换算逻辑
|
||||
cache_sprite.rotation = SR1Rotation.get_rotation(part.angle)
|
||||
if part.flip_x:
|
||||
cache_sprite.scale_x = -1
|
||||
if part.flip_y:
|
||||
cache_sprite.scale_y = -1
|
||||
self.parts_sprite[part.id] = cache_sprite
|
||||
|
||||
batch.append(part_sprite)
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
line_box_group = Group(6, parent=self.part_group)
|
||||
part_debug_box = self.rust_ship.get_part_box(p_id)
|
||||
part_debug_box = self.rust_ship.get_part_box(part.id)
|
||||
if part_debug_box:
|
||||
# 线框
|
||||
part_line_box = []
|
||||
@ -181,17 +217,17 @@ class SR1ShipRender(BaseScreen):
|
||||
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.main_batch, width=width, color=color, group=line_box_group))
|
||||
self.part_line_box[p_id] = part_line_box
|
||||
self.parts_sprite[p_id] = batch
|
||||
count += 1
|
||||
if count >= each_count:
|
||||
count = 0
|
||||
yield
|
||||
self.part_line_box[part.id] = part_line_box
|
||||
count += 1
|
||||
if count >= each_count:
|
||||
count = 0
|
||||
yield count
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
connect_line_group = Group(7, parent=self.part_group)
|
||||
for connect in self.rust_ship.connection:
|
||||
# 连接线
|
||||
parent_part_data = cache[connect[2]][0][1]
|
||||
child_part_data = cache[connect[3]][0][1]
|
||||
parent_part_data = self.part_data[connect[2]]
|
||||
child_part_data = self.part_data[connect[3]]
|
||||
color = (random.randrange(100, 255), random.randrange(0, 255), random.randrange(0, 255), 255)
|
||||
self.part_line_list.append(Line(x=parent_part_data.x * 60, y=parent_part_data.y * 60,
|
||||
x2=child_part_data.x * 60, y2=child_part_data.y * 60,
|
||||
@ -201,31 +237,6 @@ class SR1ShipRender(BaseScreen):
|
||||
if count >= each_count * 3:
|
||||
count = 0
|
||||
yield count
|
||||
|
||||
# python 渲染
|
||||
# for part_id, part in part_datas.items():
|
||||
# # 下面就是调用 pyglet 去渲染的部分
|
||||
# # render_scale = DR_status.gui_scale # 这个是 DR 的缩放比例 可以调节的
|
||||
# # 在不缩放的情况下,XML的1个单位长度对应60个像素
|
||||
# # render_x = part.x * 60
|
||||
# # render_y = part.y * 60
|
||||
# # cache_sprite = Sprite(img=self.textures.get_texture(part.textures),
|
||||
# # x=render_x, y=render_y, z=random.random(),
|
||||
# # batch=self.main_batch, group=self.part_group)
|
||||
# # # 你得帮我换算一下 XML 里的 x y 和这里的屏幕像素的关系
|
||||
# # # 旋转啥的不是大问题, 我找你要那个渲染代码就是要 x y 的换算逻辑
|
||||
# # cache_sprite.rotation = SR1Rotation.get_rotation(part.angle)
|
||||
# # if part.flip_x:
|
||||
# # cache_sprite.scale_x = -1
|
||||
# # if part.flip_y:
|
||||
# # cache_sprite.scale_y = -1
|
||||
# # self.parts_sprite[part.id] = cache_sprite
|
||||
#
|
||||
# if DR_mod_runtime.use_DR_rust:
|
||||
# count += 1
|
||||
# if count >= each_count:
|
||||
# count = 0
|
||||
# yield count
|
||||
self.drawing = False
|
||||
raise GeneratorExit
|
||||
|
||||
@ -233,28 +244,40 @@ class SR1ShipRender(BaseScreen):
|
||||
"""
|
||||
渲染船
|
||||
"""
|
||||
logger.info(sr_tr().sr1.ship.ship.load().format(self.ship_name))
|
||||
if self.textures is None:
|
||||
self.load_textures()
|
||||
logger.info(sr_tr().sr1.ship.ship.load().format(self.xml_name))
|
||||
start_time = time.perf_counter_ns()
|
||||
self.part_data: Dict[int, SR1PartData] = {}
|
||||
self.parts_sprite: Dict[int, Sprite] = {}
|
||||
self.part_line_box = {}
|
||||
self.part_line_list = []
|
||||
# self.camera.zoom = 1.0
|
||||
# self.camera.dx = 0
|
||||
# self.camera.dy = 0
|
||||
self.camera.zoom = 1.0
|
||||
self.camera.dx = 0
|
||||
self.camera.dy = 0
|
||||
parts = self.xml_root.find('Parts')
|
||||
for part_xml in parts:
|
||||
if part_xml.tag != 'Part':
|
||||
continue # 如果不是部件,则跳过
|
||||
part = get_sr1_part(part_xml)
|
||||
if part.id in self.part_data:
|
||||
print(f'hey! warning! id{part.id}')
|
||||
self.part_data[part.id] = part
|
||||
# 调用生成器 减少卡顿
|
||||
try:
|
||||
self.gen_draw = self.gen_sprite()
|
||||
self.gen_draw = self.gen_sprite(self.part_data)
|
||||
next(self.gen_draw)
|
||||
except (GeneratorExit, StopIteration):
|
||||
except GeneratorExit:
|
||||
self.drawing = False
|
||||
self.need_draw = False
|
||||
full_mass = 0
|
||||
if DR_mod_runtime.use_DR_rust:
|
||||
full_mass = self.rust_ship.mass
|
||||
for part in self.part_data:
|
||||
full_mass += self.part_list_rs.get_part_type(self.part_data[part].p_type).mass * 500
|
||||
logger.info(sr_tr().sr1.ship.ship.load_time().format(
|
||||
(time.perf_counter_ns() - start_time) / 1000000000))
|
||||
logger.info(sr_tr().sr1.ship.ship.info().format(
|
||||
len(self.rust_ship.as_list()), f'{full_mass}kg' if DR_mod_runtime.use_DR_rust else sr_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
|
||||
|
||||
def draw_batch(self, window: "ClientWindow"):
|
||||
@ -276,7 +299,7 @@ class SR1ShipRender(BaseScreen):
|
||||
if self.drawing:
|
||||
try:
|
||||
next(self.gen_draw)
|
||||
except (GeneratorExit, StopIteration):
|
||||
except GeneratorExit:
|
||||
self.drawing = False
|
||||
self.logger.info(sr_tr().sr1.ship.ship.render.done())
|
||||
|
||||
|
@ -33,8 +33,10 @@ class SR1PartData:
|
||||
|
||||
class SR1Textures(Options):
|
||||
""" 存储 sr1 的材质 img """
|
||||
def load_file(self, **kwargs):
|
||||
for image_name in self.flush_option():
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.flush_option()
|
||||
for image_name in self.cached_options:
|
||||
img = load(f'assets/textures/parts/{image_name}.png')
|
||||
img.anchor_x = img.width // 2
|
||||
img.anchor_y = img.height // 2
|
||||
@ -47,14 +49,8 @@ class SR1Textures(Options):
|
||||
:param name:
|
||||
:return:
|
||||
"""
|
||||
if name in self.cached_options:
|
||||
return self.cached_options.get(name)
|
||||
else:
|
||||
img = load(f'assets/textures/parts/{name}.png')
|
||||
img.anchor_x = img.width // 2
|
||||
img.anchor_y = img.height // 2
|
||||
setattr(self, name, img)
|
||||
return img
|
||||
assert name in self.cached_options
|
||||
return self.cached_options.get(name)
|
||||
|
||||
Battery: AbstractImage = None
|
||||
Beam: AbstractImage = None
|
||||
@ -138,11 +134,6 @@ class SR1Rotation(Options):
|
||||
|
||||
@classmethod
|
||||
def get_rotation(cls, radian: float) -> float:
|
||||
"""
|
||||
实际上就是将弧度转换为角度 (同时自带一个映射表)
|
||||
:param radian:
|
||||
:return:
|
||||
"""
|
||||
if radian in cls.radian_angle_map:
|
||||
return cls.radian_angle_map[radian]
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user