~starkingdoms/starkingdoms

93ae3b08ea2b7927ff7e0e83580bc93c46f0a7e0 — c0repwn3r 2 years ago 08c1b75
rendering work
M client/src/rendering/renderer.rs => client/src/rendering/renderer.rs +39 -1
@@ 1,9 1,11 @@
use std::error::Error;
use async_trait::async_trait;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
use log::debug;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlImageElement};
use crate::rendering::Renderer;
use wasm_bindgen::{JsCast, JsValue};
use crate::CLIENT;
use crate::textures::TextureManager;

#[derive(Debug)]
pub struct WebRenderer {


@@ 28,6 30,10 @@ impl Renderer for WebRenderer {
        let typed_canvas_element: HtmlCanvasElement = canvas_element.dyn_into::<web_sys::HtmlCanvasElement>().map_err(|_| ()).unwrap();
        let context = typed_canvas_element.get_context("2d").unwrap().unwrap().dyn_into::<CanvasRenderingContext2d>().unwrap();
        let client = CLIENT.read()?;
        if client.client_data.is_none() {
            return Err("client not yet initialized".into());
        }
        let client_data = client.client_data.as_ref().unwrap();

        context.set_transform(1f64, 0f64, 0f64, 1f64, 0f64, 0f64).map_err(|e: JsValue| e.as_string().unwrap())?;
        context.clear_rect(0f64, 0f64, typed_canvas_element.width() as f64, typed_canvas_element.height() as f64);


@@ 35,8 41,40 @@ impl Renderer for WebRenderer {
        let camera_translate_x = -client.x + (typed_canvas_element.width() / 2) as f64;
        let camera_translate_y = -client.y + (typed_canvas_element.height() / 2) as f64;

        debug!("translating to {} {}", camera_translate_x, camera_translate_y);

        context.translate(camera_translate_x, camera_translate_y).map_err(|e: JsValue| e.as_string().unwrap())?;

        for planet in &client.planets {
            let texture_image = document.get_element_by_id(&format!("tex-{}", planet.planet_type.as_texture_id())).unwrap().dyn_into::<HtmlImageElement>().unwrap();
            context.draw_image_with_html_image_element_and_dw_and_dh(&texture_image, 95f64, 65f64, planet.radius*2f64, planet.radius*2f64).map_err(|e: JsValue| e.as_string().unwrap())?;
        }

        context.begin_path();

        // Draw the outer circle.
        context
            .arc(75.0, 75.0, 50.0, 0.0, std::f64::consts::PI * 2.0)
            .unwrap();

        // Draw the mouth.
        context.move_to(110.0, 75.0);
        context.arc(75.0, 75.0, 35.0, 0.0, std::f64::consts::PI).unwrap();

        // Draw the left eye.
        context.move_to(65.0, 65.0);
        context
            .arc(60.0, 65.0, 5.0, 0.0, std::f64::consts::PI * 2.0)
            .unwrap();

        // Draw the right eye.
        context.move_to(95.0, 65.0);
        context
            .arc(90.0, 65.0, 5.0, 0.0, std::f64::consts::PI * 2.0)
            .unwrap();

        context.stroke();

        Ok(())
    }
}
\ No newline at end of file

M client/src/textures/loader_slow.rs => client/src/textures/loader_slow.rs +1 -1
@@ 15,6 15,6 @@ impl TextureManager for TextureLoader {
    }

    fn get_texture(&self, texture_id: &str) -> Option<String> {
        Some(format!("/../assets/final/{}/{}.png", self.size.to_string(), texture_id))
        Some(format!("/assets/final/{}/{}.png", self.size.to_string(), texture_id))
    }
}
\ No newline at end of file

M protocol/src/lib.rs => protocol/src/lib.rs +8 -0
@@ 79,6 79,14 @@ pub enum PlanetType {
    Earth
}

impl PlanetType {
    pub fn as_texture_id(&self) -> String {
        match self {
            PlanetType::Earth => "earth".to_string()
        }
    }
}

pub fn pc2s(pkt: &MessageC2S) -> Vec<u8> {
    rmp_serde::to_vec(pkt).unwrap()
}

M web/play.html => web/play.html +107 -83
@@ 6,95 6,119 @@
    <meta charset="utf-8">
</head>

    <body>
        <div class="chatbox">
            <div id="chats">
<body>
<div class="chatbox">
    <div id="chats">

    </div>
    <input id="chat-value" type="text" placeholder="chat text goes here"/>
    <button id="chat-submit">submit</button>
    <p id="status">Loading WASM module...</p>

    <div id="textures" style="display: none;">

    </div>
</div>

<canvas style="width: 100%; height: 100%; background-color: forestgreen;" id="canvas"></canvas>

