Added wormhole animation, also added time speedup factor to tickspeed text and a notification for when the speedup activates

This commit is contained in:
SpectralFlame 2018-09-19 20:27:11 -05:00
parent 478f3310a1
commit 9cd864c88d
4 changed files with 217 additions and 39 deletions

View File

@ -2712,17 +2712,8 @@
<div id="wormhole" class="realitytab" style="display: none;">
<button id="wormholeunlock" class="realityUpgrade" onclick="unlockWormhole()" style="text-shadow: -1px 1px 3px #d5ffd7;" ach-tooltip="The wormhole makes the game run significantly faster for a short period of time. Starts at 180x faster for 10 seconds, once per hour.">Unleash the Wormhole<br>Cost: 50 RM</button>
<div id="wormholecontainer" style="display: none">
<div class="radial-progress" id="wormholeImage" data-progress="0">
<div class="circle">
<div class="mask full">
<div class="fill"></div>
</div>
<div class="mask half">
<div class="fill"></div>
<div class="fill fix"></div>
</div>
</div>
<div class="inset"></div>
<canvas id="wormholeImage" width="400" height="400" style="border:1px solid #000000;"></canvas>
<h3 id="wormholeStatus"></h3>
</div>
<div class="wormhole-upgrades">
<button class="realityUpgrade" id="wormholeinterval" onclick="upgradeWormholeInterval()">Speed up the wormhole up 25%<br>Current interval: 3600 seconds<br>Cost: 15RM</button>

View File

