One common obstacle facing many first-time PHP game developers is the concept of how time passes in their web-based game. With desktop / mobile applications, time can continuously run via a timer mechanism because it is always running on the device. PHP works in the disconnected world of the Internet. When a request comes into the server, it fires off the request to the PHP program for parsing, parses the page and then returns the result (HTML and JavaScript typically) it to the user. But after this point, it no longer remembers the request. This is on purpose. This is how the Internet was created by design.
To help bridge the gap between a previous request and the current request, things like cookies and sessions were created. However, these alone don’t really provide an elegant and solid solution for time continuously passing. Mixing them with database tracking is usually the right answer.
There are two main mechanisms we can use to create the sense of time in your PHP game world (or any other server-side programming game). The first mechanism is to keep track of when the last request was made and what time it is now for the current request. For an example of this, let’s assume we buy a bank in our RPG game. This bank will produce 100 gold every real-world hour. I buy this building at 1pm “server time” (the time where my current server is located). I will record this time in my database as a timestamp labeled “LastCheckedTime”. I then leave to go attend to some errands. I later return at 3pm, again server time. I request a page to display how much money I have made. When I make the request to see my summary page I would check the current time, 3pm as a timestamp, and subtract the “LastCheckedTime” timestamp from this current timestamp to determine how much time has passed. I would then multiply the number of hours by 100 (the gold I make each hour). Lastly, I update the “LastCheckedTime” to the current timestamp and any future calculation would again be based off of this time. Be sure to compensate for any left over partial hours from last time.
This process described above is good for items in the game where accumulation / loss is unaffected by other factors (like a player attacking you while you are away). Even if a player attacked you, you still earn your 100 gold because you have the bank.
The second mechanism you typically see is the use of cron jobs (aka scheduled tasks). These are timed events or tasks that are scheduled at the server’s services or OS level. These types of tasks are usually reserved for global world upkeep. Like assigning resources to a user every minute, five minutes, hour, day etc based on the current state of the game world or for things like respawning. At a specific time the server starts a service which calls your script to execute, it does its job and then hibernates until the next scheduled time.
Going back to our example earlier, let’s assume that gold needs to be given to players every 5 minutes and it is based on the number of banks the player owns at that time. We may create a PHP script that essentially runs a query against the database looking at the number of banks in each player’s account and multiplies it by 30 gold, adding the product to the player’s coffers. This script can then be called as a scheduled task to make sure it regularly happens all day long, despite the player’s actions. Why would we do this versus the other method? What if our game allows people to steal gold. If we had done it the first way a player may have zero gold and when they finally log in 2 days later, they get 4,800 gold added to their account. If money had been dumped into the account every five minutes instead, a player who attacks after 2 hours can steal some money that is sitting there, because the player would have had gold deposited every 5 minutes for 2 hours. In other words, they would have some money accruing in real time. (Something to consider if your game involved interest)
With a combination of these two mechanisms you can often create a very realistic experience of time actually passing. One mechanism is updating the world like clockwork while the other only runs for a player when they send requests. Cron jobs are good for keeping accounts moving forward and adjusting while the “checking last time since request” mechanism is great for elements of the game where up to the minute world game play doesn’t really matter.
Most programmers often want their online games to be as close to real time as possible and often opt for many cron jobs running at various intervals. The one thing to be aware of is how often these scripts run and how long their tasks actually take. You don’t want to be running a script that takes 1 minute to fully run and then schedule it to run every 30 seconds. Keep this in mind when you setup your world’s game time system. Always give your cron jobs plenty of time to run their upkeep processes without conflicting with scheduling. Also make sure to keep them as low intensity as possible. In other words, don’t make them do too much. You should keep their processes lean and mean.
As for checking the last request time mechanism, make sure that the adjustments and queries you use are sharp and quick. Since these are often the mechanisms that will run the most on page requests. If your game becomes popular and you have slow queries just to update their basic resource numbers, these scripts will grind your server to a halt.
Mixing these two together in the right proportions for your game is the ultimate goal. Always do timing checks and make sure these mechanics are very solid before game launch otherwise everyone who joins your game is going to notice that time, something we all know a bit about, is a bit more unfair that we know it to be.
Thanks for reading! 🙂