<script type="module">
    // If you're getting build errors here | you need to run `just build_client_bundle` first, to compile client code
    //                                     v
    import init, {
        rust_init,
        send_chat,
        update_socket,
        set_status,
        get_texture,
        render_frame,
        send_ping_pong
    } from "./dist/starkingdoms_client.js";

    init().then(() => {
        const urlSearchParams = new URLSearchParams(window.location.search);

        if (!(urlSearchParams.has("server") || urlSearchParams.has("username") || urlSearchParams.has("textures"))) {
            window.location.href = "/index.html";
        }

        rust_init(urlSearchParams.get("server"), urlSearchParams.get("username"), urlSearchParams.get("textures")).then(() => {
            document.getElementById("chat-submit").addEventListener("click", e => {
                send_chat(document.getElementById("chat-value").value);
            });

            let interval_id;
            let interval_id2;

            interval_id = setInterval(() => {
                update_socket().catch((e) => {
                    clearInterval(interval_id);
                    clearInterval(interval_id2);
                    set_status("There was an error. Reload the page to reconnect.")
                    throw e;
                });
            }, 5);

            interval_id2 = setInterval(() => {
                send_ping_pong().catch((e) => {
                    clearInterval(interval_id2);
                    clearInterval(interval_id);
                    set_status("There was an error. Reload the page to reconnect.")
                    throw e;
                });
            }, 5);

            let start;

            </div>
            <input id="chat-value" type="text" placeholder="chat text goes here" />
            <button id="chat-submit">submit</button>
            <p id="status">Loading WASM module...</p>
            let textures = ["autoplr_cfg", "autoplr_error", "autoplr_on", "cargo_off", "cargo_on", "earth", "ecothruster_on", "hearty", "hub_off", "hub_on", "landingleg", "landingthruster_off", "landingthruster_on", "powerhub_off", "powerhub_on", "superthruster_off", "superthruster_on", "thruster_off", "thruster_on"];

            <div id="textures">
            for (let i = 0; i < textures.length; i++) {
                let texture = textures[i];

            </div>
        </div>
                let fieldset_elem = document.createElement("fieldset");
                fieldset_elem.style = "width: min-content;";
                fieldset_elem.classList.add("texturebox")
                let legend_elem = document.createElement("legend");
                legend_elem.innerText = texture;

        <canvas style="width: 100%; height: 100%" id="canvas"></canvas>
                let img_elem = document.createElement("img");
                img_elem.src = get_texture(texture);
                img_elem.id = "tex-" + texture;

        <script type="module">
            // If you're getting build errors here | you need to run `just build_client_bundle` first, to compile client code
            //                                     v
            import init, { rust_init, send_chat, update_socket, set_status, get_texture, render_frame, send_ping_pong } from "./dist/starkingdoms_client.js";
            init().then(() => {
                const urlSearchParams = new URLSearchParams(window.location.search);
                fieldset_elem.appendChild(legend_elem);
                fieldset_elem.appendChild(img_elem);
                document.getElementById("textures").appendChild(fieldset_elem);
            }
            if (urlSearchParams.has("showTextures")) {
                document.getElementById("textures").style = "";
            }

                if (!(urlSearchParams.has("server") || urlSearchParams.has("username") || urlSearchParams.has("textures"))) {
                    window.location.href = "/index.html";
            // Textures must be fully loaded (above) before rendering can start
            // They are all put on the DOM, in a hidden element, so they arent visible to the user unless showTextures=1
            // but they need to have been loaded for the canvas to render them

            function animateFrame(time) {
                if (start === undefined) {
                    start = time;
                }
                let delta = time - start;

                rust_init(urlSearchParams.get("server"), urlSearchParams.get("username"), urlSearchParams.get("textures")).then(() => {
                    document.getElementById("chat-submit").addEventListener("click", e => {
                        send_chat(document.getElementById("chat-value").value);
                    });

                    let interval_id;
                    let interval_id2;

                    interval_id = setInterval(() => {
                        update_socket().catch((e) => {
                            clearInterval(interval_id);
                            clearInterval(interval_id2);
                            set_status("There was an error. Reload the page to reconnect.")
                            throw e;
                        });
                    }, 5);

                    interval_id2 = setInterval(() => {
                        send_ping_pong().catch((e) => {
                            clearInterval(interval_id2);
                            clearInterval(interval_id);
                            set_status("There was an error. Reload the page to reconnect.")
                            throw e;
                        });
                    }, 5);

                    let start;
                    function animateFrame(time) {
                        if (start === undefined) {
                            start = time;
                        }
                        let delta = time - start;

                        render_frame(delta);
                        start = time;
                        //requestAnimationFrame(animateFrame)
                    }

                    //requestAnimationFrame(animateFrame);

                    if (urlSearchParams.has("showTextures")) {
                        let textures = ["autoplr_cfg", "autoplr_error", "autoplr_on", "cargo_off", "cargo_on", "earth", "ecothruster_on", "hearty", "hub_off", "hub_on", "landingleg", "landingthruster_off", "landingthruster_on", "powerhub_off", "powerhub_on", "superthruster_off", "superthruster_on", "thruster_off", "thruster_on"];

                        for (let i = 0; i < textures.length; i++) {
                            let texture = textures[i];

                            let fieldset_elem = document.createElement("fieldset");
                            fieldset_elem.style = "width: min-content;";
                            fieldset_elem.classList.add("texturebox")
                            let legend_elem = document.createElement("legend");
                            legend_elem.innerText = texture;

                            let img_elem = document.createElement("img");
                            img_elem.src = get_texture(texture);

                            fieldset_elem.appendChild(legend_elem);
                            fieldset_elem.appendChild(img_elem);
                            document.body.appendChild(fieldset_elem);
                        }
                    }
                });
            })
        </script>
    </body>
                try {
                    render_frame(delta);
                } catch (e) {
                    console.error("error in renderFrame: "+e);
                    return;
                }
                start = time;

                document.getElementById("canvas").getContext("2d").drawImage(document.getElementById("tex-earth"), 0, 0, 150 -2025, 2000, 2000);

                requestAnimationFrame(animateFrame);
            }

            requestAnimationFrame(animateFrame);
        });
    })
</script>
</body>
</html>