Game of Life - How I made this project?
April 18, 2024
This text is a repost. Previously published on Personal site (July 6, 2019)
Creating games is very interesting process, which got a lot of people in coding. So when I got more or less familiar with Javascript I decided to challenge myself to create a game. Because of the limitations of my skill I couldn’t create 3D or 2D game - even with Javascript’s gaming engines it takes additional knowledge.
But games are not about graphics - they are about interesting gameplay. So to create an interesting gameplay I had to think in reverse. Find a game mechanics that I know how to do and then create a gameplay around it.
In this article I will tell how I created this game. I will not get into great detail of every function. Instead, I will tell you about main milestones of the creation of this game and how I expanded game from one small function.
Step 1. Choosing game mechanics
Based on my Javascript knowledge, I decided to make my game turn-based. It’s simplest mechanics that I could think of. You add a button on your page, create addEventListener and every time player clicks on the button - it’s a new turn.
Step 2. Idea
But what this game will be about? Are there gonna be any plot? Story? What will be player's main goal? I think, this decision should be driven by your desires - what idea do you find interesting to work on. At the moment of creation this game I was very interested in idea of how nothing in life is guaranteed. Quoting Captain Picard: "It is possible to commit no mistakes and still lose. That is not a weakness. That is life". You can work hard to achieve something, but never achieve it. And vice versa - you could accidentally get something incredible just by pure luck.
So I thought - maybe I could make a game, that will imitate life and its randomness. Of course, in a very simple way. It matched my mechanics very vell - one turn could be one month. I liked this idea and decided to continue unfold it.
let month;
gameButton.addEventListener('click', liveOneMonth);
function liveOneMonth() {
month++;
};
Step 3. Main stats
Next step was to create some stats, that can be changed by players decisions. Besides months I added to game money, health, morale, intelligence, prestige and energy. This indicators could be change after one turn (month).
let money;
let health;
let morale;
let intelligence;
let prestige;
let energy;
Step 4. Decisions and its influence
But what changes these indicators? I created three different groups of things, that could influence player's stats:
-
Routines - what player chooses to do every month.
-
Events - happens with certain probability.
-
Items - optional for player to buy.
For each group I create its own class. In process of development, these classes became large, but in the beginning it got just properties for changing main stats. For example, let’s look at Routine class:
function Routine(nameR, moneyR, healthR, moraleR, intelligenceR, prestigeR, DOMR) {
this.nameR = nameR;
this.moneyR = moneyR;
this.healthR = healthR;
this.moraleR = moraleR;
this.intelligenceR = intelligenceR;
this.prestigeR = prestigeR;
this.DOMR = DOMR;
};
And as an example of Routine - “unemployed” object.
let unemployed = new Routine('Unemployed', 0, 0, -5, 0, -5, document.querySelector("#unemployedJob"))
routineArray = [unemployed];
Then we could write a function, that will change your stats if you picked unemployed option in the DOM. This function should be put into liveOneMonth function.
routineArray.forEach(function(someRoutine) {
if (someRoutine.DOMR.selected === true) {
money = money + someRoutine.moneyR;
health = health + someRoutine.healthR;
morale = morale + someRoutine.moraleR;
intelligence = intelligence + someRoutine.intelligenceR;
prestige = prestige + someRoutine.prestigeR;
};
});
As a result, if player picked unemployed option - he will get no money, no health and no intelligence. But because of stress, he will lose 5 points of morale. Moreover - lose 5 points of prestige.
This template is scalable. You can create as much Routine objects as you want and put it into array - forEach function will handle it.
Then you can expand influence of Routine class by adding new properties and making calculations with them.
Events and Items have the same logic, but with some different properties.
Step 5. Randomness
As I said earlier, my goal was to bring some randomness to the game. For example, game should assign some values for player’s main stats in the beginning. How much money, health, morale, intelligence and prestige should player get? It wouldn’t be realistic if every game player would be getting same stats. It’s great opportunity to bring luck in the game.
The simplest way to do this is to use Math.random method.
Let’s look at function, which assigns money for the player in the beginning of the game.
function getRandomMoney(){
var num = Math.random();
if (num < 0.6) {
money = 10000;
} else if (num < 0.9) {
money = 100000;
} else if (num < 0.99) {
money = 1000000;
} else {
money = 10000000;
};
};
First, it generates random number for player. If random number is less than 0,6 player will get 10,000 dollars in the beginning of the game. It basically means that with 60% probability player will get least money possible in the game. Probability for other money tiers: 30% - 100,000, 9% - 1,000,000, 1% - 10,000,000.
This approach I used in other parts of my game. For example, with effectiveness of medicine. When player gets some illness - he could buy medicine. Like in real life, some diseases are easier to cure, than other. Treatment for cold is effective - 0.8 (80% chance of success), cure for depression is less effective 0.1(10% chance of success).
Step 6. Shop
Buying items is huge feature to make game more interesting.
From code perspective it’s a large function, but conceptually it’s rather easy.
As I said earlier, all items in the shop are stored in the array. Each items got it’s own buying button stored as a property of item. ForEach function listens to every button and when it’s clicked - function for buying starts.
Select item array to initiate function to buy or sell if someItem is clicked:
itemsArray.forEach(function(someItem) {
clickToBuy(someItem);
});
Function listens to click on one of those items and initiates function to buy someItemFromShop:
function clickToBuy(someItemFromShop) {
someItemFromShop.shopBtnI.addEventListener('click', functionToBuy);
// Functions starts another function to buy specific item
function functionToBuy() {
buySpecificItem(someItemFromShop);
};
};
Conclusion
These ideas was the core of my game. Once I implemented them, most of the later work was expanding variables, adding little function for better user experience, etc.
If you interested in looking closely at my code, you can do it at GitHub.
Thanks for reading.