Implemented game loop

This commit is contained in:
thepaperpilot 2021-06-13 22:16:38 -05:00
parent 684c72ade0
commit 38e85dec2c
10 changed files with 180 additions and 65 deletions

View file

@ -1,18 +1,18 @@
<template> <template>
<div class="tpsDisplay"> <div class="tpsDisplay" v-if="tps !== 'NaN'">
TPS: {{ tps }} TPS: {{ tps }}
</div> </div>
</template> </template>
<script> <script>
import Decimal, { format } from '../../util/bignum'; import Decimal, { formatWhole } from '../../util/bignum';
import { player } from '../../store/proxies';
export default { export default {
name: 'TPS', name: 'TPS',
computed: { computed: {
tps() { tps() {
const lastTenTicks = this.$store.state.lastTenTicks; return formatWhole(Decimal.div(player.lastTenTicks.length, player.lastTenTicks.reduce((acc, curr) => acc + curr, 0)))
return format(Decimal.div(lastTenTicks.length, lastTenTicks.reduce((acc, curr) => acc + curr, 0)))
} }
} }
}; };

View file

@ -1,4 +1,4 @@
import { hasMilestone, hasUpgrade, inChallenge, getBuyableAmount } from '../util/features'; import { hasUpgrade, upgradeEffect } from '../util/features';
import { layers } from '../store/layers'; import { layers } from '../store/layers';
import { player } from '../store/proxies'; import { player } from '../store/proxies';
import Decimal from '../util/bignum'; import Decimal from '../util/bignum';
@ -44,53 +44,27 @@ const main = {
export const initialLayers = [ main, f, c, a, g, h, spook ]; export const initialLayers = [ main, f, c, a, g, h, spook ];
export function update(delta) {
let gain = new Decimal(3.19)
if (hasMilestone("p",0))gain=gain.plus(0.01)
if (hasMilestone("p",4)){
if (hasUpgrade("p",12))gain=gain.plus(0.1)
if (hasUpgrade("p",13))gain=gain.plus(0.1)
if (hasUpgrade("p",14))gain=gain.plus(0.1)
if (hasUpgrade("p",21))gain=gain.plus(0.1)
if (hasUpgrade("p",22))gain=gain.plus(0.1)
if (hasUpgrade("p",23))gain=gain.plus(0.1)
if (hasUpgrade("p",31))gain=gain.plus(0.1)
if (hasUpgrade("p",32))gain=gain.plus(0.1)
if (hasUpgrade("p",33))gain=gain.plus(0.1)
}
if (hasUpgrade("p",11))gain=gain.plus(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1)
if (hasUpgrade("p",12))gain=gain.times(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1)
if (hasUpgrade("p",13))gain=gain.pow(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1)
if (hasUpgrade("p",14))gain=gain.tetrate(hasUpgrade("p",34)?(new Decimal(1).plus(layers.p.upgrades[34].effect)):1)
if (hasUpgrade("p",71)) gain=gain.plus(1.1)
if (hasUpgrade("p",72)) gain=gain.times(1.1)
if (hasUpgrade("p",73)) gain=gain.pow(1.1)
if (hasUpgrade("p",74)) gain=gain.tetrate(1.1)
if (hasMilestone("p",5)&&!inChallenge("p",22)){
let asdf = (hasUpgrade("p",132)?player.p.gp.plus(1).pow(new Decimal(1).div(2)):hasUpgrade("p",101)?player.p.gp.plus(1).pow(new Decimal(1).div(3)):hasUpgrade("p",93)?player.p.gp.plus(1).pow(0.2):player.p.gp.plus(1).log10())
gain=gain.plus(asdf)
if (hasUpgrade("p",213))gain=gain.mul(asdf.plus(1))
}
if (hasUpgrade("p",104)) gain=gain.times(player.p.points.plus(1).pow(0.5))
if (hasUpgrade("p",142))gain=gain.times(5)
if (player.i.unlocked)gain=gain.times(player.i.points.plus(1).pow(hasUpgrade("p",235)?6.9420:1))
if (inChallenge("p",11)||inChallenge("p",21))gain=new Decimal(10).pow(gain.log10().pow(0.75))
if (inChallenge("p",12)||inChallenge("p",21))gain=gain.pow(new Decimal(1).sub(new Decimal(1).div(getBuyableAmount("p",11).plus(1))))
if (hasUpgrade("p",211))gain=gain.times(getBuyableAmount("p",21).plus(1))
if (hasMilestone("p",13))gain=gain.times(layers.p.buyables[31].effect)
if (hasMilestone("p",13))gain=gain.pow(layers.p.buyables[42].effect)
gain.times(delta);
}
export function getStartingData() { export function getStartingData() {
return { return {
points: new Decimal(10), points: new Decimal(10),
} }
} }
export function hasWon() { export const getters = {
return false; hasWon() {
return false
},
pointGain() {
if(!hasUpgrade("c", 11))
return new Decimal(0);
let gain = new Decimal(1)
if (hasUpgrade("c", 12)) gain = gain.times(upgradeEffect("c", 12))
return gain;
}
};
/* eslint-disable-next-line no-unused-vars */
export function update(delta) {
} }
/* eslint-disable-next-line no-unused-vars */ /* eslint-disable-next-line no-unused-vars */

View file

@ -16,5 +16,6 @@
"logo": null, "logo": null,
"initialTabs": [ "main", "c" ], "initialTabs": [ "main", "c" ],
"maxTickLength": 3600 "maxTickLength": 3600,
"offlineLimit": 1
} }

