Javascript supports "pointers" in form of object references. All variables which contain objects actually contain pointers to objects. Further, you can access fields of objects using the object[fieldname] syntax. Assuming you have an object clickManager and want to monitor its variable numClicks, this would look like this:
achievements.push(new Achievement("Clicktastic", clickManager, "numClicks", 1000, "You clicked 1000 times!");
The code to check the variable monitored by an achievement would then look like this:
var a = achievents[i];
if (a.monitoredObject[a.monitoredVariableName] > a.value) {
If you want to access a global variable, you can access it over the global object "window".
But as you said, this isn't really a very beautiful solution. First, it's a bit cumbersome. Second, it's not very flexible, because all it can do is monitor numerical variables. What if you have an achievement with a more complex condition? And third, it ignores one of JavaScript's most powerful features: Closures!
Javascript allows you to define inline-functions which can access variables in the current scope. These inline-functions can be passed around as variables and called from somewhere else (just like function-pointers in C). To make use of this, your achievement class would look like this:
function Achievement(name, text, checkFunction){
this.name = name;
this.checkFunctiontext = checkFunction;text;
this.textcheckFunction = text;checkFunction;
}
An example of creating an achievement:
function initClickHandling() {
var numClicks = 0;
achievements.push(new Achievement(
"Clicktastic",
"You clicked 1000 times!",
function() {
return numClicks > 1000;
})
);
window.onclick = function() {
numClicks++;
}
}
This unnamed function "captures" the local variable numClicks. When that function is executed, it will use the then-current value of numClicks. This even works when the function-call which declared that variable has already returned.
Also notice the second function, the click handler for window. It captures the same variable and manipulates it. When it does that, the check function will notice.
Your achievement management code would then look like this (using Array.prototype.forEach instead of a for-loop. Another example of using ad-hoc unnamed functions):
achievements.forEach(function(achievement) {
if (achievement.checkFunction()) {
// award the achievement
}
});