Learning To Count
An opinionated beginners guide on creating an incremental game
No longer satisfied by the ever increasing numbers of the latest incremental you now find an idea of your own starting to build inside your mind. Looking over your vast array of counters and progress bars you wonder what makes them go up sometimes in ones or twos and others in billions and trillions. Are some advanced mathematics at play weaving themselves between the dark arts of computer science?
Getting started with your own game is surprisingly easy and by the end of this guide you’ll be watching in awe as your very own numbers start going up. This adventure was inspired by wanting to update a guide by kastark1 with a small helping of not wanting my own times I’ve answered this question count to keep rising.
This guide incrementally builds in complexity from assuming no programming knowledge at all into creating and publishing a simple game. If you’re already familiar with creating HTML you can skip ahead to Count 2.
Count 0: What does any of this mean?
Newcomers to the programming world often find the sudden onslaught of terminology overwhelming with hundreds of acronyms to decipher and entirely new meanings to everyday words. So before we even start exploring here’s a handy glossary of terms that will soon become every day expressions:
HTML - Used to describe what a web page contains: Hyper Text Mark-up Language
CSS - Makes your HTML look any way you want: Cascading Style Sheets
JS - What makes all the numbers go up!: JavaScript
These three make up the core of what we’ll use to create our game but there’s a few more to cover so we’re on the same page:
Element - These are the building blocks of HTML and come in all sorts of variations.
Attribute - Information that can be added to Elements to change appearance or behaviour.
String - This is what we call text when programming and it’s usually surrounded “by quotes”
MDN - Mozilla Development Network; a great site full of helpful info that will be frequently linked
You can check out the excellent MDN Glossary for everything and anything you might come across.
Count 1: Make a web page!
The heart of programming is telling the computer what to do and while we could carefully poke and prod at our computers with wires and a resistor it’d be a lot easier if we could write down our instructions. To do this we’re going to need a text editor, which does exactly what its name suggests, called Visual Studio Code which I pray works just fine on your computer. Make sure not to install “Visual Studio” without the Code which is related but much more complex2. There are countless other editors which offer all sorts of different ways of doing things but we’re going to stick with Visual Studio Code, or VSCode for short, as you can do a whole lot with it and lots of other people like using it.
We will also need something to view our game with but as I assume you are viewing this guide in the normal manner you should already have what we need. That’s your web browser which probably has a name like Chrome, Edge, Firefox , Safari or something equally silly3. If you don’t have one of the ones named here you should still be good to go as most other browsers come with all the bits we need.
One final step before we can get stuck in is to give ourselves a little space to keep everything we make in one easy to remember place. The easiest way is to create a folder4 and give it a memorable name so open up your documents folder and create a new one called incrementals
.
Now for the moment you’ve been building yourself up for: creating our very own web page! Open up VSCode if you haven’t yet been excited enough to sneak a peak in and from the Welcome page select New File… In the box that just popped up type in index.html
, yep all lower case here, make sure to include the dot between index and html then hit enter. Now find the incrementals folder you just made and open it up then by hitting Create File we’ll be on our journey.
Into our fresh and empty file we need to tell the computer the magic words that tell it we want to display something inside our browser. To start with we just want to say hello so type out the following or copy and paste it in.
<html>
hello numbers!
</html>
Those paying attention will spot the same thing we saw in the glossary earlier “html” alongside some funky shapes and lines5. In-between that madness is some plain English that will make up our very first web page once we ask our Browser to give it a shot. This final part is the most nerve wracking as we need to go back to the folder we created just a moment ago which now should contain our fresh new page. If your file has the same icon as your browser you can open the file as normal and it should get the browser to do its thing. For those of you that don’t you might have to right click on the file then look for a line called “Open with…” which if you click on should then list your browser. Should none of these work you can even click and drag our precious file from its folder and over your browser before releasing and with a surprise landing see your new page. If none of these have worked you can find out why it’s so nerve wracking and drop by the beginners channel in the discord get some help.
After all those options we should now be looking at a very formal looking plain white screen with our “hello numbers!” hanging out at the top. Congratulations! You’ve made your first web page and with it leapt past the first step with flying colours.
There’s a lot more you could learn about web pages and if that sounds like more fun than the rest of this guide you can explore the excellent options at the Mozilla Development Network (MDN) like their Getting started with HTML guide.
Count 2: Clicking
With our brand new page working in our browser we’re ready to introduce the core feature of every incremental: clicking a button to make a number go up! To make this happen we need to add three things to our basic page: a button to click; a number that goes up and a way to link the button and number together.
Before we add anything we should make a few changes to our existing page that will help us later on. I’m not going to go over what all the new parts do as the guide linked above does a great job of that. For now we can replace the contents of our file with the following
<html>
<body>
<p>hello numbers!</p>
</body>
<html>
Now that we have a file that won’t make purists cry themselves to sleep we can add the first part of our game: the button. Luckily for us HTML comes with a way to make buttons built in which makes this step surprisingly easy. This is the button
element and we can add one just after our existing <p>hello numbers!</p>
line in similar fashion.
<html>
<body>
<p>hello numbers!</p>
<button>click me!</button>
</body>
<html>
Whatever text you put between the two button
elements will be displayed by the browser as the text on the button. Change the text to say whatever you want now and see how it looks in your browser! There are a few limitations on what you can put inside the button which you can read in complete detail in the button documentation over on the MDN. Once you’re happy with your button we can move to the number.
Keen eyed readers may have spotted the p
element around our text and wondered if we could use that to display our number. One of the advantages of HTML is its flexibility that allows almost any combination of elements to create a page but this also makes learning which one to use quite a challenge. For our game we’re going to use an input
element6 to hold our number.
Adventurous readers might try to create the input element on their own following the pattern used with the “p” and “button” elements. Trying this for ourselves gives us a surprising result:
<input>1</input>
The number 1 is placed outside of the new input box! That’s not what we wanted to happen at all. Unlike all the elements we’ve seen up until now the “input” element does not allow anything “inside” it. If we can’t put our number inside then how are we supposed to provide it? We have to use an attribute with the appropriate name. For our input element the attribute is sensibly called value
and we place it just after the first “input”. We’ll also remove the “closing” element to make sure we don’t put anything back in there later.
<input value=1 />
Our number now goes inside the input box which is where we wanted it but there’s a new problem; we can type in the box and replace our number with anything we want! Fortunately for us there’s an attribute that controls exactly this problem and it’s called readonly
. Simply by adding the word readonly
anywhere inside our input element we can prevent anyone from messing up our very important number.
We’re going to go on a quick detour to visit another attribute so if you just want to get to clicking you can skip to the next paragraph. A common part of incremental games is stopping the player when they’re out of a resource, you might then try adding “readonly” to the button element. Go ahead and try but no matter what you do it won’t stop the button from being clickable. Instead we want to use the disabled
attribute which, as the name suggests, disables whatever it’s associated with. Try adding disabled
or readonly
to every element we have and see what the results are!
<html>
<body>
<p>hello numbers!</p>
<button>click me!</button>
<input readonly value=1 />
</body>
<html>
Count 3: Counting
Now we have a button to click and a number to go up we’re ready for the step that makes the number go up when we click the button. This is where our new best friend JavaScript comes to the stage and it will be doing all the heavy lifting from now on. Like everything we’ve added so far we’ll be creating a new element that will contain our JavaScript which we want to place after the body
element7.
<html>
<body>
<p>hello numbers!</p>
<button>click me!</button>
<input readonly value=1 />
</body>
<script>
</script>
<html>
To make our lives 5 minutes from now easier we’re going to jump back to working with attributes and add two more. These will be id
attributes and we’ll add one to the button that looks like this id=”clicker”
and the other to the input id=”number”
. Make sure to include the double quotes ”
which tell the browser to use the text the right way for us.
<html>
<body>
<p>hello numbers!</p>
<button id=”clicker”>click me!</button>
<input id=”number” readonly value=1 />
</body>
<script>
</script>
<html>
We’re going to skip over the details of how this JavaScript works so we can start making our number go up already so for now just add the following inside the script element:
<script>
function count() {
let number = document.getElementById("number");
number.value = Number(number.value) + 1;
}
let clicker = document.getElementById("clicker");
clicker.onclick = count;
</script>
Now when clicking the button our number should count up by one each time; the fundamental building block of an incremental game is complete. If I can tear you away from clicking the button a few more times we can take a tour through the JavaScript and get an idea how it all comes together.
This code does two things for us: a way to make the number in our input go up and making that happen every time the button is clicked. In both places we can see the same thing happen document.getElementById
then the ids we added before. It is possible to make the same thing happen without these ids but it’d mean writing more code and that’s something everyone tries to avoid.
On the first line there’s a function
which lets us group some code together and control when it runs. If we didn’t have this the number would go up one time when the page gets opened and never again! Where we add one to our input we tell the browser that the value should be treated as a number; without this some unexpected things can happen. The final line is what links everything together and makes the function we’ve created happen whenever the button is clicked.
Phew! That was quite a lot to take in but we’ve gone through all the parts of building a basic incremental. The rest of this guide will focus on specific areas of creating a full game and won’t be introducing as many new concepts as once. You can take a break for now and enjoy clicking. Don’t be afraid to start playing around with your example and seeing what happens when you change things. You can make a copy of the existing game but you’ll find re-creating this one will go much faster second time around.8
Count 4: Refactoring
Before we get into adding more features lets take some time to review our existing code and see if there are any improvements to be made. Looking back at your existing code is a fundamental part of programming and you’ll almost always see room for improvement! For the benefit of those joining us at this step and in case you’ve broken your copy here’s our current code:
<script>
function count() {
let number = document.getElementById("number");
number.value = Number(number.value) + 1;
}
let clicker = document.getElementById("clicker");
clicker.onclick = count;
</script>
The current value of our number is always stored in the number
element; this isn’t great as it means any time want to know what it is or change it we have to fetch the entire element. This is something to avoid as it can slow down our game if used excessively and it requires a lot of writing so we’ve got a few reasons to improve it. To do all this and more we need to first choose a name. Names are a surprisingly tricky part of programming because everything we do requires one and sometimes the name will be all we know. Lets call our new thing counter
as it will be doing the counting for us.
We call things that store values “variables” because as the name suggests they can vary. Lets create our counter
variable by adding the following to the start of our code:
let counter = 0;
Now that we’re only looking at one line we can get more familiar with all the things that are happening on it. Starting off comes the term let
which is used to tell the browser we’re creating a thing. It’s a bit dramatic for every day use but if you’re not quite sure what that means think of the grand declarations “let there be light!” just on a smaller scale confined entirely within your computer. Next comes the word we’ve chosen counter
so instead of light we can declare “let there be counter!”. We can choose almost anything for a name with restrictions such as not containing a space or starting with a number; the full list of rules is worth reading once. Lastly we have = 0;
which completes our declaration by telling the browser what value our variable should start with. Our complete declaration now reads “let there be counter with the number zero!”.
Phew! That was a lot more to take in at once but now you’ve got an understanding of how declarations work try reading through the existing code and taking a note of all the declarations made in it.
With our variable in hand we can try changing our count
function to increase its value each time. Remember that we’re trying to avoid getting the element frequently.
let counter = 0;
function count() {
counter = counter + 1;
}
let clicker = document.getElementById("clicker");
clicker.onclick = count;
Try this out and you’ll find that nothing seems to be happening when we click the button. We can use the Console built into the browser to get a closer look. Open it by pressing “F12” in most browsers and the DevTools section should open with the Console at the bottom. Type counter
into the console and press enter to find out what the current value is. What happens when you click the button some more and type it again? The number stored in counter is going up!
We still need to tell the “number” element what to display when counter is clicked while avoiding asking for the element each time. To do this we’re going to put back some of the code from before but this time we’ll “lift” the declaration of number to outside of the function in the same way we’re using our counter
. Once we’ve done that we can tell it the new value similarly to before.
let counter = 0;
let number = document.getElementById("number");
function count() {
counter = counter + 1;
number.value = counter;
}
let clicker = document.getElementById("clicker");
clicker.onclick = count;
Now when we click our button a few times the number is going back up but it doesn’t go up the first time we click, why does that happen? Although we start by saying counter has a value of zero we haven’t changed the value we put in right at the start inside the number element itself. Lets take a quick look back at that to spot it
<input id="number" readonly value=1 />
Yep that’s the number 1 alright. We don’t need it so what happens if we just remove the value attribute and go from there? Try it for yourself and can you spot the problem? Our button counts up correctly now but there’s nothing shown inside our input at the start. It might seem like you can solve this by changing the starting value to be 0 but this is only a temporary fix. If instead of 0 we wanted to start counting from 100; we’d now have two places to change! This is how games get bugs. We can avoid having any value in the element by setting the value to the starting value of counter
right away:
let counter = 0;
let number = document.getElementById("number");
number.value = counter;
function count() {
counter = counter + 1;
number.value = counter;
}
let clicker = document.getElementById("clicker");
clicker.onclick = count;
Now whatever number we pick to start counting from the correct value is shown inside our input. We’re now in a much better place to begin work on our game loop.
Count 5: Automatic Counting
So far we’ve been limited to making a single number go up in direct response to an interaction. To take our game to the next level we want the number to go up all the time without any clicking required. There’s a specific term used to describe the sort of code we’re about to write - the “game loop” - and there are lots of different styles and variations. We’ll be using a straightforward one but now you know the term try and find other examples.
Creating a game loop can be quite a daunting task for beginners but luckily for us JavaScript comes with one built in: the setInterval
function. We’ll be responsible for telling it what to run each time it loops and how often those loops should happen. With the refactoring done in the previous chapter we’ve already identified what should happen each time we loop with the count
function. All that’s left is to pick the amount of time between loops; we’re going to go for a leisurely 1 second to give us time to see what’s happening in real-time.
setInterval(count, 1000);
The first thing that jumps out is that huge 1000 but didn’t we agree on 1? Computers can do a lot of crunching in a second so we’re counting in milliseconds instead of whole seconds. There’s 1000 milliseconds in a second9 so converting between the two is quite straightforwards. As you learn more about programming counting in milliseconds will become second nature.
The second is the way we’re using our function from before: count
. Functions can be passed about in JavaScript just like any other variable. We’ve already used this without noticing when we assigned the onclick
to our click button element. A common mistake on this step is to write the following:
setInterval(count(), 1000); // incorrect!
By adding the ()
to the function name we’re telling the browser to run the function right there and then not every 1000 milliseconds. The count
function doesn’t give anything back after it runs so our loop ends up not doing anything which isn’t what we want to happen.
When we look at our page now we can see the number going up by 1 every second. Clicking our button still counts up by 1 as well but having the number just go up by itself isn’t especially satisfying. We can make the number go up faster by reducing the interval between loops. Try out different values and see what happens!
A core feature of most incremental games is being able to increase the amount our number goes up by each second. It looks like we could just change the + 1
inside count
but there’s a problem with this - it’s also controlling how much our button increments. We could fix this by duplicating the existing count
function and having one for the button and another for the loop but as we’ve seen before this is a great way to introduce bugs.
We’re going to solve this problem by adding the ability for our count
function to be told how much to count by each time. This is done by adding a parameter to the function. Changing the count function to include a parameter involves two parts: adding it to the definition and using it.
function count(increment) {
counter = counter + increment;
number.value = counter;
}
If we try to view our page now we’ll find that everything’s broken! We’ve added a parameter to count
but we didn’t tell anyone using it what to pass in. As we discovered with setInterval
we can’t change our current usage to include a number as that would run the function e.g.
clicker.onclick = count(1); // incorrect!
Instead we’re going to have to define two new functions that will use count with the correct value. So far we’ve been using the “tradition” way of creating a function by writing out the word function
then giving it a name and so on. There’s another way that’s perfect for this task so lets try that instead.
clicker.onclick = () => count(1);
That’s some pretty funky looking code! It’s called a lambda expression10 and uses this fat arrow =>
to become a function. They’re very handy for tiny functions that need to “wrap” around other functions exactly like we’re doing now. Lets add another to fix our loop.
setInterval(() => count(1), 1000);
Now we’ve gained the ability to independently alter how much we increment with in the loop and by clicking the button. Lets take a look at the complete file with everything working.
<html>
<body>
<p>hello numbers!</p>
<button id="clicker">click me!</button>
<input id="number" readonly />
</body>
<script>
let counter = 0;
let number = document.getElementById("number");
number.value = counter;
function count(increment) {
counter = counter + increment;
number.value = counter;
}
let clicker = document.getElementById("clicker");
clicker.onclick = () => count(1);
setInterval(() => count(1), 1000);
</script>
<html>
Count 6: Counting counters
Changing the values by altering the code is fun for us but it’s not going to work for a game. The final change we’ll make will be introducing a second button that increases the rate of counting. We’ll need another button to click on and some way of joining the number of clicks on that button to the amount we increment by each second.
You’ve already made a button so try adding one yourself; how far can you get armed with the knowledge from the rest of this guide?
I’ve added a button to my version and given it the id “incrementer”.
<body>
<p>hello numbers!</p>
<button id="clicker">click me!</button>
<input id="number" readonly />
<button id="incrementer">increment more</button>
</body>
Next is adding a new variable and function so we can keep track of how many times the new button has been pressed. This is something you’ve done once before; try and get it working before checking out my version.
let incremental = 0;
let incrementer = document.getElementById("incrementer");
incrementer.onclick = () => incremental = incremental + 1;
Since we know we’ll always (or will we?) be increasing this value by 1 we’re not separating out the function like before. Instead we can write the entire expression after the arrow to save us a bunch of writing.
There’s one last change to bring everything together so can you work it out? We’re going to use the current value of incremental
in our game loop.
setInterval(() => count(incremental), 1000);
We’ve made quite a few changes so lets look over the entire file again.
<html>
<body>
<p>hello numbers!</p>
<button id="clicker">click me!</button>
<input id="number" readonly />
<button id="incrementer">increment more</button>
</body>
<script>
let counter = 0;
let number = document.getElementById("number");
number.value = counter;
function count(increment) {
counter = counter + increment;
number.value = counter;
}
let incremental = 0;
let incrementer = document.getElementById("incrementer");
incrementer.onclick = () => incremental = incremental + 1;
let clicker = document.getElementById("clicker");
clicker.onclick = () => count(1);
setInterval(() => count(incremental), 1000);
</script>
<html>
Take a look at it in action and watch that number go up! Things are happening but the satisfaction of watching a number go up every second isn’t quite there. We want the number to change more often without making the rate it increases go up.
Making it update more often is a simple task. By changing the value given to setInterval
to 100 the updates happen ten times more often but our number is going up ten times as fast! To solve this problem we can reduce the amount given to count
by ten as well.
setInterval(() => count(incremental/10), 100);
Now things are updating frequently but we get a lot of decimals sometimes which don’t look great. We only want to show whole numbers to the player. So far we’ve been doing basic maths that has dedicated symbols “+, -, *, /” but there isn’t a symbol for “whole numbers only please”. To achieve this we’ll use the extensive set of functions included in the mathematics library and pick floor.
We have to be careful here to only change the value shown to the user, if we used floor
in our game loop we’d lose all the small updates. The final change is inside our count
function to floor the value as we display it.
number.value = Math.floor(counter);
Look at that number smoothly go up faster and faster! We’ve successfully built the basics of an incremental so while there’s always more to learn it’s a good place for us to wrap up. Here’s the full file of the final code for you to change and remix as much as you like:
<html>
<body>
<p>hello numbers!</p>
<button id="clicker">click me!</button>
<input id="number" readonly />
<button id="incrementer">increment more</button>
</body>
<script>
let counter = 0;
let number = document.getElementById("number");
number.value = counter;
function count(increment) {
counter = counter + increment;
number.value = Math.floor(counter);
}
let incremental = 0;
let incrementer = document.getElementById("incrementer");
incrementer.onclick = () => incremental = incremental + 1;
let clicker = document.getElementById("clicker");
clicker.onclick = () => count(1);
setInterval(() => count(incremental/10), 100);
</script>
<html>
Can you think of features you’d want to add? Here’s a few suggestions on what to look at next
What could be done to make it look more interesting
Require something to add more counters
Saving and loading across refreshes
Versioning your code files
Originally published on 2023/07/31