View file

@ -3,6 +3,7 @@ import App from './App';
import store from './store'; import store from './store';
import { addLayer} from './store/layers'; import { addLayer} from './store/layers';
import { setVue } from './util/vue'; import { setVue } from './util/vue';
import { startGameLoop } from './store/game';
import './components/index'; import './components/index';
// Setup // Setup
@ -21,5 +22,5 @@ requestAnimationFrame(async () => {
setVue(vue); setVue(vue);
vue.$mount('#app'); vue.$mount('#app');
// Start game loop startGameLoop();
}); });

117
src/store/game.js Normal file
View file

@ -0,0 +1,117 @@
import { update as modUpdate } from '../data/mod';
import Decimal from '../util/bignum';
import modInfo from '../data/modInfo.json';
import store from './index';
import { layers } from './layers';
import { player } from './proxies';
function updatePopups(/* diff */) {
// TODO
}
function updateParticles(/* diff */) {
// TODO
}
function update() {
let now = Date.now();
let diff = (now - player.time) / 1e3;
player.time = now;
let trueDiff = diff;
// Always update UI
updatePopups(trueDiff);
updateParticles(trueDiff);
player.lastTenTicks.push(trueDiff);
if (player.lastTenTicks.length > 10) {
player.lastTenTicks = player.lastTenTicks.slice(1);
}
// Stop here if the game is paused on the win screen
if (store.getters.hasWon && !player.keepGoing) {
return;
}
diff = new Decimal(diff).max(0);
// Add offline time if any
if (player.offTime != undefined) {
if (player.offTime.remain > modInfo.offlineLimit * 3600) {
player.offTime.remain = modInfo.offlineLimit * 3600;
}
if (player.offTime.remain > 0) {
let offlineDiff = Math.max(player.offTime.remain / 10, diff);
player.offTime.remain -= offlineDiff;
diff = diff.add(offlineDiff);
}
if (!player.offlineProd || player.offTime.remain <= 0) {
player.offTime = undefined;
}
}
// Cap at max tick length
diff = Decimal.min(diff, modInfo.maxTickLength);
// Apply dev speed
if (player.devSpeed != undefined) {
diff = diff.times(player.devSpeed);
}
// Update
if (diff.eq(0)) {
return;
}
player.timePlayed = player.timePlayed.add(diff);
if (player.points != undefined) {
player.points = player.points.add(Decimal.times(store.getters.pointGain, diff));
}
modUpdate(diff);
// Update each active layer
const activeLayers = Object.keys(layers).filter(layer => !layers[layer].deactivated);
activeLayers.forEach(layer => {
if (player[layer].resetTime != undefined) {
player[layer].resetTime = player[layer].resetTime.add(diff);
}
if (layers[layer].passiveGeneration) {
player[layer].points =
player[layer].points.add(Decimal.times(layers[layer].resetGain, layers[layer].passiveGeneration).times(diff));
}
layers[layer].update?.(diff);
});
// Automate each active layer
activeLayers.forEach(layer => {
if (layers[layer].autoReset && layers[layer].canReset) {
layers[layer].reset();
}
layers[layer].automate?.();
if (layers[layer].upgrades && layers[layer].autoUpgrade) {
Object.values(layers[layer].upgrades).forEach(upgrade => upgrade.buy());
}
});
// Check each active layer for newly unlocked achievements or milestones
activeLayers.forEach(layer => {
if (layers[layer].milestones) {
Object.values(layers[layer].milestones).forEach(milestone => {
if (milestone.unlocked !== false && !milestone.earned && milestone.done) {
player[layer].milestones.push(milestone.id);
milestone.onComplete?.();
// TODO popup notification
player[layer].lastMilestone = milestone.id;
}
});
}
if (layers[layer].achievements) {
Object.values(layers[layer].achievements).forEach(achievement => {
if (achievement.unlocked !== false && !achievement.earned && achievement.done) {
player[layer].achievements.push(achievement.id);
achievement.onComplete?.();
// TODO popup notification
}
});
}
});
}
export function startGameLoop() {
setInterval(update, 50);
}

