mirror of
https://github.com/zyllian/zyllian.github.io.git
synced 2025-01-18 03:32:30 -08:00
pet logic is implemented!!
This commit is contained in:
parent
b43bcb8a7e
commit
fde22ee9c2
3 changed files with 279 additions and 34 deletions
|
@ -4,22 +4,50 @@ scripts: ["js/pet.js"]
|
|||
styles: ["pet.css"]
|
||||
---
|
||||
|
||||
<div id="pet">
|
||||
<noscript><p>javascript is required for the pet game!!</p></noscript>
|
||||
<div id="pet-display">
|
||||
<h2 class="pet-name"></h2>
|
||||
<p>--pet placeholder here--</p>
|
||||
<!-- TODO: make pets interactable -->
|
||||
</div>
|
||||
|
||||
<div id="egg">
|
||||
<p>whoa! you just found an egg somewhere! maybe you should watch it and see what happens..</p>
|
||||
<p>whoa! you just found a weird egg! maybe you should watch it and see what happens..</p>
|
||||
</div>
|
||||
|
||||
<div id="pet-setup" class="hidden">
|
||||
<div id="adult-info" class="hidden">
|
||||
<p><span class="pet-name"></span> has grown up to be an adult!! what will they do with their life now....</p>
|
||||
<button class="advance">okay!</button>
|
||||
</div>
|
||||
|
||||
<div id="elder-info" class="hidden">
|
||||
<p>oh? <span class="pet-name"></span> has aged and is now an elder creature! they may not have much left in their life.... hopefully it's been a good life!</p>
|
||||
<button class="advance">hopefully!!</button>
|
||||
</div>
|
||||
|
||||
<div id="passed-away-info" class="hidden">
|
||||
<p>oh... <span class="pet-name"></span> has finally gone and kicked the bucket. its story comes to an end....</p>
|
||||
<button>but what's this egg lying here about..?</button>
|
||||
</div>
|
||||
|
||||
<form id="pet-setup" class="hidden">
|
||||
<p>whoa! your egg just hatched into a new creature! what should you name it?</p>
|
||||
<input type="text" name="pet-name" max-length="50">
|
||||
<button>name it!</button>
|
||||
<input type="text" name="pet-name" min-length="3" max-length="50">
|
||||
<button type="submit">name it!</button>
|
||||
</form>
|
||||
|
||||
<div id="pet-actions">
|
||||
<div name="hatched-actions" class="hidden">
|
||||
<button name="feed">feed</button>
|
||||
<button name="pet">pet</button>
|
||||
<button name="clean">clean</button>
|
||||
</div>
|
||||
<button name="pause">pause</button>
|
||||
</div>
|
||||
|
||||
<div id="debug-section">
|
||||
<button id="force-update">force update</button>
|
||||
<p>LS: <span name="ls"></span> A: <span name="a"></span> F: <span name="f"></span> B: <span name="b"></span> P: <span name="p"></span></p>
|
||||
<div id="debug-section" class="hidden">
|
||||
<button id="force-update">force update</button> <button id="reset">reset</button>
|
||||
<p>LS: <span name="ls"></span> A: <span name="a"></span> F: <span name="f"></span> B: <span name="b"></span> P: <span name="p"></span> MC: <span name="mc"></span> H: <span name="h"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
(function () {
|
||||
"use strict";
|
||||
|
||||
const UPDATES_PER_MINUTE = 2;
|
||||
const UPDATES_PER_HOUR = UPDATES_PER_MINUTE * 60;
|
||||
const UPDATES_PER_DAY = UPDATES_PER_HOUR * 24;
|
||||
|
||||
/** the current pet version.. */
|
||||
const CURRENT_PET_VERSION = 1;
|
||||
/** the max food a pet will eat */
|
||||
|
@ -8,11 +12,37 @@
|
|||
/** the amount of time it takes for a pet to have to GO */
|
||||
const POTTY_TIME = 100;
|
||||
/** how fast a pet's food value decays */
|
||||
const FOOD_DECAY = 5;
|
||||
const FOOD_DECAY = MAX_FOOD / (UPDATES_PER_HOUR * 8); // to stay on top should be fed roughly once every 8 hours?
|
||||
/** the rate at which a pet ages */
|
||||
const AGING_RATE = 1;
|
||||
/** how fast a pet's potty need decays */
|
||||
const POTTY_DECAY = 5;
|
||||
const POTTY_DECAY = FOOD_DECAY / 2; // roughly every 4 hours?
|
||||
/** how much mess can be in a pet's space at once */
|
||||
const MAX_MESS = 5;
|
||||
/** how fast a pet's happiness decays */
|
||||
const HAPPINESS_DECAY = FOOD_DECAY;
|
||||
/** a pet's maximum happiness */
|
||||
const MAX_HAPPINESS = 100;
|
||||
/** how quickly a pet's happiness will be reduced by when hungry */
|
||||
const HAPPINESS_EMPTY_STOMACH_MODIFIER = -10 / UPDATES_PER_HOUR;
|
||||
/** how quickly a pet's happiness will be reduced by when their space is messy, per piece of mess */
|
||||
const HAPPINESS_MESS_MODIFIER = -5 / UPDATES_PER_HOUR;
|
||||
|
||||
/** the amount of happiness gained when the pet is fed (excluding when the pet doesn't yet need food) */
|
||||
const FEED_HAPPINESS = 5;
|
||||
/** the amount of happiness gained when the pet is pet */
|
||||
const PET_HAPPINESS = 20;
|
||||
/** the amount of happiness gained when the pet's space is cleaned */
|
||||
const CLEAN_HAPPINESS = 1;
|
||||
|
||||
/** the minimum amount of time between feedings */
|
||||
const FEED_TIMER = 5000;
|
||||
/** the minimum amount of time between pets */
|
||||
const PET_TIMER = 2000;
|
||||
/** the minimum amount of time between cleans */
|
||||
const CLEAN_TIMER = 5000;
|
||||
|
||||
const PET_SAVE_KEY = "pet-game";
|
||||
|
||||
/** life stage for an egg */
|
||||
const LIFE_STAGE_EGG = 1;
|
||||
|
@ -23,25 +53,45 @@
|
|||
/** life stage for an elder pet */
|
||||
const LIFE_STAGE_ELDER = 4;
|
||||
/** the time it takes for a pet to grow past the egg phase */
|
||||
const EGG_TIME = 2;
|
||||
const EGG_TIME = UPDATES_PER_MINUTE;
|
||||
/** the time it takes for a pet to grow past the pup phase */
|
||||
const PUP_TIME = 300;
|
||||
const PUP_TIME = UPDATES_PER_DAY * 7;
|
||||
/** the time it takes for a pet to grow past the adult phase */
|
||||
const ADULT_TIME = 900;
|
||||
const ADULT_TIME = UPDATES_PER_DAY * 15;
|
||||
/** the time it takes for a pet to grow past the elder phase */
|
||||
const ELDER_TIME = 300;
|
||||
const ELDER_TIME = UPDATES_PER_DAY * 7;
|
||||
|
||||
const petDisplay = document.querySelector("#pet-display");
|
||||
const petName = document.querySelectorAll(".pet-name");
|
||||
const eggDiv = document.querySelector("div#egg");
|
||||
const petSetup = document.querySelector("div#pet-setup");
|
||||
const petSetup = document.querySelector("#pet-setup");
|
||||
const adultInfo = document.querySelector("div#adult-info");
|
||||
const elderInfo = document.querySelector("div#elder-info");
|
||||
const passedAwayInfo = document.querySelector("div#passed-away-info");
|
||||
const name = petSetup.querySelector("input[name=pet-name]");
|
||||
const nameItButton = petSetup.querySelector("button");
|
||||
|
||||
const petActions = document.querySelector("div#pet-actions");
|
||||
const pauseButton = petActions.querySelector("button[name=pause]");
|
||||
const hatchedActions = petActions.querySelector("div[name=hatched-actions]");
|
||||
const feedButton = hatchedActions.querySelector("button[name=feed]");
|
||||
const petButton = hatchedActions.querySelector("button[name=pet]");
|
||||
const cleanButton = hatchedActions.querySelector("button[name=clean]");
|
||||
|
||||
const debug = document.querySelector("div#debug-section");
|
||||
const debugLifeStage = debug.querySelector("span[name=ls]");
|
||||
const debugAge = debug.querySelector("span[name=a]");
|
||||
const debugFood = debug.querySelector("span[name=f]");
|
||||
const debugBehavior = debug.querySelector("span[name=b]");
|
||||
const debugPotty = debug.querySelector("span[name=p]");
|
||||
const debugMessCounter = debug.querySelector("span[name=mc]");
|
||||
const debugHappiness = debug.querySelector("span[name=h]");
|
||||
const forceUpdateButton = debug.querySelector("button#force-update");
|
||||
const resetButton = debug.querySelector("button#reset");
|
||||
|
||||
let canFeed = true;
|
||||
let canPet = true;
|
||||
let canClean = true;
|
||||
|
||||
/**
|
||||
* class containing information about a pet
|
||||
|
@ -55,6 +105,8 @@
|
|||
alive = true;
|
||||
/** whether the pet simulation is paused */
|
||||
paused = false;
|
||||
/** whether the pet simulation needs an interactive advancement */
|
||||
needsAdvancement = false;
|
||||
/** the pet's current life stage */
|
||||
lifeStage = LIFE_STAGE_EGG;
|
||||
/** the pet's name */
|
||||
|
@ -67,6 +119,10 @@
|
|||
behavior = 0;
|
||||
/** how long until the pet needs to go potty */
|
||||
pottyTimer = POTTY_TIME;
|
||||
/** how much mess the pet has made */
|
||||
messCounter = 0;
|
||||
/** the pet's current happiness */
|
||||
#happiness = MAX_HAPPINESS;
|
||||
/** the time the pet was last updated */
|
||||
lastUpdate = Date.now();
|
||||
/** the time the egg was found */
|
||||
|
@ -78,50 +134,55 @@
|
|||
* updates a pet
|
||||
*/
|
||||
update() {
|
||||
if (!this.alive || this.paused) {
|
||||
if (!this.alive || this.paused || this.needsAdvancement) {
|
||||
return;
|
||||
}
|
||||
console.log("update");
|
||||
|
||||
this.lastUpdate = Date.now();
|
||||
this.age += AGING_RATE;
|
||||
|
||||
if (this.lifeStage !== LIFE_STAGE_EGG) {
|
||||
this.food -= FOOD_DECAY;
|
||||
this.pottyTimer -= POTTY_DECAY;
|
||||
this.happiness -= HAPPINESS_DECAY;
|
||||
|
||||
if (this.food < 0) {
|
||||
this.happiness += HAPPINESS_EMPTY_STOMACH_MODIFIER;
|
||||
this.food = 0;
|
||||
if (this.canDie) {
|
||||
// TODO: pet dies
|
||||
} else {
|
||||
this.food = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.pottyTimer < 0) {
|
||||
this.goPotty();
|
||||
}
|
||||
for (let i = 0; i < this.messCounter; i++) {
|
||||
this.happiness += HAPPINESS_MESS_MODIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.lifeStage === LIFE_STAGE_EGG && this.age >= EGG_TIME) {
|
||||
this.paused = true;
|
||||
this.needsAdvancement = true;
|
||||
this.lifeStage = LIFE_STAGE_PUP;
|
||||
this.age = 0;
|
||||
} else if (this.lifeStage === LIFE_STAGE_PUP && this.age >= PUP_TIME) {
|
||||
this.paused = true;
|
||||
this.needsAdvancement = true;
|
||||
this.lifeStage = LIFE_STAGE_ADULT;
|
||||
this.age = 0;
|
||||
} else if (
|
||||
this.lifeStage === LIFE_STAGE_ADULT &&
|
||||
this.age >= ADULT_TIME
|
||||
) {
|
||||
this.paused = true;
|
||||
this.needsAdvancement = true;
|
||||
this.lifeStage = LIFE_STAGE_ELDER;
|
||||
this.age = 0;
|
||||
} else if (
|
||||
this.lifeStage === LIFE_STAGE_ELDER &&
|
||||
this.age >= ELDER_TIME
|
||||
) {
|
||||
this.paused = true;
|
||||
this.needsAdvancement = true;
|
||||
this.alive = false;
|
||||
// TODO: DEATH
|
||||
}
|
||||
|
@ -134,15 +195,27 @@
|
|||
updateDom() {
|
||||
eggDiv.classList.add("hidden");
|
||||
petSetup.classList.add("hidden");
|
||||
hatchedActions.classList.remove("hidden");
|
||||
|
||||
if (this.lifeStage === LIFE_STAGE_EGG) {
|
||||
eggDiv.classList.remove("hidden");
|
||||
hatchedActions.classList.add("hidden");
|
||||
} else if (this.lifeStage === LIFE_STAGE_PUP) {
|
||||
if (this.paused && this.name === "") {
|
||||
if (this.needsAdvancement) {
|
||||
petSetup.classList.remove("hidden");
|
||||
}
|
||||
} else if (this.lifeStage === LIFE_STAGE_ADULT) {
|
||||
if (this.needsAdvancement) {
|
||||
adultInfo.classList.remove("hidden");
|
||||
}
|
||||
} else if (this.lifeStage === LIFE_STAGE_ELDER) {
|
||||
if (this.needsAdvancement) {
|
||||
if (this.alive) {
|
||||
elderInfo.classList.remove("hidden");
|
||||
} else {
|
||||
passedAwayInfo.classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugLifeStage.innerText = this.lifeStage;
|
||||
|
@ -150,6 +223,10 @@
|
|||
debugFood.innerText = this.food;
|
||||
debugBehavior.innerText = this.behavior;
|
||||
debugPotty.innerText = this.pottyTimer;
|
||||
debugMessCounter.innerText = this.messCounter;
|
||||
debugHappiness.innerText = this.happiness;
|
||||
|
||||
this.save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,6 +238,10 @@
|
|||
return;
|
||||
}
|
||||
this.food += amount;
|
||||
if (this.food <= MAX_FOOD) {
|
||||
this.happiness += FEED_HAPPINESS;
|
||||
}
|
||||
this.updateDom();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,34 +251,164 @@
|
|||
if (this.behavior > 15) {
|
||||
// go potty properly
|
||||
} else {
|
||||
// make a mess of that shit
|
||||
this.messCounter += 1;
|
||||
if (this.messCounter > MAX_MESS) {
|
||||
this.messCounter = MAX_MESS;
|
||||
}
|
||||
}
|
||||
this.pottyTimer = POTTY_TIME;
|
||||
pet.updateDom();
|
||||
}
|
||||
|
||||
/**
|
||||
* pets the pet
|
||||
*/
|
||||
pet() {
|
||||
this.behavior += 0.5;
|
||||
this.happiness += PET_HAPPINESS;
|
||||
pet.updateDom();
|
||||
}
|
||||
|
||||
/**
|
||||
* cleans the pet's space
|
||||
*/
|
||||
clean() {
|
||||
if (this.messCounter > 0) {
|
||||
this.messCounter -= 1;
|
||||
this.happiness += CLEAN_HAPPINESS;
|
||||
} else {
|
||||
this.behavior += 1;
|
||||
this.happiness -= CLEAN_HAPPINESS;
|
||||
}
|
||||
pet.updateDom();
|
||||
}
|
||||
|
||||
/**
|
||||
* saves the pet
|
||||
*/
|
||||
save() {
|
||||
localStorage.setItem(PET_SAVE_KEY, JSON.stringify(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* loads the pet
|
||||
*/
|
||||
load() {
|
||||
const item = localStorage.getItem(PET_SAVE_KEY);
|
||||
if (item != undefined) {
|
||||
const loaded = JSON.parse(localStorage.getItem(PET_SAVE_KEY));
|
||||
for (let k of Object.keys(loaded)) {
|
||||
this[k] = loaded[k];
|
||||
}
|
||||
this.version = CURRENT_PET_VERSION;
|
||||
this.updateDom();
|
||||
}
|
||||
}
|
||||
|
||||
/** whether the pet can be updated */
|
||||
get canUpdate() {
|
||||
return !this.paused && !this.needsAdvancement;
|
||||
}
|
||||
|
||||
/** the pet's happiness */
|
||||
get happiness() {
|
||||
return this.#happiness;
|
||||
}
|
||||
|
||||
set happiness(amount) {
|
||||
if (amount < 0) {
|
||||
amount = 0;
|
||||
} else if (amount > MAX_HAPPINESS) {
|
||||
amount = MAX_HAPPINESS;
|
||||
}
|
||||
this.#happiness = amount;
|
||||
}
|
||||
}
|
||||
|
||||
let pet = new Pet();
|
||||
pet.updateDom();
|
||||
|
||||
nameItButton.addEventListener("click", () => {
|
||||
petSetup.addEventListener("submit", (e) => {
|
||||
e.preventDefault();
|
||||
const newName = name.value;
|
||||
console.log(newName);
|
||||
if (newName.trim().length === 0) {
|
||||
return;
|
||||
}
|
||||
pet.name = newName;
|
||||
pet.paused = false;
|
||||
for (let name of petName) {
|
||||
name.innerText = pet.name;
|
||||
}
|
||||
pet.hatched = Date.now();
|
||||
pet.needsAdvancement = false;
|
||||
pet.updateDom();
|
||||
});
|
||||
|
||||
feedButton.addEventListener("click", () => {
|
||||
if (!canFeed || !pet.canUpdate) {
|
||||
return;
|
||||
}
|
||||
canFeed = false;
|
||||
setTimeout(() => {
|
||||
canFeed = true;
|
||||
}, FEED_TIMER);
|
||||
|
||||
pet.feed(38);
|
||||
});
|
||||
|
||||
petButton.addEventListener("click", () => {
|
||||
if (!canPet || !pet.canUpdate) {
|
||||
return;
|
||||
}
|
||||
canPet = false;
|
||||
setTimeout(() => {
|
||||
canPet = true;
|
||||
}, PET_TIMER);
|
||||
|
||||
pet.pet();
|
||||
});
|
||||
|
||||
cleanButton.addEventListener("click", () => {
|
||||
if (!canClean || !pet.canUpdate) {
|
||||
return;
|
||||
}
|
||||
canClean = false;
|
||||
setTimeout(() => {
|
||||
canClean = true;
|
||||
}, CLEAN_TIMER);
|
||||
|
||||
pet.clean();
|
||||
});
|
||||
|
||||
const advance = () => {
|
||||
pet.needsAdvancement = false;
|
||||
pet.updateDom();
|
||||
};
|
||||
for (let btn of document.querySelectorAll("button.advancement")) {
|
||||
btn.addEventListener("click", advance);
|
||||
}
|
||||
|
||||
const update = () => {
|
||||
pet.update();
|
||||
};
|
||||
|
||||
// update the pet every 30 seconds?
|
||||
setInterval(update, 30000);
|
||||
setInterval(update, 60000 / UPDATES_PER_MINUTE);
|
||||
|
||||
forceUpdateButton.addEventListener("click", update);
|
||||
resetButton.addEventListener("click", () => {
|
||||
pet = new Pet();
|
||||
pet.updateDom();
|
||||
});
|
||||
|
||||
pet.load();
|
||||
|
||||
for (let name of petName) {
|
||||
name.innerText = pet.name;
|
||||
}
|
||||
|
||||
if (document.body.classList.contains("debug")) {
|
||||
debug.classList.remove("hidden");
|
||||
}
|
||||
|
||||
pet.updateDom();
|
||||
|
||||
console.log(pet);
|
||||
})();
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
#pet {
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#debug-section [name] {
|
||||
font-weight: bold;
|
||||
#debug-section [name] {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue