misc/graves_js_anim.xhtml
author unC0Rr
Wed, 28 Aug 2024 13:41:51 +0200
changeset 16049 9be943326d9c
parent 16007 20adaa127663
permissions -rw-r--r--
Store all snowflakes in a separate array, achieving performance increase of about 10% for the whole engine on winter maps

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- There is, at present, no official xsd for (X)HTML5. A pity. Usefulness would depend on the parser and extensions made by the site.  -->
    <title>Hedgewars Graves</title>

    <style type="text/css">
* {padding: 0; margin: 0; }
body
{
    background: url('//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Sky.png') fixed no-repeat bottom left;
    background-color: #0B203D;
    color: #FFD902;
    -moz-background-size: 200%;
    background-size: 100% 100%;
    font-family: sans-serif;
}
form, p
{
    background-color: #0B203D;
    padding: 1em;
    margin: 1em;
    border-style: solid;
    border-radius: 5px;
    border-width: 2px;
    border-color: #FFD902;
}
h1 {
    text-shadow: 0 0 2px white;
    color: black;
    margin:10px;
}
a {
    color: #BFBED0;
    text-decoration: none;
}
.grave
{
    margin-top: 12px;
    margin-left: 20px;
    float: left;
    height: 32px;
    width: 32px;
    color: transparent;
}
.girder
{
    width: 100%;
    height: 30px;
    clear: left;
    background-image: url('//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Themes/Nature/Girder.png');
    background-repeat: repeat-x;
}
.hide { visibility: hidden; }
a div
{
    margin-top: 6px;
    height: 32px;
    width: 32px;
}
    </style>
    <script type="application/ecmascript">
//<![CDATA[
let IS_LOCAL=false; // set to true to fetch flags locally. Useful for testing.
let graves;
if (IS_LOCAL) {
/* JavaScript version of a sprite sheet - this could be pretty trivially done in pure HTML, but maintenance
would be easier with a server-side portion. list of sprites could be gotten from server, but would require XSS whitelisting */
// Last updated: 1.0.0
graves=["Badger","Bone","bp2","bubble","Cherry","chest","Clover","coffin",
"deadhog","dragonball","Duck2","Earth","Egg","eyecross","Flower","Ghost",
"Grave","heart","money","mouton1","octopus","Old_Apple","pi","plant2",
"plant3","Plinko","pokeball","pyramid","ring","Rip","Rubberduck","Simple",
"Simple_reversed","skull","star","Statue","TV","Whisky","Yin_and_Yang"];
}
else
{
graves = [];
}

let themes = {
// Last updated: 1.0.0
"Art":1,
"Beach":1,
"Bamboo":1,
"Bath":1,
//"Blox":0, //unused, has no Sky.png or Border.png
"Brick":0,
"Cake":0,
"Castle":1,
"Cave":1,
"City":1,
"Cheese":0,
"Christmas":1,
"Compost":1,
"CrazyMission":0,
"Deepspace":0,
"Desert":1,
"EarthRise":0,
"Eyes":0,
"Freeway":0,
"Fruit":1,
"Halloween":1,
"Hell":0,
"Hoggywood":1,
"Island":0,
"Jungle":1,
"Golf":1,
"Nature":1,
"Olympics":1,
"Planes":0,
"Sheep":1,
"Snow":1,
"Stage":1,
"Underwater":1};
let girder;
let animationInterval;

on_xml_loaded = function(ex)
{
    let resp = this.responseText;
    let r = />([^<]*).png</g;
    let x;
    while(x = r.exec(resp))
    {
        graves.push(x[1]);
    }
    on_graves_loaded();
}

on_xml_error = function()
{
    let p = document.createElement("p");
    p.appendChild(document.createTextNode("ERROR: List of graves could not be fetched from the server!"));
    document.body.appendChild(p);
}

window.onload = function()
{
    // Load list of graves
    if (!IS_LOCAL) {
        // Request list of graves from repository URL
        let xml=new XMLHttpRequest();
        xml.open("GET", "//hg.hedgewars.org/hedgewars/file/tip/share/hedgewars/Data/Graphics/Graves/");
        xml.addEventListener("error", on_xml_error);
        xml.onload = on_xml_loaded;
        xml.send();
    }
    else
    {
        on_graves_loaded();
    }
}

on_graves_loaded = function()
{
    // Render girders
    let s = document.styleSheets[0].cssRules;
    for(let i=0;i<s.length;i++)
    {
        if (s[i].selectorText.toLowerCase() === ".girder")
            girder = s[i];
    }

    let a = document.createElement("a");
    let g = document.createElement("div");
    g.className="girder";
    a.className="grave";
    a.appendChild(document.createElement("div"));
    a.lastChild.appendChild(document.createTextNode(""));

    // Render graves
    let missingGraves = [];
    let img;
    let j = 0;
    let toDelete = [];
    for (let i=0;i<graves.length;i++)
    {
        let h = document.body.appendChild(a.cloneNode(true));
        if (IS_LOCAL)
            h.href = "../share/hedgewars/Data/Graphics/Graves/"+graves[i]+".png";
        else
            h.href = "//hg.hedgewars.org/hedgewars/raw-file/tip/share/hedgewars/Data/Graphics/Graves/"+graves[i]+".png";

        h.lastChild.style.backgroundImage = 'url("'+h.href+'")';
        h.title = graves[i];
        h.idle = Math.floor(Math.random()*16);
        if (j%8 === 7 || i === graves.length-1)
            document.body.appendChild(g.cloneNode(false));
        j++;
    }

    // Quick and dirty animation
    animationInterval = setInterval(animateGraves, 128);

    // Theme selection drop-down list
    let form = document.body.appendChild(document.createElement("form"));

    let opt = document.createElement("option");
    opt.appendChild(document.createTextNode(""));

    let label = document.createElement("label");
    label.htmlFor = "theme_select";
    label.appendChild(document.createTextNode("Theme: "));
    form.appendChild(label);

    let sel = form.appendChild(document.createElement("select"));
    sel.id = "theme_select";
    sel.onchange = switchTheme;
    for(let theme in themes)
    {
        sel.appendChild(opt.cloneNode(true));
        sel.lastChild.value = theme;
        sel.lastChild.lastChild.data = theme;
        if(theme === "Nature")
            sel.lastChild.selected = true;
    }
    form.appendChild(document.createElement("br"));

    // Checkbox: Switch animation
    let chk = document.createElement("input");
    chk.id = "anim";
    chk.type = "checkbox";
    chk.onclick = switchAnim;
    chk.checked = true;
    form.appendChild(chk);
    label = document.createElement("label");
    label.htmlFor = "anim";
    label.appendChild(document.createTextNode(" Animate graves"));
    form.appendChild(label);

    form.appendChild(document.createElement("br"));

    // Checkbox: Hide girders
    chk = document.createElement("input");
    chk.id = "hide_girders";
    chk.type = "checkbox";
    chk.onclick = hideGirders;
    chk.checked = true;
    form.appendChild(chk);
    label = document.createElement("label");
    label.htmlFor = "hide_girders";
    label.appendChild(document.createTextNode(" Show girders"));
    form.appendChild(label);

    document.body.appendChild(form);

    switchTheme();
}

function animateGraves()
{
    let a = document.getElementsByTagName("a");
    for (let i=0;i<a.length;i++)
    {
        if (a[i].className !== "grave")
            continue;
        // Cycle thru animation frames

        let maskName = a[i].title;
        // Grave
        a[i].firstChild.style.backgroundPosition=Math.floor(a[i].idle/16)*-32+"px "+(a[i].idle%16)*-32+"px";

        // Next frame
        a[i].idle++;
        if (a[i].idle > 15)
            a[i].idle = 0;
    }
}

// Turn on or off grave animation
function switchAnim()
{
    if (animationInterval)
    {
        clearInterval(animationInterval);
        animationInterval = null;
    }
    else animationInterval = setInterval(animateGraves, 128);
}

// Turn on or off girders
function hideGirders()
{
    let g = document.getElementsByClassName("girder");
    for(let i=0;i<g.length;i++)
        if (this.checked)
            g[i].className = "girder";
        else
            g[i].className = "girder hide";

}

// Select theme according to drop-down list value
function switchTheme()
{
    let prefix;
    if (!IS_LOCAL)
        prefix = "//hg.hedgewars.org/hedgewars/raw-file/tip";
    else
        prefix = "..";
    let theme = this.value || "Nature";
    document.body.style.backgroundImage='url("'+prefix+'/share/hedgewars/Data/Themes/'+theme+'/Sky.png")';
    if (themes[theme])
        girder.style.backgroundImage='url("'+prefix+'/share/hedgewars/Data/Themes/'+theme+'/Girder.png")';
    else
        girder.style.backgroundImage='url("'+prefix+'/share/hedgewars/Data/Graphics/Girder.png")';
}
//]]>
    </script>
</head>
<body>
<h1>List of Hedgewars graves</h1>
<noscript>
<p><strong>ERROR</strong>: We're so sorry, but this webpage only works with JavaScript enabled. It seems JavaScript is disabled or not supported in your browser.<br/>
Normally, this webpage would display an animated preview of the graves in Hedgewars.</p>
</noscript>
</body>
</html>