Work on porting from quicksilver

This commit is contained in:
Stephen Seo 2023-02-15 15:52:25 +09:00
parent 996e568b50
commit 71fc3de042
3 changed files with 247 additions and 179 deletions

View file

@ -3,7 +3,24 @@ use std::path::Path;
use crate::faux_quicksilver::{Circle, Color, Rectangle, Transform, Vector}; use crate::faux_quicksilver::{Circle, Color, Rectangle, Transform, Vector};
pub trait ImageInterface { pub trait ImageInterface {
fn draw(&mut self, x: f32, y: f32) -> Result<(), String>; fn draw(&mut self, x: f32, y: f32, color: Color) -> Result<(), String>;
fn draw_sub(&mut self, sub_rect: Rectangle, x: f32, y: f32, color: Color)
-> Result<(), String>;
fn draw_transform(
&mut self,
x: f32,
y: f32,
color: Color,
transform: Transform,
) -> Result<(), String>;
fn draw_sub_transform(
&mut self,
sub_rect: Rectangle,
x: f32,
y: f32,
color: Color,
transform: Transform,
) -> Result<(), String>;
fn get_w(&self) -> usize; fn get_w(&self) -> usize;
fn get_h(&self) -> usize; fn get_h(&self) -> usize;
fn get_wh_rect(&self) -> Rectangle; fn get_wh_rect(&self) -> Rectangle;
@ -21,12 +38,21 @@ pub trait MusicInterface {
fn play(&mut self, vol: f32) -> Result<(), String>; fn play(&mut self, vol: f32) -> Result<(), String>;
fn pause(&mut self) -> Result<(), String>; fn pause(&mut self) -> Result<(), String>;
fn stop(&mut self) -> Result<(), String>; fn stop(&mut self) -> Result<(), String>;
fn set_loop(&mut self, loop_enable: bool) -> Result<(), String>;
}
pub trait CameraInterface {
fn get_view(&self) -> Result<Rectangle, String>;
fn get_view_xy(&self) -> Result<(f32, f32), String>;
fn set_view(&mut self, rect: Rectangle) -> Result<(), String>;
fn set_view_xy(&mut self, x: f32, y: f32) -> Result<(), String>;
} }
pub trait GameInterface { pub trait GameInterface {
fn get_dimensions(&self) -> Result<(f32, f32), String>; fn get_dimensions(&self) -> Result<(f32, f32), String>;
fn get_key_pressed(&mut self, key: char) -> Result<bool, 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_pressed(&mut self) -> Result<Option<(f32, f32)>, String>;
fn get_delta_time(&self) -> f32;
fn clear_window(&mut self, color: Color) -> Result<(), String>; fn clear_window(&mut self, color: Color) -> Result<(), String>;
fn begin_drawing(&mut self) -> Result<(), String>; fn begin_drawing(&mut self) -> Result<(), String>;
fn end_drawing(&mut self) -> Result<(), String>; fn end_drawing(&mut self) -> Result<(), String>;
@ -64,4 +90,8 @@ pub trait GameInterface {
fn load_font(&mut self, path: &Path) -> Result<Box<dyn FontInterface>, String>; fn load_font(&mut self, path: &Path) -> Result<Box<dyn FontInterface>, String>;
fn load_sound(&mut self, path: &Path) -> Result<Box<dyn SoundInterface>, String>; fn load_sound(&mut self, path: &Path) -> Result<Box<dyn SoundInterface>, String>;
fn load_music(&mut self, path: &Path) -> Result<Box<dyn MusicInterface>, String>; fn load_music(&mut self, path: &Path) -> Result<Box<dyn MusicInterface>, String>;
fn get_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
fn get_default_camera(&mut self) -> Result<Box<dyn CameraInterface>, String>;
fn set_camera(&mut self, camera: &Box<dyn CameraInterface>) -> Result<(), String>;
} }

View file

@ -200,9 +200,9 @@ impl Transform {
Self { Self {
mat: [ mat: [
rot.cos(), rot.cos(),
rot.sin(),
0.0,
-rot.sin(), -rot.sin(),
0.0,
rot.sin(),
rot.cos(), rot.cos(),
0.0, 0.0,
0.0, 0.0,
@ -231,8 +231,6 @@ impl Transform {
} }
} }
pub struct View {}
pub struct Window { pub struct Window {
gi: Box<dyn GameInterface>, gi: Box<dyn GameInterface>,
images: HashMap<String, Box<dyn ImageInterface>>, images: HashMap<String, Box<dyn ImageInterface>>,

View file

@ -1,3 +1,6 @@
use std::{path::PathBuf, str::FromStr};
use agnostic_interface::CameraInterface;
//use quicksilver::{ //use quicksilver::{
// geom::{Circle, Rectangle, Transform, Vector}, // geom::{Circle, Rectangle, Transform, Vector},
// graphics::{ // graphics::{
@ -15,21 +18,21 @@ use serde::{Deserialize, Serialize};
mod agnostic_interface; mod agnostic_interface;
mod faux_quicksilver; mod faux_quicksilver;
use faux_quicksilver::{Circle, Color, Event, Key, Rectangle, Transform, Vector, View, Window}; use faux_quicksilver::{Circle, Color, Event, Key, Rectangle, Transform, Vector, Window};
const WIDTH_F: f32 = 800.0; const WIDTH_F: f32 = 800.0;
const HEIGHT_F: f32 = 600.0; const HEIGHT_F: f32 = 600.0;
const MUSIC2_LENGTH: f64 = 2.0 * 60.0 * 1000.0; const MUSIC2_LENGTH: f32 = 2.0 * 60.0 * 1000.0;
const TEXT_RATE: f64 = 100.0; const TEXT_RATE: f32 = 100.0;
const PP_GEN_RATE: f64 = 75.0; const PP_GEN_RATE: f32 = 75.0;
const PARTICLE_RAND_VEL_RANGE: f32 = 0.2; const PARTICLE_RAND_VEL_RANGE: f32 = 0.2;
const PARTICLE_RAND_VEL_DIST: f32 = 0.2828427; // dist where x and y = 0.2 const PARTICLE_RAND_VEL_DIST: f32 = 0.2828427; // dist where x and y = 0.2
const PARTICLE_RAND_ROT_RANGE: f32 = 0.5; const PARTICLE_RAND_ROT_RANGE: f32 = 0.5;
const JOINING_OPACITY_RATE: f32 = 0.00013; const JOINING_OPACITY_RATE: f32 = 0.00013;
const JOINING_FAR_DIST: f32 = 700.0; const JOINING_FAR_DIST: f32 = 700.0;
const JOINING_NEAR_DIST: f32 = 150.0; const JOINING_NEAR_DIST: f32 = 150.0;
const DOUBLE_CLICK_TIME: f64 = 350.0; const DOUBLE_CLICK_TIME: f32 = 350.0;
const SL_NOTIF_TIME: f64 = 5000.0; const SL_NOTIF_TIME: f32 = 5000.0;
const MAX_MOONS: usize = 5; const MAX_MOONS: usize = 5;
fn interp_sq_inv(x: f32) -> f32 { fn interp_sq_inv(x: f32) -> f32 {
@ -65,7 +68,7 @@ enum MenuItemType {
current_text: String, current_text: String,
text_size: f32, text_size: f32,
text_c: Color, text_c: Color,
timer: f64, timer: f32,
}, },
InstantText { InstantText {
text: &'static str, text: &'static str,
@ -74,8 +77,8 @@ enum MenuItemType {
text_color: Color, text_color: Color,
}, },
Pause { Pause {
timer: f64, timer: f32,
length: f64, length: f32,
}, },
} }
@ -221,7 +224,7 @@ impl Menu {
} }
} }
fn pause(length: f64, first: bool) -> MenuItem { fn pause(length: f32, first: bool) -> MenuItem {
MenuItem { MenuItem {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
@ -558,16 +561,16 @@ struct Particle {
vely: f32, vely: f32,
velr: f32, velr: f32,
r: f32, r: f32,
lifetime: f64, lifetime: f32,
life_timer: f64, life_timer: f32,
} }
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
struct ParticleSystem { struct ParticleSystem {
particles: Vec<Particle>, particles: Vec<Particle>,
spawn_timer: f64, spawn_timer: f32,
spawn_time: f64, spawn_time: f32,
lifetime: f64, lifetime: f32,
host_rect: Rectangle, host_rect: Rectangle,
host_circle: Circle, host_circle: Circle,
is_rect: bool, is_rect: bool,
@ -579,8 +582,8 @@ struct ParticleSystem {
impl ParticleSystem { impl ParticleSystem {
fn new( fn new(
spawn_time: f64, spawn_time: f32,
lifetime: f64, lifetime: f32,
host_rect: Rectangle, host_rect: Rectangle,
host_circle: Circle, host_circle: Circle,
is_rect: bool, is_rect: bool,
@ -604,7 +607,7 @@ impl ParticleSystem {
} }
} }
fn update(&mut self, dt: f64) { fn update(&mut self, dt: f32) {
for i in (0..self.particles.len()).rev() { for i in (0..self.particles.len()).rev() {
self.particles[i].life_timer += dt; self.particles[i].life_timer += dt;
if self.particles[i].life_timer > self.particles[i].lifetime { if self.particles[i].life_timer > self.particles[i].lifetime {
@ -710,8 +713,8 @@ struct RotatingParticleSystem {
impl RotatingParticleSystem { impl RotatingParticleSystem {
fn new( fn new(
spawn_time: f64, spawn_time: f32,
lifetime: f64, lifetime: f32,
host_rect: Rectangle, host_rect: Rectangle,
host_circle: Circle, host_circle: Circle,
is_rect: bool, is_rect: bool,
@ -741,7 +744,7 @@ impl RotatingParticleSystem {
} }
} }
fn update(&mut self, dt: f64) { fn update(&mut self, dt: f32) {
if self.particle_system.is_rect { if self.particle_system.is_rect {
let saved_rect = self.particle_system.host_rect; let saved_rect = self.particle_system.host_rect;
self.particle_system self.particle_system
@ -803,15 +806,15 @@ struct ExplConvCircleParticle {
struct ExplConvParticleSystem { struct ExplConvParticleSystem {
particles: Vec<ExplConvCircleParticle>, particles: Vec<ExplConvCircleParticle>,
lifetime: f64, lifetime: f32,
host_circle: Circle, host_circle: Circle,
color: Color, color: Color,
opacity: f32, opacity: f32,
life_timer: f64, life_timer: f32,
} }
impl ExplConvParticleSystem { impl ExplConvParticleSystem {
fn new(lifetime: f64, host_circle: Circle, color: Color, opacity: f32) -> Self { fn new(lifetime: f32, host_circle: Circle, color: Color, opacity: f32) -> Self {
ExplConvParticleSystem { ExplConvParticleSystem {
particles: Vec::new(), particles: Vec::new(),
lifetime, lifetime,
@ -834,7 +837,7 @@ impl ExplConvParticleSystem {
} }
// returns true if finished // returns true if finished
fn update(&mut self, dt: f64, planets: &mut Vec<Planet>) -> bool { fn update(&mut self, dt: f32, planets: &mut Vec<Planet>) -> bool {
self.life_timer += dt; self.life_timer += dt;
if self.life_timer >= self.lifetime { if self.life_timer >= self.lifetime {
if !self.particles.is_empty() { if !self.particles.is_empty() {
@ -873,7 +876,10 @@ impl ExplConvParticleSystem {
self.color.a = (((self.life_timer / self.lifetime) as f32 / 2.0 + 0.5) self.color.a = (((self.life_timer / self.lifetime) as f32 / 2.0 + 0.5)
* self.opacity * self.opacity
* 255.0) as u8; * 255.0) as u8;
window.draw_ex(&particle.circle, Col(self.color), transform, 1); window
.get_gi_mut()
.draw_circle_transform(particle.circle, self.color, transform)
.ok();
} }
} }
} }
@ -933,7 +939,7 @@ impl Planet {
planet planet
} }
fn update(&mut self, dt: f64) { fn update(&mut self, dt: f32) {
self.particle_system.host_circle.x = self.circle.x; self.particle_system.host_circle.x = self.circle.x;
self.particle_system.host_circle.y = self.circle.y; self.particle_system.host_circle.y = self.circle.y;
self.particle_system.update(dt); self.particle_system.update(dt);
@ -946,7 +952,10 @@ impl Planet {
fn draw(&mut self, window: &mut Window, transform: Transform) { fn draw(&mut self, window: &mut Window, transform: Transform) {
self.particle_system.draw(window, transform); self.particle_system.draw(window, transform);
window.draw_ex(&self.circle, Col(self.color), transform, 1); window
.get_gi_mut()
.draw_circle_transform(self.circle, self.color, transform)
.ok();
for moon in &mut self.moons { for moon in &mut self.moons {
moon.draw(window, transform); moon.draw(window, transform);
} }
@ -995,22 +1004,25 @@ impl Star {
star star
} }
fn update(&mut self, dt: f64) { fn update(&mut self, dt: f32) {
self.particle_system.update(dt); self.particle_system.update(dt);
self.r += self.velr * dt as f32; self.r += self.velr * dt as f32;
} }
fn draw(&mut self, image: &mut String, window: &mut Window, transform: Transform) { fn draw(&mut self, image: &str, window: &mut Window, transform: Transform) {
self.particle_system.draw(window, transform); self.particle_system.draw(window, transform);
let mut image_rect = image.area_rect(); let image = window.get_image(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.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; image_rect.y = self.particle_system.host_circle.y - image_rect.h / 2.0;
window.draw_ex( image
&image_rect, .draw_transform(
Blended(image, self.color), image_rect.x,
transform * Transform::rotate(self.r), image_rect.y,
1, self.color,
); transform * Transform::rotate(self.r),
)
.ok();
} }
} }
@ -1018,12 +1030,14 @@ impl Star {
struct Fish { struct Fish {
pos: Vector, pos: Vector,
r: f32, r: f32,
swim_time: f64, swim_time: f32,
swim_timer: f64, swim_timer: f32,
swim_v: f32, swim_v: f32,
anim_timer: f64, anim_timer: f32,
anim_time: f64, anim_time: f32,
color: Color, color: Color,
body_rect: Rectangle,
tail_rect: Rectangle,
} }
enum FishState { enum FishState {
@ -1043,6 +1057,18 @@ impl Fish {
anim_timer, anim_timer,
anim_time: anim_timer, anim_time: anim_timer,
color, color,
body_rect: Rectangle {
x: 0.0,
y: 0.0,
w: 32.0,
h: 16.0,
},
tail_rect: Rectangle {
x: 32.0,
y: 0.0,
w: 16.0,
h: 16.0,
},
} }
} }
@ -1066,7 +1092,7 @@ impl Fish {
} }
} }
fn update(&mut self, dt: f64) { fn update(&mut self, dt: f32) {
self.swim_time -= dt; self.swim_time -= dt;
if self.swim_time < 220.0 { if self.swim_time < 220.0 {
self.swim_v /= 1.1; self.swim_v /= 1.1;
@ -1087,41 +1113,40 @@ impl Fish {
self.pos += Transform::rotate(self.r) * Vector::new(self.swim_v, 0.0) * dt as f32; self.pos += Transform::rotate(self.r) * Vector::new(self.swim_v, 0.0) * dt as f32;
} }
fn draw( fn draw(&mut self, i_fish: &str, window: &mut Window, transform: Transform) {
&mut self, let fish_img = window
fish_body: &String, .get_image(i_fish)
fish_tail: &String, .expect("\"fish\" Image should be loaded");
window: &mut Window, let anim_angle = ((self.anim_timer / self.anim_time) * std::f32::consts::PI * 2.0).sin();
transform: Transform, let mut body_rect = self.body_rect;
) {
let anim_angle = ((self.anim_timer / self.anim_time) * std::f64::consts::PI * 2.0).sin();
let mut body_rect = fish_body.area_rect();
body_rect.x = self.pos.x - body_rect.w / 2.0; body_rect.x = self.pos.x - body_rect.w / 2.0;
body_rect.y = self.pos.y - body_rect.h / 2.0; body_rect.y = self.pos.y - body_rect.h / 2.0;
let body_tr = let body_tr =
Transform::rotate(anim_angle as f32 * 30.0) * Transform::rotate(self.r + 180.0); Transform::rotate(anim_angle as f32 * 30.0) * Transform::rotate(self.r + 180.0);
window.draw_ex( fish_img.draw_sub_transform(
&body_rect, self.body_rect,
Blended(fish_body, self.color), body_rect.x,
body_rect.y,
self.color,
transform * body_tr, transform * body_tr,
1,
); );
let mut tail_rect = fish_tail.area_rect(); let mut tail_rect = self.tail_rect;
tail_rect.x = self.pos.x - tail_rect.w / 2.0; tail_rect.x = self.pos.x - tail_rect.w / 2.0;
tail_rect.y = self.pos.y - tail_rect.h / 2.0; tail_rect.y = self.pos.y - tail_rect.h / 2.0;
let anim_angle = ((self.anim_timer / self.anim_time) * std::f64::consts::PI * 2.0 let anim_angle = ((self.anim_timer / self.anim_time) * std::f32::consts::PI * 2.0
- std::f64::consts::PI / 3.0) - std::f32::consts::PI / 3.0)
.sin(); .sin();
let tail_tr = body_tr let tail_tr = body_tr
* Transform::translate(body_rect.x / 1.5, 0.0) * Transform::translate(body_rect.x / 1.5, 0.0)
* Transform::translate(-tail_rect.x / 2.0, 0.0) * Transform::translate(-tail_rect.x / 2.0, 0.0)
* Transform::rotate(-anim_angle as f32 * 45.0) * Transform::rotate(-anim_angle as f32 * 45.0)
* Transform::translate(tail_rect.x / 2.0, 0.0); * Transform::translate(tail_rect.x / 2.0, 0.0);
window.draw_ex( fish_img.draw_sub_transform(
&tail_rect, self.tail_rect,
Blended(fish_tail, self.color), tail_rect.x,
tail_rect.y,
self.color,
transform * tail_tr, transform * tail_tr,
1,
); );
} }
} }
@ -1136,26 +1161,22 @@ struct SaveData {
} }
enum SaveLoadNotification { enum SaveLoadNotification {
Save { text: Option<String>, timer: f64 }, Save { text: Option<String>, timer: f32 },
Load { text: Option<String>, timer: f64 }, Load { text: Option<String>, timer: f32 },
} }
struct GameState { struct GameState {
s_boom: Sound, s_boom: String,
s_get: Sound, s_get: String,
s_power_up: Sound, s_power_up: String,
s_tap: Sound, s_tap: String,
s_speak_m: Sound, s_speak_m: String,
s_speak_f: Sound, s_speak_f: String,
font: Font, font: String,
music2: Sound, music2: String,
i_star: Option<String>, i_star: String,
i_star_actual: Option<String>,
i_fish: String, i_fish: String,
i_fish_body: Option<String>,
i_fish_tail: Option<String>,
music_on: bool, music_on: bool,
music_timer: f64,
menu: Menu, menu: Menu,
state: u32, state: u32,
state_dirty: bool, state_dirty: bool,
@ -1163,42 +1184,110 @@ struct GameState {
current_item: Option<usize>, current_item: Option<usize>,
current_finished: bool, current_finished: bool,
player: Rectangle, player: Rectangle,
player_r: f64, player_r: f32,
player_particles: ParticleSystem, player_particles: ParticleSystem,
joining_particles: RotatingParticleSystem, joining_particles: RotatingParticleSystem,
is_create_mode: bool, is_create_mode: bool,
click_release_time: f64, click_release_time: f32,
dbl_click_timeout: Option<f64>, dbl_click_timeout: Option<f32>,
click_time: Option<f64>, click_time: Option<f32>,
click_pos: Vector, click_pos: Vector,
mouse_pos: Vector, mouse_pos: Vector,
expl_conv_p_systems: Vec<ExplConvParticleSystem>, expl_conv_p_systems: Vec<ExplConvParticleSystem>,
planets: Vec<Planet>, planets: Vec<Planet>,
stars: Vec<Star>, stars: Vec<Star>,
fishes: Vec<Fish>, fishes: Vec<Fish>,
camera: Rectangle, camera: Box<dyn CameraInterface>,
move_to: Vector, move_to: Vector,
save_load_notification: Option<SaveLoadNotification>, save_load_notification: Option<SaveLoadNotification>,
} }
impl GameState { impl GameState {
fn new() -> Result<Self, String> { fn new(window: &mut Window) -> Result<Self, String> {
let s_boom = String::from("boom.mp3");
window.load_sound(
&PathBuf::from_str("static/boom.mp3")
.map_err(|_| String::from("Failed to load \"static/boom.mp3\""))?,
s_boom.clone(),
)?;
let s_get = String::from("get.mp3");
window.load_sound(
&PathBuf::from_str("static/get.mp3")
.map_err(|_| String::from("Failed to load \"static/get.mp3\""))?,
s_get.clone(),
)?;
let s_power_up = String::from("power_up.mp3");
window.load_sound(
&PathBuf::from_str("static/power_up.mp3")
.map_err(|_| String::from("Failed to load \"static/power_up.mp3\""))?,
s_power_up.clone(),
)?;
let s_tap = String::from("tap.mp3");
window.load_sound(
&PathBuf::from_str("static/tap.mp3")
.map_err(|_| String::from("Failed to load \"static/tap.mp3\""))?,
s_tap.clone(),
)?;
let s_speak_m = String::from("speak_m.mp3");
window.load_sound(
&PathBuf::from_str("static/speak_m.mp3")
.map_err(|_| String::from("Failed to load \"static/speak_m.mp3\""))?,
s_speak_m.clone(),
)?;
let s_speak_f = String::from("speak_f.mp3");
window.load_sound(
&PathBuf::from_str("static/speak_f.mp3")
.map_err(|_| String::from("Failed to load \"static/speak_f.mp3\""))?,
s_speak_f.clone(),
)?;
let font = String::from("ClearSans-Regular.ttf");
window.load_font(
&PathBuf::from_str("static/ClearSans-Regular.ttf")
.map_err(|_| String::from("Failed to load \"static/ClearSans-Regular.ttf\""))?,
font.clone(),
)?;
let music2 = String::from("music2.mp3");
window.load_music(
&PathBuf::from_str("static/music2.mp3")
.map_err(|_| String::from("Failed to load \"static/music2.mp3\""))?,
music2.clone(),
)?;
let i_star = String::from("star.png");
window.load_image(
&PathBuf::from_str("static/star.png")
.map_err(|_| String::from("Failed to load \"static/star.png\""))?,
i_star.clone(),
)?;
let i_fish = String::from("fish.png");
window.load_image(
&PathBuf::from_str("static/fish.png")
.map_err(|_| String::from("Failed to load \"static/fish.png\""))?,
i_fish.clone(),
)?;
let camera = window.get_gi_mut().get_default_camera()?;
camera.set_view(Rectangle {
x: 0.0,
y: 0.0,
w: WIDTH_F,
h: HEIGHT_F,
});
Ok(Self { Ok(Self {
s_boom: Sound::load("boom.mp3"), s_boom,
s_get: Sound::load("get.mp3"), s_get,
s_power_up: Sound::load("power_up.mp3"), s_power_up,
s_tap: Sound::load("tap.mp3"), s_tap,
s_speak_m: Sound::load("speak_m.mp3"), s_speak_m,
s_speak_f: Sound::load("speak_f.mp3"), s_speak_f,
font: Font::load("ClearSans-Regular.ttf"), font,
music2: Sound::load("music2.mp3"), music2,
i_star: Some(Image::load("star.png")), i_star,
i_star_actual: None, i_fish,
i_fish: Image::load("fish.png"),
i_fish_body: None,
i_fish_tail: None,
music_on: false, music_on: false,
music_timer: 0.0,
menu: Menu::start(), menu: Menu::start(),
state: 0, state: 0,
state_dirty: false, state_dirty: false,
@ -1242,7 +1331,7 @@ impl GameState {
planets: Vec::new(), planets: Vec::new(),
stars: Vec::new(), stars: Vec::new(),
fishes: Vec::new(), fishes: Vec::new(),
camera: Rectangle::new(0.0, 0.0, WIDTH_F, HEIGHT_F), camera,
move_to: Vector::new(400.0, 300.0), move_to: Vector::new(400.0, 300.0),
save_load_notification: None, save_load_notification: None,
}) })
@ -1505,8 +1594,10 @@ impl GameState {
x: self.player.x, x: self.player.x,
y: self.player.y, y: self.player.y,
}; };
self.camera.x = self.player.x - WIDTH_F / 2.0; self.camera.set_view_xy(
self.camera.y = self.player.y - HEIGHT_F / 2.0; self.player.x - WIDTH_F / 2.0,
self.player.y - HEIGHT_F / 2.0,
);
self.dbl_click_timeout = None; self.dbl_click_timeout = None;
self.click_time = None; self.click_time = None;
self.click_release_time = DOUBLE_CLICK_TIME; self.click_release_time = DOUBLE_CLICK_TIME;
@ -1535,7 +1626,7 @@ impl GameState {
} }
fn update(&mut self, window: &mut Window) -> Result<(), String> { fn update(&mut self, window: &mut Window) -> Result<(), String> {
let dt = window.update_rate(); let dt = window.get_gi().get_delta_time();
self.click_release_time += dt; self.click_release_time += dt;
if let Some(t) = &mut self.click_time { if let Some(t) = &mut self.click_time {
@ -1560,25 +1651,22 @@ impl GameState {
(self.player.x - self.joining_particles.particle_system.host_rect.x) / 30.0; (self.player.x - self.joining_particles.particle_system.host_rect.x) / 30.0;
self.joining_particles.particle_system.host_rect.y += self.joining_particles.particle_system.host_rect.y +=
(self.player.y - self.joining_particles.particle_system.host_rect.y) / 30.0; (self.player.y - self.joining_particles.particle_system.host_rect.y) / 30.0;
self.camera.x += (self.player.x - WIDTH_F / 2.0 - self.camera.x) / 40.0; let (cx, cy) = self.camera.get_view_xy()?;
self.camera.y += (self.player.y - HEIGHT_F / 2.0 - self.camera.y) / 40.0; self.camera.set_view_xy(
window.set_view(View::new(self.camera)); (self.player.x - WIDTH_F / 2.0 - cx) / 40.0,
(self.player.y - HEIGHT_F / 2.0 - cy) / 40.0,
)?;
window.get_gi_mut().set_camera(&self.camera);
self.player_r += dt / 10.0; self.player_r += dt / 10.0;
if self.state_dirty { if self.state_dirty {
self.state_dirty = false; self.state_dirty = false;
if self.state > 1 && !self.music_on { if self.state > 1 && !self.music_on {
let mut music_on = false; let music = window.get_music(&self.music2)?;
self.music2.execute(|m2| { music.set_loop(true)?;
music_on = true; music.play(0.5)?;
m2.set_volume(0.6); self.music_on = true;
m2.play()
})?;
if music_on {
self.music_on = true;
self.music_timer = 0.0;
}
} }
match self.state { match self.state {
1 => { 1 => {
@ -1649,8 +1737,7 @@ impl GameState {
self.player.x = WIDTH_F / 2.0; self.player.x = WIDTH_F / 2.0;
self.player.y = HEIGHT_F / 2.0; self.player.y = HEIGHT_F / 2.0;
self.move_to = Vector::new(WIDTH_F / 2.0, HEIGHT_F / 2.0); self.move_to = Vector::new(WIDTH_F / 2.0, HEIGHT_F / 2.0);
self.camera.x = 0.0; self.camera.set_view_xy(0.0, 0.0);
self.camera.y = 0.0;
self.click_time = None; self.click_time = None;
} }
} }
@ -1674,22 +1761,12 @@ impl GameState {
} }
if self.music_on { if self.music_on {
self.music_timer += dt;
if self.music_timer > MUSIC2_LENGTH {
self.music_timer = 0.0;
self.music2.execute(|m2| m2.play())?;
}
} else if self.state == 10 { } else if self.state == 10 {
let mut music_on = false; let mut music_on = false;
self.music2.execute(|m2| { let music = window.get_music(&self.music2)?;
music_on = true; music.set_loop(true)?;
m2.set_volume(0.6); music.play(0.5)?;
m2.play() self.music_on = true;
})?;
if music_on {
self.music_on = true;
self.music_timer = 0.0;
}
} }
for i in 0..self.menu.items.len() { for i in 0..self.menu.items.len() {
@ -1835,37 +1912,6 @@ impl GameState {
} }
} }
if self.i_star_actual.is_none() {
if let Some(i_s) = &mut self.i_star {
let mut star: Option<Image> = None;
i_s.execute(|i| {
star = Some(i.clone());
Ok(())
})?;
self.i_star_actual = star;
}
if self.i_star_actual.is_some() {
self.i_star = None;
}
}
if self.i_fish_body.is_none() {
let mut body: Option<Image> = None;
self.i_fish.execute(|i| {
body = Some(i.subimage(Rectangle::new(0.0, 0.0, 32.0, 16.0)));
Ok(())
})?;
self.i_fish_body = body;
}
if self.i_fish_tail.is_none() {
let mut tail: Option<Image> = None;
self.i_fish.execute(|i| {
tail = Some(i.subimage(Rectangle::new(32.0, 0.0, 16.0, 16.0)));
Ok(())
})?;
self.i_fish_tail = tail;
}
for fish in &mut self.fishes { for fish in &mut self.fishes {
fish.update(dt); fish.update(dt);
} }
@ -1899,7 +1945,7 @@ impl GameState {
let mut image_rect = image.get_wh_rect(); let mut image_rect = image.get_wh_rect();
image_rect.x = mi.x + (mi.w - image_rect.w) / 2.0; 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_rect.y = mi.y + (mi.h - image_rect.h) / 2.0;
image.draw(image_rect.x, image_rect.y)?; image.draw(image_rect.x, image_rect.y, Color::WHITE)?;
} }
} }
MenuItemType::AppearingText { MenuItemType::AppearingText {
@ -1912,7 +1958,7 @@ impl GameState {
} => { } => {
if let Some(i) = text_image { if let Some(i) = text_image {
let image = window.get_image_mut(&i)?; let image = window.get_image_mut(&i)?;
image.draw(mi.x, mi.y)?; image.draw(mi.x, mi.y, Color::WHITE)?;
} }
} }
MenuItemType::InstantText { MenuItemType::InstantText {
@ -1924,7 +1970,7 @@ impl GameState {
if let Some(i) = text_image { if let Some(i) = text_image {
let image = window.get_image_mut(&i)?; let image = window.get_image_mut(&i)?;
let mut image_rect = image.get_wh_rect(); let mut image_rect = image.get_wh_rect();
image.draw(mi.x, mi.y)?; image.draw(mi.x, mi.y, Color::WHITE)?;
} }
} }
MenuItemType::Pause { timer, length } => (), MenuItemType::Pause { timer, length } => (),
@ -1945,18 +1991,12 @@ impl GameState {
planet.draw(window, Transform::IDENTITY); planet.draw(window, Transform::IDENTITY);
} }
if let Some(i) = &mut self.i_star_actual { for star in &mut self.stars {
for star in &mut self.stars { star.draw(&self.i_star, window, Transform::IDENTITY);
star.draw(i, window, Transform::IDENTITY);
}
} }
if let Some(body) = &self.i_fish_body { for fish in &mut self.fishes {
if let Some(tail) = &self.i_fish_tail { fish.draw(&self.i_fish, window, Transform::IDENTITY);
for fish in &mut self.fishes {
fish.draw(body, tail, window, Transform::IDENTITY);
}
}
} }
// TODO // TODO