//! Main engine implementation. //! 主引擎实现。 use wasm_bindgen::prelude::*; use super::context::WebGLContext; use super::error::Result; use crate::input::InputManager; use crate::renderer::Renderer2D; use crate::resource::TextureManager; /// Engine configuration options. /// 引擎配置选项。 #[derive(Debug, Clone)] pub struct EngineConfig { /// Maximum sprites per batch. /// 每批次最大精灵数。 pub max_sprites: usize, /// Enable debug mode. /// 启用调试模式。 pub debug: bool, } impl Default for EngineConfig { fn default() -> Self { Self { max_sprites: 10000, debug: false, } } } /// Main game engine. /// 主游戏引擎。 /// /// Coordinates all engine subsystems including rendering, input, and resources. /// 协调所有引擎子系统,包括渲染、输入和资源。 pub struct Engine { /// WebGL context. /// WebGL上下文。 context: WebGLContext, /// 2D renderer. /// 2D渲染器。 renderer: Renderer2D, /// Texture manager. /// 纹理管理器。 texture_manager: TextureManager, /// Input manager. /// 输入管理器。 input_manager: InputManager, /// Engine configuration. /// 引擎配置。 #[allow(dead_code)] config: EngineConfig, } impl Engine { /// Create a new engine instance. /// 创建新的引擎实例。 /// /// # Arguments | 参数 /// * `canvas_id` - The HTML canvas element ID | HTML canvas元素ID /// * `config` - Engine configuration | 引擎配置 /// /// # Returns | 返回 /// A new Engine instance or an error | 新的Engine实例或错误 pub fn new(canvas_id: &str, config: EngineConfig) -> Result { let context = WebGLContext::new(canvas_id)?; // Initialize WebGL state | 初始化WebGL状态 context.set_viewport(); context.enable_blend(); // Create subsystems | 创建子系统 let renderer = Renderer2D::new(context.gl(), config.max_sprites)?; let texture_manager = TextureManager::new(context.gl().clone()); let input_manager = InputManager::new(); log::info!("Engine created successfully | 引擎创建成功"); Ok(Self { context, renderer, texture_manager, input_manager, config, }) } /// Create a new engine instance from external WebGL context. /// 从外部 WebGL 上下文创建引擎实例。 /// /// This is designed for environments like WeChat MiniGame. /// 适用于微信小游戏等环境。 pub fn from_external( gl_context: JsValue, width: u32, height: u32, config: EngineConfig, ) -> Result { let context = WebGLContext::from_external(gl_context, width, height)?; context.set_viewport(); context.enable_blend(); let renderer = Renderer2D::new(context.gl(), config.max_sprites)?; let texture_manager = TextureManager::new(context.gl().clone()); let input_manager = InputManager::new(); log::info!("Engine created from external context | 从外部上下文创建引擎"); Ok(Self { context, renderer, texture_manager, input_manager, config, }) } /// Clear the screen with specified color. /// 使用指定颜色清除屏幕。 pub fn clear(&self, r: f32, g: f32, b: f32, a: f32) { self.context.clear(r, g, b, a); } /// Get canvas width. /// 获取画布宽度。 #[inline] pub fn width(&self) -> u32 { self.context.width() } /// Get canvas height. /// 获取画布高度。 #[inline] pub fn height(&self) -> u32 { self.context.height() } /// Submit sprite batch data for rendering. /// 提交精灵批次数据进行渲染。 pub fn submit_sprite_batch( &mut self, transforms: &[f32], texture_ids: &[u32], uvs: &[f32], colors: &[u32], ) -> Result<()> { self.renderer.submit_batch( transforms, texture_ids, uvs, colors, &self.texture_manager, ) } /// Render the current frame. /// 渲染当前帧。 pub fn render(&mut self) -> Result<()> { self.renderer.render(self.context.gl()) } /// Load a texture from URL. /// 从URL加载纹理。 pub fn load_texture(&mut self, id: u32, url: &str) -> Result<()> { self.texture_manager.load_texture(id, url) } /// Check if a key is currently pressed. /// 检查某个键是否当前被按下。 pub fn is_key_down(&self, key_code: &str) -> bool { self.input_manager.is_key_down(key_code) } /// Update input state. /// 更新输入状态。 pub fn update_input(&mut self) { self.input_manager.update(); } }