I am trying to have a virtual calendar for a game. I have events that will last a certain time in reality (1 week, 1 month). In the game those events should always be equal to 1 year.
To make things simple my goal was to use date-fns and work with timestamps to keep a ratio.
Lets say I have an event running for 1 week (real life) In game that would be 1 year. If I try to get the in-game date when I’m at event start + 3 days (almost half of the event passed). Theoretically I should be close to 6 months in the virtual calendar however while testing its gives me an answer years later.
import { addDays, addYears, getTime } from "date-fns"; // Initiate Dates const now = new Date() const nextWeek = addDays(now, 7); const nextYear = addYears(now, 1); // Initiate Timestamp convertions const currentTimestamp = getTime(now) const tmrTimestamp = getTime(addDays(now, 3)) const nextWeekTimestamp = getTime(nextWeek) // Calculate differences const differenceReal = nextWeekTimestamp - currentTimestamp const differenceVirtual = getTime(nextYear) - currentTimestamp console.log(`difference_real : ${differenceReal}`) console.log(`difference_virtual : ${differenceVirtual}`) // Calculate the ratio const ratio = differenceReal / differenceVirtual // Log information console.log(`ratio: ${ratio}`) console.log(`ts_now ${getTime(now)}`) console.log(`ts_tmr ${getTime(tmrTimestamp)}`) //Calculate equivalence of day+1 on a year const nextDayRatioed = tmrTimestamp / ratio console.log(`ts_ratioed: ${Math.round(nextDayRatioed)}`) console.log(`ts_next_year: ${getTime(nextYear)}`) console.log(`next_year: ${nextYear.toLocaleString()}`) console.log(`tmr_relative: ${new Date(Math.round(nextDayRatioed)).toLocaleString()}`)
Output:
How could I get the tmr_relative
to be the correct value which would be more or less January of 2022
Advertisement
Answer
You must keep as constant
- the start time of your game as the point of origin.
- the ratio that you want for time. In your case 1 week is 1 year for your game.
Check the following way to achieve that using only date.
const ratio = 365/7; //This is the virtual ration that you want const nowReal = new Date() //This would always be the basis to compare //Use a fixed date one week later to test how it would behave const nextWeekReal = new Date(); nextWeekReal.setDate(nextWeekReal.getDate() + 7); //Use a fixed date 2 week later to test how it would behave const doubleNextWeekReal = new Date(); doubleNextWeekReal.setDate(doubleNextWeekReal.getDate() + 14); //Check the next week virtual date console.log(virtualDate(nowReal, datediff(nowReal, nextWeekReal), ratio)); //Check after 2 weeks the virtual date console.log(virtualDate(nowReal, datediff(nowReal, doubleNextWeekReal), ratio)); function datediff(first: any, second: any) { // Take the difference between the dates and divide by milliseconds per day. // Round to nearest whole number to deal with DST. return Math.round((second-first)/(1000*60*60*24)); } function virtualDate(basis: Date, diff: number, ration: number){ const virtualDate = new Date(); virtualDate.setDate(basis.getDate() + diff * ratio); return virtualDate; }
Result considering that you start the game now on 24/7/21.
After 1 week have passed in real time it will print you 1 year later from the point of origin
After 2 weeks have passed in real time it will print you 2 years later from the point of origin
Lets say I have an event running for 1 week (real life) In game that would be 1 year. If I try to get the in-game date when I’m at event start + 3 days (almost half of the event passed). Theoretically I should be close to 6 months
//Use a fixed date half a week later to test how it would behave const halfWeekReal = new Date(); halfWeekReal.setDate(halfWeekReal.getDate() + 3); console.log("Half Week have passed in real time " + halfWeekReal); //Check after half week the virtual date console.log("Virtual date will be " + virtualDate(nowReal, datediff(nowReal, halfWeekReal), ratio));
This will print
It is about 5 months, which is the correct behavior you have described.