Browse Source

colour is a source file

master
Inderjit Gill 1 year ago
parent
commit
4928164fb2
6 changed files with 709 additions and 20 deletions
  1. +0
    -8
      Cargo.lock
  2. +0
    -2
      Cargo.toml
  3. +675
    -0
      src/colour.rs
  4. +12
    -0
      src/error.rs
  5. +1
    -1
      src/game.rs
  6. +21
    -9
      src/lib.rs

+ 0
- 8
Cargo.lock View File

@@ -98,13 +98,6 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "sen-colour"
version = "0.2.0"
dependencies = [
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -223,7 +216,6 @@ name = "wasm_tetris"
version = "0.1.0"
dependencies = [
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sen-colour 0.2.0",
"wasm-bindgen 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
]


+ 0
- 2
Cargo.toml View File

@@ -9,8 +9,6 @@ crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.13"
failure = "0.1.1"
sen-colour = { path = "../sen-colour" }


[profile.release]
# Include function names in the `.wasm` for better debugging and

+ 675
- 0
src/colour.rs View File

@@ -0,0 +1,675 @@

// |--------+-----------+-------------+-------------|
// | format | element 0 | element 1 | element 2 |
// |--------+-----------+-------------+-------------|
// | RGB | R 0..1 | G 0..1 | B 0..1 |
// | HSL | H 0..360 | S 0..1 | L 0..1 |
// | HSLuv | H 0..360 | S 0..100 | L 0..100 |
// | LAB | L 0..100 | A -128..128 | B -128..128 |
// |--------+-----------+-------------+-------------|

use error;
use std;

use sin;
use cos;
use pow;
use sqrt;
use atan2;

const REF_U: f64 = 0.197_830_006_642_836_807_64;
const REF_V: f64 = 0.468_319_994_938_791_003_70;

// http://www.brucelindbloom.com/index.html?Equations.html
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

// we're using an sRGB working space with a D65 reference white

// https://uk.mathworks.com/help/images/ref/whitepoint.html
// the D65 whitepoint
const WHITEPOINT_0: f64 = 0.9504;
const WHITEPOINT_1: f64 = 1.0;
const WHITEPOINT_2: f64 = 1.0888;

const CIE_EPSILON: f64 = 0.008_856;
const CIE_KAPPA: f64 = 903.3;

// intent from the CIE
//
// #define CIE_EPSILON (216.0f / 24389.0f)
// #define CIE_KAPPA (24389.0f / 27.0f)

// RGB to XYZ (M)
// 0.4124564 0.3575761 0.1804375
// 0.2126729 0.7151522 0.0721750
// 0.0193339 0.1191920 0.9503041

// XYZ to RBG (M)^-1
// 3.2404542 -1.5371385 -0.4985314
// -0.9692660 1.8760108 0.0415560
// 0.0556434 -0.2040259 1.0572252

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Format {
RGB,
HSLuv,
HSL,
LAB,
HSV,
}

#[derive(Debug, Clone, Copy)]
pub enum Colour {
RGB(f64, f64, f64, f64),
HSLuv(f64, f64, f64, f64),
HSL(f64, f64, f64, f64),
LAB(f64, f64, f64, f64),
HSV(f64, f64, f64, f64),
XYZ(f64, f64, f64, f64),
LUV(f64, f64, f64, f64),
LCH(f64, f64, f64, f64),
}

impl Colour {
pub fn is_format(&self, format: Format) -> bool {
match format {
Format::RGB => {
match *self {
Colour::RGB(_, _, _, _) => true,
_ => false,
}
},
Format::HSLuv => {
match *self {
Colour::HSLuv(_, _, _, _) => true,
_ => false,
}
},
Format::HSL => {
match *self {
Colour::HSL(_, _, _, _) => true,
_ => false,
}
},
Format::LAB => {
match *self {
Colour::LAB(_, _, _, _) => true,
_ => false,
}
},
Format::HSV => {
match *self {
Colour::HSV(_, _, _, _) => true,
_ => false,
}
},
}
}

pub fn clone_as(&self, format: Format) -> error::Result<Colour> {
match *self {
Colour::HSL(h, s, l, alpha) => {
match format {
Format::HSL => Ok(Colour::HSL(h, s, l, alpha)),
Format::HSLuv => hsluv_from_xyz(xyz_from_rgb(rgb_from_hsl(*self)?)?),
Format::HSV => hsv_from_rgb(rgb_from_hsl(*self)?),
Format::LAB => lab_from_xyz(xyz_from_rgb(rgb_from_hsl(*self)?)?),
Format::RGB => rgb_from_hsl(*self),
}
},
Colour::HSLuv(h, s, l, alpha) => {
match format {
Format::HSL => hsl_from_rgb(rgb_from_xyz(xyz_from_hsluv(*self)?)?),
Format::HSLuv => Ok(Colour::HSLuv(h, s, l, alpha)),
Format::HSV => hsv_from_rgb(rgb_from_xyz(xyz_from_hsluv(*self)?)?),
Format::LAB => lab_from_xyz(xyz_from_hsluv(*self)?),
Format::RGB => rgb_from_xyz(xyz_from_hsluv(*self)?),
}
},
Colour::HSV(h, s, v, alpha) => {
match format {
Format::HSL => hsl_from_rgb(rgb_from_hsv(*self)?),
Format::HSLuv => hsluv_from_xyz(xyz_from_rgb(rgb_from_hsv(*self)?)?),
Format::HSV => Ok(Colour::HSV(h, s, v, alpha)),
Format::LAB => lab_from_xyz(xyz_from_rgb(rgb_from_hsv(*self)?)?),
Format::RGB => rgb_from_hsv(*self),
}
},
Colour::LAB(l, a, b, alpha) => {
match format {
Format::HSL => hsl_from_rgb(rgb_from_xyz(xyz_from_lab(*self)?)?),
Format::HSLuv => hsluv_from_xyz(xyz_from_lab(*self)?),
Format::HSV => hsv_from_rgb(rgb_from_xyz(xyz_from_lab(*self)?)?),
Format::LAB => Ok(Colour::LAB(l, a, b, alpha)),
Format::RGB => rgb_from_xyz(xyz_from_lab(*self)?),
}
},
Colour::RGB(r, g, b, alpha) => {
match format {
Format::HSL => hsl_from_rgb(*self),
Format::HSLuv => hsluv_from_xyz(xyz_from_rgb(*self)?),
Format::HSV => hsv_from_rgb(*self),
Format::LAB => lab_from_xyz(xyz_from_rgb(*self)?),
Format::RGB => Ok(Colour::RGB(r, g, b, alpha)),
}
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}
}

fn colour_to_axis(component: f64) -> f64{
if component > 0.04045 {
pow((component + 0.055) / 1.055, 2.4)
} else {
(component / 12.92)
}
}

fn axis_to_colour(a: f64) -> f64 {
if a > 0.003_130_8 {
(1.055 * pow(a, 1.0 / 2.4)) - 0.055
} else {
a * 12.92
}
}

fn xyz_from_rgb(rgb: Colour) -> error::Result<Colour> {
match rgb {
Colour::RGB(r, g, b, alpha) => {
let rr = colour_to_axis(r);
let gg = colour_to_axis(g);
let bb = colour_to_axis(b);

// multiply by matrix
// see http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
// sRGB colour space with D65 reference white
//

let x = (rr * 0.412_390_799_265_959_5) +
(gg * 0.357_584_339_383_877_96) + (bb * 0.180_480_788_401_834_3);
let y = (rr * 0.212_639_005_871_510_36) +
(gg * 0.715_168_678_767_755_927_46) + (bb * 0.072_192_315_360_733_715_00);
let z = (rr * 0.019_330_818_715_591_850_69) +
(gg * 0.119_194_779_794_625_987_91) + (bb * 0.950_532_152_249_660_580_86);

Ok(Colour::XYZ(x, y, z, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn rgb_from_xyz(xyz: Colour) -> error::Result<Colour> {
match xyz {
Colour::XYZ(x, y, z, alpha) => {
let r = (x * 3.240_969_941_904_521_343_77) + (y * -1.537_383_177_570_093_457_94) +
(z * -0.498_610_760_293_003_283_66);
let g = (x * -0.969_243_636_280_879_826_13) + (y * 1.875_967_501_507_720_667_72) +
(z * 0.041_555_057_407_175_612_47);
let b = (x * 0.055_630_079_696_993_608_46) + (y * -0.203_976_958_888_976_564_35) +
(z * 1.056_971_514_242_878_560_72);

let rr = axis_to_colour(r);
let gg = axis_to_colour(g);
let bb = axis_to_colour(b);

Ok(Colour::RGB(rr, gg, bb, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn axis_to_lab_component(a: f64) -> f64 {
if a > CIE_EPSILON {
a.cbrt()
} else {
((CIE_KAPPA * a) + 16.0) / 116.0
}
}

fn lab_from_xyz(xyz: Colour) -> error::Result<Colour> {
match xyz {
Colour::XYZ(x, y, z, alpha) => {
let xr = x / WHITEPOINT_0;
let yr = y / WHITEPOINT_1;
let zr = z / WHITEPOINT_2;

let fx = axis_to_lab_component(xr);
let fy = axis_to_lab_component(yr);
let fz = axis_to_lab_component(zr);

let l = (116.0 * fy) - 16.0;
let a = 500.0 * (fx - fy);
let b = 200.0 * (fy - fz);

Ok(Colour::LAB(l, a, b, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn max_channel(r: f64, g: f64, b: f64) -> i32 {
let hi = if r > g { 0 } else { 1 };
let hival = if r > g { r } else { g };

if b > hival { 2 } else { hi }
}

// TODO: implement a better fmod, this one is not exact
fn fmod(a: f64, b: f64) -> f64 {
a - b * (a / b).floor()
}

// http://www.rapidtables.com/convert/color/rgb-to-hsl.htm
fn hue(colour: Colour, max_chan: i32, chroma: f64) -> error::Result<f64> {
if chroma == 0.0 {
// return Err(error::TetrisError::InvalidHue)
return Ok(0.0)
}

let mut angle: f64;

match colour {
Colour::RGB(r, g, b, _) => angle = match max_chan {
0 => fmod((g - b) / chroma, 6.0),
1 => ((b - r) / chroma) + 2.0,
2 => ((r - g) / chroma) + 4.0,
_ => return Err(error::TetrisError::InvalidChannel)
},
_ => return Err(error::TetrisError::IncorrectFormat)
}

angle *= 60.0;

while angle < 0.0 {
angle += 360.0;
}

Ok(angle)
}

// http://www.rapidtables.com/convert/color/rgb-to-hsl.htm
fn hsl_from_rgb(colour: Colour) -> error::Result<Colour> {
match colour {
Colour::RGB(r, g, b, alpha) => {

let min_val = r.min(g).min(b);
let max_val = r.max(g).max(b);
let max_ch = max_channel(r, g, b);

let delta = max_val - min_val;

let h = hue(colour, max_ch, delta)?;
let lightness = 0.5 * (min_val + max_val);
let saturation: f64 = if delta == 0.0 {
0.0
} else {
delta / (1.0 - ((2.0 * lightness) - 1.0).abs())
};

Ok(Colour::HSL(h, saturation, lightness, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}

}

fn hsv_from_rgb(colour: Colour) -> error::Result<Colour> {
match colour {
Colour::RGB(r, g, b, alpha) => {

let min_val = r.min(g).min(b);
let max_val = r.max(g).max(b);
let max_ch = max_channel(r, g, b);

let chroma = max_val - min_val;
let h = hue(colour, max_ch, chroma)?;

// valid_hue: bool = chroma != 0.0;

let saturation: f64 = if chroma == 0.0 {
0.0
} else {
chroma / max_val
};

// TODO: set valid_hue
// return col.set('valid_hue', valid_hue);

Ok(Colour::HSV(h, saturation, max_val, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn rgb_from_chm(chroma: f64, h: f64, m: f64, alpha: f64) -> Colour {
// todo: validhue test
//
// if (c.get('validHue') === undefined) {
// return construct(Format.RGB, [m, m, m, element(c, ALPHA)]);
//}

let hprime = h / 60.0;
let x = chroma * (1.0 - (fmod(hprime, 2.0) - 1.0).abs());
let mut r = 0.0;
let mut g = 0.0;
let mut b = 0.0;

if hprime < 1.0 {
r = chroma;
g = x;
b = 0.0;
} else if hprime < 2.0 {
r = x;
g = chroma;
b = 0.0;
} else if hprime < 3.0 {
r = 0.0;
g = chroma;
b = x;
} else if hprime < 4.0 {
r = 0.0;
g = x;
b = chroma;
} else if hprime < 5.0 {
r = x;
g = 0.0;
b = chroma;
} else if hprime < 6.0 {
r = chroma;
g = 0.0;
b = x;
}

Colour::RGB(r + m, g + m, b + m, alpha)
}

fn rgb_from_hsl(hsl: Colour) -> error::Result<Colour> {
match hsl {
Colour::HSL(h, s, l, alpha) => {
let chroma = (1.0 - ((2.0 * l) - 1.0).abs()) * s;
let m = l - (0.5 * chroma);

// todo: set validhue
// f64 col = c.set('validHue', true);

Ok(rgb_from_chm(chroma, h, m, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn lab_component_to_axis(l: f64) -> f64 {
if pow(l, 3.0) > CIE_EPSILON {
pow(l, 3.0)
} else {
((116.0 * l) - 16.0) / CIE_KAPPA
}
}

fn xyz_from_lab(lab: Colour) -> error::Result<Colour> {
match lab {
Colour::LAB(l, a, b, alpha) => {

let fy = (l + 16.0) / 116.0;
let fz = fy - (b / 200.0);
let fx = (a / 500.0) + fy;

let xr = lab_component_to_axis(fx);
let mut yr;
if l > (CIE_EPSILON * CIE_KAPPA) {
yr = (l + 16.0) / 116.0;
yr = yr * yr * yr;
} else {
yr = l / CIE_KAPPA;
}
let zr = lab_component_to_axis(fz);

Ok(Colour::XYZ(WHITEPOINT_0 * xr, WHITEPOINT_1 * yr, WHITEPOINT_2 * zr, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn rgb_from_hsv(hsv: Colour) -> error::Result<Colour> {
match hsv {
Colour::HSV(h, s, v, alpha) => {
let chroma = v * s;
let m = v - chroma;

Ok(rgb_from_chm(chroma, h, m, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

// the luv and hsluv code is based on https://github.com/hsluv/hsluv-c
// which uses the MIT License:

// # The MIT License (MIT)

// Copyright © 2015 Alexei Boronine (original idea, JavaScript implementation)
// Copyright © 2015 Roger Tallada (Obj-C implementation)
// Copyright © 2017 Martin Mitáš (C implementation, based on Obj-C
// implementation)

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#[derive(Debug, Clone, Copy)]
struct Bounds {
a: f64,
b: f64,
}

fn get_bounds(l: f64, bounds: &mut [Bounds]) {
let tl = l + 16.0;
let sub1 = (tl * tl * tl) / 1_560_896.0;
let sub2 = if sub1 > CIE_EPSILON { sub1 } else { l / CIE_KAPPA };

let mut m = [[0f64; 3]; 3];
m[0][0] = 3.240_969_941_904_521_343_77;
m[0][1] = -1.537_383_177_570_093_457_94;
m[0][2] = -0.498_610_760_293_003_283_66;
m[1][0] = -0.969_243_636_280_879_826_13;
m[1][1] = 1.875_967_501_507_720_667_72;
m[1][2] = 0.041_555_057_407_175_612_47;
m[2][0] = 0.055_630_079_696_993_608_46;
m[2][1] = -0.203_976_958_888_976_564_35;
m[2][2] = 1.056_971_514_242_878_560_72;

for channel in 0..3 {
let m1 = m[channel][0];
let m2 = m[channel][1];
let m3 = m[channel][2];

for t in 0..2 {
let top1 = (284_517.0 * m1 - 94_839.0 * m3) * sub2;
let top2 = (838_422.0 * m3 + 769_860.0 * m2 + 731_718.0 * m1) * l * sub2 -
769_860.0 * (t as f64) * l;
let bottom = (632_260.0 * m3 - 126_452.0 * m2) * sub2 + 126_452.0 * (t as f64);

bounds[channel * 2 + t].a = top1 / bottom;
bounds[channel * 2 + t].b = top2 / bottom;
}
}
}

fn ray_length_until_intersect(theta: f64, line: &Bounds) -> f64 {
line.b / (sin(theta) - line.a * cos(theta))
}

fn max_chroma_for_lh(l: f64, h: f64) -> f64 {
let mut min_len = std::f64::MAX;
let hrad = h * 0.017_453_292_519_943_295_77; /* (2 * pi / 260) */
let mut bounds = [Bounds { a: 0.0, b: 0.0 }; 6];

get_bounds(l, &mut bounds);

for b in &bounds {
let l2 = ray_length_until_intersect(hrad, &b);

if l2 >= 0.0 && l2 < min_len {
min_len = l2;
}
}

min_len
}

/* http://en.wikipedia.org/wiki/CIELUV
* In these formulas, Yn refers to the reference white point. We are using
* illuminant D65, so Yn (see refY in Maxima file) equals 1. The formula is
* simplified accordingly.
*/
fn y2l(y: f64) -> f64 {
if y <= CIE_EPSILON {
y * CIE_KAPPA
} else {
116.0 * y.cbrt() - 16.0
}
}

fn l2y(l: f64) -> f64 {
if l <= 8.0 {
l / CIE_KAPPA
} else {
let x = (l + 16.0) / 116.0;
x * x * x
}
}

fn luv_from_xyz(xyz: Colour) -> error::Result<Colour> {
match xyz {
Colour::XYZ(x, y, z, alpha) => {
let var_u = (4.0 * x) / (x + (15.0 * y) + (3.0 * z));
let var_v = (9.0 * y) / (x + (15.0 * y) + (3.0 * z));
let l = y2l(y);
let u = 13.0 * l * (var_u - REF_U);
let v = 13.0 * l * (var_v - REF_V);

if l < 0.000_000_01 {
Ok(Colour::LUV(l, 0.0, 0.0, alpha))
} else {
Ok(Colour::LUV(l, u, v, alpha))
}
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn xyz_from_luv(luv: Colour) -> error::Result<Colour> {
match luv {
Colour::LUV(l, u, v, alpha) => {
if l <= 0.000_000_01 {
return Ok(Colour::XYZ(0.0, 0.0, 0.0, alpha))
}

let var_u = u / (13.0 * l) + REF_U;
let var_v = v / (13.0 * l) + REF_V;
let y = l2y(l);
let x = -(9.0 * y * var_u) / ((var_u - 4.0) * var_v - var_u * var_v);
let z = (9.0 * y - (15.0 * var_v * y) - (var_v * x)) / (3.0 * var_v);

Ok(Colour::XYZ(x, y, z, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn lch_from_luv(luv: Colour) -> error::Result<Colour> {

match luv {
Colour::LUV(l, u, v, alpha) => {
let mut h: f64;
let c = sqrt(u * u + v * v);

if c < 0.000_000_01 {
h = 0.0;
} else {
h = atan2(v, u) * 57.295_779_513_082_320_876_80; /* (180 / pi) */
if h < 0.0 {
h += 360.0;
}
}

Ok(Colour::LCH(l, c, h, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}

}

fn luv_from_lch(lch: Colour) -> error::Result<Colour> {
match lch {
Colour::LCH(l, c, h, alpha) => {
let hrad = h * 0.017_453_292_519_943_295_77; /* (pi / 180.0) */
let u = cos(hrad) * c;
let v = sin(hrad) * c;

Ok(Colour::LUV(l, u, v, alpha))
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn lch_from_hsluv(hsluv: Colour) -> error::Result<Colour> {
match hsluv {
Colour::HSLuv(h, s, l, alpha) => {
let c = if l > 99.999_999_9 || l < 0.000_000_01 {
0.0
} else {
max_chroma_for_lh(l, h) / 100.0 * s
};

if s < 0.000_000_01 {
Ok(Colour::LCH(l, c, 0.0, alpha))
} else {
Ok(Colour::LCH(l, c, h, alpha))
}
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn hsluv_from_lch(lch: Colour) -> error::Result<Colour> {
match lch {
Colour::LCH(l, c, h, alpha) => {
let s = if l > 99.999_999_9 || l < 0.000_000_01 {
0.0
} else {
c / max_chroma_for_lh(l, h) * 100.0
};

if c < 0.000_000_01 {
Ok(Colour::HSLuv(0.0, s, l, alpha))
} else {
Ok(Colour::HSLuv(h, s, l, alpha))
}
},
_ => Err(error::TetrisError::IncorrectFormat)
}
}

fn xyz_from_hsluv(hsluv: Colour) -> error::Result<Colour> {
xyz_from_luv(luv_from_lch(lch_from_hsluv(hsluv)?)?)
}

fn hsluv_from_xyz(xyz: Colour) -> error::Result<Colour> {
hsluv_from_lch(lch_from_luv(luv_from_xyz(xyz)?)?)
}

+ 12
- 0
src/error.rs View File

@@ -14,4 +14,16 @@ pub enum TetrisError {

#[fail(display = "Invalid Colour Format")]
InvalidColourFormat,

#[fail(display = "General")]
GeneralError,

#[fail(display = "IncorrectFormat")]
IncorrectFormat,

#[fail(display = "InvalidHue")]
InvalidHue,

#[fail(display = "InvalidChannel")]
InvalidChannel,
}

+ 1
- 1
src/game.rs View File

@@ -3,7 +3,7 @@ use error;
use geometry::Geometry;
use log;
use audio_play;
use sen_colour::{Colour, Format};
use colour::{Colour, Format};
use sprite::Sprite;
use std::collections::HashMap;
use units::*;

+ 21
- 9
src/lib.rs View File

@@ -6,25 +6,37 @@

#[macro_use]
extern crate failure;
extern crate sen_colour;
extern crate wasm_bindgen;

use wasm_bindgen::prelude::*;

pub mod controller;
pub mod error;
pub mod game;
pub mod geometry;
pub mod sprite;
pub mod text;
pub mod units;
mod controller;
mod error;
mod game;
mod colour;
mod geometry;
mod sprite;
mod text;
mod units;

use controller::{Controller, ControllerAction, ControllerButton};
use game::Game;
use geometry::Geometry;

#[wasm_bindgen(js_namespace = console)]
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = Math)]
fn sin(a: f64) -> f64;
#[wasm_bindgen(js_namespace = Math)]
fn cos(a: f64) -> f64;
#[wasm_bindgen(js_namespace = Math)]
fn pow(a: f64, b: f64) -> f64;
#[wasm_bindgen(js_namespace = Math)]
fn sqrt(a: f64) -> f64;
#[wasm_bindgen(js_namespace = Math)]
fn atan2(a: f64, b: f64) -> f64;

#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}


Loading…
Cancel
Save