@ -121,11 +121,35 @@ function buyMaxTickSpeed() {
function updateTickSpeed() {
var exp = player.tickspeed.e;
if (exp > 1) document.getElementById("tickSpeedAmount").textContent = 'Tickspeed: ' + player.tickspeed.toFixed(0);
else {
document.getElementById("tickSpeedAmount").textContent = 'Tickspeed: ' + player.tickspeed.times(new Decimal(100).dividedBy(Decimal.pow(10, exp))).toFixed(0) + ' / ' + shorten(new Decimal(100).dividedBy(Decimal.pow(10, exp)));
}
let exp = player.tickspeed.e;
let tickSpeedText;
if (exp > 1)
tickSpeedText = 'Tickspeed: ' + player.tickspeed.toFixed(0);
else
tickSpeedText = 'Tickspeed: ' + player.tickspeed.times(new Decimal(100).dividedBy(Decimal.pow(10, exp))).toFixed(0) + ' / ' + shorten(new Decimal(100).dividedBy(Decimal.pow(10, exp)));
// Accelerated game speed suffix
let gameSpeedMult = 1;
if (player.currentEternityChall == "eterc12")
gameSpeedMult /= 1000;
try {
for (let i = 0; i < player.reality.glyphs.active.length; i++) {
let currGlyph = player.reality.glyphs.active[i];
if (currGlyph.type === "time" && currGlyph.effects.speed != undefined)
gameSpeedMult *= currGlyph.effects.speed;
}
}
catch (err) {
// No glyphs
}
if (player.wormhole.active)
gameSpeedMult *= player.wormhole.power;
let speedAccelText = " (γ = " + gameSpeedMult.toFixed(3) + ")";
if (gameSpeedMult != 1)
document.getElementById("tickSpeedAmount").textContent = tickSpeedText + speedAccelText;
else
document.getElementById("tickSpeedAmount").textContent = tickSpeedText;
}
function resetTickspeed() {

View File

@ -17,6 +17,8 @@
$("#wormholeduration").html("Extend the wormhole duration by 30%<br>Current duration: "+(player.wormhole.duration).toFixed(1)+" seconds<br>Cost: "+shortenDimensions(getWormholeDurationCost())+"RM")
if (player.reality.realityMachines < getWormholeDurationCost()) $("#wormholeduration").addClass("rUpgUn")
else $("#wormholeduration").removeClass("rUpgUn")
recalculateOrbit();
}
function unlockWormhole() {
@ -44,6 +46,7 @@ function getWormholeDurationCost() {
}
function upgradeWormholeInterval() {
totalPhase = getTotalPhase();
var cost = getWormholeIntervalCost()
if (player.reality.realityMachines.lt(cost)) return false
player.reality.realityMachines = player.reality.realityMachines.minus(cost)
@ -52,6 +55,7 @@ function upgradeWormholeInterval() {
}
function upgradeWormholePower() {
totalPhase = getTotalPhase();
var cost = getWormholePowerCost()
if (player.reality.realityMachines.lt(cost)) return false
player.reality.realityMachines = player.reality.realityMachines.minus(cost)
@ -60,6 +64,7 @@ function upgradeWormholePower() {
}
function upgradeWormholeDuration() {
totalPhase = getTotalPhase();
var cost = getWormholeDurationCost()
if (player.reality.realityMachines.lt(cost)) return false
player.reality.realityMachines = player.reality.realityMachines.minus(cost)
@ -67,38 +72,196 @@ function upgradeWormholeDuration() {
updateWormholeUpgrades()
}
let totalPhase;
function wormHoleLoop(diff) {
let wormholeImage = document.getElementById("wormholeImage");
// Change wormhole state
let incPhase = diff / 1000;
if (player.wormhole.active) {
player.wormhole.phase += diff / 1000 / player.wormhole.power
wormholeImage.setAttribute('ach-tooltip', "Wormhole is active for " + (player.wormhole.duration - player.wormhole.phase).toFixed(1) + " more seconds.");
incPhase /= player.wormhole.power;
document.getElementById("wormholeStatus").textContent = "Wormhole is active for " + (player.wormhole.duration - player.wormhole.phase).toFixed(1) + " more seconds.";
if (player.wormhole.phase >= player.wormhole.duration) {
player.wormhole.phase = 0
player.wormhole.active = false
updateTickSpeed();
}
} else {
player.wormhole.phase += diff / 1000
wormholeImage.setAttribute('ach-tooltip', "Wormhole will activate in " + (player.wormhole.speed - player.wormhole.phase).toFixed(1) + " seconds.");
document.getElementById("wormholeStatus").textContent = "Wormhole will activate in " + (player.wormhole.speed - player.wormhole.phase).toFixed(1) + " seconds.";
if (player.wormhole.phase >= player.wormhole.speed) {
player.wormhole.phase = 0
player.wormhole.active = true
updateTickSpeed();
if (player.wormhole.speed > 60)
$.notify("Wormhole activated!", "info")
}
}
player.wormhole.phase += incPhase;
totalPhase = getTotalPhase();
// Update orbital position parameters (polar coordinates centered on hole, theta goes 0 to 1 because I'm apparently stupid)
E0 = E(eccentricity, 2 * Math.PI * totalPhase / period); // "eccentric anomaly"
r = semimajorAxis*(1 - eccentricity*Math.cos(E0));
theta = 2 * Math.atan(Math.sqrt((1+eccentricity)/(1-eccentricity) * Math.pow(Math.tan(E0/2), 2)));
if (Math.tan(E0/2) < 0)
theta *= -1;
planet.radius = r;
planet.angle = theta / (2*Math.PI);
var rotation = player.wormhole.phase / player.wormhole.speed * 180
if (player.wormhole.active ) {
$('.radial-progress .inset').css("background-color", "red")
var rotation = player.wormhole.phase / player.wormhole.duration * 180
$('.circle .fill').css("background-color", 'red');
}
else {
$('.radial-progress .inset').css("background-color", "#fbfbfb")
$('.circle .fill').css("background-color", "#97a71d")
}
$('.circle .fill').css("transform", 'rotate(' + rotation + 'deg)');
$('.circle .full').css("transform", 'rotate(' + rotation + 'deg)');
$('.circle .fill .fix').css("transform", 'rotate(' + (rotation * 2) + 'deg)');
// Time dilation factor (Realistic formula, but only actually used for particle speed)
delta = 1 / Math.sqrt(1 - bhSize/r);
// Move+draw everything
document.getElementById("wormholeImage").getContext('2d').clearRect(0, 0, 400, 400);
for (let i = 0; i < particleList.length; i++) {
particleList[i].update();
particleList[i].draw();
}
}
// Drawing code that runs for each particle
let planetSize = 1.5;
function Dot(dotSize, dotType, r, theta) {
this.size = dotSize;
this.isParticle = dotType == 'particle';
this.isPlanet = dotType == 'planet';
this.radius = r;
this.angle = theta;
this.respawn = true;
this.canvas = document.getElementById("wormholeImage");
this.draw = function () {
let disp = this.canvas.getContext('2d');
let x = this.radius * Math.sin(2*Math.PI * this.angle);
let y = this.radius * Math.cos(2*Math.PI * this.angle);
disp.beginPath();
disp.lineWidth = 2*this.size;
// Wormhole active, draw some trails
if (player.wormhole.active && this.isParticle && !this.respawn) {
let prevX = this.prevRadius * Math.sin(2*Math.PI * this.prevAngle);
let prevY = this.prevRadius * Math.cos(2*Math.PI * this.prevAngle);
disp.lineCap = 'round';
disp.lineWidth *= 1;
disp.moveTo(x + 200, y + 200);
disp.lineTo(prevX + 200, prevY + 200);
}
else
disp.arc(x + 200, y + 200, this.size, 0, 2*Math.PI);
if (this.isParticle)
if (player.wormhole.active)
disp.strokeStyle = "rgb(255, 0, 0)";
else
disp.strokeStyle = "rgb(150, 150, 150)";
else if (this.isPlanet)
disp.strokeStyle = "rgb(0, 0, 255)";
else
disp.strokeStyle = "rgb(0, 0, 0)";
disp.stroke();
}
// Move particles
this.update = function () {
if (this.isParticle) {
let particleSpeed = 0.05 * Math.min(Math.pow(Math.max(delta,2)/2, 3), 5);
if (player.wormhole.active) {
this.prevAngle = this.angle;
this.prevRadius = this.radius;
}
this.angle = (this.angle + 20*particleSpeed*Math.PI*Math.pow(this.radius, -1.5)) % 1;
this.radius /= 1 + 0.3*particleSpeed*Math.pow(this.radius / bhSize, -2);
if (this.radius < bhSize) { // Particle fell in, disable the trail and respawn it outside
this.radius = getRandomRadius();
this.angle += Math.random();
this.respawn = true;
}
else
this.respawn = false;
}
}
}
// Code was originally written to use phase over a cycle of active+inactive time and would be really difficult to rewrite to use the current wormhole phase
// Example on what this is: if the wormhole has intervals of 100+10 then this ranges from 0 to 110 and is active when less than 5 or more than 105
function getTotalPhase() {
if (player.wormhole.active)
return (player.wormhole.phase - player.wormhole.duration/2 + period) % period;
else
return player.wormhole.phase + player.wormhole.duration/2;
}
// Should only be run once on game load
let particleList = [];
function initializeWormhole() {
// Black hole and planet
planet = new Dot(planetSize, 'planet', 0, 0);
hole = new Dot(0, 'hole', 0, 0);
// Orbital size parameters
semimajorAxis = 100; // Basically orbit size in pixels, can be changed
period = player.wormhole.speed + player.wormhole.duration; // Time taken for one orbit (in seconds)
totalPhase = getTotalPhase();
// A fair bit of calculation, should probably only be called on-load and after upgrades
calculateOrbitParams();
hole.size = (bhSize - planetSize) / 2; // Prevent planet+hole overlapping
// Particles (scaled to take the same range as the orbit)
particleList = [hole];
numParticles = 50;
for (let i = 0; i < numParticles; i++)
particleList.push(new Dot(planetSize / 3, 'particle', getRandomRadius(), Math.random()));
particleList.push(planet);
}
// Only run on purchase, recalculates orbital parameters and makes sure the planet doesn't move much after upgrades
let eccentricity, semimajorAxis, period, bhSize, planet, hole;
function recalculateOrbit() {
let currOrbitPos = totalPhase / period;
period = player.wormhole.speed + player.wormhole.duration; // Update orbital period
calculateOrbitParams();
hole.size = (bhSize - planetSize) / 2; // Prevent planet+hole overlapping
// Do stuff to make sure the relative position of the planet stays about the same
totalPhase = currOrbitPos * period;
if (player.wormhole.active) {
}
else {
player.wormhole.phase = totalPhase - player.wormhole.duration/2;
if (player.wormhole.phase < 0) {
player.wormhole.active = true;
player.wormhole.phase += player.wormhole.duration/2;
}
}
}
// Calculates "eccentric anomaly" from "mean anomaly", see https://en.wikipedia.org/wiki/Kepler%27s_equation#Numerical_approximation_of_inverse_problem
// Needed for accurate Keplerian orbit shape and velocity, apparently math is hard
function E(eccentricity, M) {
let E0 = M
maxIter = 20; // idk I hope 20 is enough to converge
for (let k = 0; k < maxIter; k++)
E0 = M + eccentricity * Math.sin(E0);
return E0;
}
// Finds and sets orbital parameters so the wormhole active time approximately corresponds to time with >2x
let activeThreshold = 2;
function calculateOrbitParams() {
// Fixed-point iteration for eccentricity (I'm really hoping this always converges)
y = (1 - Math.pow(activeThreshold, -2)) / (1 - Math.pow(player.wormhole.power, -2));
eccentricity = 0.5;
maxIter = 1000;
for (let k = 0; k < maxIter; k++)
eccentricity = (y - 1) / (y*Math.cos(E(eccentricity, 2 * Math.PI * (player.wormhole.duration / period))) - 1)
// Black hole size, calculated from orbit shape in order to give the right max boost
bhSize = semimajorAxis*(1 - eccentricity) * (1 - Math.pow(player.wormhole.power, -2));
}
// Used for particle spawning, note that particles can be farther out when active
function getRandomRadius() {
return bhSize + 0.5*semimajorAxis*Math.random() * (player.wormhole.active ? 2 : 1);
}

View File

@ -3660,8 +3660,8 @@ function gameLoop(diff) {
var textLines = oldText.split("\n");
document.getElementById(allAchievements[key]).setAttribute("ach-tooltip", textLines[0] + lockText);
}
}
}
player.lastUpdate = thisUpdate;
}
@ -4137,6 +4137,7 @@ function init() {
showDimTab('antimatterdimensions')
showChallengesTab('challenges')
showEternityTab('timestudies', true)
initializeWormhole();
load_game();
updateTickSpeed();
updateAutobuyers();
@ -4144,7 +4145,6 @@ function init() {
kong.init();
//if (typeof kongregate === 'undefined') document.getElementById("shopbtn").style.display = "none"
}
setInterval(function () {