Commit 10dc1fcf authored by Rahix's avatar Rahix 🦀
Browse files

Merge 'Enforced rendering with the rendering resource'

See merge request !10
parents 3fe0bbf9 4ceb095d
...@@ -21,17 +21,16 @@ pub fn draw_edges( ...@@ -21,17 +21,16 @@ pub fn draw_edges(
#[resource] rendering: &mut resources::Rendering, #[resource] rendering: &mut resources::Rendering,
) { ) {
// TODO: Replace by proper API // TODO: Replace by proper API
let ctx = &mut rendering.ctx;
for edge in <&Edge>::query().iter(world) { for edge in <&Edge>::query().iter(world) {
let mut positions = <&components::Position>::query(); let mut positions = <&components::Position>::query();
let pos1 = positions.get(world, edge.node1).unwrap(); let pos1 = positions.get(world, edge.node1).unwrap();
let pos2 = positions.get(world, edge.node2).unwrap(); let pos2 = positions.get(world, edge.node2).unwrap();
ctx.begin_path(); rendering.begin_path();
ctx.set_line_width(7.0); rendering.set_line_width(7.0);
ctx.set_stroke_style(&"#2a005e".into()); rendering.set_stroke_style(&resources::Color::with_rgb(0.164, 0.0, 0.367));
ctx.move_to(pos1.0.x as f64, pos1.0.y as f64); rendering.move_to(pos1.0.x as f64, pos1.0.y as f64);
ctx.line_to(pos2.0.x as f64, pos2.0.y as f64); rendering.line_to(pos2.0.x as f64, pos2.0.y as f64);
ctx.stroke(); rendering.stroke();
} }
} }
...@@ -53,61 +53,59 @@ pub fn draw_nodes( ...@@ -53,61 +53,59 @@ pub fn draw_nodes(
#[resource] clock: &resources::Clock, #[resource] clock: &resources::Clock,
) { ) {
// TODO: Replace by proper API // TODO: Replace by proper API
let ctx = &mut rendering.ctx; rendering.begin_path();
ctx.begin_path(); rendering.set_fill_style(&resources::Color::with_rgb(0.63, 0.54, 0.137));
ctx.set_fill_style(&"#100e23".into()); rendering.arc(
ctx.arc(
pos.0.x as f64, pos.0.x as f64,
pos.0.y as f64, pos.0.y as f64,
10.0, 10.0,
0.0, 0.0,
std::f64::consts::TAU, std::f64::consts::TAU,
) );
.unwrap(); rendering.fill();
ctx.fill();
ctx.begin_path(); rendering.begin_path();
ctx.set_line_width(5.0); rendering.set_line_width(5.0);
ctx.set_stroke_style(&"#41008b".into()); rendering.set_stroke_style(&resources::Color::with_rgb(0.254, 0.0, 0.543));
ctx.arc( rendering.arc(
pos.0.x as f64, pos.0.x as f64,
pos.0.y as f64, pos.0.y as f64,
10.0, 10.0,
0.0, 0.0,
std::f64::consts::TAU, std::f64::consts::TAU,
) );
.unwrap(); rendering.stroke();
ctx.stroke();
let time = clock.wall_time(); let time = clock.wall_time();
let node_color = resources::Color::with_hex_string("#6800e7").unwrap();
if let Some(amount_completed) = node.amount_completed(time) { if let Some(amount_completed) = node.amount_completed(time) {
ctx.begin_path(); rendering.begin_path();
ctx.set_stroke_style(&"#6800e7".into()); rendering.set_stroke_style(&node_color);
ctx.arc( rendering.arc(
pos.0.x as f64, pos.0.x as f64,
pos.0.y as f64, pos.0.y as f64,
18.0, 18.0,
0.0, 0.0,
std::f64::consts::TAU * amount_completed, std::f64::consts::TAU * amount_completed,
) );
.unwrap(); rendering.stroke();
ctx.stroke();
} }
if let Some(ping_time) = node.ping_time { if let Some(ping_time) = node.ping_time {
let radius = (time - ping_time) * 180.0 + 18.0; let radius = (time - ping_time) * 180.0 + 18.0;
let transparency = (1.0 - (time - ping_time) * 2.0).max(0.0).powi(2); let alpha = (1.0 - (time - ping_time) * 2.0).max(0.0).powi(2);
let mut ring_color = node_color.clone();
ring_color.alpha = alpha;
ctx.begin_path(); rendering.begin_path();
ctx.set_stroke_style(&format!("#6800e7{:02x}", (transparency * 255.0) as u8).into()); rendering.set_stroke_style(&ring_color);
ctx.arc( rendering.arc(
pos.0.x as f64, pos.0.x as f64,
pos.0.y as f64, pos.0.y as f64,
radius, radius,
0.0, 0.0,
std::f64::consts::TAU, std::f64::consts::TAU,
) );
.unwrap(); rendering.stroke();
ctx.stroke();
} }
} }
...@@ -11,43 +11,39 @@ pub fn draw_thesun( ...@@ -11,43 +11,39 @@ pub fn draw_thesun(
#[resource] clock: &resources::Clock, #[resource] clock: &resources::Clock,
) { ) {
// TODO: Replace by proper API // TODO: Replace by proper API
let ctx = &mut rendering.ctx; rendering.begin_path();
ctx.begin_path(); rendering.set_fill_style(&resources::Color::with_rgb(0.695, 0.223, 1.0));
ctx.set_fill_style(&"#b239ff".into()); rendering.arc(
ctx.arc(
pos.0.x as f64, pos.0.x as f64,
pos.0.y as f64, pos.0.y as f64,
30.0, 30.0,
0.0, 0.0,
std::f64::consts::TAU, std::f64::consts::TAU,
) );
.unwrap(); rendering.fill();
ctx.fill();
let now = clock.wall_time(); let now = clock.wall_time();
ctx.set_line_width(10.0); rendering.set_line_width(10.0);
ctx.begin_path(); rendering.begin_path();
ctx.set_stroke_style(&"#67029f".into()); rendering.set_stroke_style(&resources::Color::with_rgb(0.402, 0.008, 0.621));
ctx.arc( rendering.arc(
pos.0.x as f64, pos.0.x as f64,
pos.0.y as f64, pos.0.y as f64,
40.0, 40.0,
0.0 + now, 0.0 + now,
0.4 * std::f64::consts::TAU + now, 0.4 * std::f64::consts::TAU + now,
) );
.unwrap(); rendering.stroke();
ctx.stroke();
ctx.begin_path(); rendering.begin_path();
ctx.set_stroke_style(&"#440069".into()); rendering.set_stroke_style(&resources::Color::with_rgb(0.266, 0.0, 0.410));
ctx.arc( rendering.arc(
pos.0.x as f64, pos.0.x as f64,
pos.0.y as f64, pos.0.y as f64,
55.0, 55.0,
4.0 - now, 4.0 - now,
4.0 + 0.66 * std::f64::consts::TAU - now, 4.0 + 0.66 * std::f64::consts::TAU - now,
) );
.unwrap(); rendering.stroke();
ctx.stroke();
} }
use nalgebra;
pub struct Camera {
pub position: nalgebra::Point2<f64>,
pub size: nalgebra::Vector2<f64>,
}
impl Camera {
pub fn new(width: f64, height: f64) -> Self {
Camera {
position: nalgebra::Point2::new(0.0, 0.0),
size: nalgebra::Vector2::new(width, height),
}
}
pub fn draw_coordinate(&self) -> nalgebra::Point2<f64> {
-(self.position + self.size / 2.0)
}
}
mod camera;
mod clock; mod clock;
mod rendering; mod rendering;
pub use camera::Camera;
pub use clock::Clock; pub use clock::Clock;
pub use rendering::Color;
pub use rendering::ImageHandle; pub use rendering::ImageHandle;
pub use rendering::Rendering; pub use rendering::Rendering;
...@@ -3,8 +3,120 @@ use anyhow::Context; ...@@ -3,8 +3,120 @@ use anyhow::Context;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
use web_sys; use web_sys;
fn get_hex_color_format(value: &str) -> u32 {
let valid_characters = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B',
'C', 'D', 'E', 'F',
];
let (hash_tag, value) = value.split_at(1);
if hash_tag == "#" {
value
.chars()
.map(|character| {
if valid_characters.contains(&character) {
1
} else {
0
}
})
.fold(0, |acc, x| acc * x + 1)
} else {
0
}
}
#[derive(Copy, Clone, Debug)]
pub struct Color {
pub red: f64,
pub green: f64,
pub blue: f64,
pub alpha: f64,
}
impl Color {
pub fn with_rgba(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
Color {
red,
green,
blue,
alpha,
}
}
pub fn with_rgb(red: f64, green: f64, blue: f64) -> Self {
Color {
red,
green,
blue,
alpha: 1.0,
}
}
pub fn with_hex_string(hex_string: &str) -> Option<Self> {
match get_hex_color_format(hex_string) {
3 => {
let number = u16::from_str_radix(hex_string.get(1..4).unwrap(), 16).unwrap();
let r = (number & 0xF00) >> 8;
let g = (number & 0x0F0) >> 4;
let b = number & 0x00F;
Some(Self::with_rgb(
r as f64 / 15.0,
g as f64 / 15.0,
b as f64 / 15.0,
))
}
4 => {
let number = u16::from_str_radix(hex_string.get(1..5).unwrap(), 16).unwrap();
let r = (number & 0xF000) >> 12;
let g = (number & 0x0F00) >> 8;
let b = (number & 0x00F0) >> 4;
let a = number & 0x000F;
Some(Self::with_rgba(
r as f64 / 15.0,
g as f64 / 15.0,
b as f64 / 15.0,
a as f64 / 15.0,
))
}
6 => {
let number = u32::from_str_radix(hex_string.get(1..7).unwrap(), 16).unwrap();
let r = (number & 0xFF0000) >> 16;
let g = (number & 0x00FF00) >> 8;
let b = number & 0x0000FF;
Some(Self::with_rgb(
r as f64 / 255.0,
g as f64 / 255.0,
b as f64 / 255.0,
))
}
8 => {
let number = u32::from_str_radix(hex_string.get(1..9).unwrap(), 16).unwrap();
let r = (number & 0xFF000000) >> 24;
let g = (number & 0x00FF0000) >> 16;
let b = (number & 0x0000FF00) >> 8;
let a = number & 0x000000FF;
Some(Self::with_rgba(
r as f64 / 255.0,
g as f64 / 255.0,
b as f64 / 255.0,
a as f64 / 255.0,
))
}
_ => None,
}
}
pub fn as_color_string(&self) -> String {
format!(
"#{:02X}{:02X}{:02X}{:02X}",
(self.red * 255.0) as u8,
(self.green * 255.0) as u8,
(self.blue * 255.0) as u8,
(self.alpha * 255.0) as u8,
)
}
}
pub struct Rendering { pub struct Rendering {
pub ctx: web_sys::CanvasRenderingContext2d, ctx: web_sys::CanvasRenderingContext2d,
images: Vec<web_sys::HtmlImageElement>, images: Vec<web_sys::HtmlImageElement>,
} }
...@@ -52,4 +164,47 @@ impl Rendering { ...@@ -52,4 +164,47 @@ impl Rendering {
.map_err(JsError::from)?; .map_err(JsError::from)?;
Ok(()) Ok(())
} }
pub fn set_fill_style(&self, color: &Color) {
self.ctx.set_fill_style(&color.as_color_string().into());
}
pub fn set_stroke_style(&self, color: &Color) {
self.ctx.set_stroke_style(&color.as_color_string().into());
}
pub fn fill_rect(&self, x: f64, y: f64, width: f64, height: f64) {
self.ctx.fill_rect(x, y, width, height);
}
pub fn begin_path(&self) {
self.ctx.begin_path();
}
pub fn stroke(&self) {
self.ctx.stroke();
}
pub fn arc(&self, x: f64, y: f64, radius: f64, start_angle: f64, end_angle: f64) {
self.ctx.arc(x, y, radius, start_angle, end_angle).unwrap();
}
pub fn fill(&self) {
self.ctx.fill();
}
pub fn set_line_width(&self, width: f64) {
self.ctx.set_line_width(width);
}
pub fn move_to(&self, x: f64, y: f64) {
self.ctx.move_to(x, y);
}
pub fn line_to(&self, x: f64, y: f64) {
self.ctx.line_to(x, y);
}
pub fn set_transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
self.ctx.set_transform(a, b, c, d, e, f).unwrap();
}
} }
...@@ -97,8 +97,8 @@ impl state::State for HeavenState { ...@@ -97,8 +97,8 @@ impl state::State for HeavenState {
fn update(&mut self) -> state::Transition { fn update(&mut self) -> state::Transition {
{ {
let rendering = self.resources.get_mut::<resources::Rendering>().unwrap(); let rendering = self.resources.get_mut::<resources::Rendering>().unwrap();
rendering.ctx.set_fill_style(&"#100e23".into()); rendering.set_fill_style(&resources::Color::with_rgb(0.0625, 0.06, 0.125));
rendering.ctx.fill_rect(0.0, 0.0, 1920.0, 1080.0); rendering.fill_rect(0.0, 0.0, 1920.0, 1080.0);
} }
self.node_schedule self.node_schedule
......
use crate::resources; use crate::resources;
use crate::state; use crate::state;
use crate::svg_loader; use crate::svg_loader;
use crate::systems;
use crate::utils; use crate::utils;
pub struct InGameState { pub struct InGameState {
...@@ -12,13 +13,23 @@ pub struct InGameState { ...@@ -12,13 +13,23 @@ pub struct InGameState {
impl InGameState { impl InGameState {
pub fn new(level: svg_loader::SvgLevel) -> InGameState { pub fn new(level: svg_loader::SvgLevel) -> InGameState {
let mut rendering = resources::Rendering::new("game-canvas").unwrap();
let foreground = rendering.register_image(level.foreground_image);
let background = rendering.register_image(level.background_image);
let mut resources = legion::Resources::default(); let mut resources = legion::Resources::default();
resources.insert(resources::Clock::new()); resources.insert(resources::Clock::new());
resources.insert(resources::Rendering::new("game-canvas").unwrap()); resources.insert(rendering);
resources.insert(resources::Camera::new(1920.0, 1080.0));
let world = legion::World::default(); let world = legion::World::default();
let schedule = legion::Schedule::builder().build(); let schedule = legion::Schedule::builder()
.add_system(systems::moving_system())
.add_thread_local(systems::camera_system())
.add_thread_local(systems::draw_level_layer_system(background))
.add_thread_local(systems::draw_level_layer_system(foreground))
.build();
InGameState { InGameState {
gui_svg: utils::get_element_by_id("ingame-ui").unwrap(), gui_svg: utils::get_element_by_id("ingame-ui").unwrap(),
...@@ -36,17 +47,35 @@ impl state::State for InGameState { ...@@ -36,17 +47,35 @@ impl state::State for InGameState {
.set_property("display", "block") .set_property("display", "block")
.unwrap(); .unwrap();
let rendering = resources::Rendering::new("game-canvas").unwrap(); state::Transition::Loop
rendering.ctx.set_fill_style(&"#100e23".into());
rendering.ctx.fill_rect(0.0, 0.0, 1920.0, 1080.0);
state::Transition::Sleep
} }
fn deinit(&mut self) { fn deinit(&mut self) {
self.resources.get::<resources::Rendering>()
.unwrap()
.set_transform(
1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
self.gui_svg self.gui_svg
.style() .style()
.set_property("display", "none") .set_property("display", "none")
.unwrap(); .unwrap();
} }
fn update(&mut self) -> state::Transition {
{
let rendering = self.resources.get::<resources::Rendering>().unwrap();
rendering.set_fill_style(&resources::Color::with_hex_string("#100e23").unwrap());
rendering.fill_rect(0.0, 0.0, 1920.0, 1080.0);
}
self.schedule.execute(&mut self.world, &mut self.resources);
let done = {
let camera = self.resources.get::<resources::Camera>().unwrap();
camera.position.x > 50.0
};
if done {
state::Transition::Pop
} else {
state::Transition::Loop
}
}
} }
...@@ -57,8 +57,8 @@ impl state::State for LevelLoadingState { ...@@ -57,8 +57,8 @@ impl state::State for LevelLoadingState {
fn update(&mut self) -> state::Transition { fn update(&mut self) -> state::Transition {
{ {
let rendering = self.resources.get_mut::<resources::Rendering>().unwrap(); let rendering = self.resources.get_mut::<resources::Rendering>().unwrap();
rendering.ctx.set_fill_style(&"#100e23".into()); rendering.set_fill_style(&resources::Color::with_rgb(0.0625, 0.06, 0.125));
rendering.ctx.fill_rect(0.0, 0.0, 1920.0, 1080.0); rendering.fill_rect(0.0, 0.0, 1920.0, 1080.0);
} }
self.node_schedule self.node_schedule
......
...@@ -188,4 +188,12 @@ impl SvgLevel { ...@@ -188,4 +188,12 @@ impl SvgLevel {
} }
} }
} }
pub fn width(&self) -> u32 {
self.foreground_image.width()
}
pub fn height(&self) -> u32 {
self.foreground_image.height()
}
} }
use crate::resources;
#[legion::system]
pub fn camera(
#[resource] rendering: &resources::Rendering,
#[resource] camera: &resources::Camera,
) {
let pos = -camera.position + camera.size / 2.0;
rendering.set_transform(1.0, 0.0, 0.0, 1.0, pos.x, pos.y);
}
mod camera;
mod level; mod level;
mod moving;
pub use camera::camera_system;
pub use level::draw_level_layer_system; pub use level::draw_level_layer_system;
pub use moving::moving_system;
use crate::resources;
#[legion::system]
pub fn moving(#[resource] camera: &mut resources::Camera) {