Work on porting from quicksilver
This commit is contained in:
parent
996e568b50
commit
71fc3de042
3 changed files with 247 additions and 179 deletions
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>>,
|
||||||
|
|
388
src/main.rs
388
src/main.rs
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue