From beb7bfe3e6be55a6de3be5f643b8dee6ef7e6326 Mon Sep 17 00:00:00 2001 From: Alula Date: Tue, 20 Oct 2020 22:45:56 +0200 Subject: [PATCH] some stuff related to touch controls --- Cargo.toml | 2 +- src/lib.rs | 54 +++++++++++++++++++++++---------------- src/shared_game_state.rs | 5 ++++ src/touch_controls.rs | 55 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 src/touch_controls.rs diff --git a/Cargo.toml b/Cargo.toml index 9bb6a67..bc6f015 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ bitflags = "1" bitvec = "0.17.4" byteorder = "1.3" case_insensitive_hashmap = "1.0.0" -cpal = {git = "https://github.com/alula/cpal.git", branch = "android-support"} +cpal = {git = "https://github.com/doukutsu-rs/cpal.git", branch = "android-support"} directories = "2" gfx = "0.18" gfx_core = "0.9" diff --git a/src/lib.rs b/src/lib.rs index ee27b96..2e28c0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,7 +22,7 @@ use winit::event::{ElementState, Event, KeyboardInput, WindowEvent, TouchPhase}; use winit::event_loop::ControlFlow; use crate::builtin_fs::BuiltinFS; -use crate::ggez::{Context, ContextBuilder, filesystem, GameResult}; +use crate::ggez::{Context, ContextBuilder, filesystem, GameResult, GameError}; use crate::ggez::conf::{Backend, WindowMode, WindowSetup}; use crate::ggez::event::{KeyCode, KeyMods}; use crate::ggez::graphics; @@ -34,7 +34,6 @@ use crate::scene::loading_scene::LoadingScene; use crate::scene::Scene; use crate::shared_game_state::{SharedGameState, TimingMode}; use crate::ui::UI; -use crate::ggez::event::winit_event::ModifiersState; mod bmfont; mod bmfont_renderer; @@ -64,6 +63,7 @@ mod stage; mod sound; mod text_script; mod texture_set; +mod touch_controls; mod ui; mod weapon; @@ -128,6 +128,9 @@ impl Game { if let Some(scene) = self.scene.as_mut() { scene.draw(&mut self.state, ctx)?; + if self.state.settings.touch_controls { + self.state.touch_controls.draw(&self.state.constants, &mut self.state.texture_set, ctx)?; + } graphics::set_transform(ctx, self.def_matrix); graphics::apply_transformations(ctx)?; @@ -234,27 +237,34 @@ pub fn android_main() { init().unwrap(); } -fn init_ctx>(event_loop: &winit::event_loop::EventLoopWindowTarget<()>, resource_dir: P) -> GameResult { - let backend = if cfg!(target_os = "android") { - Backend::OpenGLES { major: 2, minor: 0 } - } else { - Backend::OpenGL { major: 3, minor: 2 } - }; +static BACKENDS: [Backend; 4] = [ + Backend::OpenGL {major: 3, minor: 2}, + Backend::OpenGLES { major: 3, minor: 2}, + Backend::OpenGLES { major: 3, minor: 0}, + Backend::OpenGLES { major: 2, minor: 0} +]; - let mut ctx = ContextBuilder::new("doukutsu-rs") - .window_setup(WindowSetup::default().title("Cave Story (doukutsu-rs)")) - .window_mode(WindowMode::default() - .resizable(true) - .min_dimensions(320.0, 240.0) - .dimensions(854.0, 480.0)) - .add_resource_path(resource_dir) - .add_resource_path(path::PathBuf::from(str!("./"))) - .backend(backend) - .build(event_loop)?; +fn init_ctx + Clone>(event_loop: &winit::event_loop::EventLoopWindowTarget<()>, resource_dir: P) -> GameResult { + for backend in BACKENDS.iter() { + let mut ctx = ContextBuilder::new("doukutsu-rs") + .window_setup(WindowSetup::default().title("Cave Story (doukutsu-rs)")) + .window_mode(WindowMode::default() + .resizable(true) + .min_dimensions(320.0, 240.0) + .dimensions(854.0, 480.0)) + .add_resource_path(resource_dir.clone()) + .add_resource_path(path::PathBuf::from(str!("./"))) + .backend(*backend) + .build(event_loop); - ctx.filesystem.mount_vfs(Box::new(BuiltinFS::new())); + if let Ok(mut ctx) = ctx { + ctx.filesystem.mount_vfs(Box::new(BuiltinFS::new())); - Ok(ctx) + return Ok(ctx); + } + } + + Err(GameError::EventLoopError("Failed to initialize OpenGL backend. Perhaps the driver is outdated?".to_string())) } pub fn init() -> GameResult { @@ -345,7 +355,7 @@ pub fn init() -> GameResult { } WindowEvent::Touch(touch) => { if let Some(game) = &mut game { - + game.state.touch_controls.process_winit_event(game.state.scale, &mut game.state.key_state, touch); } } WindowEvent::KeyboardInput { @@ -405,5 +415,5 @@ pub fn init() -> GameResult { } _ => {} } - }); + }) } diff --git a/src/shared_game_state.rs b/src/shared_game_state.rs index 4e93848..bec4b0b 100644 --- a/src/shared_game_state.rs +++ b/src/shared_game_state.rs @@ -19,6 +19,7 @@ use crate::str; use crate::text_script::{TextScriptExecutionState, TextScriptVM, ScriptMode}; use crate::texture_set::TextureSet; use crate::ggez::graphics::Canvas; +use crate::touch_controls::TouchControls; #[derive(PartialEq, Eq, Copy, Clone)] pub enum TimingMode { @@ -43,6 +44,7 @@ pub struct Settings { pub original_textures: bool, pub enhanced_graphics: bool, pub debug_outlines: bool, + pub touch_controls: bool, } pub struct SharedGameState { @@ -57,6 +59,7 @@ pub struct SharedGameState { pub carets: Vec, pub key_state: KeyState, pub key_trigger: KeyState, + pub touch_controls: TouchControls, pub font: BMFontRenderer, pub texture_set: TextureSet, pub base_path: String, @@ -115,6 +118,7 @@ impl SharedGameState { carets: Vec::with_capacity(32), key_state: KeyState(0), key_trigger: KeyState(0), + touch_controls: TouchControls::new(), font, texture_set: TextureSet::new(base_path), base_path: str!(base_path), @@ -127,6 +131,7 @@ impl SharedGameState { original_textures: false, enhanced_graphics: true, debug_outlines: false, + touch_controls: cfg!(target_os = "android") }, constants, new_npcs: Vec::with_capacity(8), diff --git a/src/touch_controls.rs b/src/touch_controls.rs new file mode 100644 index 0000000..46a5acb --- /dev/null +++ b/src/touch_controls.rs @@ -0,0 +1,55 @@ +use winit::event::TouchPhase; +use crate::texture_set::TextureSet; +use crate::ggez::{Context, GameResult}; +use crate::common::{KeyState, Rect}; +use crate::engine_constants::EngineConstants; + +struct TouchPoint { + id: u64, + position: (f64, f64), + last_position: (f64, f64), +} + +pub struct TouchControls { + points: Vec, +} + +impl TouchControls { + pub fn new() -> TouchControls { + TouchControls { + points: Vec::with_capacity(8), + } + } + + pub fn process_winit_event(&mut self, scale: f32, key_state: &mut KeyState, touch: winit::event::Touch) { + match touch.phase { + TouchPhase::Started | TouchPhase::Moved => { + if let Some(point) = self.points.iter_mut().find(|p| p.id == touch.id) { + point.last_position = point.position; + point.position = (touch.location.x, touch.location.y); + } else { + self.points.push(TouchPoint { + id: touch.id, + position: (touch.location.x, touch.location.y), + last_position: (0.0, 0.0) + }); + } + } + TouchPhase::Ended | TouchPhase::Cancelled => { + self.points.retain(|p| p.id != touch.id); + } + } + } + + pub fn draw(&self, constants: &EngineConstants, texture_set: &mut TextureSet, ctx: &mut Context) -> GameResult { + let batch = texture_set.get_or_load_batch(ctx, constants, "Caret")?; + let rect = Rect::new_size(104, 120, 24, 24); + for point in self.points.iter() { + batch.add_rect(point.position.0 as f32 - 12.0, point.position.1 as f32 - 12.0, &rect); + } + + batch.draw(ctx)?; + + Ok(()) + } +}