Tutorial 1: Hello IncrementalJS

Purpose
To get started with IncrementalJS
What should you be able to do by the end of this tutorial?

1. Setting Up
1aStarting Web Page
The IncrementalJS Library consists of Javascript objects that help you focus on your game logic with a structure to work with and some really useful features. Over the next few parts in this tutorial, we will examine what these features are and how they help!

For this tutorial, let's use the following blank HTML template:
<!DOCTYPE HTML>

<html>

	<head>
	
		<title>Hello IncrementalJS</title>
		
	</head>
	
	<body>
	
	
	
	</body>
	
</html>
1a. The HTML skeleton we want to start with!
Now, the use of this library is directed towards those who, at the very least, have limited Javascript experience and assumes some HTML and CSS knowledge.
Regardless, if you are a complete beginner to HTML/CSS/Javascript, then here's a brief breakdown of the 3 using the human body as an analogy:
For HTML/CSS/JS beginners
HTML (HyperText Markup Language) - the code above - provides the basic skeleton/structure of the page

CSS (Cascading Style Sheets) - we'll see examples later - provides the style/looks/visuals/formatting for the Skeleton written in HTML

Javascript (the 'JS' in IncrementalJS) - a dynamic programming language for the web, in particular client-side (the browser/user's computer side/offline side) - provides dynamic functionality for our pages.

So, in keeping with the body analogy,
HTML provides the skeleton and its components such as the arms, legs, head, eyes ..etc,
CSS makes the eyes look like eyes, the head look like a head, and so on
Javascript is the code nature embedded in our brains to do things with our different components, and lets our brain process information when we touch something

1b Files Required
Alright so now, let's include the files we require. Currently, the only dependency/external file required by this library is jQuery to carry out certain functionality. It will not be required soon, but for now let's go ahead and include it.
<!DOCTYPE HTML>

<html>

	<head>
	
		<title>Hello IncrementalJS</title>
		<script src="http://aldo111.github.io/incremental-game-engine-js/js/incrementalObject.js"></script>
		<script src="http://aldo111.github.io/incremental-game-engine-js/js/jquery.js"></script>
		
		<!--Our Javascript Code-->
		<script type="text/javascript">
		
		
		</script>
		
		
	</head>
	
	<body>
	
	
	
	</body>
	
</html>
1b. The files we need and script tags for our own javascript code
As you can see, there is another <script> block, which is where all our Javascript code will go into!
Note: Placement of Javascript in HTML
Many like to place their main Javascript code at the end of the body tags. This is completely alright and normally doesn't make much of a difference in ordinary usage scenarios. It's typically done to let the relevant page elements load/render before getting to the javascript, and is helpful in animation heavy/dynamic pages. This can usually be taken care of, though, using window.onload or other methods such as document.onreadystatechange depending on your use-case and browser support.

1c Our Demo Setup
We need some kind of idea to test this stuff with, right? So let's come up with a VERY simple demo, a standard 'Hello World' of sorts for Incremental Games, where all we do is Earn 1 point per click - and for 10 points we can buy an upgrade that gives us 2 points per second!

Let's add the following HTML that consists of
  • 2 buttons (one to earn points and one to buy the upgrade that allows us to get some points per second)
  • 1 element to show our points, and
  • 1 element to show how many points per second we earn
<body>

	Points: <span id="points"></span>
	<input type='button' id='earn' value='Earn Points'>
	
	<hr>
	
	Points Per Second: <span id="points_per_second"></span>
	<input type='button' id='getSome' value='Get Some!'>



</body>
1c. Our View/Interface/Display setup


Similarly, we need to setup our Javascript code.

Most setups can simply be broken down into 3(maybe even 2 if you combine the first two) steps:
  • Declaration - Declare and Include variables/scripts/functions/objects used
  • We've already included the 2 Javascript files we need.. in addition to that, we need a variable to store IncrementalJS' Game object, a variable to store our points, and a variable to store how many points we earn per second
  • Initialization - Initialize all our variables and/or objects
  • We'll need a function where we can do all our initializations in one organized place
  • Execution - Execute our main code.. in this case, our game loop
  • We'll need a function where we can write code that needs to be executed in every loop of the game

Let's also not forget that we actually have to invoke these functions in order for cool things to happen!
<!--Our Javascript Code-->
<script type="text/javascript">

	//Variable Declarations & Initializations
	var game;
	
	
	//the init() function initializes or sets up our game
	function init()
	{
		
		game=new Game();
		game.play(play);//Tells the Game() object's play() function that we want to execute the code in our play() function for every loop iteration in the game loop
		
	}
	
	//the play() function contains essential game code
	function play() 
	{
		
	}
	
	//this checks if the window has loaded - includes the document, and all objects/elements in it - and executes the function init() when it has
	window.onload=init;

</script>
1c. Our Javascript Setup
That's our lovely, elegant setup! And look, we also created our new Incremental Game object as well as executed our game loop - the game.play(play) kicks off our game loop!.
Game()
The Game() object is IncrementalJS' main object through which almost everything is done! Upon creating a new Game object as above, its internal variable, fps (denotes Frames Per Second - number of times play() is executed per second), is by default set to 1. You can however choose to use a different FPS by doing simply doing:
game=new Game(30); //initializes to 30fps
Caution: If your game loop performs any numeric operations such as addition, you will want to take into account the FPS through game.getFPS() so that you don't increase/decrease values too fast within a particular period of time. We'll see an example near the end in our demo.


The Game() object's play(...) function takes a function as an argument and it runs the game loop every 'FPS' times per second, where FPS is the FPS specified - it even runs in the background!
But, where are the other two variables we mentioned? And what do we with play() ? When we refresh, we see nothing different than what we had before this javascript. So how do we make things work?
For that, we need to look at two things: Attributes and Clickers


2. Attributes and Trackers
2aWhat are Attributes?
If you've seen the Documentation (which you should), you'll see an object called AttributeSet and an object called Common.
Common contains variables and functions that are common to and required by each Game, EntitySet, and Entity.
But more specifically, it contains one variable called 'attributes', which is simply - an AttributeSet.
AttributeSet is an empty javascript object with some helpful Prototype methods (core functions available to all AttributeSets). This stores 'attributes' or variables that we can keep track of in an organized manner in each type of object - whether in the context of Game, an EntitySet, or an Entity.

2bK, so AttributeSet is just a glorified object that stores my variables. Now what? How do I use it to make my game?
:( .. Pretty simple:

//the init() function initializes or sets up our game
function init()
{
	//create Game() instance	
	game=new Game();
	
	//add attributes
	game.addAttribute("Points",0);
	game.addAttribute("PointsPerSecond",0);
	
	/* 
		I can also do the following:
	
			game.addAttribute("Points",0).addAttribute("PointsPerSecond",0); 
			
	
		Hurray for chaining! This works because addAttribute returns the AttributeSet itself
		So you can reuse its functions. There's a lot of chaining in IncrementalJS!
	*/

	game.play(play);
	
}

2b. Adding attributes
AttributeSet/Common
Other than addAttribute, there is also a setAttribute function which is used in the same exact way as addAttribute. Both can be used to update values or add new ones, but setAttribute is semantically used only to update an attribute, while addAttribute can be used to 'track' attributes in shorthand.

In order to access an attribute, you can do any of the following:
  • Object.getAttribute("name_of_attribute") - eg. game.getAttribute("Points")
  • Object.attributes.name_of_attribute - eg. game.attributes.Points (only works when you have non-spaced attribute names)
  • Object.attributes["name_of_attribute"] - eg. game.attributes["Points"] - for when you have spaces
If you refresh now, do you see anything cool? Nope, because nothing's changed in our view! We don't even see a damn number!
So how do we modify the view? It's simple, We kill the Batm- we use Trackers

2cTrackers
Trackers are simply little ..cameras that watch your variables in the locker room as they change and display them in the HTML element of your choice!
There are many different ways to 'track' attributes.. and you can further customize how you want each value to be displayed!
//1. Primary way to track
game.addAttribute("Points",0);
game.track("Points","#points");

//2. Chaining - AttributeSets also have track/untrack methods
game.addAttribute("Points",0).track("Points","#points");

//3. Short-Hand
game.addAttribute("Points",0,"#points"); //note: this will only work with addAttribute, not setAttribute

//------CUSTOM DISPLAY------\\
//Very cool extra feature - each of these tracking methods take an additional argument as a function
//this function, should you supply one, should return the string you want to be displayed
//in place of the tracked value - also note: the function receives the value as an argument, so have a parameter called 'value'
//By default, in IncrementalJS, this function simply returns the tracked attribute value

game.track("Points","#points", function (value) {
	
	return Math.round(value); //will only display a rounded value
});

game.addAttribute("Points",0,"#points",function (value) {
	
	return Math.round(value); //will only display a rounded value
});

2c. The many ways by which you can track, and custom-display, attribute values
Okay, that's kinda cool. So you're telling me I don't have to do another document.getElementById(".....").innerHTML?
Yep! The only catch here, as you can see in the code, is that you need to supply the 'tag' that is associated with how you identify an element. So, if you're identifying an element by its id, like we are with our <span id="points">, then we provide a # (hash). If we want to identify by a class, we use a . prefix (.points). Otherwise, we just type the name of the element in (div, span, p, ..etc). Cool, so now let's use this in our little game?
Absolutely!
<!--Our Javascript Code-->
<script type="text/javascript">

	//Variable Declarations & Initializations
	var game;
	
	
	//the init() function initializes or sets up our game
	function init()
	{
		//create Game() instance	
		game=new Game();
		
		//add attributes
		game.addAttribute("Points",0).track("Points","#points");
		game.addAttribute("PointsPerSecond",0,"#points_per_second");
		
		
		
		game.play(play);
		
			
	}
	
	//the play() function contains essential game code
	function play() 
	{
		
		
	}
	
	//this checks if the window has loaded - includes the document, and all objects/elements in it - and executes the function init() when it has
	window.onload=init;

</script>
2c. Our Javascript so far
Go ahead, refresh your page!
Great, I can now see 0s. But the buttons don't do anything?
Ah yes, for that, let's check out..


3. Clickers
3aWhat are Clickers?
Clickers are HTML elements that have been associated with a click event through the Game object! Only the Game() object comes with an addClicker(...) method.

3bHow do I use one
Let's see, if we wanted to make our 'Earn Points' button clickable and actually earn us points, we can just do:
//add clickers
game.addClicker("#earn",function() { 
	game.attributes.Points+=2;
});


3b. How to use a clicker [Refer to the documentation for additional parameter]
Essentially, you provide the identifier/class/name of the element you want to make clickable, and give it a function to execute on click. We provided an anonymous function function with our code that will henceforth always be executed whenever #earn is clicked. Great, click-event handling taken care of. What about the other button?
The syntax for addClicker stays the same, but the code inside our anonymous function will, obviously, be a bit more complex.
game.addClicker("#getSome", function() {
	//this function also shows another way to access attributes
	var p=game.getAttribute("Points");
	var cost=10;
	var increase=2;
	
	if (p>=cost)
	{
		//we can buy
		p-=cost;
		game.setAttribute("Points",p);
		var pps=game.getAttribute("PointsPerSecond");
		pps+=increase;
		game.setAttribute("PointsPerSecond",pps);
	}
		
	
	
	
});
3b. Code to actually buy stuff - this also shows a different way to access attributes

Great, so we have our clickers in place! Let's put it all together!

3cPutting things together
<script>
//the init() function initializes or sets up our game
function init()
{
	//create Game() instance	
	game=new Game();
	
	//add attributes
	game.addAttribute("Points",0).track("Points","#points", function(value) { return value.toFixed(0); });
	game.addAttribute("PointsPerSecond",0,"#points_per_second");
	
	//add clickers
	game.addClicker("#earn",function() { 
		game.attributes.Points+=2;
	});
	
	game.addClicker("#getSome", function() {
		//this function also shows another way to access attributes
		var p=game.getAttribute("Points");
		var cost=10;
		var increase=2;
		
		if (p>=cost)
		{
			//we can buy
			p-=cost;
			game.setAttribute("Points",p);
			var pps=game.getAttribute("PointsPerSecond");
			pps+=increase;
			game.setAttribute("PointsPerSecond",pps);
		}
			
		
		
		
	});
	
	//play
	game.play(play);
	
		
}
</script>
3c. Our Init function
You'll notice I added an anonymous function to the track() method for the first attribute, Points. If you recall from the sub-section on trackers (2c), this is an optional function that takes in one parameter, the value of the attribute being tracked, and returns the way it should be displayed. I have simply set it to return no decimals, only the integer itself, in case I decide to change cost from 2 to some other decimal value.
If you refresh your game and try playing it, you'll notice you can earn points and buy more 'Points Per Second'. However, nothing actually happens 'per second'. This is where our play() function comes in handy.
//the play() function contains essential game code
function play() 
{
	
	//here we see another way to get/update attributes more quickly
	var g=game.attributes;
	g["Points"]+=g["PointsPerSecond"]/game.getFPS(); 
	//divide by FPS because we have to take into account the Frames Per Second when adding anything per Second,
	
	
}

3c. the play() function - also demonstrating yet another way to access attributes

Fairly straightforward, right?
We're accessing the Points attribute directly and adding to it the PointsPerSecond attribute, since it does make sense. But wait, why are we dividing the points added per second by the game's FPS - the game's FPS is 1 by default, so it doesn't matter right?
Yes, in its current state - the FPS of the game is 1 and so the division is unnecessary. But what if you decide to set the FPS to 10, or 15, or 30?

Let's do the math to see what happens if we exclude the divided-by-game.getFPS() and the FPS is 10
Suppose the PPS (points per second) is 2. The play() loops runs 10 times (frames) per second.
Expected Behaviour: In 1 second, the Points attribute should increase by 2.
Actual Behaviour: In 1 second, the Points attribute increases by 20 per second, because 2 was added 10 times per second.

Hence, in such operations, make sure you factor in the FPS, whether it is 30 or 1 (to be safe). By dividing the FPS here, we are basically adding up 10 parts of 2 in the span of 1 second. 1/10th of 2 is 1/5. So by adding 1/5 ten times to the Points attribute, we get 2 in one second!
10-15 FPS is a good choice because it also updates the tracked variables quicker. Currently, clicking on either button doesn't update the displayed corresponding attribute immediately - the trackers waits until the next loop iteration to update, so we would have to manually throw in a Javascript/HTML text manipulation in our click functions.
Increasing the FPS would alleviate this problem at this scale.


Final Code - Play with it and make it more interesting
<!DOCTYPE HTML>

<html>

	<head>
	
		<title>Hello IncrementalJS</title>
		<script src="incremental-game-engine-js/js/incrementalObject.js"></script>
		<script src="http://aldo111.github.io/incremental-game-engine-js/js/jquery.js"></script>
		
		<!--Our Javascript Code-->
		<script type="text/javascript">
		
			//Variable Declarations & Initializations
			var game;
			
			
			//the init() function initializes or sets up our game
			function init()
			{
				//create Game() instance	
				game=new Game(30);
				
				//add attributes
				game.addAttribute("Points",0).track("Points","#points", function(value) { return value.toFixed(0); });
				game.addAttribute("PointsPerSecond",0,"#points_per_second");
				
				//play
				game.play(play);
				
				//add clickers
				game.addClicker("#earn",function() { 
					game.attributes.Points+=2;
					game.addClickerText("+2");//adds clicker/particle text - still under works!
				});
				
				game.addClicker("#getSome", function() {
					//this function also shows another way to access attributes
					var p=game.getAttribute("Points");
					var cost=10;
					var increase=2;
					
					if (p>=cost)
					{
						//we can buy
						p-=cost;
						game.setAttribute("Points",p);
						var pps=game.getAttribute("PointsPerSecond");
						pps+=increase;
						game.setAttribute("PointsPerSecond",pps);
					}
						
					
					
					
				});
				
				
				
					
			}
			
			//the play() function contains essential game code
			function play() 
			{
				
				//here we see another way to get/update attributes more quickly
				var g=game.attributes;
				g["Points"]+=g["PointsPerSecond"]/game.getFPS(); 
				//divide by FPS because we have to take into account the Frames Per Second when adding anything per Second, because this play() loop is execute game.getFPS() times per second!
				
				
			}
			
			//this checks if the window has loaded - includes the document, and all objects/elements in it - and executes the function init() when it has
			window.onload=init;
		
		</script>
		
		
	</head>
	
	<body>
	
		Points: <span id="points"></span>
		<input type='button' id='earn' value='Earn Points'>
		
		<hr>
		
		Points Per Second: <span id="points_per_second"></span>
		<input type='button' id='getSome' value='Get Some!'>
	
	
	
	</body>
	
</html>
Wrap-Up
So that's pretty much it! There are a lot more small-medium-big features, such as flags, timers for functions, particle/clickerTexts (I threw in a clickerText in the code above, it should popup when you click Earn Points) the other objects EntitySet and Entity - I will post a tutorial on these soon as well!

I really hope, despite the length of this tutorial to convey the creation of a very simply test - you find this library useful and I welcome any and all suggestions! I encourage you to read the Documentation if you are interested in knowing about the other things and are willing to try experimenting with them!

I previously made a game after v1.5, Descent so you are welcome to examine the Javascript portion of the source code, in particular the init() function, to see how EntitySets and/or Entities are used!