This commit is contained in:
derv 2023-11-14 16:00:12 -05:00
commit 417b8577e7
25 changed files with 2546 additions and 0 deletions

12
src/app.html Normal file
View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
%sveltekit.body%
</body>
</html>

37
src/lib/Button.svelte Normal file
View file

@ -0,0 +1,37 @@
<style>
.button {
background: var(--gray);
color: var(--white);
text-decoration: none;
width: 128px;
padding: 10px;
border-radius: 10px;
text-align: center;
display: inline-block;
margin: 10px;
transition: transform 0.3s;
}
.hover-true {
transform: scale(1.2);
}
.icon {
background: var(--teal);
width: 100%;
border-radius: inherit;
}
</style>
<script>
export let href, content, icon;
let hover = false;
</script>
<a class='button hover-{hover}' href={href} on:mouseover={() => hover = true} on:mouseleave={() => hover = false}>
{#if icon}
<img src={icon} class='icon'>
{/if}
{content}
</a>

View file

@ -0,0 +1,51 @@
<script>
import { numString } from "$lib/util.js";
export let currency = {};
</script>
<div class="wrapper">
<img src="/{currency.type}.svg" />
<span class="amount bottom right">{numString(currency.amount)}X</span>
<span class="amount bottom">{numString(currency.perClick)}/1CLK</span>
<span class="amount"
>{numString(currency.perDelay)}/{numString(
currency.delay / 1000
)}SEC</span
>
<span class="amount right">{currency.name}</span>
</div>
<style>
.amount {
position: absolute;
font-weight: bold;
font-family: monospace;
text-align: left;
width: 128px;
height: 128px;
left: 0;
top: 0;
font-size: 0.9em;
filter: drop-shadow(1.5px 1.5px 0 var(--black));
}
.right {
text-align: right;
justify-content: end;
}
.bottom {
display: flex;
align-items: end;
}
.wrapper {
position: relative;
margin: 16px;
}
</style>

View file

@ -0,0 +1,54 @@
<script>
export let factory = {};
export let currencies = {};
let costs = "";
$: {
if (factory.costs) {
costs = Object.entries(factory.costs)
.map((x) => x.join(": "))
.join(", ");
}
}
</script>
<div class="wrapper-wrapper" on:click={() => factory.buy(currencies)}>
<img src="/{factory.type}.svg" />
<a class="wrapper" href="#">
{factory.canUse ? factory.amount + "x" : ""}
{factory.name} (<b>COSTS</b> | {costs}) {factory.canUse
? ""
: "(LOCKED)"}
</a>
</div>
<style>
a {
text-decoration: none;
}
.wrapper-wrapper {
position: relative;
margin: 16px;
width: 128px;
height: 128px;
}
.wrapper {
background: var(--black);
padding: 10px;
color: var(--white);
position: absolute;
top: 100px;
left: 100px;
width: 200px;
z-index: 2;
font-family: monospace;
}
.wrapper-wrapper:hover .wrapper {
display: block;
}
.wrapper-wrapper .wrapper {
display: none;
}
</style>

78
src/lib/clicker.js Normal file
View file

@ -0,0 +1,78 @@
class Currency {
constructor(name, causeUpdate, type) {
this.name = name;
this.amount = 0;
this.perClick = 0;
this.delay = 1000;
this.perDelay = 0;
this.ticks = 0;
this.causeUpdate = causeUpdate;
this.interval = setInterval(() => { this.tick() }, 200);
this.type = type;
}
upgrade({ perClick, delay, perDelay }) {
this.perClick += perClick;
this.delay /= delay;
this.perDelay += perDelay;
clearInterval(this.interval);
this.interval = setInterval(() => { this.tick() }, 200);
this.causeUpdate();
}
click() {
this.amount += this.perClick;
this.causeUpdate();
}
tick() {
this.ticks += 200;
this.amount += Math.floor(this.ticks / this.delay) * this.perDelay;
this.ticks = this.ticks % this.delay;
if (!this.causeUpdate) return;
this.causeUpdate();
}
}
class Factory {
constructor(name, costs, upgrades, costInc, causeUpdate, isUpgrade, type) {
this.name = name;
this.costs = costs;
this.upgrades = upgrades;
this.costInc = costInc;
this.amount = 0;
this.causeUpdate = causeUpdate;
this.isUpgrade = isUpgrade;
this.canUse = true;
this.type = type;
}
buy(currencies) {
if (!this.canUse) return;
for (let currency in this.costs) {
if (this.costs[currency] > currencies[currency].amount) return;
}
for (let currency in this.costs) {
let curr = currencies[currency];
curr.amount -= this.costs[currency];
this.costs[currency] = Math.round(this.costs[currency] * this.costInc);
}
for (let upgrade in this.upgrades) {
currencies[upgrade].upgrade(this.upgrades[upgrade]);
}
if (this.isUpgrade) this.canUse = false;
this.amount++;
this.causeUpdate();
}
}
export {
Currency,
Factory
};

21
src/lib/util.js Normal file
View file

@ -0,0 +1,21 @@
// https://github.com/berezaa/minershaven/blob/d5c8b41ca8ed9f1bd91176ec397e8dff9a259130/src/ReplicatedStorage/MoneyLib.lua#L13
const prefixes = [
"","k","M","B","T","qd","Qn","sx","Sp","O","N","de","Ud","DD","tdD","qdD","QnD","sxD","SpD","OcD","NvD","Vgn","UVg","DVg","TVg","qtV","QnV","SeV","SPG","OVG","NVG","TGN","UTG","DTG","tsTG","qtTG","QnTG","ssTG","SpTG","OcTG","NoTG","QdDR","uQDR","dQDR","tQDR","qdQDR","QnQDR","sxQDR","SpQDR","OQDDr","NQDDr","qQGNT","uQGNT","dQGNT","tQGNT","qdQGNT","QnQGNT","sxQGNT","SpQGNT", "OQQGNT","NQQGNT","SXGNTL"
]
function numString(number) {
let exp = Math.floor(Math.log10(number + 1) / 3);
let base = number / (10 ** (exp*3) );
let prefix = prefixes[exp] || '';
base = (base+'').slice(0, 5);
base += prefix;
if (prefix != '') base = `(${base})`;
return base;
}
export {
numString
}

59
src/routes/+layout.svelte Normal file
View file

@ -0,0 +1,59 @@
<h2>
<a href='https://potatoplusplus.com/'>Potato++</a> |
<a href="https://discord.gg/KnAU3Snc9g">Discord</a>
</h2>
<slot />
<style>
:global(:root) {
--black: rgb(15, 15, 15);
--gray: rgb(54, 53, 61);
--light-gray: rgb(142, 170, 192);
--white: rgb(240, 246, 253);
--teal: rgb(27, 28, 36);
color: var(--white);
font-family: sans-serif;
}
:global(a) {
color: var(--light-gray);
}
:global(body) {
background: var(--teal);
min-height: 100vh;
display: flex;
align-items: center;
flex-direction: column;
}
:global(.row, .left) {
display: flex;
justify-content: start;
flex-direction: column;
width: 50vw;
min-width: 350px;
}
:global(.row) {
align-items: center;
flex-direction: row;
flex-wrap: wrap;
}
:global(img) {
width: 128px;
height: 128px;
}
:global(p) {
margin: 10px;
}
h2 a {
text-decoration: none;
}
</style>

34
src/routes/+page.svelte Normal file
View file

@ -0,0 +1,34 @@
<script>
import Button from "$lib/Button.svelte";
</script>
<section class="left">
<h1 class="row">
<img src="/potatoplusplus.svg" alt="icon" />
<p>Welcome to Potato++</p>
</h1>
<p>
Potato++ is a website where two brothers make games and put them here so
people can play them.
</p>
<section class="row">
<Button href="https://discord.gg/KnAU3Snc9g" content="Discord" />
<Button
href="https://github.com/potato-plus-plus/ppp"
content="Source Code"
/>
</section>
<h1>Games</h1>
<section class="row">
<Button
href="researchclicker"
content="Research Clicker"
icon="/research.svg"
/>
</section>
<h1>Credits</h1>
<section class="row">
<Button href="https://github.com/thepotatoplus" content="Potato" />
<Button href="https://github.com/nanodev-x" content="NDX" />
</section>
</section>

View file

@ -0,0 +1,138 @@
<script>
let technologicalProgression = "Stone";
import { Currency, Factory } from "$lib/clicker.js";
import CurrencyItem from "$lib/CurrencyItem.svelte";
import FactoryItem from "$lib/FactoryItem.svelte";
let causeUpdate = () => {
currencies = { ...currencies };
upgrades = { ...upgrades };
technology.stoneTools.invis = !(upgrades.scientist.amount > 9);
};
let currencies = {
research: new Currency("TECH", causeUpdate, "research"),
land: new Currency("LAND", causeUpdate, "land"),
stone: new Currency("ROCK", causeUpdate, "stone"),
wood: new Currency("WOOD", causeUpdate, "wood"),
dirt: new Currency("DIRT", causeUpdate, "dirt"),
};
currencies.research.perClick = 1;
currencies.stone.delay = 3000;
let upgrades = {
scientist: new Factory(
"Scientist",
{
research: 15,
},
{
research: {
perClick: 0,
delay: 1,
perDelay: 1,
},
},
1.1,
causeUpdate,
false,
"scientist"
),
miner: new Factory(
"Miner",
{
stone: 10,
},
{
stone: {
perClick: 0,
delay: 1,
perDelay: 1,
},
},
1.1,
causeUpdate,
false,
"miner"
),
};
let technology = {
rockfinding: new Factory(
"Rock Finding",
{
research: 15,
},
{
stone: {
perClick: 0.1,
delay: 1,
perDelay: 0,
},
},
1.1,
causeUpdate,
true,
"stone"
),
stoneTools: new Factory(
"Stone Tools",
{
research: 100,
stone: 50,
},
{
stone: {
perClick: 0.1,
delay: 1,
perDelay: 0,
},
},
1.1,
causeUpdate,
true,
"research"
),
};
</script>
<h1>{technologicalProgression} Age</h1>
<a
on:click={() => {
for (let currency in currencies) {
currencies[currency].click();
}
}}><img src="/research.svg" /></a
>
<p>Click to <b>Research</b></p>
<h2>Raw Resources</h2>
<section class="row">
{#each Object.values(currencies) as currency}
{#if !currency.invis}
<CurrencyItem {currency} />
{/if}
{/each}
</section>
<h2>Generators</h2>
<section class="row">
{#each Object.values(upgrades) as upgrade}
{#if !upgrade.invis}
<FactoryItem factory={upgrade} {currencies} />
{/if}
{/each}
</section>
<h2>Research</h2>
<section class="row">
{#each Object.values(technology) as upgrade}
{#if !upgrade.invis}
<FactoryItem factory={upgrade} {currencies} />
{/if}
{/each}
</section>