mirror of
https://github.com/zyllian/zyllian.github.io.git
synced 2025-05-09 10:06:42 -07:00
add very basic clicker game
This commit is contained in:
parent
3ccd5b0df8
commit
19ffac4a90
9 changed files with 335 additions and 17 deletions
|
@ -1,7 +1,7 @@
|
||||||
base_url: "https://zyl.gay"
|
base_url: "https://zyl.gay"
|
||||||
title: zyl is gay
|
title: zyl is gay
|
||||||
description: "zyl's website."
|
description: "zyl's website."
|
||||||
sass_styles: [index.scss, "pet.scss"]
|
sass_styles: [index.scss, pet.scss, click.scss]
|
||||||
images_per_page: 10
|
images_per_page: 10
|
||||||
blog_posts_per_page: 20
|
blog_posts_per_page: 20
|
||||||
cdn_url: "https://i.zyl.gay"
|
cdn_url: "https://i.zyl.gay"
|
||||||
|
|
10
site/pages/click.md
Normal file
10
site/pages/click.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
title: click
|
||||||
|
scripts: ["js/click.js"]
|
||||||
|
styles: ["click.css"]
|
||||||
|
embed:
|
||||||
|
title: click
|
||||||
|
site_name: zyl.gay
|
||||||
|
description: click click click
|
||||||
|
extra: click
|
||||||
|
---
|
11
site/pages/games.md
Normal file
11
site/pages/games.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
title: games!
|
||||||
|
---
|
||||||
|
|
||||||
|
# games
|
||||||
|
|
||||||
|
little games i've made on here :3
|
||||||
|
|
||||||
|
<h2><a href="/pet">pet game</a></h2>
|
||||||
|
|
||||||
|
<h2><a href="/click">clicker game</a></h2>
|
222
site/root/js/click.js
Normal file
222
site/root/js/click.js
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const click = document.querySelector("#click");
|
||||||
|
const petsCounter = click.querySelector("#pets");
|
||||||
|
const petsPerSecondCounter = click.querySelector("#pets-per-second");
|
||||||
|
const barksCounter = click.querySelector("#barks");
|
||||||
|
const barksPerSecondCounter = click.querySelector("#barks-per-second");
|
||||||
|
const kissesCounter = click.querySelector("#kisses");
|
||||||
|
const kissesPerSecondCounter = click.querySelector("#kisses-per-second");
|
||||||
|
const barker = click.querySelector("#barker");
|
||||||
|
const toolsEl = click.querySelector(".tools");
|
||||||
|
|
||||||
|
const toolPriceFactor = 0.1;
|
||||||
|
const upgradePriceFactor = 0.2;
|
||||||
|
const upgradeProductionFactor = 1.1;
|
||||||
|
|
||||||
|
const toolData = {
|
||||||
|
hand: {
|
||||||
|
priceIn: "barks",
|
||||||
|
basePrice: 10,
|
||||||
|
petsPerSecond: 0.5,
|
||||||
|
},
|
||||||
|
puppy: {
|
||||||
|
priceIn: "pets",
|
||||||
|
basePrice: 5,
|
||||||
|
barksPerSecond: 0.5,
|
||||||
|
},
|
||||||
|
foodBowl: {
|
||||||
|
priceIn: "barks",
|
||||||
|
basePrice: 50,
|
||||||
|
barksPerSecond: 1.3,
|
||||||
|
},
|
||||||
|
kisser: {
|
||||||
|
priceIn: "pets",
|
||||||
|
basePrice: 500,
|
||||||
|
kissesPerSecond: 0.25,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let barks = 0;
|
||||||
|
let pets = 0;
|
||||||
|
let kisses = 0;
|
||||||
|
let tools = {};
|
||||||
|
|
||||||
|
let petsPerSecond = 0;
|
||||||
|
let barksPerSecond = 0;
|
||||||
|
let kissesPerSecond = 0;
|
||||||
|
|
||||||
|
function calcPrice(base, count) {
|
||||||
|
return Math.floor(base ** (1 + toolPriceFactor * count));
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcUpgradePrice(base, count) {
|
||||||
|
return Math.floor((base * 2) ** (1 + upgradePriceFactor * count));
|
||||||
|
}
|
||||||
|
|
||||||
|
const getValue = (name) => {
|
||||||
|
if (name === "pets") {
|
||||||
|
return pets;
|
||||||
|
} else if (name === "barks") {
|
||||||
|
return barks;
|
||||||
|
} else if (name === "kisses") {
|
||||||
|
return kisses;
|
||||||
|
} else if (name === "petsPerSecond") {
|
||||||
|
return petsPerSecond;
|
||||||
|
} else if (name === "barksPerSecond") {
|
||||||
|
return barksPerSecond;
|
||||||
|
} else if (name === "kissesPerSecond") {
|
||||||
|
return kissesPerSecond;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setValue = (name, value) => {
|
||||||
|
if (name === "pets") {
|
||||||
|
pets = value;
|
||||||
|
} else if (name === "barks") {
|
||||||
|
barks = value;
|
||||||
|
} else if (name === "kisses") {
|
||||||
|
kisses = value;
|
||||||
|
} else if (name === "petsPerSecond") {
|
||||||
|
petsPerSecond = value;
|
||||||
|
} else if (name === "barksPerSecond") {
|
||||||
|
barksPerSecond = value;
|
||||||
|
} else if (name === "kissesPerSecond") {
|
||||||
|
kissesPerSecond = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updatePerSecondValues = () => {
|
||||||
|
let pets = 0;
|
||||||
|
let barks = 0;
|
||||||
|
let kisses = 0;
|
||||||
|
|
||||||
|
for (const [id, tool] of Object.entries(tools)) {
|
||||||
|
pets +=
|
||||||
|
(toolData[id].petsPerSecond || 0) *
|
||||||
|
tool.count *
|
||||||
|
tool.upgrades *
|
||||||
|
upgradeProductionFactor;
|
||||||
|
barks +=
|
||||||
|
(toolData[id].barksPerSecond || 0) *
|
||||||
|
tool.count *
|
||||||
|
tool.upgrades *
|
||||||
|
upgradeProductionFactor;
|
||||||
|
kisses +=
|
||||||
|
(toolData[id].kissesPerSecond || 0) *
|
||||||
|
tool.count *
|
||||||
|
tool.upgrades *
|
||||||
|
upgradeProductionFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
petsPerSecond = pets;
|
||||||
|
barksPerSecond = barks;
|
||||||
|
kissesPerSecond = kisses;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateDisplay = () => {
|
||||||
|
petsCounter.innerText = pets;
|
||||||
|
petsPerSecondCounter.innerText = petsPerSecond.toFixed(2);
|
||||||
|
barksCounter.innerText = barks;
|
||||||
|
barksPerSecondCounter.innerText = barksPerSecond.toFixed(2);
|
||||||
|
kissesCounter.innerText = kisses;
|
||||||
|
kissesPerSecondCounter.innerText = kissesPerSecond.toFixed(2);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const el of toolsEl.querySelectorAll(".tool")) {
|
||||||
|
const id = el.getAttribute("data-tool");
|
||||||
|
if (id) {
|
||||||
|
const data = toolData[id];
|
||||||
|
if (data) {
|
||||||
|
const toolInfo = {
|
||||||
|
count: 0,
|
||||||
|
upgrades: 1,
|
||||||
|
};
|
||||||
|
tools[id] = toolInfo;
|
||||||
|
|
||||||
|
const count = el.querySelector(".count");
|
||||||
|
const level = el.querySelector(".level");
|
||||||
|
const buy = el.querySelector(".buy");
|
||||||
|
const upgrade = el.querySelector(".upgrade");
|
||||||
|
|
||||||
|
const updateText = () => {
|
||||||
|
count.innerText = toolInfo.count;
|
||||||
|
level.innerText = toolInfo.upgrades;
|
||||||
|
const price = calcPrice(data.basePrice, toolInfo.count);
|
||||||
|
const upgradePrice = calcUpgradePrice(
|
||||||
|
data.basePrice,
|
||||||
|
toolInfo.upgrades
|
||||||
|
);
|
||||||
|
buy.innerText = `buy - ${price} ${data.priceIn}`;
|
||||||
|
upgrade.innerText = `upgrade - ${upgradePrice} kisses`;
|
||||||
|
};
|
||||||
|
updateText();
|
||||||
|
|
||||||
|
buy.addEventListener("click", () => {
|
||||||
|
const price = calcPrice(data.basePrice, toolInfo.count);
|
||||||
|
const v = getValue(data.priceIn);
|
||||||
|
if (v >= price) {
|
||||||
|
setValue(data.priceIn, v - price);
|
||||||
|
toolInfo.count += 1;
|
||||||
|
updatePerSecondValues();
|
||||||
|
updateText();
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
upgrade.addEventListener("click", () => {
|
||||||
|
const price = calcUpgradePrice(data.basePrice, toolInfo.upgrades);
|
||||||
|
if (kisses >= price) {
|
||||||
|
kisses -= price;
|
||||||
|
toolInfo.upgrades += 1;
|
||||||
|
updatePerSecondValues();
|
||||||
|
updateText();
|
||||||
|
updateDisplay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
barker.addEventListener("click", () => {
|
||||||
|
barks += 1;
|
||||||
|
updateDisplay();
|
||||||
|
});
|
||||||
|
|
||||||
|
let lastUpdate = 0;
|
||||||
|
let petsQueued = 0;
|
||||||
|
let barksQueued = 0;
|
||||||
|
let kissesQueued = 0;
|
||||||
|
|
||||||
|
const checkQueue = (name, queued) => {
|
||||||
|
const perSecond = getValue(`${name}PerSecond`);
|
||||||
|
if (perSecond > 0) {
|
||||||
|
const amount = 1000 / perSecond;
|
||||||
|
const toAdd = Math.floor(queued / amount);
|
||||||
|
setValue(name, getValue(name) + toAdd);
|
||||||
|
updateDisplay();
|
||||||
|
queued -= toAdd * amount;
|
||||||
|
} else {
|
||||||
|
queued = 0;
|
||||||
|
}
|
||||||
|
return queued;
|
||||||
|
};
|
||||||
|
|
||||||
|
const update = (ts) => {
|
||||||
|
requestAnimationFrame(update);
|
||||||
|
|
||||||
|
const diff = ts - lastUpdate;
|
||||||
|
petsQueued += diff;
|
||||||
|
barksQueued += diff;
|
||||||
|
kissesQueued += diff;
|
||||||
|
|
||||||
|
petsQueued = checkQueue("pets", petsQueued);
|
||||||
|
barksQueued = checkQueue("barks", barksQueued);
|
||||||
|
kissesQueued = checkQueue("kisses", kissesQueued);
|
||||||
|
|
||||||
|
lastUpdate = ts;
|
||||||
|
};
|
||||||
|
|
||||||
|
requestAnimationFrame(update);
|
||||||
|
})();
|
27
site/sass/click.scss
Normal file
27
site/sass/click.scss
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#click {
|
||||||
|
.resources {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 0fr);
|
||||||
|
grid-auto-flow: row;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
margin-right: 5px;
|
||||||
|
width: max-content;
|
||||||
|
|
||||||
|
&.resource {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#barker {
|
||||||
|
font-size: 2rem;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
.name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
<span class="pronouns">it/puppy(/she)</span>
|
<span class="pronouns">it/puppy(/she)</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
<a href="/pet">creature</a> |
|
<a href="/games">games</a> |
|
||||||
<a href="/projects">my projects</a> |
|
<a href="/projects">my projects</a> |
|
||||||
<a href="/blog/">blog</a> |
|
<a href="/blog/">blog</a> |
|
||||||
<a href="/images/">images</a> |
|
<a href="/images/">images</a> |
|
||||||
|
|
30
site/templates/extras/click.hbs
Normal file
30
site/templates/extras/click.hbs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<div id="click">
|
||||||
|
<p>WARNING: no save mechanic is implemented yet!!</p>
|
||||||
|
<h1>click</h1>
|
||||||
|
<noscript>
|
||||||
|
<h1>javascript is required for the clicker game!!</h1>
|
||||||
|
</noscript>
|
||||||
|
<div class="resources">
|
||||||
|
{{#*inline "resource"}}
|
||||||
|
<span class="resource">{{name}}</span><span id={{id}}>0</span> <span>(<span
|
||||||
|
id="{{id}}-per-second">0</span>/s)</span>
|
||||||
|
{{/inline}}
|
||||||
|
{{> resource id="pets" name="pets"}}
|
||||||
|
{{> resource id="barks" name="barks"}}
|
||||||
|
{{> resource id="kisses" name="kisses"}}
|
||||||
|
</div>
|
||||||
|
<button id="barker">bark</button>
|
||||||
|
<div class="tools">
|
||||||
|
{{#*inline "tool"}}
|
||||||
|
<div class="tool" data-tool={{id}}>
|
||||||
|
<p class="name">{{name}} (<span class="count">0</span>, lvl <span class="level">1</span>)</p>
|
||||||
|
<p class="description">{{description}}</p>
|
||||||
|
<button class="buy">buy</button> <button class="upgrade">upgrade</button>
|
||||||
|
</div>
|
||||||
|
{{/inline}}
|
||||||
|
{{> tool id="hand" name="hand" description="don't bite the hand that pets you"}}
|
||||||
|
{{> tool id="puppy" name="puppy" description="arf arf wruff :3"}}
|
||||||
|
{{> tool id="foodBowl" name="food bowl" description="more food for more barking"}}
|
||||||
|
{{> tool id="kisser" name="kisser wow" description="someone to kiss all those poor puppies,,"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -10,9 +10,7 @@ use pulldown_cmark::{Options, Parser};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::{
|
use crate::{resource::ResourceBuilder, util, PageMetadata, Site, ROOT_PATH, SASS_PATH};
|
||||||
extras::Extra, resource::ResourceBuilder, util, PageMetadata, Site, ROOT_PATH, SASS_PATH,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Struct containing data to be sent to templates when rendering them.
|
/// Struct containing data to be sent to templates when rendering them.
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -283,8 +281,8 @@ impl<'a> SiteBuilder<'a> {
|
||||||
// Modify HTML output
|
// Modify HTML output
|
||||||
let mut out = self.rewrite_html(out)?;
|
let mut out = self.rewrite_html(out)?;
|
||||||
|
|
||||||
if let Some(Extra::HtmlModification(f)) = extra {
|
if let Some(extra) = extra {
|
||||||
out = f(out, self)?;
|
out = extra.handle(out, self)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.serving {
|
if !self.serving {
|
||||||
|
|
|
@ -5,17 +5,46 @@ use crate::{blog::BlogPostMetadata, builder::SiteBuilder, resource::ResourceTemp
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Extra {
|
pub enum Extra {
|
||||||
|
Basic(&'static str),
|
||||||
HtmlModification(fn(page: String, builder: &SiteBuilder) -> eyre::Result<String>),
|
HtmlModification(fn(page: String, builder: &SiteBuilder) -> eyre::Result<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Extra {
|
||||||
|
/// runs the handler for the extra
|
||||||
|
pub fn handle(&self, page: String, builder: &SiteBuilder) -> eyre::Result<String> {
|
||||||
|
match self {
|
||||||
|
Self::Basic(template) => {
|
||||||
|
println!("{template}");
|
||||||
|
let content = builder.reg.render(template, &())?;
|
||||||
|
append_to(&page, &content, "main.page")
|
||||||
|
}
|
||||||
|
Self::HtmlModification(f) => (f)(page, builder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the extra for the given value.
|
/// Gets the extra for the given value.
|
||||||
pub fn get_extra(extra: &str) -> Option<Extra> {
|
pub fn get_extra(extra: &str) -> Option<Extra> {
|
||||||
match extra {
|
match extra {
|
||||||
"index" => Some(Extra::HtmlModification(index)),
|
"index" => Some(Extra::HtmlModification(index)),
|
||||||
|
"click" => Some(Extra::Basic("extras/click")),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn append_to(page: &str, content: &str, selector: &str) -> eyre::Result<String> {
|
||||||
|
Ok(lol_html::rewrite_str(
|
||||||
|
page,
|
||||||
|
RewriteStrSettings {
|
||||||
|
element_content_handlers: vec![element!(selector, move |el| {
|
||||||
|
el.append(content, lol_html::html_content::ContentType::Html);
|
||||||
|
Ok(())
|
||||||
|
})],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)?)
|
||||||
|
}
|
||||||
|
|
||||||
/// Extra to add a sidebar to the index page with recent blog posts on it.
|
/// Extra to add a sidebar to the index page with recent blog posts on it.
|
||||||
fn index(page: String, builder: &SiteBuilder) -> eyre::Result<String> {
|
fn index(page: String, builder: &SiteBuilder) -> eyre::Result<String> {
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -42,14 +71,5 @@ fn index(page: String, builder: &SiteBuilder) -> eyre::Result<String> {
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(lol_html::rewrite_str(
|
append_to(&page, &sidebar, "#content")
|
||||||
&page,
|
|
||||||
RewriteStrSettings {
|
|
||||||
element_content_handlers: vec![element!("#content", move |el| {
|
|
||||||
el.append(&sidebar, lol_html::html_content::ContentType::Html);
|
|
||||||
Ok(())
|
|
||||||
})],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue