JS Incremental Game

James Zhong



Get Help

Table of Contents

In this workshop, we will be creating an idle/clicker game using HTML, CSS, and JavaScript. Experience with these languages is recommended but not required. The project presented is meant to allow for creative expansion off of the framework provided, so don't be afraid to experiment or add in your own unique touch.

Project Demo

Here's a fully functional demo of the application we will be creating. The source code for this will be available at the end of the workshop.

Project Setup


Before we start coding, we must set up the workspace and prepare some assets. In this workshop we will use repl.it, but any other code editor or IDE will work as well. Click the button below to generate a repl.it project with a precreated document structure.

Assets and Files

The only assets we require for this workshop are images, which will go into the same folder as index.html for now. We will need three images, all of which can be downloaded below (click on the image buttons).

Once you have moved the images into your project folder, the file structure should look something like this:

HTML Document Structure

Fortunately, repl.it has already set up most of the document structure for us. However, a few things must be modified to suit the needs of this project.

First, we will changing the title of our web page. This can be done via the <title> element in index.html. Once you have located <title>, modify the internal text as seen below.

<title> in index.html
<title>Pencil Clicker</title>

If you run index.html now, you should see that the page title has been changed.

The second change we need to make is one that will not affect us until the JS portion of this workshop. Find the <body> tag in index.html and change its properties as seen below.

<body> in index.html
<body onload="updateResources()">

That's it. We have successfully set up the document structure. From now on, we will be adding code into <body>, style.css, and script.js.

HTML Content

First, we will be creating the resource bar that is present at the top of the page. Read through and then insert the following lines into <body> of index.html above <script>.

<body> in index.html
<!-- The number of pencils, pencil makers, and pencil sharpeners you currently have -->
<div id="resource-bar">
	<img src="pencil.png" width="32" height="32"> &times; <span id="pencil-count">0</span>
	<img src="pencil-maker.png" width="32" height="32"> &times; <span id="maker-count">0</span>
	<img src="pencil-sharpener.png" width="32" height="32"> &times; <span id="sharpener-count">1</span>
</div>

<!-- The rate at which your pencil makers create additional pencils -->
<p><br>
	<span id="pencils-per-second">+0.00</span>
	<img src="pencil.png" width="12" height="12"> per second
</p><br>

Now, try running index.html. If everything has been done correctly, then in the top left corner of the page you should see something like this:


We will now add in the buttons that the player uses to interact with the game. Insert the following lines into <body> below the resource bar.

<body> in index.html
<!-- Buttons for making pencils and buying things -->
<!-- Pencils -->
<button onclick="makePencils()">
	<span id="pencils-per-click">+1</span>
	<img src="pencil.png" width="64" height="64">
</button>

<p>Make more pencils<br>Cost: Free!</p><br>

<!-- Pencil Makers -->
<button onclick="buyPencilMaker()">+1
	<img src="pencil-maker.png" width="64" height="64">
</button>

<p>Buy a pencil maker
	<br>+0.50 <img src="pencil.png" width="12" height="12"> per second
	<br>Cost: <span id="maker-cost">10</span> <img src="pencil.png" width="12" height="12">
</p><br>

<!-- Pencil Sharpeners -->
<button onclick="buyPencilSharpener()">+1
	<img src="pencil-sharpener.png" width="64" height="64">
</button>

<p>Buy a pencil sharpener
	<br>+1 <img src="pencil.png" width="12" height="12"> per click
	<br>Cost: <span id="sharpener-cost">10</span> <img src="pencil.png" width="12" height="12">
</p>

We are more-or-less finished with page content now. If you run index.html, you should see this below the resource bar:

If you find the HTML to be intimidating or confusing, try to go through the code line-by-line and figure out how the various elements are used to construct the document.


CSS Aesthetics

What we currently have looks already looks decent, but it could be better. We will be fixing that in this section using CSS, which can greatly improve the appearance of your website. For this workshop, all you will have to do is insert the following code into style.css.

style.css
/* Page setup */

body {
	background-color: white;

	color: black;
	font-family: monospace;
	font-size: 24px;

	text-align: center
}

img { vertical-align: middle; }

p {
	margin: 0;
	font-size: 14px;
}

/*
This selector essentially says
"Find a <div> with id='resource-bar',
then retrieve all the <span> elements
inside except for the last one."
*/

div#resource-bar span:not(:last-child) { margin-right: 30px; }

/* Modifying button properties to suit our needs */

button {
	font-size: 32px;
	cursor: pointer;

	background: white;
	border: 1px #888 solid;
	
	padding: 10px 15px;
	outline: none;
	margin: 0 5px 5px 0;
}

button:hover { background-color: #ddd; }

button:active { background-color: #bbb; }

When run, index.html will now look identical to the page presented in the demo above (although the buttons won't work). If you are already familiar with CSS, then you are more than welcome to change around the properties to suit your needs. If not, then take a minute to look at the CSS and figure out how it all goes together.

JS Functionality

Finally, we have arrived at the JavaScript section of the workshop. Read through the following code (the comments are there to help) before inserting it into script.js.

script.js
// Initializing the variables that we will need
// Feel free to adjust the values to suit your preferences
let pencils = 0.0,
	pencilMakers = 0,
	pencilsPerSec = 0.5, // number of pencils per second per pencil maker
	pencilSharpeners = 1,
	pencilMakerPrice = 10, // the initial price in pencils
	pencilSharpenerPrice = 10; // the initial price in pencils

// Called when the player presses the 'Make more pencils button'
function makePencils() {
	// Adding pencils to the player's inventory each time the button is pressed
	pencils += pencilSharpeners;

	// Updating document HTML after each button press
	// (x).toFixed(n) means that n decimal places will be shown when x is printed
	document.getElementById("pencil-count").innerHTML = pencils.toFixed(0);
}

// Called when the player presses the 'Buy a pencil maker' button
function buyPencilMaker() {
	// Checking whether the player can buy a pencil maker
	if(pencils >= pencilMakerPrice) {
		// Buying a pencil maker - note the order in which the statements are called
		pencils -= pencilMakerPrice;

		// Incrementing the price of successive pencil makers after each purchase
		pencilMakerPrice += 3;

		// Adding a pencil maker to they player's inventory
		pencilMakers++;

		// Updating document HTML after each successful purchase
		updateResources();
	}
}

// Called when the player presses the 'buy a pencil sharpener' button
function buyPencilSharpener() {
	if(pencils >= pencilSharpenerPrice) {
		// Buying a pencil sharpener - see corresponding comments above
		pencils -= pencilSharpenerPrice;
		pencilSharpenerPrice += (10 + pencilSharpeners);
		pencilSharpeners++;

		updateResources();
	}
}

// Creating a looping timer that invokes addPencils() every 1/10th* of a second 
let ticksPerSecond = 10;
let tickPencils = setInterval(addPencils, 1000 / ticksPerSecond);

// Adding the pencils created by pencil makers every time tickPencils loops
function addPencils() {
	// The math is not as complex as it may seem at first
	pencils += pencilMakers * pencilsPerSec / ticksPerSecond;
	document.getElementById("pencil-count").innerHTML = pencils.toFixed(0);
}

// Updating the document HTML to match the game code
// Note that this is not the most efficient way to sync the page
function updateResources() {
	// Retrieving an element by ID ( <[e] id="..."> ) and modifying the text stored within
	document.getElementById("pencil-count").innerHTML = pencils.toFixed(0);
	document.getElementById("maker-count").innerHTML = pencilMakers;
	document.getElementById("sharpener-count").innerHTML = pencilSharpeners;

	document.getElementById("pencils-per-click").innerHTML = pencilSharpeners;
	document.getElementById("pencils-per-second").innerHTML = (pencilMakers * pencilsPerSec).toFixed(2);

	document.getElementById("maker-cost").innerHTML = pencilMakerPrice;
	document.getElementById("sharpener-cost").innerHTML = pencilSharpenerPrice;
}

Congratulations! You have successfully created a web-based incremental game using HTML, CSS, and JavaScript. Be sure to take some time to analyze the code and experiment with it before moving on to the next tutorial!



Full Source Code Back to Workshops