There are many different types of games that can easily be built with a framework of choice. From tic-tac-toe to Magic The Gathering, there are a ton of different games that can be built with Angular. Card games, trivia games, board games, mobile hide-and-seek, etc. can be built using raw, unoptimized AngularJS.
Think about the last time you were in an Applebee’s (a chain restaurant popular in the US) and there was an interactive trivia game on the different TVs. Using a single-page-app (SPA), it can be built in an afternoon. With CSS3/HTML5, we don’t even need fancy animation libraries as 2D and 3D can be performed using only native web elements.
For instance, to run a 3D wipe of an element, we can apply CSS3 to it. Then, when we are ready for the element to transition, we can simply apply the CSS class.
What about building DOM-heavy games? Isn’t Angular really poor at handling LOTS of run-time DOM manipulations? It can be. Due to the way Angular 1.x runs, it has it’s own event handler, which adds overhead to the DOM and building any heavy pixel-heavy games can be painful. Because of the extra event loop, building a DOM-manipulation-based game in only Angular may not be the best approach.
However, there are many other components to building a game, for instance, most (if not all) games have scoreboards. There are HUDS (heads up displays), chat messages, event feeds, multiplayer stats, high scoreboards. How about game invitations, providing a pay-wall to guarentee a player has access to play premium content?
These are all elements that game libraries are not optimized to provide and can be tricky & complex to build. On the other hand, web application libraries such as angular are great at building these components.
While game libraries are great at handling physics, animation, and sounds, we’ll use angular to power the container.
In today’s post, we are looking at how to build the eco-system of a game using angular as the vehicle to deliver the game content, node/express to power the game’s back-end, phaser.io and socket.io to connect the two in real-time.
The game flow looks like the following:
Angular
Let’s start building our the angular-side of our game. This will provide us with a container to build our application from within.
First and foremost, we build our angular applications in a module-based methodology. This provides us with a method to build our applications in isolation, easily share common components, and build focused tests for specific functionality.
To build our application, let’s grab angular using the client-side package manager bower (or save the angular source from angularjs.org):
1
|
$ bower install --save angular
|
In order to build module-based applications, we’ll need to use the fantastic ui-router in conjunction with angular’s built-in modularity. First, let’s install the ui-router either using the client-side package manager bower or save the angular-ui-router.js from the github repo.
1
|
$ bower install --save angular-ui-router
|
Once we have the library, we can reference it in our index.html. Let’s go ahead and build our index.html. A very basic version of the file might look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<!doctype html>
<html>
<head>
<title>Game client</title>
</head>
<body ng-app="app">
<div class='content'>
<div ui-view></div>
</div>
<script type="text/javascript"
src="bower_components/angular/angular.min.js"></script>
<script type="text/javascript"
src="bower_components/angular-ui-router /release/angular-ui-router.min.js"></script>
<script type="text/javascript"
src="scripts/ng-game.js"></script>
</body>
</html>
|
In our source, we’re doing the basics we need to build our app. We’re:
- including the ng-app directive in the body pointing to an angular module we’ll build called app
- loading the required dependencies of angular, angular-ui-router, and our ng-game.js file
- We’re including the ui-view directive in the body of our html
If we load the index.html in a browser, we’ll see a blank page and an error in the console. We haven’t yet defined the angular module app. Let’s go ahead and create a directory called scripts/ and place a file in it called ng-game.js.
In this file, we’ll need to define our angular app. We can do this using the module() function provided by angular:
1
2
|
// In /scripts/ng-game.js
angular.module('app', [])
|
Since we’re dependent upon the ui-router, we’ll need to include it’s module as a module-level dependency. Let’s change the module definition from above to include it:
1
2
3
4
|
// In /scripts/ng-game.js
angular.module('app', [
'ui.router'
]);
|
Building the menu
With our module set up, let’s build our game menu. This game menu will be responsible for listing the currently active games along with allowing the user to join these active games.
To build the game’s menu, let’s create a second directory in our scripts/ called menu/ and place a index.js file. In here, we’ll create the game menu angular module:
2
|
// In scripts/menu/index.js
angular.module('app.menu', [])
|
With our new module created, let’s build our first routes. The reason we need to use ui-router to build our game is that each individule module will be responsible for defining their own routes. Rather than having a global routing table where a single file determines all of the routes, each individual module can be responsible for building our their own route dependencies.
To see this benefit in action, let’s start by building the game module. To define routes, we’ll use the module config() function and inject uiRouter’s $stateProvider:
1
2
3
4
|
angular.module('app.menu', [])
.config(function($stateProvider) {
// Define routes in here
});
|
Within our config() function, we can define the first route:
1
2
3
4
5
6
7
8
9
|
angular.module('app.menu', [])
.config(function($stateProvider) {
// Our first state called `menu`
$stateProvider
.state('menu', {
url: '',
template: '<h2>There is a menu here</h2>'
});
});
|
Now that we have a menu state, we’ll need to set this menu state as a dependency of our main application. First, we’ll need to load our game in our index.html (or use an AMD-library or a CommonJS library):
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!doctype html>
<html>
<head>
<title>Game client</title>
</head>
<body ng-app="app">
<div class='content'>
<div ui-view></div>
</div>
<script type="text/javascript"
src="bower_components/angular/angular.min.js"></script>
<script type="text/javascript"
src="bower_components/angular-ui-router /release/angular-ui-router.min.js"></script>
<script type="text/javascript"
src="scripts/ng-game.js"></script>
<script type="text/javascript"
src="scripts/menu/index.js"></script>
</body>
</html>
|
And lastly, we’ll need to set the app.menu as a module-level dependency for our applicaiton:
When we load our browser, we’ll see the incredibly boring message of There is a menu here. Let’s make that a bit more functional.
Instead of setting the template key in our menu state, let’s load a template as well as add our first controller. In the scripts/menu/index.js, let’s change the menu state definition to include the templateUrl and the controller
3
4
5
6
7
8
9
10
|
angular.module('app.menu', [])
.config(function($stateProvider) {
// Our first state called `menu`
$stateProvider
.state('menu', {
url: '',
templateUrl: '/scripts/menu/main.html',
controller: 'MenuController as ctrl'
});
});
|
If we load this in the browser, we’ll see two potential errors. The first is a loading issue. In order to run this game, we have to serve it using a server, rather than loading it from the file.
You can use any server you’d lke to use. For the purposes of our work in this tutorial, we’ll use the node-static server. To install node-static, ensure that you have nodejs installed and use the npm command to install it:
1
|
$ npm install -g node-static
|
With node-static installed, we can simply type static in the directory that contains our index.html to boot a simple static server. We don’t need anything else yet.
1
|
$ static
|
With the server running, we can visit the address http://localhost:8080 to load our page again.
The second error we see is that a controller cannot be found called MenuController. Of course the browser can’t find the controller, we haven’t written it yet! Let’s go ahead and start building our MenuController.
In a new file in the scripts/menu/menu_controller.js file, let’s create the controller on our app.menu module. We’ll use the getter form of the module() function to reference the app.menu module:
2
3
4
5
|
angular.module('app.menu')
.controller('MenuController', function() {
var ctrl = this;
// Define our controller here
});
|
Great! Now we need to reference this new file in the browser in our index.html to load the file in the browser. In our index.html, let’s modify it to:
1
2
3
4
|
<!-- ... -->
<script type="text/javascript"
src="scripts/ng-game.js"></script>
<script type="text/javascript"
src="scripts/menu/index.js"></script>
<script type="text/javascript"
src="scripts/menu/menu_controller.js"></script> |
Now, although we don’t yet have any content to show, our page loads now and we can build our menu.
Before we build the interface, let’s look at what the interface will show. First, it will show a list of possible games currently being played on the site. Secondly, it will allow a user to create a game.
Since we don’t yet have any games to show, we’ll build the interface, but focus on showing these games after we’ve built our application. For the time being, we’ll create the interface as follows:
1
2
3
4
5
6
7
8
9
10
11
|
<div>
<div class="panel play"
ng-repeat="room in ctrl.rooms track by room.id"
ui-sref='game.play({id: room.id})'>
<span ng-bind="room.players.length"></span> Players
</div>
<div class="panel create"
ui-sref='game.play({id: ctrl.createId()})'>
<a>Create a game</a>
</div>
</div>
|
The view is incredibly simple. We’re going to loop through all rooms available on the controller (we haven’t placed any yet, but we will in the future) and display them in a panel. We’ve also created a Create a game button that will take us to a state we haven’t yet created called game.play.
Since we’ve referenced a new state, let’s go ahead and build our game module. We’ll need to repeat the same steps we took to build the app.menu module. Let’s:
Create a new directory in scripts/ called game/ and place an index.js file in it.
Load the scripts/game/index.js in our index.html
Set the new module as a dependency of our main application.
First, let’s create our new module in the scripts/game/index.js file:
1
|
angular.module('app.game', [])
|
Next, let’s load the new file in our index.html file so it loads in the browser:
1
2
3
4
5
|
<!-- ... -->
<script type="text/javascript"
src="scripts/ng-game.js"></script>
<script type="text/javascript"
src="scripts/menu/index.js"></script>
<script type="text/javascript"
src="scripts/menu/menu_controller.js"></script>
<script type="text/javascript"
src="scripts/game/index.js"></script> |
Finally, let’s ensure that the new module is a dependency of the main application:
2
3
4
5
6
|
// In /scripts/ng-game.js
angular.module('app', [
'ui.router',
'app.menu',
'app.game'
]);
|
As you may have guessed, we’ll build our our states for our game. We’ll use one state to play the game. For other phases of the game, we can use different states, but we’ll stick with only one for the time being.
Just as we did previously for the menu state, let’s use the config() function to define our game states:
1
2
3
4
|
angular.module('app.game', [])
.config(function($stateProvider) {
// Define routes in here
});
|
We’ll write our ggame.play state as a child state of the game state. There are a few good reasons for setting it up in this way, including nesting routes. Let’s first create our parent state and template:
angular.module('app.game', [])
.config(function($stateProvider) {
$stateProvider
.state('game', {
url: '/game',
abstract: true,
template: '<div class='game'>\
<div ui-view></div>\
</div>'
});
});
Notice that we’re using a template key rather than a templateUrl. Since the template is so small, it’s usually a good idea to keep small templates in the route. Plus, this is a small optimization (that’s almost insignificant).
Anyway, building our game.play state is a nested state underneath our new game state. When playing a game, we’ll want the game itself to have a route for a few crucial reasons:
- We need to separate different, available games
- We’ll want to be able to invite players to play the game
This is all to say that the
url must include a game id. Our basic route will look like the following:
angular.module('app.game', [])
.config(function($stateProvider) {
$stateProvider
.state('game', {
url: '/game',
abstract: true,
template: '<div class='game'>\
<div ui-view></div>\
</div>'
})
.state('game.play', {
url: '/:id',
template: '<div>\
<div id="gameCanvas"></div>\
</div>',
controller: 'GameController'
})
});
The basic route definition sets a template, a url, and a controller. Let’s go ahead and create our GameController that will handle building our game. Let’s create a file in /scripts/game/game_controller.js. In this file, we’ll create the controller on the app.game module using the controller() method:
2
3
4
5
|
// in /scripts/game/game_controller.js
angular.module('app.game')
.controller('GameController', function() {
// Set up our GameController here
});
|
Of course, we’ll need to set up some functionality in our GameController eventually. We need to ensure that we actually load this file in our index.html so it loads in the browser. Let’s update our index.html to include the <script> tag to load the game_controller.js:
1
2
3
4
5
6
|
<!-- ... -->
<script type="text/javascript"
src="scripts/ng-game.js"></script>
<script type="text/javascript"
src="scripts/menu/index.js"></script>
<script type="text/javascript"
src="scripts/menu/menu_controller.js"></script>
<script type="text/javascript"
src="scripts/game/index.js"></script>
<script type="text/javascript"
src="scripts/game/game_controller.js"></script> |
Loading our application in the browser, we’ll see a single button to load create the game (and it’s a fairly ugly one). Clicking on this button will take us to a blank screen. Since we have nothing in the game state, this makes sense.
Source: ng-newsletter (countinue)
If you feel useful for you and for everyone, please share it!
Suggest for you:
Learn Angular 2 Development By Building 10 Apps
Angular 2 and NodeJS - The Practical Guide to MEAN Stack 2.0
Angular 2 - The Complete Guide (Updated to RC4!)
Angular 2 with TypeScript for Beginners: The Pragmatic Guide
Angular 2 Fundamentals: Learn By Creating A Real Web App


No comments:
Post a Comment