Work on porting from quicksilver

Can compile at this point, but does not run.
This commit is contained in:
Stephen Seo 2023-02-16 17:53:03 +09:00
parent f14841e27e
commit 751ce637e0
3 changed files with 332 additions and 385 deletions

View file

@ -27,7 +27,7 @@ pub trait ImageInterface {
}
pub trait FontInterface {
fn draw(&mut self, s: &str, size: u32) -> Result<(), String>;
fn draw(&mut self, s: &str, size: u32, x: f32, y: f32, color: Color) -> Result<(), String>;
}
pub trait SoundInterface {
@ -52,6 +52,9 @@ pub trait GameInterface {
fn get_dimensions(&self) -> Result<(f32, f32), String>;
fn get_key_pressed(&mut self, key: char) -> Result<bool, String>;
fn get_mouse_pressed(&mut self) -> Result<Option<(f32, f32)>, String>;
fn get_mouse_down(&mut self) -> Result<Option<(f32, f32)>, String>;
fn get_mouse_xy(&self) -> Result<(f32, f32), String>;
fn get_mouse_xy_vec(&self) -> Result<Vector, String>;
fn get_delta_time(&self) -> f32;
fn clear_window(&mut self, color: Color) -> Result<(), String>;
fn begin_drawing(&mut self) -> Result<(), String>;

View file

@ -143,19 +143,19 @@ impl Vector {
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Transform {
pub mat: [f32; 9],
translate: Vector,
rotate: f32,
//translate: Vector,
//rotate: f32,
}
impl Default for Transform {
fn default() -> Self {
Self {
mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
translate: Vector { x: 0.0, y: 0.0 },
rotate: 0.0,
//translate: Vector { x: 0.0, y: 0.0 },
//rotate: 0.0,
}
}
}
@ -187,14 +187,16 @@ impl Mul<Transform> for Transform {
self.mat[6] * rhs.mat[1] + self.mat[7] * rhs.mat[4] + self.mat[8] * rhs.mat[7],
self.mat[6] * rhs.mat[2] + self.mat[7] * rhs.mat[5] + self.mat[8] * rhs.mat[8],
],
translate: self.translate + rhs.translate,
rotate: self.rotate + rhs.rotate,
//translate: self.translate + rhs.translate,
//rotate: self.rotate + rhs.rotate,
}
}
}
impl Transform {
pub const IDENTITY: Self = Self::default();
pub const IDENTITY: Self = Self {
mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
};
pub fn rotate(rot: f32) -> Self {
Self {
@ -209,7 +211,7 @@ impl Transform {
0.0,
1.0,
],
rotate: rot,
//rotate: rot,
..Default::default()
}
}
@ -217,18 +219,18 @@ impl Transform {
pub fn translate(x: f32, y: f32) -> Self {
Self {
mat: [1.0, 0.0, x, 0.0, 1.0, y, 0.0, 0.0, 1.0],
translate: Vector { x, y },
//translate: Vector { x, y },
..Default::default()
}
}
pub fn get_translate(&self) -> Vector {
self.translate
}
//pub fn get_translate(&self) -> Vector {
// self.translate
//}
pub fn get_rotation(&self) -> f32 {
self.rotate
}
//pub fn get_rotation(&self) -> f32 {
// self.rotate
//}
}
pub struct Window {
@ -290,7 +292,7 @@ impl Window {
.as_ref())
}
pub fn get_image_mut(&self, name: &str) -> Result<&mut dyn ImageInterface, String> {
pub fn get_image_mut(&mut self, name: &str) -> Result<&mut dyn ImageInterface, String> {
Ok(self
.images
.get_mut(name)
@ -306,7 +308,7 @@ impl Window {
.as_ref())
}
pub fn get_font_mut(&self, name: &str) -> Result<&mut dyn FontInterface, String> {
pub fn get_font_mut(&mut self, name: &str) -> Result<&mut dyn FontInterface, String> {
Ok(self
.fonts
.get_mut(name)
@ -322,7 +324,7 @@ impl Window {
.as_ref())
}
pub fn get_sound_mut(&self, name: &str) -> Result<&mut dyn SoundInterface, String> {
pub fn get_sound_mut(&mut self, name: &str) -> Result<&mut dyn SoundInterface, String> {
Ok(self
.sounds
.get_mut(name)
@ -338,7 +340,7 @@ impl Window {
.as_ref())
}
pub fn get_music_mut(&self, name: &str) -> Result<&mut dyn MusicInterface, String> {
pub fn get_music_mut(&mut self, name: &str) -> Result<&mut dyn MusicInterface, String> {
Ok(self
.music
.get_mut(name)
@ -346,7 +348,3 @@ impl Window {
.as_mut())
}
}
pub struct Key {}
pub struct Event {}

View file

@ -18,7 +18,7 @@ use serde::{Deserialize, Serialize};
mod agnostic_interface;
mod faux_quicksilver;
use faux_quicksilver::{Circle, Color, Event, Key, Rectangle, Transform, Vector, Window};
use faux_quicksilver::{Circle, Color, Rectangle, Transform, Vector, Window};
const WIDTH_F: f32 = 800.0;
const HEIGHT_F: f32 = 600.0;
@ -57,14 +57,12 @@ fn interp_sq(x: f32) -> f32 {
enum MenuItemType {
Button {
text: &'static str,
text_image: Option<String>,
text_c: Color,
h_c: Color,
c: Color,
},
AppearingText {
text: &'static str,
text_image: Option<String>,
current_text: String,
text_size: f32,
text_c: Color,
@ -72,7 +70,6 @@ enum MenuItemType {
},
InstantText {
text: &'static str,
text_image: Option<String>,
text_size: f32,
text_color: Color,
},
@ -122,7 +119,6 @@ impl Menu {
h,
item_type: MenuItemType::Button {
text: s,
text_image: None,
text_c: t_color,
h_c: boxh_color,
c: box_color,
@ -141,7 +137,6 @@ impl Menu {
h: 150.0,
item_type: MenuItemType::Button {
text: "Start the Game",
text_image: None,
text_c: Color::WHITE,
h_c: Color::from_rgba(0x66, 0xFF, 0xFF, 255),
c: Color::from_rgba(0x33, 0xDD, 0xDD, 255),
@ -194,7 +189,6 @@ impl Menu {
h: 0.0,
item_type: MenuItemType::InstantText {
text: s,
text_image: None,
text_size,
text_color: Color::WHITE,
},
@ -212,7 +206,6 @@ impl Menu {
h: 0.0,
item_type: MenuItemType::AppearingText {
text: s,
text_image: None,
text_size,
current_text: String::new(),
text_c: Color::WHITE,
@ -1011,7 +1004,7 @@ impl Star {
fn draw(&mut self, image: &str, window: &mut Window, transform: Transform) {
self.particle_system.draw(window, transform);
let image = window.get_image(image).expect("Should be loaded image");
let image = window.get_image_mut(image).expect("Should be loaded image");
let mut image_rect = image.get_wh_rect();
image_rect.x = self.particle_system.host_circle.x - image_rect.w / 2.0;
image_rect.y = self.particle_system.host_circle.y - image_rect.h / 2.0;
@ -1115,7 +1108,7 @@ impl Fish {
fn draw(&mut self, i_fish: &str, window: &mut Window, transform: Transform) {
let fish_img = window
.get_image(i_fish)
.get_image_mut(i_fish)
.expect("\"fish\" Image should be loaded");
let anim_angle = ((self.anim_timer / self.anim_time) * std::f32::consts::PI * 2.0).sin();
let mut body_rect = self.body_rect;
@ -1269,7 +1262,7 @@ impl GameState {
i_fish.clone(),
)?;
let camera = window.get_gi_mut().get_default_camera()?;
let mut camera = window.get_gi_mut().get_default_camera()?;
camera.set_view(Rectangle {
x: 0.0,
y: 0.0,
@ -1337,13 +1330,15 @@ impl GameState {
})
}
fn event(&mut self, event: &Event, window: &mut Window) -> Result<(), String> {
match event {
Event::MouseMoved(v) => {
self.mouse_pos = *v;
fn update(&mut self, window: &mut Window) -> Result<(), String> {
let dt = window.get_gi().get_delta_time();
// check mouse pos
{
self.mouse_pos = window.get_gi().get_mouse_xy_vec()?;
let mut hovered = false;
for i in 0..self.menu.items.len() {
if self.menu.items[i].is_inside(v.x, v.y) {
if self.menu.items[i].is_inside(self.mouse_pos.x, self.mouse_pos.y) {
self.menu.items[i].is_hover = true;
self.current_item = Some(i);
hovered = true;
@ -1355,12 +1350,13 @@ impl GameState {
self.current_item = None;
}
}
Event::MouseButton(button, state) => {
if let ButtonState::Released = state {
// check mouse down
if window.get_gi_mut().get_mouse_down()?.is_none() {
if self.dbl_click_timeout.is_none() {
self.click_release_time = 0.0;
}
} else if let ButtonState::Pressed = state {
} else {
if self.current_finished {
if self.is_create_mode {
if self.click_release_time < DOUBLE_CLICK_TIME {
@ -1378,10 +1374,7 @@ impl GameState {
self.expl_conv_p_systems.push(expl_conv_system);
self.state = 9;
self.state_dirty = true;
self.s_boom.execute(|s| {
s.set_volume(0.8);
s.play()
})?;
window.get_sound_mut(&self.s_boom)?.play(0.8)?;
} else if self.state == 10 {
let mut rng = rand::thread_rng();
let rand_out = rng.gen_range(0.0, 1.0);
@ -1402,10 +1395,8 @@ impl GameState {
),
1.0,
);
expl_conv_system.activate(
rng.gen_range(13, 40),
rng.gen_range(150.0, 300.0),
);
expl_conv_system
.activate(rng.gen_range(13, 40), rng.gen_range(150.0, 300.0));
self.expl_conv_p_systems.push(expl_conv_system);
} else if rand_out < 0.85 {
// spawn star
@ -1444,10 +1435,7 @@ impl GameState {
));
}
}
self.s_boom.execute(|s| {
s.set_volume(0.8);
s.play()
})?;
window.get_sound_mut(&self.s_boom)?.play(0.8)?;
}
} else if self.state == 10 {
self.click_time = Some(0.0);
@ -1486,10 +1474,7 @@ impl GameState {
self.joining_particles.particle_system.color =
Color::from_rgba(0xFF, 0xAA, 0xAA, 255);
}
self.s_get.execute(|s| {
s.set_volume(0.7);
s.play()
})?;
window.get_sound_mut(&self.s_get)?.play(0.7)?;
}
_ => {
self.state = 0;
@ -1512,60 +1497,36 @@ impl GameState {
match &mut mi.item_type {
MenuItemType::AppearingText {
text,
text_image,
current_text,
text_size,
text_c,
timer,
} => {
self.font.execute(|f| {
*current_text = text.to_string();
let style = FontStyle::new(*text_size, *text_c);
*text_image = Some(f.render(text, &style)?);
Ok(())
})?;
}
MenuItemType::Button {
text,
text_image,
text_c,
h_c,
c,
} => {
if text_image.is_none() {
self.font.execute(|font| {
let style = FontStyle::new(42.0, *text_c);
*text_image = Some(font.render(text, &style)?);
Ok(())
})?;
}
//let style = FontStyle::new(42.0, *text_c);
}
MenuItemType::Pause { timer, length } => (),
MenuItemType::InstantText {
text,
text_image,
text_size,
text_color,
} => {
if text_image.is_none() {
self.font.execute(|f| {
let style = FontStyle::new(*text_size, *text_color);
*text_image = Some(f.render(text, &style)?);
Ok(())
})?;
}
}
} => {}
}
mi.is_loaded = true;
}
self.current_finished = true;
}
}
}
Event::Key(key, state) => {
if let ButtonState::Pressed = state {
match key {
Key::S => {
// check pressed keys
if window.get_gi_mut().get_key_pressed('s')? {
if self.state == 10 {
let save_data = SaveData {
planets: self.planets.clone(),
@ -1574,59 +1535,48 @@ impl GameState {
player: self.player.clone(),
joining_particles: self.joining_particles.clone(),
};
save("OneAndAll_LD45", "slot0", &save_data)?;
// TODO
//save("OneAndAll_LD45", "slot0", &save_data)?;
self.save_load_notification = Some(SaveLoadNotification::Save {
text: None,
timer: SL_NOTIF_TIME,
});
}
}
Key::L => {
let load_result = load::<SaveData>("OneAndAll_LD45", "slot0");
if let Ok(save_data) = load_result {
self.planets = save_data.planets;
self.stars = save_data.stars;
self.fishes = save_data.fishes;
self.player = save_data.player;
self.joining_particles = save_data.joining_particles;
self.expl_conv_p_systems.clear();
self.move_to = Vector {
x: self.player.x,
y: self.player.y,
};
self.camera.set_view_xy(
self.player.x - WIDTH_F / 2.0,
self.player.y - HEIGHT_F / 2.0,
);
self.dbl_click_timeout = None;
self.click_time = None;
self.click_release_time = DOUBLE_CLICK_TIME;
} else if window.get_gi_mut().get_key_pressed('l')? {
// TODO
//let load_result = load::<SaveData>("OneAndAll_LD45", "slot0");
//if let Ok(save_data) = load_result {
// self.planets = save_data.planets;
// self.stars = save_data.stars;
// self.fishes = save_data.fishes;
// self.player = save_data.player;
// self.joining_particles = save_data.joining_particles;
// self.expl_conv_p_systems.clear();
// self.move_to = Vector {
// x: self.player.x,
// y: self.player.y,
// };
// self.camera.set_view_xy(
// self.player.x - WIDTH_F / 2.0,
// self.player.y - HEIGHT_F / 2.0,
// );
// self.dbl_click_timeout = None;
// self.click_time = None;
// self.click_release_time = DOUBLE_CLICK_TIME;
self.state = 10;
self.state_dirty = true;
self.save_load_notification = Some(SaveLoadNotification::Load {
text: None,
timer: SL_NOTIF_TIME,
});
}
}
Key::R => {
// self.state = 10;
// self.state_dirty = true;
// self.save_load_notification = Some(SaveLoadNotification::Load {
// text: None,
// timer: SL_NOTIF_TIME,
// });
//}
} else if window.get_gi_mut().get_key_pressed('r')? {
if self.state == 10 {
self.state = 0;
self.state_dirty = true;
}
}
_ => (),
}
}
}
_ => (),
}
Ok(())
}
fn update(&mut self, window: &mut Window) -> Result<(), String> {
let dt = window.get_gi().get_delta_time();
self.click_release_time += dt;
if let Some(t) = &mut self.click_time {
@ -1663,7 +1613,7 @@ impl GameState {
if self.state_dirty {
self.state_dirty = false;
if self.state > 1 && !self.music_on {
let music = window.get_music(&self.music2)?;
let music = window.get_music_mut(&self.music2)?;
music.set_loop(true)?;
music.play(0.5)?;
self.music_on = true;
@ -1763,7 +1713,7 @@ impl GameState {
if self.music_on {
} else if self.state == 10 {
let mut music_on = false;
let music = window.get_music(&self.music2)?;
let music = window.get_music_mut(&self.music2)?;
music.set_loop(true)?;
music.play(0.5)?;
self.music_on = true;
@ -1775,28 +1725,26 @@ impl GameState {
match &mut mi.item_type {
MenuItemType::Button {
text,
text_image,
text_c,
h_c,
c,
} => {
self.font.execute(|font| {
let style = FontStyle::new(42.0, *text_c);
*text_image = Some(font.render(text, &style)?);
Ok(())
})?;
if text_image.is_some() {
//self.font.execute(|font| {
// let style = FontStyle::new(42.0, *text_c);
// *text_image = Some(font.render(text, &style)?);
// Ok(())
//})?;
//if text_image.is_some() {
mi.is_loaded = true;
if i + 1 < self.menu.items.len() {
self.menu.items[i + 1].is_loaded = false;
} else {
self.current_finished = true;
}
}
//}
}
MenuItemType::AppearingText {
text,
text_image,
current_text,
text_size,
text_c,
@ -1808,10 +1756,7 @@ impl GameState {
let next = text.chars().nth(current_text.len());
if let Some(next_t) = next {
current_text.push(next_t);
self.s_tap.execute(|s| {
s.set_volume(0.2);
s.play()
})?;
window.get_sound_mut(&self.s_tap)?.play(0.2)?;
} else {
mi.is_loaded = true;
if i + 1 < self.menu.items.len() {
@ -1821,11 +1766,11 @@ impl GameState {
}
continue;
}
self.font.execute(|font| {
let style = FontStyle::new(*text_size, *text_c);
*text_image = Some(font.render(current_text, &style)?);
Ok(())
})?;
//self.font.execute(|font| {
// let style = FontStyle::new(*text_size, *text_c);
// *text_image = Some(font.render(current_text, &style)?);
// Ok(())
//})?;
}
}
MenuItemType::Pause { timer, length } => {
@ -1841,25 +1786,24 @@ impl GameState {
}
MenuItemType::InstantText {
text,
text_image,
text_size,
text_color,
} => {
if text_image.is_none() {
self.font.execute(|f| {
let style = FontStyle::new(*text_size, *text_color);
*text_image = Some(f.render(text, &style)?);
Ok(())
})?;
}
if text_image.is_some() {
//if text_image.is_none() {
// self.font.execute(|f| {
// let style = FontStyle::new(*text_size, *text_color);
// *text_image = Some(f.render(text, &style)?);
// Ok(())
// })?;
//}
//if text_image.is_some() {
mi.is_loaded = true;
if i + 1 < self.menu.items.len() {
self.menu.items[i + 1].is_loaded = false;
} else {
self.current_finished = true;
}
}
//}
}
}
}
@ -1888,12 +1832,12 @@ impl GameState {
if *timer <= 0.0 {
self.save_load_notification = None;
} else if text.is_none() {
self.font.execute(|f| {
*text = Some(
f.render("Saved the Game", &FontStyle::new(45.0, Color::WHITE))?,
);
Ok(())
})?;
//self.font.execute(|f| {
// *text = Some(
// f.render("Saved the Game", &FontStyle::new(45.0, Color::WHITE))?,
// );
// Ok(())
//})?;
}
}
SaveLoadNotification::Load { text, timer } => {
@ -1901,12 +1845,12 @@ impl GameState {
if *timer <= 0.0 {
self.save_load_notification = None;
} else if text.is_none() {
self.font.execute(|f| {
*text = Some(
f.render("Loaded the Game", &FontStyle::new(45.0, Color::WHITE))?,
);
Ok(())
})?;
//self.font.execute(|f| {
// *text = Some(
// f.render("Loaded the Game", &FontStyle::new(45.0, Color::WHITE))?,
// );
// Ok(())
//})?;
}
}
}
@ -1930,7 +1874,6 @@ impl GameState {
match &mut mi.item_type {
MenuItemType::Button {
text,
text_image,
text_c,
h_c,
c,
@ -1940,38 +1883,41 @@ impl GameState {
} else {
window.get_gi_mut().draw_rect(rect, *c)?;
}
if let Some(i) = text_image {
let image = window.get_image_mut(&i)?;
let mut image_rect = image.get_wh_rect();
image_rect.x = mi.x + (mi.w - image_rect.w) / 2.0;
image_rect.y = mi.y + (mi.h - image_rect.h) / 2.0;
image.draw(image_rect.x, image_rect.y, Color::WHITE)?;
}
window.get_font_mut(&self.font)?.draw(
text,
rect.h.round() as u32,
rect.x,
rect.y,
*text_c,
)?;
}
MenuItemType::AppearingText {
text,
text_image,
current_text,
text_size,
text_c,
timer,
} => {
if let Some(i) = text_image {
let image = window.get_image_mut(&i)?;
image.draw(mi.x, mi.y, Color::WHITE)?;
}
window.get_font_mut(&self.font)?.draw(
text,
text_size.round() as u32,
rect.x,
rect.y,
*text_c,
)?;
}
MenuItemType::InstantText {
text,
text_image,
text_size,
text_color,
} => {
if let Some(i) = text_image {
let image = window.get_image_mut(&i)?;
let mut image_rect = image.get_wh_rect();
image.draw(mi.x, mi.y, Color::WHITE)?;
}
window.get_font_mut(&self.font)?.draw(
text,
text_size.round() as u32,
rect.x,
rect.y,
*text_color,
)?;
}
MenuItemType::Pause { timer, length } => (),
}