added update loop and game state.

This commit is contained in:
2025-08-22 11:35:45 -05:00
parent 56c2a6440c
commit 6c7662b5e6
3 changed files with 192 additions and 67 deletions

View File

@@ -3,7 +3,7 @@ use std::f64;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
//use web_sys::console;
use web_sys::console;
mod cga;
use cga::CGA;
@@ -58,9 +58,9 @@ const E2: usize = 2;
//const E12345: usize = 31;
struct Ship {
_pos: CGA,
_vel: CGA,
_orientation: CGA,
pos: CGA,
//_vel: CGA,
//_orientation: CGA,
}
enum Geometry {
@@ -97,7 +97,8 @@ fn point_to_screen_space(x: f64, y: f64) -> (f64, f64) {
fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) {
//Naively assume we are given a valid point
let (x,y) = point_to_screen_space(point[E1], point[E2]);
let (x,y) = get_point(point);
let (x,y) = point_to_screen_space(x, y);
context.begin_path();
context.set_fill_style_str(RED);
@@ -105,6 +106,18 @@ fn draw_point(context: &CanvasRenderingContext2d, point: &CGA) {
context.fill();
}
//TODO Integrate into get geometry
fn get_point(point: &CGA) -> (f64, f64) {
let e_vec = CGA::e4();
let e_bar = CGA::e5();
let n_vec = &e_vec + &e_bar; //Null vector for the point at infinity.
let normalization = -(point | &n_vec)[SCALAR];
let x = point[E1] / normalization;
let y = point[E2] / normalization;
(x,y)
}
fn get_geometry(circle: &CGA) -> Geometry {
//Naively assume we are given a valid line/circle
let n_bar = CGA::e4() - CGA::e5();
@@ -146,24 +159,116 @@ fn draw_line(context: &CanvasRenderingContext2d, line: &CGA) {
let canvas_r = r*RADIUS;
context.arc(canvas_x, canvas_y, canvas_r, 0., TWO_PI).unwrap();
},
Geometry::Line(x,y,theta) => {
let (p1x, p1y) = (x - theta.cos(), y - theta.sin());
let (p2x, p2y) = (x + theta.cos(), y + theta.sin());
let (canvas_x1, canvas_y1) = point_to_screen_space(p1x, p1y);
let (canvas_x2, canvas_y2) = point_to_screen_space(p2x, p2y);
draw_point(&context, &point_to_cga(x,y));
context.move_to(canvas_x1, canvas_y1);
context.line_to(canvas_x2, canvas_y2);
},
Geometry::Line(x,y,theta) => {
let (p1x, p1y) = (x - theta.cos(), y - theta.sin());
let (p2x, p2y) = (x + theta.cos(), y + theta.sin());
let (canvas_x1, canvas_y1) = point_to_screen_space(p1x, p1y);
let (canvas_x2, canvas_y2) = point_to_screen_space(p2x, p2y);
draw_point(&context, &point_to_cga(x,y));
context.move_to(canvas_x1, canvas_y1);
context.line_to(canvas_x2, canvas_y2);
},
}
context.stroke();
}
fn get_hyperbolic_translation(vec: &CGA) -> CGA {
let vec_sqr = (vec * vec)[SCALAR];
if vec_sqr >= 1. {
panic!("Translation Vector Out of Bounds");
}
let message = format!("Get TX\nvec {} \nvecvec {}\nvec_sqr {}", vec, vec*vec, vec_sqr);
console::log_1(&message.into());
let t = 1.0 / ( 1. - vec_sqr).sqrt() * ( CGA::new(1., SCALAR) + CGA::e5()*vec);
t
}
fn get_hyperbolic_point(vec: &CGA) -> CGA {
let vec_sqr = (vec * vec)[SCALAR];
if vec_sqr >= 1. {
panic!("Vector out of bounds");
}
let p = 1. / (1. - vec_sqr)*(CGA::new(vec_sqr, SCALAR) + 2.*vec - (CGA::e4() - CGA::e5()));
p
}
struct Asteroid {
}
#[wasm_bindgen]
pub struct Game {
context: CanvasRenderingContext2d,
ship: Ship,
//asteroids: Vec::<Asteroid>,
point: (f64, f64),
//keys: HashSet<String>,
}
#[wasm_bindgen]
impl Game {
#[wasm_bindgen(constructor)]
pub fn new(canvas_id: &str) -> Self {
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let canvas = document
.get_element_by_id(canvas_id)
.ok_or_else( || JsValue::from_str("Canvas not found")).unwrap()
.dyn_into::<HtmlCanvasElement>().unwrap();
canvas.set_width(WIDTH as u32);
canvas.set_height(HEIGHT as u32);
let context = canvas
.get_context("2d").unwrap()
.ok_or_else( || JsValue::from_str("Failed to get context")).unwrap()
.dyn_into::<CanvasRenderingContext2d>().unwrap();
let ship = Ship { pos: get_hyperbolic_point(&CGA::zero()) };
Game { context: context, point: (0.,0.), ship }
}
pub fn draw(&self) {
self.context.begin_path();
self.context.set_fill_style_str(BACKGROUND);
self.context.fill_rect(0.0, 0.0, WIDTH, HEIGHT);
self.context.fill();
self.context.set_stroke_style_str(BLACK);
self.context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap();
self.context.stroke();
let x = self.point.0;
let y = self.point.1;
draw_point(&self.context, &self.ship.pos);
//self.context.begin_path();
//self.context.set_fill_style_str(GREEN);
//self.context.arc(x, y, 20., 0., TWO_PI).unwrap();
//self.context.fill();
}
pub fn update(&mut self, dt: f64) { //dt in milliseconds
let theta:f64 = 0.1;
let vel:f64 = 1.*dt/1000.;
let dir = theta.cos()*CGA::e1() + theta.sin()*CGA::e2();
let vec = vel* &dir;
let tx = get_hyperbolic_translation(&vec);
let txr = tx.Reverse();
self.ship.pos = &tx * &self.ship.pos * &txr;
let norm = (&self.ship.pos | CGA::e4() )[SCALAR];
self.ship.pos = &self.ship.pos * (1.0 / norm);
}
}
// Start entry point
#[wasm_bindgen(start)]
pub fn start() -> Result<(), JsValue> {
let _ship = Ship { _pos: point_to_cga(0.,0.), _vel: CGA::zero(), _orientation: CGA::zero() };
// let _ship = Ship { _pos: point_to_cga(0.,0.), _vel: CGA::zero(), _orientation: CGA::zero() };
/*
// Grab document and canvas
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
@@ -178,7 +283,7 @@ pub fn start() -> Result<(), JsValue> {
let context = canvas
.get_context("2d")?
.unwrap()
.dyn_into::<CanvasRenderingContext2d>()?;
.dyn_into::<CanvasRenderingContext2d>().unwrap();
//Set up play area.
context.begin_path();
@@ -188,51 +293,51 @@ pub fn start() -> Result<(), JsValue> {
context.set_stroke_style_str(BLACK);
context.arc(CENTER_X, CENTER_Y, RADIUS, 0., TWO_PI).unwrap();
context.stroke();
*/
/* //Testing example lines and circles.
let point = point_to_cga(0.,0.);
draw_point(&context, &point);
//Testing example lines and circles.
let point = point_to_cga(0.,0.);
draw_point(&context, &point);
let p1 = point_to_cga(0.9, 0.0);
draw_point(&context, &p1);
let p2 = point_to_cga(0.0, 0.9);
draw_point(&context, &p2);
let p3 = point_to_cga(0.7, 0.6);
draw_point(&context, &p3);
let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3(); //wedge e3 to force into the plane
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.0);
draw_point(&context, &p1);
let p2 = point_to_cga(0.0, 0.9);
draw_point(&context, &p2);
let p3 = point_to_cga(0.7, 0.6);
draw_point(&context, &p3);
let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3(); //wedge e3 to force into the plane
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.2);
draw_point(&context, &p1);
let p2 = point_to_cga(-0.9, -0.);
draw_point(&context, &p2);
let p3 = point_to_cga(0., 0.1);
draw_point(&context, &p3);
let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.2);
draw_point(&context, &p1);
let p2 = point_to_cga(-0.9, -0.);
draw_point(&context, &p2);
let p3 = point_to_cga(0., 0.1);
draw_point(&context, &p3);
let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.1);
draw_point(&context, &p1);
let p2 = point_to_cga(-0.9, -0.1);
draw_point(&context, &p2);
let p3 = point_to_cga(0., 0.0);
draw_point(&context, &p3);
let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.1);
draw_point(&context, &p1);
let p2 = point_to_cga(-0.9, -0.1);
draw_point(&context, &p2);
let p3 = point_to_cga(0., 0.0);
draw_point(&context, &p3);
let circle = &p1 ^ &p2 ^ &p3 ^ &CGA::e3();
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.);
draw_point(&context, &p1);
let p2 = point_to_cga(0.9, -0.1);
draw_point(&context, &p2);
let circle = &p1 ^ &p2 ^ &CGA::e4() ^ &CGA::e3(); //Wedge e4 to create a circle through p1 and p1 that is tangent to the unit circle.
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.);
draw_point(&context, &p1);
let p2 = point_to_cga(0.9, -0.1);
draw_point(&context, &p2);
let circle = &p1 ^ &p2 ^ &CGA::e4() ^ &CGA::e3(); //Wedge e4 to create a circle through p1 and p1 that is tangent to the unit circle.
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.);
draw_point(&context, &p1);
let p2 = point_to_cga(0.9, -0.1);
draw_point(&context, &p2);
let circle = &p1 ^ &p2 ^ &CGA::e5() ^ &CGA::e3(); //Orthogonal to the line at infinity
draw_line(&context, &circle);
let p1 = point_to_cga(0.9, 0.);
draw_point(&context, &p1);
let p2 = point_to_cga(0.9, -0.1);
draw_point(&context, &p2);
let circle = &p1 ^ &p2 ^ &CGA::e5() ^ &CGA::e3(); //Orthogonal to the line at infinity
draw_line(&context, &circle);*/
Ok(())
}