Reputation: 8111
I have a game that I created using three.js, which is entirely rendered in a canvas element.
As an exercise to help me to get familiar with Angular JS, I have started to add a UI layer on top of my canvas which is to be managed by the Angular framework.
Rough example of my markup looks like so:
<div class="container" ng-app="hud-layer">
<div class="level" ng-controller="HUDCtrl">
<h1>Level: {{level}}</h1>
<button ng-click="decreaseLevel()">-</button>
<button ng-click="increaseLevel()">+</button>
</div>
<div id="game"></div>
</div>
I obviously intend to add more UI elements to my HUD but I need to know how to call functions in my game.js from Angular.
My game.js is encapsulated in its own namespace eg:
(function(){
var VECTORS = {
init: function(){
},
reset: function(){
}
// ... blah blah blah
}
});
I want Angular to watch over the level, score variables etc. but I want these variables reflected in my game.js, should I just mirror the $scope in the game.js somehow?
Any help or direction appreciated.
Upvotes: 4
Views: 899
Reputation: 108491
You're going to have to do something like return an interface from your game module pattern into the global namespace (window), and then inject $window into your Angular controller or service (depending on how advanced you wanted to get).
So something like (psuedo-code):
var game = (function(){
var VECTORS = {
init: function(){
},
reset: function(){
},
// ... blah blah blah
}
//return an interface to your game.
return {
doSomething: function () {
//do anything you want here.
VECTORS.foo++;
VECTORS.bar += VECTORS.foo;
return VECTORS.bar;
}
}
})();
and then in your controller (or in this case service):
app.factory('gameService', ['$window', function($window) {
return {
doSomething: function (){
return $window.game.doSomething();
}
};
}]);
app.controller('FooCtrl', ['$scope', 'gameService', function($scope, gameService) {
$scope.clickyThing = function () {
gameService.doSomething();
};
}]);
Obviously, then in your game's doSomething() function you can do whatever it is you need to do with items in that closure without fully exposing them to your Angular app.
It will keep things modular.
I hope that helps.
Upvotes: 4
Reputation: 35829
Its no problem your game.js is in a closure. AngularJs has a great feature: dependency injection. So let's use it.
You can define a module and a service within your game.js
, which will be registered in angular.js. The service is responsible for returning the game data to the controller outside your closure.
So you create a module:
var app = angular.module('game-bridge', []);
And an interfacing service (e.g. GameBridge) in your game.js:
app.factory('GameBridge', ['$log', function($log) {
return {
...
};
}]);
Your hud-layer module loads the game-bridge module and its controller injects the GameBridge service:
var app = angular.module('hud-layer', ['game-bridge']);
app.controller('HUDCtrl', ['$log', 'GameBridge', function($log, GameBridge) {
...
}]);
Upvotes: 1