This article is the third part of a tutorial aiming at discovering Svelte while building a game. I also wrote a short post on Svelte and the idea behind this tutorial. Below you can find the links to check those posts or other parts of the tutorial.
In this part we will focus mostly on how to implement an upgrade system.
Upgrades
Now we will implement upgrades for our game. Upgrades are buyable bonuses that grants bonuses to production in many way. The most straightforward is giving a multiplier bonus to the production of a building. That’s what we will be working on right now. Note that Clicker Idle upgrades gives a bonus to buildings depending on how many specific building has been bought by the player (not the total number of building the player has, because we have buildings producing other buildings). We will have to track that number bought to implement the upgrades.
Also Derivative Clicker gives the same bonus to all the buildings on the same row (all the buildings on the top row are tier1 buildings, producing a currency, then tier2 buildings on the second row produces tier1 buildings and so on and so forth for tier3, tier4…).
An example: if the bonus is 1% bonus to tier1 building for each tier1 buildings bought, if you buy 5 “1th Derivative” and 5 “Combinatorics” buildings, you have 10% bonus to all of those buildings.
Differentiating building bought and building total.
To do that first thing is to create a variable in store.js to handle the new information.
1
2
3
4
5
6
7
8
9
10
11
/* store.js */
...
// first level buildings
exportconstfirstDerivativeNum=writable(0);
exportconstfirstDerivativeBoughtNum=writable(0);
exportconstcombinatoricsNum=writable(0);
exportconstcombinatoricsBoughtNum=writable(0);
// second level buildings
exportconstsecondDerivativeNum=writable(0);
exportconstsecondDerivativeBoughtNum=writable(0);
Now that we have that, we can define props for the buildings and adjust the template:
In the last part we introduced a bug. A building’s cost is dependent on how many of that building there are. But now that other buildings can generate buildings themselves, that’d be better if the cost would be associated with how many buildings were bought, not how many there are in total. Because we already solved the issue of differentiating bought versus total, the fix is as simple as:
Let’s define a new component. To do that, let’s create a new file called Upgrade.svelte.
Their states will be:
how many we bought (you can buy the same upgrade many times)
they will have a cost that scale of of how many we bought
they’ll have a name
Upgrade component has a lot in common with the Building component, it is even a subset of it. We can copy the Building component and remove what we don’t need. (Mostly anything that has to do with producing things).
I made another big ugly thing here, using the div around the <Upgrade> tag to push it down the page. We will refactor all those ugly bits at the end of the tutorial because let’s face it it’s not the most interesting things to spend time on right now. But keep in mind that this is not the nicest way to do it.
Updating the production to take into account upgrades
Now we have to modify how Building.svelte calculate how it produces its currency.
We need to have a props to know the bonus given by the upgrade.
Also we need to move things a bit, before we had a variable buildingProduction = 1 which is gonna be replaced by a reactive declaration taking account the bonus given by the upgrade given as a prop, and this will impact productionPerTick.
We used Math.floor() to restrict the upgrade bonus to only whole number, so if a building produce initially 10 unit of currency each tick, with a bonus of 25%, it actually produces 12 unit per tick and not 12.5. For now I will let it that way, even so the upgrade is weaker than what is advertised, it is made to deal only with Integer (Num) and not Float or Double. Another way to do this is to calculate correctly the upgrade without flooring or rounding and to only apply the rounding on the number when we display it.
Note also that is the formula we have twice the magic number 1 which refers to the initial number of unit produced by the building. I will let it that way for now, but in the future we will change it to allow for more flexibility when creating buildings.
Next we need to change App.svelte to calculate the upgrade bonus and pass it to the buildings. For now for each building of the first tier we will get 25% bonus. These numbers are for development purpose and will be changed when we will balance the game progression.
Great! Now we can buy upgrades for our first tier buildings :)
One thing that is far from perfect is $: firstTierBuildingBought = $firstDerivativeBoughtNum + $combinatoricsBoughtNum;. Every time we are gonna add a new tier1 building, we are gonna need to update this. For now we will keep it that way but maybe later on we will find a way to simplify this.
Extending the upgrades for the second tier (and adding an initial cost to upgrades)
If you looked carefully at the last code snippet we used a placeholder for the upgrade bonus of “2nd Derivative” <Building name="2nde Derivative" currencyProduced={firstDerivativeNum} numberOfBuilding={secondDerivativeNum} numberOfBuildingBought={secondDerivativeBoughtNum} upgradeBonus={0}></Building>.
That would be better to implement the upgrade for that tier of building too and it is pretty straightforward.
This time we pass an initial cost to the upgrade so that the first upgrade cost 100 time less than the second.
Also I put the Buildings into div to make the second tier building on a row below the first tier building. As usual, it is to not use CSS now, but at the end we’ll do a cleanup phase to use proper semantic for HTML and use CSS when needed.
Add a second tier building
A last thing before wrapping up this part, we’ll add a second tier2 building that will produce Combinatorics to make things even (two tier1, two tier2 and two upgrades). To do that we need to have the proper values in store.js then adding the component into App.svelte.
If you have questions, suggestions or want to discuss about this subject,
I'd be more than happy if you reach me at conta-remove-ct@julienrouse.com. See also my open invite