chaos-framework 0.1.2

Game framework for creating games!
Documentation
/*
An example for a simple 2D game using an orthographic camera
*/
use chaos_framework::*;
use glfw::Key;

fn main() {
    let mut el = EventLoop::new(600, 600);
    let mut renderer = Renderer::new();

    unsafe {
        Enable(DEPTH_TEST);
    }

    /* default projection type is perspective */
    renderer.camera.set_projection(ProjectionType::Orthographic);
    renderer.add_light(Light { position: vec3(0.0, 0.0, 3.0), color: Vec3::ONE })
        .unwrap();

    /* we'll represent our player using a quad */
    let player_handle = renderer.add_mesh(Quad::new(Vec3::ONE * 0.1, Vec4::ONE).mesh())
        .unwrap();

    renderer.meshes[player_handle].position = Vec3::Z * 2.0; // so the player stays in front of everything

    let mut segments = vec![];
    for _ in 0..128 {
        let new_segment = Segment::new(vec3(0.0, 0.0, 0.0), 0.05, &mut renderer);

        segments.push(new_segment);
    }

    renderer.meshes[segments[0].handle].hidden = true;
    renderer.meshes[segments[segments.len()-1].handle].hidden = true;

    renderer.meshes[player_handle].hidden = true;
    

    segments[0].pos = Vec3::new(-2.0, -2.0, 0.0);

    let mut clamped_pos;
    let mut player_vel;
    let mut old_pos = Vec3::ZERO;

    while !el.window.should_close() {
        el.update();
        renderer.update();
        
        segments.iter_mut().for_each(|s| {
            s.update(&mut renderer);
        });
        
        let player = &mut renderer.meshes[player_handle];
        let mp = el.event_handler.mouse_pos / el.event_handler.width * 2.0;
        let clamped_player_pos = {
            // clamped_pos = lerp(clamped_pos, player.position, 0.1);
            clamped_pos = player.position;

            vec3(clamped_pos.x, clamped_pos.y, 0.0)
        };
        fabrik(&mut segments, {
            if el.event_handler.lmb {
                clamped_player_pos + vec3(mp.x, mp.y, 0.0)
            } else {
                clamped_player_pos
            }
        }, 0.0, 2);

        let first_segment_position = segments[0].pos;
        let seg_amm = segments.len() as f32;
        let distance = first_segment_position.distance(segments[segments.len()-1].pos);
        let len = segments[0].length;
        if distance > segments.len() as f32 * segments[0].length + segments[0].length {
            segments[0].pos += ((clamped_player_pos - first_segment_position) / seg_amm) * len * f32::powf(distance, 2.3);
        }

        player_vel = player.position - old_pos;
        old_pos = player.position;

        player.color = vec3(0.5, 0.0, el.time.sin());
        move_player(&el, &mut player.position);
    
        renderer.camera.update(lerp(renderer.camera.pos, player.position, 0.125), &el);
        renderer.camera.mouse_callback(el.event_handler.mouse_pos, &el.window);

        let frame = el.ui.frame(&mut el.window);
        frame.text("Hello, world! This is imgui.");
        frame.text(format!("p: {:.1}\nv: {:.3}", player.position, player_vel));

        unsafe {
            Clear(COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT);
            ClearColor(0.1, 0.2, 0.3, 1.0);
            
            renderer.draw();
            el.ui.draw();
        }
    }
}

struct Segment {
    pos: Vec3,
    length: f32,
    angle: f32,
    handle: MeshHandle,
}

impl Segment {
    fn new(a: Vec3, length: f32, renderer: &mut Renderer) -> Self {
        let handle = renderer.add_mesh(Quad::new(Vec3::ONE * length, Vec4::ONE).mesh())
            .unwrap();

        Self {
            pos: a,
            length: length / 2.0,
            angle: 0.0,
            handle: handle,
        }
    }

    fn get_end(&self) -> Vec3 {
        self.pos + Vec3::new(self.length * self.angle.cos(), self.length * self.angle.sin(), 0.0)
    }

    fn update_position(&mut self, new_pos: Vec3) {
        self.pos = new_pos;
    }

    fn update_angle(&mut self, direction: Vec3) {
        self.angle = direction.y.atan2(direction.x);
    }

    fn update(&mut self, renderer: &mut Renderer) {
        let rot = Quat::from_axis_angle(Vec3::Z, self.angle);

        renderer.meshes[self.handle].position = self.pos;
        renderer.meshes[self.handle].rotation = rot;
    }
}

fn fabrik(segments: &mut [Segment], target: Vec3, tolerance: f32, max_iterations: usize) {
    let b = segments[0].pos;
    let mut diff = (segments.last().unwrap().get_end() - target).length();
    let mut iterations = 0;

    while diff > tolerance && iterations < max_iterations {
        iterations += 1;

        segments.last_mut().unwrap().update_position(target);
        for i in (2..segments.len()).rev() {
            let parent_end = segments[i].get_end();
            let direction = (segments[i - 1].pos - parent_end).normalize();
            let new_pos = parent_end + direction * segments[i - 1].length;
            segments[i - 1].update_position(new_pos);
            segments[i - 1].update_angle(direction);
        }

        segments[0].update_position(b);
        for i in 1..segments.len()-1 {
            let parent_end = segments[i - 1].get_end();
            let direction = (segments[i].pos - parent_end).normalize();
            let new_pos = parent_end + direction * segments[i - 1].length;
            segments[i].update_position(new_pos);
            segments[i].update_angle(direction);
        }

        diff = (segments.last().unwrap().get_end() - target).length();
    }
}




fn move_player(el: &EventLoop, pos: &mut Vec3) {
    let mut velocity = Vec3::ZERO; 
    let mut speed = 1.5;

    if el.is_key_down(Key::LeftShift) {
        speed *= 1.5;
    }

    if el.is_key_down(Key::W) {
        velocity.y+=speed;
    }
    if el.is_key_down(Key::S) {
        velocity.y-=speed;
    }
    if el.is_key_down(Key::D) {
        velocity.x+=speed;
    }
    if el.is_key_down(Key::A) {
        velocity.x-=speed;
    }

    *pos += velocity * el.dt;
}