summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs438
1 files changed, 438 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..7e882f3
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,438 @@
+use sdl2::gfx::primitives::DrawRenderer;
+use sdl2::pixels::Color;
+use sdl2::event::Event;
+use sdl2::rect::{Rect, Point};
+use sdl2::keyboard::Keycode;
+use sdl2::render::Texture;
+use std::time::Duration;
+use std::collections::HashMap;
+
+struct Camera {
+ x: f32,
+ y: f32,
+ scale: f32,
+ offset: Pos,
+ rotation: Rot,
+}
+#[allow(dead_code)]
+impl Camera {
+ pub fn new() -> Camera {
+ Camera { x: 0.0, y: 0.0, scale: 1.0, offset: Pos(0.0, 0.0), rotation: Rot::new() }
+ }
+
+ fn translate(&mut self, x: f32, y: f32) {
+ self.x += x;
+ self.y += y;
+ }
+
+ fn set_pos(&mut self, x: f32, y: f32) {
+ self.x = x;
+ self.y = y;
+ }
+
+ fn get_pos(&self) -> Pos {
+ Pos(self.x.into(), self.y.into())
+ }
+
+ fn get_scale(&self) -> f32 {
+ self.scale
+ }
+
+ fn set_scale(&mut self, d: f32) {
+ if d.is_finite() {
+ self.scale = d;
+ }
+ }
+
+ fn modify_scale(&mut self, d: f32) {
+ let d = self.scale + d;
+ if d < 0.1 {
+ self.scale = 0.1
+ } else {
+ self.scale = d
+ }
+ }
+
+ fn set_rotation(&mut self, deg: f32) {
+ self.rotation.set(deg);
+ }
+
+ fn modify_rotation(&mut self, deg: f32) {
+ self.rotation.modify(deg);
+ }
+
+ fn rotate_point(&self, p_origin: Pos, p: Pos, deg: Rot) -> Pos {
+ let deg = deg.get_deg();
+ let p = Pos(p.0 - p_origin.0, p.1 - p_origin.1);
+ let p = Pos(
+ p.0 * deg.cos() - p.1 * deg.sin(),
+ p.0 * deg.sin() + p.1 * deg.cos()
+ );
+ p
+ }
+
+ fn transform(&self, mut p: Pos, window_size: (u32, u32)) -> Pos {
+ p.0 = self.x + p.0 * self.scale;
+ p.1 = self.y - p.1 * self.scale;
+
+ let window_size = Pos(window_size.0 as f32, window_size.1 as f32) / 2.0;
+ let mut p = self.rotate_point(Pos(window_size.0, window_size.1), p, self.rotation);
+
+ p.0 += window_size.0;
+ p.1 += window_size.1;
+
+ p
+ }
+
+ fn translate_offset(&mut self, p: Pos) {
+ self.offset += p * (self.get_scale().powi(-1) + 0.3)
+ }
+
+ fn reset(&mut self) {
+ self.offset = Pos(0.0, 0.0);
+ self.rotation = Rot::new();
+ self.scale = 1.0;
+ }
+
+ fn center_on(&mut self, pos: &Pos, window_size: (u32, u32)) {
+ self.x = (window_size.0 / 2) as f32 - (pos.0 * self.scale) - (self.offset.0 * self.scale);
+ self.y = (window_size.1 / 2) as f32 + (pos.1 * self.scale) + (self.offset.1 * self.scale);
+ }
+}
+
+#[derive(Copy, Clone, Debug)]
+struct Pos(f32, f32);
+impl std::ops::Add for Pos {
+ type Output = Self;
+
+ fn add(self, rhs: Self) -> Self::Output {
+ Self(self.0 + rhs.0, self.1 + rhs.1)
+ }
+}
+impl std::ops::Sub for Pos {
+ type Output = Self;
+
+ fn sub(self, rhs: Self) -> Self::Output {
+ Self(self.0 - rhs.0, self.1 - rhs.1)
+ }
+}
+impl std::ops::Div<f32> for Pos {
+ type Output = Self;
+
+ fn div(self, rhs: f32) -> Self::Output {
+ Pos(self.0 / rhs, self.1 / rhs)
+ }
+}
+impl std::ops::Mul<f32> for Pos {
+ type Output = Self;
+
+ fn mul(self, rhs: f32) -> Self::Output {
+ Pos(self.0 * rhs, self.1 * rhs)
+ }
+}
+impl std::ops::AddAssign for Pos {
+ fn add_assign(&mut self, rhs: Self) {
+ self.0 += rhs.0;
+ self.1 += rhs.1;
+ }
+}
+impl From<Pos> for Point {
+ fn from(value: Pos) -> Self {
+ (value.0 as i32, value.1 as i32).into()
+ }
+}
+impl From<Point> for Pos {
+ fn from(value: Point) -> Self {
+ Pos(value.x as f32, value.y as f32)
+ }
+}
+
+
+const PI: f32 = 3.14159;
+#[derive(Copy, Clone, Debug)]
+struct Rot(f32);
+impl Rot {
+ fn new() -> Rot {
+ Rot(0.0)
+ }
+
+ fn modify(&mut self, deg: f32) {
+ self.0 = Rot::sanitize(self.0 + deg);
+ }
+
+ fn set(&mut self, deg: f32) {
+ self.0 = Rot::sanitize(deg);
+ }
+
+ #[allow(dead_code)]
+ fn get(&self) -> f32 {
+ self.0
+ }
+
+ fn sanitize(deg: f32) -> f32 {
+ if deg > 360.0 {
+ -360.0 + deg.fract()
+ } else if deg < -360.0 {
+ Rot::sanitize(deg * -1.0) * -1.0
+ } else {
+ deg
+ }
+ }
+
+ fn get_deg(&self) -> f32 {
+ ((self.0 / 360.0) * PI) * -1.0
+ }
+}
+
+
+#[derive(Copy, Clone)]
+
+enum Object {
+ Circle(Pos, Rot, f32),
+ Rect(Rot, Rect),
+}
+impl Object {
+ fn get_pos(&self) -> Pos {
+ match self {
+ Self::Circle(p, _, _) => *p,
+ Self::Rect(_, rect) => {rect.center().into()},
+ }
+ }
+
+ fn translate(&mut self, pos: Pos) {
+ match self {
+ Self::Circle(p, _, _) => {
+ let new = *p + pos;
+ p.0 = new.0;
+ p.1 = new.1;
+ },
+ Self::Rect(_, rect) => {
+ rect.offset(pos.0 as i32, pos.1 as i32)
+ }
+ }
+ }
+
+ fn modify_rotation(&mut self, deg: f32) {
+ match self {
+ Self::Circle(_, r, _) => {
+ r.modify(deg)
+ },
+ Self::Rect(r, _) => {
+ r.modify(deg)
+ }
+ }
+ }
+
+ fn draw(&mut self, canvas: &mut sdl2::render::Canvas<sdl2::video::Window>, cam: &Camera, color: Color, t: Option<&Texture>) {
+ let x = match self {
+ Self::Circle(p, _, rad) => {
+ let p = cam.transform(*p, canvas.output_size().unwrap());
+ canvas.aa_circle(p.0 as i16, p.1 as i16, (*rad * cam.scale) as i16, color)
+ },
+ Self::Rect(r, rect) => {
+ let r = *r;
+ let window_size = canvas.output_size().unwrap();
+ let center = rect.center().into();
+
+ let tl = rect.top_left().into();
+ let tr = rect.top_right().into();
+ let bl = rect.bottom_left().into();
+ let br = rect.bottom_right().into();
+
+ let tl = cam.rotate_point(center, tl, r) + center;
+ let tr = cam.rotate_point(center, tr, r) + center;
+ let bl = cam.rotate_point(center, bl, r) + center;
+ let br = cam.rotate_point(center, br, r) + center;
+
+ let tl = cam.transform(tl, window_size);
+ let tr = cam.transform(tr, window_size);
+ let bl = cam.transform(bl, window_size);
+ let br = cam.transform(br, window_size);
+
+
+ let pos1 = Point::from(tl); // Top Left
+ let pos2 = Point::from(tr); // Top Right
+ let pos3 = Point::from(br); // Bottom Right
+ let pos4 = Point::from(bl); // Bottom Left
+
+ match t {
+ Some(n) => {
+ canvas.copy_ex(n, *rect, None, r.get_deg() as f64, rect.center(), false, false)
+ },
+ None => {
+ canvas.aa_polygon(&[pos1.x as i16, pos2.x as i16, pos3.x as i16, pos4.x as i16], &[pos1.y as i16, pos2.y as i16, pos3.y as i16, pos4.y as i16], color)
+ }
+ }
+ }
+ };
+
+ match x {
+ Ok(_) => (),
+ Err(n) => println!("Draw Error: {}", n),
+ }
+ }
+
+ fn new_rect(p: Pos, p2: Pos) -> Object {
+ let w = p2.0 - p.0;
+ let h = p2.1 - p.1;
+ let center = Pos(p.0 - (w / 2.0), p.1 - (h / 2.0));
+ Self::Rect(Rot::new(), Rect::new(center.0 as i32, center.1 as i32, w as u32, h as u32))
+ }
+}
+
+struct KeyState(HashMap<Keycode, bool>);
+impl KeyState {
+ fn new() -> KeyState {
+ KeyState (
+ HashMap::new()
+ )
+ }
+
+ #[allow(dead_code)]
+ fn get(&self, k: Keycode) -> bool {
+ *self.0.get(&k).unwrap_or(&false)
+ }
+
+ fn set(&mut self, k: Keycode, v: bool) {
+ self.0.insert(k, v);
+ }
+
+ fn pairs(&self) -> Vec<(Keycode, bool)> {
+ self.0.clone().into_iter().collect()
+ }
+}
+
+fn main() {
+ println!("--Program start--");
+
+ let sdl_context = sdl2::init().unwrap();
+ let video_subsystem = sdl_context.video().unwrap();
+ let window = video_subsystem.window("rust-sdl2 demo", 800, 600)
+ .position_centered()
+ .build()
+ .unwrap();
+ let mut canvas = window.into_canvas().build().unwrap();
+ // let texture_creator = canvas.texture_creator();
+ let mut event_pump = sdl_context.event_pump().unwrap();
+ let mut cam = Camera::new();
+
+ let mut keymap = KeyState::new();
+ // let mut character = Object::Circle(Pos(0.0, 0.0), Rot::new(), 10.0);
+ let mut character = Object::new_rect(Pos(0.0, 0.0), Pos(100.0, 100.0));
+
+ let mut degree = Rot::new();
+
+ 'main: loop {
+ degree.modify(0.8 * PI);
+
+ // Clear the frame
+ canvas.set_draw_color(Color::RGB(128, 128, 128));
+ canvas.clear();
+
+ let window_size = canvas.output_size().unwrap();
+
+ // Process events
+ for event in event_pump.poll_iter() {
+ match event {
+ Event::Quit {..} |
+ Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
+ // Quit program without saving
+ break 'main
+ },
+ Event::KeyDown { keycode: Some(n), ..} => {
+ keymap.set(n, true);
+ }
+ Event::KeyUp { keycode: Some(n), .. } => {
+ keymap.set(n, false)
+ }
+ _ => ()
+ }
+ }
+
+ // Process keymap
+ for x in keymap.pairs() {
+ match x {
+ (n, true) => {
+ use Keycode::*;
+ match n {
+ // Character translation
+ W => character.translate(Pos(0.0, 5.0)),
+ A => character.translate(Pos(-5.0, 0.0)),
+ S => character.translate(Pos(0.0, -5.0)),
+ D => character.translate(Pos(5.0, 0.0)),
+ // Character rotation
+ Q => character.modify_rotation(-2.0),
+ E => character.modify_rotation(2.0),
+ // Camera translation (local axis)
+ Up => cam.translate_offset(Pos(0.0, 5.0)),
+ Left => cam.translate_offset(Pos(-5.0, 0.0)),
+ Down => cam.translate_offset(Pos(0.0, -5.0)),
+ Right => cam.translate_offset(Pos(5.0, 0.0)),
+ // Camera translation (global axis)
+ I => cam.translate_offset(cam.rotate_point(Pos(0.0, 0.0), Pos(0.0, 5.0), cam.rotation)),
+ J => cam.translate_offset(cam.rotate_point(Pos(0.0, 0.0), Pos(-5.0, 0.0), cam.rotation)),
+ K => cam.translate_offset(cam.rotate_point(Pos(0.0, 0.0), Pos(0.0, -5.0), cam.rotation)),
+ L => cam.translate_offset(cam.rotate_point(Pos(0.0, 0.0), Pos(5.0, 0.0), cam.rotation)),
+ // Camera rotation
+ U => cam.modify_rotation(-2.0),
+ O => cam.modify_rotation(2.0),
+ // Camera scale
+ N => cam.modify_scale(0.1),
+ M => cam.modify_scale(-0.1),
+ // Reset Camera
+ Space => cam.reset(),
+ _ => (),
+ }
+ },
+ _ => ()
+ }
+ }
+
+ // Center on the character
+ cam.center_on(&character.get_pos(), canvas.output_size().unwrap());
+
+ //Draw stuff
+ let mut wall = Object::Circle(Pos(-15.0, -100.0), Rot::new(), 5.0);
+ wall.draw(&mut canvas, &cam, Color::RGB(255, 255, 255), None);
+
+ // let rect_pos = cam.transform(Pos(0.0, 0.0));
+ // let rect = Rect::new(rect_pos.0 as i32, rect_pos.1 as i32, 5, 5);
+ // canvas.draw_rect(rect).unwrap();
+
+ // let mut circle = Object::Circle(Pos(50.0, 50.0), 100.0);
+ // circle.draw(&canvas, &cam, Color::RGB(255,255,255));
+
+ canvas.set_draw_color(Color::RGB(50, 255, 50));
+ let start = cam.transform(Pos(0.0, -300.0), window_size);
+ let end = cam.transform(Pos(0.0, 300.0), window_size);
+ canvas.draw_line(start, end);
+ let start = cam.transform(Pos(-300.0, 0.0), window_size);
+ let end = cam.transform(Pos(300.0, 0.0), window_size);
+ canvas.draw_line(start, end);
+
+ let trigon_center = Pos(30.0, -30.0);
+ let trigon_1 = cam.transform(cam.rotate_point(trigon_center, Pos(0.0, 0.0), degree), window_size);
+ let trigon_2 = cam.transform(cam.rotate_point(trigon_center, Pos(-20.0, -60.0), degree), window_size);
+ let trigon_3 = cam.transform(cam.rotate_point(trigon_center, Pos(20.0, -60.0), degree), window_size);
+ canvas.trigon(trigon_1.0 as i16,
+ trigon_1.1 as i16,
+ trigon_2.0 as i16,
+ trigon_2.1 as i16,
+ trigon_3.0 as i16,
+ trigon_3.1 as i16,
+ Color::RGB(255, 255, 255))
+ .unwrap();
+
+
+ // Draw player
+ character.draw(&mut canvas, &cam, Color::RGB(255, 0, 255), None);
+
+ // Draw text
+ // let s_pos = cam.transform(Pos(50.0, 50.0), window_size);
+ // canvas.string(s_pos.0 as i16, s_pos.1 as i16, "Hello", Color::RGB(255, 255, 255));
+
+ // Present the screen and sleep for 1/60th a second
+ canvas.present();
+ ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
+ }
+}