Spelchan.com Logo

From Scratch Web Games: A Beginners Guide to Game Development using HTML, CSS, and JavaScript

Chapter 4.13: Functions

DRY, which stands for Don’t Repeat Yourself, is a coding philosophy that tries to avoid cut and paste coding. Code in two or more different places that does the same thing can be a source of bugs if you change one version but forget to change another. This is the basis for functions which are known as methods in Java, are named blocks of code that can be called by using the name of the function. This allows you to create a block of code that can be re-used without having to duplicate the code every time it is used.

Functions are defined by using the function keyword. You specify the name of the function, which is similar to a variable name but instead of referring to a variable it is the name of the function. Common practice is to name functions with a lowercase character. While this is not a requirement, it is highly recommended for reasons that will become clear in later chapters.

Say you were writing a program that would be printing lots of text to the console (or to a text field, something that will be covered later). We could simply have a console.log statement placed wherever we wanted to have the line separator, but what happens if we decide that we need to change what the separator looks like? We would have to search through all our code to find where we wrote a separator and replace it with our new version. Had we used a function to draw the separator, we could then simply change the separator by changing the function. A separator function would probably look something like this:

function separator() {
   console.log(" ---------------------------");
}

And to use the function we would do something like this:

separator();
console.log("Here is a message between two separators");
separator();

You will notice this is like how the Math functions work, but without the library preface. This is because Math is an object that contains functions. Objects are essentially a combination of variables combined with the functions used to manipulate those variables. This, along with the topic of creating objects, will be covered in chapter 7.

The above function can be handy if the code just does one thing. Often, though, we want to have code deal with conditions or other stateful operations. While we could have the function use global variables to determine what it wants to do, this is obviously dangerous and would result in hard to understand code. To enable functions to handle variables without resorting to global variables we can give the function parameters. Parameters are values that the function can use. You can have a function use as many parameters as you need by separating them with commas. For example, lets say you wanted to automate the generation of ranges of numbers by writing a function to generate a random number within a range of integers. We can do this:

function printRandomRange(low, high) {
   let range = high - low + 1;
   let r = Math.floor(Math.random() * range + low)
   console.log(r);
}
printRandomRange(7, 11);

This lets us generate random numbers in a specified range, but has the downside that the results are sent to the console. What if we wanted to get the result and do something with it? Functions may also optionally return a value by using the return keyword. An example of a function would be:

function roll3D6() {
   let d1 = Math.floor(Math.random()*6+1);
   let d2 = Math.floor(Math.random()*6+1);
   let d3 = Math.floor(Math.random()*6+1);

   return d1+d2+d3;
}
This function rolls three dice and returns the result. While this function does not take any parameters, you can still have parameters and still return a result. To use a return value, you simply need to store it in a variable as demonstrated here:
let roll2 = roll3D6();
let roll1 = roll3D6();
console.log("The rolls were " + roll1 + " and " + roll2);

It is also possible to assign a function to a variable, allowing you to pass a function to another function. In the earlier section you seen a function being created in-line to be assigned to a variable. To assign an already existing function to a variable you simply uses the function’s name without any parentheses and followed by a semicolon.

variable_holding_3D6 = roll3D6;
console.log("rolling3D6 with variable " + variable_holding_3D6());
let roll3 = variable_holding_3D6();
console.log("another variable roll " + variable_holding_3D6());

You can see that we can use the variable version of this function just like it were a function. This is because it is. We will cover more about this in future chapters but I am sure many readers will be asking why you would want to pass a function to a function. This is a very powerful technique for advanced programming. This lets you create functions that use one or more passed function to perform some of their actions, meaning that you can have several different functions, each of which does something slightly different and use the appropriate function when calling the original function. This is the procedural equivalent of the strategy pattern, but design patters are a topic beyond the scope of this book.

Let’s demonstrate this by creating a character for a roll-playing game. By having the method of rolling as a function that is passed into the generator, we can change how we generate the stats by simply specifying the rolling method you will be using. We can also demonstrate default parameters. The last parameters you call can have default values used. In our case, we want to be able to specify the character to use to end the line so that the demo html page can use the same generator as the console. HTML uses <br> to end lines instead of a “\n” line return character that would be treated as whitespace in HTML

function generateCharacter(roller, lineEnd="\n") {
   let s = "Strength: " + roller() + lineEnd;
   s += "Intelligence: " + roller() + lineEnd;
   s += "Wisdom: " + roller() + lineEnd;
   s += "Dexterity: " + roller() + lineEnd;
   s += "Constitution: " + roller() + lineEnd;
   s += "Charisma: " + roller() + lineEnd;

   return s;
}
console.log(generateCharacter(variable_holding_3D6));
separator();
console.log(generateCharacter(roll3D6));

You will notice that we can call using the variable we created or call the function using the function name without any parameters just like we did when creating the variable version of the function. And if we wanted to create a new function that rolls 4 dice and keeps the highest 3 we would do the following:

function roll3D6Cheat() {
   let d1 = Math.floor(Math.random()*6+1);
   let d2 = Math.floor(Math.random()*6+1);
   let d3 = Math.floor(Math.random()*6+1);
   let d4 = Math.floor(Math.random()*6+1);
   
   return d1+d2+d3+d4-Math.min(d1,d2,d3,d4)
}
console.log(generateCharacter(roll3D6Cheat));

You can also go to the extreme and create the called function right inside the parameter list for the function instead of creating a function. This is useful if you are only ever going to use that function once. Here is my ultimate cheat version.

console.log(generateCharacter(function(){
   return 18;
}));

Of course, functions aren’t the only way of eliminating duplicate code, another very powerful feature of programming languages is the concept of a loop, which is what we will be looking at next.

Chapter contents

Chapter 4 Contents

4.1 Cheat Sheets

A quick summary of the basics of JavaScript.

4.2 History of JavaScript

A brief look at how JavaScript was written in 10 days.

4.3 Comment Controversy

Comments. Why programmers don't write them, and how they should be written

4.4 Variables

Variables are used to store the state of a program.

4.5 (extra) How Computers Represent Data

Bits, Bytes, and data types.

4.6 Math

Math on the computer similar but some symbol differences.

Math functions

Various math operations can be used through the Math class.

4.8 Strings

Strings are what we call blocks of text and are used extensively.

4.9 Calculating true and false

Determining if a conditional expression is true or false

4.10 if (Conditional statements)

Conditional code using the if statement.

4.11 Nested conditions

If statements can contain other if statements, this is called nesting.

4.12 Switch statement

Switch statements are a way of replacing large number of else if statements.

4.13 Functions

Functions let you put common code into a named function that can be called anywhere.

4.14 Looping

Loops allow you to repeat sections of code until conditions are met.

4.15 Nested loops

Just like conditional statements, loops can be nested but this has some special considerations.

4.16 Accessing the Web page

Scripting languages give us the ability to dynamically change the web page.

4.17 Events

Reacting to the user actions is done by handling events.

4.18 Project: Where’s Wendy

Coming June 23rd, 2024

4.19 Project: Where’s Wendy implementation

Coming June 30th, 2024

← previous section
The Switch Statement
next section →
Looping
Table of Contents