View file

@ -1,9 +1,11 @@
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex' import Vuex from 'vuex'
import { getInitialStore } from '../util/load'; import { getInitialStore } from '../util/load';
import { getters } from '../data/mod';
Vue.use(Vuex); Vue.use(Vuex);
export default new Vuex.Store({ export default new Vuex.Store({
state: getInitialStore() state: getInitialStore(),
getters
}); });

View file

@ -34,6 +34,9 @@ export function addLayer(layer) {
if (layer.onClick != undefined) { if (layer.onClick != undefined) {
layer.onClick.forceCached = false; layer.onClick.forceCached = false;
} }
if (layer.update != undefined) {
layer.update.forceCached = false;
}
const getters = {}; const getters = {};
@ -55,7 +58,7 @@ export function addLayer(layer) {
for (let id in layer.upgrades) { for (let id in layer.upgrades) {
if (isPlainObject(layer.upgrades[id])) { if (isPlainObject(layer.upgrades[id])) {
layer.upgrades[id].bought = function() { layer.upgrades[id].bought = function() {
return !this.deactivated && player[layer.id].upgrades.some(upgrade => upgrade == id); return !layer.deactivated && player[layer.id].upgrades.some(upgrade => upgrade == id);
} }
if (layer.upgrades[id].canAfford == undefined) { if (layer.upgrades[id].canAfford == undefined) {
layer.upgrades[id].canAfford = function() { layer.upgrades[id].canAfford = function() {
@ -130,7 +133,7 @@ export function addLayer(layer) {
for (let id in layer.achievements) { for (let id in layer.achievements) {
if (isPlainObject(layer.achievements[id])) { if (isPlainObject(layer.achievements[id])) {
layer.achievements[id].earned = function() { layer.achievements[id].earned = function() {
return !this.deactivated && player[layer.id].achievements.some(achievement => achievement == id); return !layer.deactivated && player[layer.id].achievements.some(achievement => achievement == id);
} }
} }
} }
@ -142,13 +145,13 @@ export function addLayer(layer) {
for (let id in layer.challenges) { for (let id in layer.challenges) {
if (isPlainObject(layer.challenges[id])) { if (isPlainObject(layer.challenges[id])) {
layer.challenges[id].completed = function() { layer.challenges[id].completed = function() {
return !this.deactivated && !!player[layer.id].challenges[id]; return !layer.deactivated && !!player[layer.id].challenges[id];
} }
layer.challenges[id].completions = function() { layer.challenges[id].completions = function() {
return player[layer.id].challenges[id]; return player[layer.id].challenges[id];
} }
layer.challenges[id].maxed = function() { layer.challenges[id].maxed = function() {
return !this.deactivated && Decimal.gte(player[layer.id].challenges[id], this.completionLimit); return !layer.deactivated && Decimal.gte(player[layer.id].challenges[id], this.completionLimit);
} }
if (layer.challenges[id].mark == undefined) { if (layer.challenges[id].mark == undefined) {
layer.challenges[id].mark = function() { layer.challenges[id].mark = function() {
@ -156,7 +159,7 @@ export function addLayer(layer) {
} }
} }
layer.challenges[id].active = function() { layer.challenges[id].active = function() {
return !this.deactivated && player[layer.id].activeChallenge === id; return !layer.deactivated && player[layer.id].activeChallenge === id;
} }
if (layer.challenges[id].canComplete == undefined) { if (layer.challenges[id].canComplete == undefined) {
layer.challenges[id].canComplete = function() { layer.challenges[id].canComplete = function() {
@ -227,7 +230,7 @@ export function addLayer(layer) {
player[layer.id].buyables[id] = amount; player[layer.id].buyables[id] = amount;
} }
layer.buyables[id].canBuy = function() { layer.buyables[id].canBuy = function() {
return !this.deactivated && this.unlocked !== false && this.canAfford !== false && return !layer.deactivated && this.unlocked !== false && this.canAfford !== false &&
Decimal.lt(player[layer.id].buyables[id], this.purchaseLimit); Decimal.lt(player[layer.id].buyables[id], this.purchaseLimit);
} }
if (layer.buyables[id].purchaseLimit == undefined) { if (layer.buyables[id].purchaseLimit == undefined) {
@ -292,7 +295,7 @@ export function addLayer(layer) {
} }
} }
layer.milestones[id].earned = function() { layer.milestones[id].earned = function() {
return !this.deactivated && player[layer.id].milestones.some(milestone => milestone == id); return !layer.deactivated && player[layer.id].milestones.some(milestone => milestone == id);
} }
} }
} }
@ -572,6 +575,12 @@ export const defaultLayerProperties = {
return this.canReset && this.resetGain.gte(player[this.layer].points.div(10)); return this.canReset && this.resetGain.gte(player[this.layer].points.div(10));
} }
return false; return false;
},
reset(force = false) {
console.warn("Not yet implemented!", force);
},
resetData(keep = []) {
console.warn("Not yet implemented!", keep);
} }
}; };
const gridProperties = [ 'upgrades', 'achievements', 'challenges', 'buyables', 'clickables' ]; const gridProperties = [ 'upgrades', 'achievements', 'challenges', 'buyables', 'clickables' ];

View file

@ -16,7 +16,7 @@ export const tmp = new Proxy({}, {
const playerHandler = { const playerHandler = {
get(target, key) { get(target, key) {
if (key == 'isProxy') { if (key === 'isProxy') {
return true; return true;
} }
@ -35,6 +35,17 @@ const playerHandler = {
}, },
set(target, property, value) { set(target, property, value) {
Vue.set(target, property, value); Vue.set(target, property, value);
if (property === 'points') {
if (target.best != undefined) {
target.best = Decimal.max(target.best, value);
}
if (target.total != undefined) {
const diff = Decimal.sub(value, target.points);
if (diff.gt(0)) {
target.total = target.total.add(diff);
}
}
}
return true; return true;
} }
}; };
@ -80,7 +91,7 @@ function travel(callback, object, objectProxy, getters, prefix) {
function getHandler(prefix) { function getHandler(prefix) {
return { return {
get(target, key, receiver) { get(target, key, receiver) {
if (key == 'isProxy') { if (key === 'isProxy') {
return true; return true;
} }
@ -119,7 +130,7 @@ function getHandler(prefix) {
function getGridHandler(prefix) { function getGridHandler(prefix) {
return { return {
get(target, key, receiver) { get(target, key, receiver) {
if (key == 'isProxy') { if (key === 'isProxy') {
return true; return true;
} }
@ -157,7 +168,7 @@ function getGridHandler(prefix) {
function getCellHandler(id) { function getCellHandler(id) {
return { return {
get(target, key, receiver) { get(target, key, receiver) {
if (key == 'isProxy') { if (key === 'isProxy') {
return true; return true;
} }

View file

@ -1,14 +1,13 @@
import Decimal from './bignum'; import Decimal from './bignum';
import { isPlainObject } from './common'; import { isPlainObject } from './common';
import { layers } from '../store/layers';
// TODO make layer.reset(force = false)
export function resetLayer(layer, force = false) { export function resetLayer(layer, force = false) {
console.warn("Not yet implemented!", layer, force); layers[layer].reset(force);
} }
// TODO make layer.resetData(keep = [])
export function resetLayerData(layer, keep = []) { export function resetLayerData(layer, keep = []) {
console.warn("Not yet implemented!", layer, keep); layers[layer].resetData(keep);
} }
export function cache(func) { export function cache(func) {

View file

@ -1,6 +1,7 @@
import modInfo from '../data/modInfo'; import modInfo from '../data/modInfo';
import { getStartingData, initialLayers } from '../data/mod'; import { getStartingData, initialLayers } from '../data/mod';
import { getStartingBuyables, getStartingClickables, getStartingChallenges } from './layers'; import { getStartingBuyables, getStartingClickables, getStartingChallenges } from './layers';
import Decimal from './bignum';
export function getInitialStore() { export function getInitialStore() {
return { return {
@ -8,7 +9,7 @@ export function getInitialStore() {
time: Date.now(), time: Date.now(),
autosave: true, autosave: true,
offlineProd: true, offlineProd: true,
timePlayed: 0, timePlayed: new Decimal(0),
keepGoing: false, keepGoing: false,
hasNaN: false, hasNaN: false,
lastTenTicks: [], lastTenTicks: [],