#![allow(dead_code)] use std::{collections::HashSet, f64::consts::PI, time::Duration}; use crate::engine::{Color, Key, Renderer, Scene, Shape, V3}; mod engine; struct Game { objects: Vec, next_object_id: u32, keys_pressed: HashSet, } impl Game { fn new() -> Self { Self { objects: Vec::new(), next_object_id: 0, keys_pressed: HashSet::new(), } } fn spawn(&mut self, object_kind: ObjectKind) { let object = Object { kind: object_kind, id: self.next_object_id, }; self.objects.push(object); self.next_object_id += 1 } fn despawn(&mut self, id: u32) { let index = self .objects .iter() .position(|o| o.id == id) .expect("doesn't exist"); self.objects.remove(index); } } impl engine::Game for Game { fn update(&mut self, delta_time: Duration) { for object in &mut self.objects { if self.keys_pressed.contains(&Key::A) { match &mut object.kind { ObjectKind::SkateBoard { pivot_deg, .. } => { *pivot_deg -= 18.0 * delta_time.as_secs_f64(); if *pivot_deg < -12.5 { *pivot_deg = -12.5; } } } } if self.keys_pressed.contains(&Key::D) { match &mut object.kind { ObjectKind::SkateBoard { pivot_deg: pivot_factor, .. } => { *pivot_factor += 18.0 * delta_time.as_secs_f64(); if *pivot_factor > 12.5 { *pivot_factor = 12.5; } } } } if !(self.keys_pressed.contains(&Key::A) || self.keys_pressed.contains(&Key::D)) { match &mut object.kind { ObjectKind::SkateBoard { pivot_deg: pivot_factor, .. } => { let decay_rate = 1.0 - (2.0 * delta_time.as_secs_f64()); *pivot_factor *= decay_rate; } } } if self.keys_pressed.contains(&Key::R) { match &mut object.kind { ObjectKind::SkateBoard { rot, pos, .. } => { *pos = V3(0.0, -0.1, -0.6); *rot = V3(0.0, 0.5 * PI, 0.0); } } } if self.keys_pressed.contains(&Key::W) { match &mut object.kind { ObjectKind::SkateBoard { rot, .. } => rot.0 += 1.0 * delta_time.as_secs_f64(), } } if self.keys_pressed.contains(&Key::S) { match &mut object.kind { ObjectKind::SkateBoard { rot, .. } => rot.0 -= 1.0 * delta_time.as_secs_f64(), } } if self.keys_pressed.contains(&Key::Left) { match &mut object.kind { ObjectKind::SkateBoard { rot, .. } => rot.1 -= 1.0 * delta_time.as_secs_f64(), } } if self.keys_pressed.contains(&Key::Right) { match &mut object.kind { ObjectKind::SkateBoard { rot, .. } => rot.1 += 1.0 * delta_time.as_secs_f64(), } } if self.keys_pressed.contains(&Key::Down) { match &mut object.kind { ObjectKind::SkateBoard { pos, .. } => pos.1 -= 0.5 * delta_time.as_secs_f64(), } } if self.keys_pressed.contains(&Key::Up) { match &mut object.kind { ObjectKind::SkateBoard { pos, .. } => pos.1 += 0.5 * delta_time.as_secs_f64(), } } object.update(delta_time); } } fn render(&mut self, r: &mut R) { let mut scene = Scene::new(); for object in &self.objects { object.render(&mut scene); } scene.render(r, V3(0.0, 0.0, -1.0)); } fn event(&mut self, event: engine::Event) { match event { engine::Event::KeyDown { key } => self.keys_pressed.insert(key), engine::Event::KeyUp { key } => self.keys_pressed.remove(&key), }; } } struct Object { kind: ObjectKind, id: u32, } enum ObjectKind { SkateBoard { pos: V3, vel: V3, rot: V3, nyoom_factor: f64, pivot_deg: f64, }, } struct ShapeGroupShape { shape: Shape, offset: V3, } struct ShapeGroup { pub shapes: Vec, } impl ShapeGroup { pub fn new(shapes: Vec) -> Self { Self { shapes } } pub fn rotate(mut self, rot: V3) -> Self { for shape in &mut self.shapes { shape.shape = shape .shape .translate(shape.offset) .rotate(rot) .translate(shape.offset * -1.0); } self } pub fn translate(mut self, offset: V3) -> Self { for shape in &mut self.shapes { shape.shape = shape.shape.translate(offset); } self } pub fn draw(self, pos: V3, scene: &mut Scene, outline_color: Color, fill_color: Color) { for shape in self.shapes { scene.draw_shape( pos, &shape.shape.translate(shape.offset), outline_color, fill_color, ); } } } impl Object { fn update(&mut self, delta_time: Duration) { match &mut self.kind { ObjectKind::SkateBoard { pos, vel, nyoom_factor, pivot_deg: pivot_factor, .. } => { vel.0 = *pivot_factor * delta_time.as_secs_f64(); *pos += *vel * delta_time.as_secs_f64(); *nyoom_factor += 16.0 * delta_time.as_secs_f64(); // rot.0 += delta_time.as_secs_f64() * PI * 1.0; // rot.1 += delta_time.as_secs_f64() * PI * 0.2; // rot.2 += delta_time.as_secs_f64() * PI * 2.0; } } } fn render(&self, scene: &mut Scene) { match self.kind { ObjectKind::SkateBoard { pos, rot, nyoom_factor, pivot_deg: pivot_factor, .. } => { let board_size = V3(0.175, 0.005, 0.05); let trucks = { let anchor_size = V3(0.005, 0.01, 0.005); let anchor_y = -anchor_size.1 - board_size.1 * 0.5; let pivot = vec![ ShapeGroupShape { shape: Shape::new_cube(anchor_size), offset: V3( anchor_size.0 * -0.5 + board_size.0 * 0.4, anchor_y, anchor_size.2 * -0.5, ), }, ShapeGroupShape { shape: Shape::new_cube(anchor_size), offset: V3( anchor_size.0 * -0.5 - board_size.0 * 0.4, anchor_y, anchor_size.2 * -0.5, ), }, ]; let wheel_rail_size = V3(anchor_size.0, anchor_size.0, board_size.2 * 0.8); let wheel_rail_y = anchor_y - wheel_rail_size.1; let wheel_rail = vec![ ShapeGroupShape { shape: Shape::new_cube(wheel_rail_size), offset: V3( wheel_rail_size.0 * -0.5 + board_size.0 * 0.4, wheel_rail_y, wheel_rail_size.2 * -0.5, ), }, ShapeGroupShape { shape: Shape::new_cube(wheel_rail_size), offset: V3( wheel_rail_size.0 * -0.5 - board_size.0 * 0.4, wheel_rail_y, wheel_rail_size.2 * -0.5, ), }, ]; let wheel_size = V3(0.01, 0.01, 0.0025); let wheel_y = wheel_rail_y - wheel_size.1 * 0.25; let wheel_rot = V3(0.0, 0.0, nyoom_factor); let wheel_rot_trans = V3(0.5, 0.5, 0.0); let wheel = vec![ ShapeGroupShape { shape: Shape::new_cube(wheel_size) .translate(wheel_size * wheel_rot_trans * -1.0) .rotate(wheel_rot) .translate(wheel_size * wheel_rot_trans), offset: V3( wheel_size.0 * -0.5 + board_size.0 * 0.4, wheel_y, wheel_rail_size.2 * -0.5 - wheel_size.2, ), }, ShapeGroupShape { shape: Shape::new_cube(wheel_size) .translate(wheel_size * wheel_rot_trans * -1.0) .rotate(wheel_rot) .translate(wheel_size * wheel_rot_trans), offset: V3( wheel_size.0 * -0.5 - board_size.0 * 0.4, wheel_y, wheel_rail_size.2 * -0.5 - wheel_size.2, ), }, ShapeGroupShape { shape: Shape::new_cube(wheel_size) .translate(wheel_size * wheel_rot_trans * -1.0) .rotate(wheel_rot) .translate(wheel_size * wheel_rot_trans), offset: V3( wheel_size.0 * -0.5 + board_size.0 * 0.4, wheel_y, wheel_rail_size.2 * 0.5, ), }, ShapeGroupShape { shape: Shape::new_cube(wheel_size) .translate(wheel_size * wheel_rot_trans * -1.0) .rotate(wheel_rot) .translate(wheel_size * wheel_rot_trans), offset: V3( wheel_size.0 * -0.5 - board_size.0 * 0.4, wheel_y, wheel_rail_size.2 * 0.5, ), }, ]; vec![pivot, wheel_rail, wheel].into_iter().flatten() }; let board_pivot_trans = V3(0.0, 0.5, 0.5); let mut board = vec![ShapeGroupShape { shape: Shape::new_cube(board_size) .translate(board_size * board_pivot_trans * -1.0) .rotate(V3(pivot_factor * (PI / 180.0), 0.0, 0.0)) .translate(board_size * board_pivot_trans), offset: board_size * -0.5, }]; board.extend(trucks); let board = ShapeGroup::new(board).rotate(rot); board.draw(pos, scene, Color::Green, Color::Black); scene.draw_shape( V3(-0.5, -5.0, 0.0), &Shape::new_cube(V3(1.0, 0.0, 100.0)), Color::Red, Color::Red, ); } } } } fn main() -> Result<(), Box> { let mut sdl_io = engine::SdlIo::new()?; let mut game = Game::new(); let mut objects: Vec = Vec::new(); objects.push(ObjectKind::SkateBoard { pos: V3(0.0, -0.1, -0.6), vel: V3(0.0, 0.0, 0.0), rot: V3(0.0, PI * 0.5, 0.0), nyoom_factor: 0.0, pivot_deg: 0.0, }); for object in objects { game.spawn(object) } sdl_io.run(&mut game); Ok(()) }