Well I only wanted to implement saving and got carried away.

I cleaned the code up a bit. Everything auto-saves now (every 10s)
except for achievements. Maybe we should look at them together.
This commit is contained in:
Kevin Dungs
2014-08-04 02:16:05 +02:00
committed by Tadej Novak
parent 014c84239a
commit fa12f3c14e
7 changed files with 347 additions and 230 deletions
+8 -4
View File
@@ -47,7 +47,7 @@
<h4 class="media-heading">{{ r.level > 0 ? r.name : '?????' }} <span ng-show="r.level > 0" class="badge">Level {{ r.level }}</span></h4>
<p ng-show="r.level > 0">{{ r.description }} Researching it will give you {{ r.reputation }} reputation.</p>
<div class="btn-group">
<button class="btn btn-primary" ng-disabled="!r.is_available()" ng-click="r.research()">Research <small>({{ r.cost | niceNumber }} data)</small></button>
<button class="btn btn-primary" ng-disabled="!r.is_available()" ng-click="rc.doResearch(r)">Research <small>({{ r.cost | niceNumber }} data)</small></button>
<button class="btn btn-info" ng-show="r.level > 0" ng-click="r.showInfo()"><span class="glyphicon glyphicon-exclamation-sign"></span></button>
</div>
</div>
@@ -56,7 +56,8 @@
</div>
<div class="col-xs-5 scrollable" ng-controller="LabController as lc">
<h3 id="mylab" contenteditable>{{ lc.lab.name }} <small>Click here to change the name</small></h3> <button class="pull-right btn btn-info achievements-button" data-toggle="modal" data-target="#achievements-modal"><span class="glyphicon glyphicon-thumbs-up"></span></button>
<h3 id="mylab" contenteditable>{{ lc.lab.name }} <small>Click here to change the name</small></h3>
<button class="pull-right btn btn-info achievements-button" data-toggle="modal" data-target="#achievements-modal"><span class="glyphicon glyphicon-thumbs-up"></span></button>
<hr>
<button class="pull-right btn btn-info" ng-click="lc.showDetectorInfo()"><span class="glyphicon glyphicon-info-sign"></span></button>
<div id="detector" ng-controller="DetectorController as dc">
@@ -97,7 +98,7 @@
<div class="media-body">
<h4 class="media-heading">{{ w.name }} <span ng-show="w.hired > 0" class="badge">{{ w.hired | niceNumber }}</span></h4>
<p ng-show="w.hired > 0">{{ w.description }} They produce {{ w.rate }} data per second.</p>
<button class="btn btn-primary" ng-disabled="!w.is_available()" ng-click="w.hire()">Hire <small>({{ w.cost | currency }})</small></button>
<button class="btn btn-primary" ng-disabled="!w.is_available()" ng-click="hrc.hire(w)">Hire <small>({{ w.cost | currency }})</small></button>
</div>
</li>
</ul>
@@ -111,7 +112,7 @@
<div class="media-body">
<h4 class="media-heading">{{ u.name }}</h4>
<p>{{ u.description }}</p>
<button class="btn btn-primary" ng-disabled="!u.is_available()" ng-click="u.buy()">Buy <small>({{ u.cost | currency }})</small></button>
<button class="btn btn-primary" ng-disabled="!u.is_available()" ng-click="uc.upgrade(u)">Buy <small>({{ u.cost | currency }})</small></button>
</div>
</li>
</ul>
@@ -191,6 +192,9 @@
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="js/external/retina.js"></script>
<script src="js/storage.js"></script>
<script src="js/helpers.js"></script>
<script src="js/gameobjects.js"></script>
<script src="js/event.js"></script>
<script src="js/detector.js"></script>
<script src="js/achievements.js"></script>
+1 -1
View File
@@ -74,7 +74,7 @@ var achievements =
achievements[type][subtype] >= achievements.list[i].threshold
)
{
console.log(achievements.list[i].threshold, achievements[type][subtype]);
//console.log(achievements.list[i].threshold, achievements[type][subtype]);
achievements.list[i].completed = true;
achievements.displayAchievement(i);
+47 -191
View File
@@ -1,203 +1,25 @@
'use strict';
(function() {
var loadFile = function(filename) {
var res;
$.ajax({
async: false,
url : filename,
success : function(data) {
res = data;
}
});
return res;
}
var lab = GameObjects.lab;
var research = GameObjects.research;
var workers = GameObjects.workers;
var upgrades = GameObjects.upgrades;
var showModal = function(title, text) {
var $modal = $('#infoBox');
$modal.find('#infoBoxLabel').html(title);
$modal.find('.modal-body').html(text);
$modal.modal({show: true});
};
var lab = {
name: 'My Awesome Lab',
detector: {
rate: 1
},
factor: {
rate: 5
},
data: 0,
reputation: 0,
money: 0,
getGrant: function () {
var addition = this.reputation * this.factor.rate; // TODO: adjust factor
this.money += addition;
showUpdateValue("#update-funding", formatNiceNumber(addition));
achievements.update('count', 'money', addition);
},
acquire: function(amount) {
this.data += amount;
achievements.update('count', 'data', amount);
showUpdateValue("#update-data", formatNiceNumber(amount));
},
research: function(cost, reputation) {
if (this.data >= cost) {
this.data -= cost;
this.reputation += reputation;
achievements.update('count', 'reputation', reputation);
showUpdateValue("#update-data", formatNiceNumber(-cost));
showUpdateValue("#update-reputation", formatNiceNumber(reputation));
return true;
}
return false;
},
buy: function(cost) {
if (this.money >= cost) {
this.money -= cost;
showUpdateValue("#update-funding", formatNiceNumber(-cost));
return true;
}
return false;
},
sell: function(cost) {
this.money += cost;
}
};
var research = loadFile('json/research.json');
achievements.addResearch(research);
research.map(function(item) {
item.level = 0;
item.is_visible = function() {
return this.level > 0 || lab.data >= this.cost * .7;
};
item.is_available = function() {
return lab.data >= this.cost;
};
item.research = function() {
if (lab.research(this.cost, this.reputation)) {
achievements.update('count', 'dataSpent', this.cost);
this.level++;
this.cost = Math.round(this.cost * this.cost_increase);
achievements.update('research', this.name, 1);
}
};
item.getInfo = function() {
if (!this._info) {
this._info = loadFile(this.info);
}
return this._info;
},
item.showInfo = function() {
showModal(this.name, this.getInfo());
};
});
var workers = loadFile('json/workers.json');
achievements.addWorkers(workers);
workers.map(function(worker) {
worker.hired = 0;
worker.is_visible = function() {
return this.hired > 0 || lab.money >= this.cost * .7;
};
worker.is_available = function() {
return lab.money >= this.cost;
};
worker.hire = function() {
if (lab.buy(this.cost)) {
achievements.update('count', 'moneyWorkers', this.cost);
this.hired++;
this.cost = Math.round(this.cost * this.cost_increase);
achievements.update('workers', this.name, 1);
achievements.update('count', 'workers', 1);
}
};
});
var upgrades = loadFile('json/upgrades.json');
upgrades.map(function(upgrade) {
upgrade.getReceiver = function() {
if (this.type === "detector") {
return lab.detector;
} else if (this.type === "reputation"){
return lab.factor;
}
else {
var context;
if (this.type === "research") { context = research; }
else if (this.type === "hr") { context = workers; }
else { return null; }
for (var i = 0; i < context.length; i++) {
if (context[i].name === this.receiver) {
return context[i];
}
}
return null;
}
};
upgrade.hasReceiver = function() {
if (this.type === "detector") {
return true;
}
if (this.type === "reputation") {
return true;
}
var rec = this.getReceiver();
if (this.type === "research") {
return rec.level > 0;
} else if (this.type === "hr") {
return rec.hired > 0;
}
return false;
};
upgrade.is_visible = function() {
return !this.used && this.hasReceiver() && lab.money >= this.cost * .7;
};
upgrade.is_available = function() {
return !this.used && this.hasReceiver() && lab.money >= this.cost;
};
upgrade.buy = function() {
if (!this.used && lab.buy(this.cost)) {
achievements.update('count', 'moneyUpgrades', this.cost);
this.used = true;
var rec = this.getReceiver();
if (rec) {
rec[this.property] = rec[this.property] * this.factor + this.constant;
}
}
};
});
var app = angular.module('particleClicker', []);
app.filter('niceNumber', ['$filter', function($filter) {
return Helpers.formatNumberPostfix;
}]);
app.filter('currency', ['$filter', function($filter) {
return function(input) {
return 'JTN ' + $filter('niceNumber')(input);
};
}]);
function formatNiceNumber(number) {
var abs = Math.abs(number);
if (abs >= Math.pow(10, 12)) {
number = (number / Math.pow(10, 12)).toFixed(1) + "T";
} else if (abs >= Math.pow(10, 9)) {
number = (number / Math.pow(10, 9)).toFixed(1) + "B";
} else if (abs >= Math.pow(10, 6)) {
number = (number / Math.pow(10, 6)).toFixed(1) + "M";
} else if (abs >= Math.pow(10, 3)) {
number = (number / Math.pow(10, 3)).toFixed(1) + "k";
} else {
number = number.toFixed(0);
}
return number;
}
app.filter('niceNumber', ['$filter', function($filter) {
return formatNiceNumber;
}]);
app.filter('reverse', ['$filter', function($filter) {
return function(items) {
return items.slice().reverse();
@@ -209,6 +31,8 @@
lab.acquire(lab.detector.rate);
detector.addEvent();
achievements.update('count', 'clicks', 1);
achievements.update('count', 'data', lab.detector.rate);
UI.showUpdateValue("#update-data", lab.detector.rate);
return false;
};
});
@@ -217,12 +41,14 @@
this.lab = lab;
this.showDetectorInfo = function() {
if (!this._detectorInfo) {
this._detectorInfo = loadFile('html/detector.html');
this._detectorInfo = Helpers.loadFile('html/detector.html');
}
showModal('Detector', this._detectorInfo);
UI.showModal('Detector', this._detectorInfo);
};
$interval(function() { // one tick
lab.getGrant();
var grant = lab.getGrant();
achievements.update('count', 'money', grant);
UI.showUpdateValue("#update-funding", grant);
var sum = 0;
for (var i = 0; i < workers.length; i++) {
sum += workers[i].hired * workers[i].rate;
@@ -234,14 +60,38 @@
app.controller('ResearchController', function() {
this.research = research;
this.doResearch = function(item) {
var cost = item.research();
if (cost > 0) {
achievements.update('count', 'reputation', item.reputation);
achievements.update('count', 'dataSpent', cost);
achievements.update('research', item.name, 1);
UI.showUpdateValue("#update-data", -cost);
UI.showUpdateValue("#update-reputation", item.reputation);
}
};
});
app.controller('HRController', function() {
this.workers = workers;
this.hire = function(worker) {
var cost = worker.hire();
if (cost > 0) {
achievements.update('count', 'moneyWorkers', cost);
achievements.update('workers', worker.name, 1);
achievements.update('count', 'workers', 1);
UI.showUpdateValue("#update-funding", cost);
}
};
});
app.controller('UpgradesController', function() {
this.upgrades = upgrades;
this.upgrade = function(upgrade) {
if (upgrade.buy()) {
achievements.update('count', 'moneyUpgrades', upgrade.cost);
}
}
});
app.controller('AchievementsController', function() {
@@ -249,5 +99,11 @@
this.achievementsAll = achievements.list;
});
achievements.setList(loadFile('json/achievements.json'));
achievements.setList(Helpers.loadFile('json/achievements.json'));
// Activate auto-saving every 10 seconds
setInterval(function () {
GameObjects.saveAll();
console.log('The game has been saved.');
}, 10000);
})();
+187
View File
@@ -0,0 +1,187 @@
'use strict';
/** Define all objects used in the game.
* They can be either loaded from localStorage or from JSON in case nothing is
* found in the localStorage.
*/
var GameObjects = (function() {
/** Lab
*/
var labPrototype = {
name: 'My Awesome Lab',
detector: {
rate: 1
},
factor: {
rate: 5
},
data: 0,
reputation: 0,
money: 0,
getGrant: function () {
var addition = this.reputation * this.factor.rate;
this.money += addition;
return addition;
},
acquire: function(amount) {
this.data += amount;
},
research: function(cost, reputation) {
if (this.data >= cost) {
this.data -= cost;
this.reputation += reputation;
return true;
}
return false;
},
buy: function(cost) {
if (this.money >= cost) {
this.money -= cost;
return true;
}
return false;
},
sell: function(cost) {
this.money += cost;
}
};
var lab = $.extend({}, labPrototype, ObjectStorage.load('lab'));
/** Research
*/
var researchPrototype = {
level: 0,
is_visible: function() {
return this.level > 0 || lab.data >= this.cost * .7;
},
is_available: function() {
return lab.data >= this.cost;
},
research: function() {
if (lab.research(this.cost, this.reputation)) {
this.level++;
var oldCost = this.cost;
this.cost = Math.round(this.cost * this.cost_increase);
return oldCost;
}
return -1;
},
getInfo: function() {
if (!this._info) {
this._info = Helpers.loadFile(this.info);
}
return this._info;
},
showInfo: function() {
Helpers.showModal(this.name, this.getInfo());
}
};
var research = $.extend([], Helpers.loadFile('json/research.json'),
ObjectStorage.load('research'));
research = research.map(function(item) {
return $.extend({}, researchPrototype, item);
});
/** Workers
*/
var workersPrototype = {
hired: 0,
is_visible: function() {
return this.hired > 0 || lab.money >= this.cost * .7;
},
is_available: function() {
return lab.money >= this.cost;
},
hire: function() {
if (lab.buy(this.cost)) {
this.hired++;
var cost = this.cost;
this.cost = Math.round(this.cost * this.cost_increase);
return cost;
}
return -1;
}
};
var workers = $.extend([], Helpers.loadFile('json/workers.json'),
ObjectStorage.load('workers'));
workers = workers.map(function(worker) {
return $.extend({}, workersPrototype, worker);
});
/** Upgrades
*/
var upgradesPrototype = {
getReceiver: function() {
if (this.type === "detector") {
return lab.detector;
} else if (this.type === "reputation"){
return lab.factor;
} else {
var context;
if (this.type === "research") { context = research; }
else if (this.type === "hr") { context = workers; }
else { return null; }
for (var i = 0; i < context.length; i++) {
if (context[i].name === this.receiver) {
return context[i];
}
}
return null;
}
},
hasReceiver: function() {
if (this.type === "detector" || this.type === "reputation") {
return true;
}
var rec = this.getReceiver();
if (this.type === "research") {
return rec.level > 0;
} else if (this.type === "hr") {
return rec.hired > 0;
}
return false;
},
is_visible: function() {
return !this.used && this.hasReceiver() && lab.money >= this.cost * .7;
},
is_available: function() {
return !this.used && this.hasReceiver() && lab.money >= this.cost;
},
buy: function() {
if (!this.used && lab.buy(this.cost)) {
this.used = true;
var rec = this.getReceiver();
if (rec) {
rec[this.property] = rec[this.property] * this.factor + this.constant;
}
return true;
}
return false;
}
};
var upgrades = $.extend([], Helpers.loadFile('json/upgrades.json'),
ObjectStorage.load('upgrades'));
upgrades = upgrades.map(function(upgrade) {
return $.extend({}, upgradesPrototype, upgrade);
});
/** Save all the game objects at once.
*/
var saveAll = function() {
ObjectStorage.save('lab', lab);
ObjectStorage.save('research', research);
ObjectStorage.save('workers', workers);
ObjectStorage.save('upgrades', upgrades);
};
return {
lab: lab,
research: research,
workers: workers,
upgrades: upgrades,
saveAll: saveAll
}
})();
+42
View File
@@ -0,0 +1,42 @@
'use strict';
/** Define some useful helpers that are used throughout the game.
*/
var Helpers = (function() {
/** Load a file (usually JSON).
*/
var loadFile = function(filename) {
var res;
$.ajax({
async: false,
url : filename,
success : function(data) {
res = data;
}
});
return res;
};
/** Format a number with proper postfix.
*/
var formatNumberPostfix = function(number) {
var abs = Math.abs(number);
if (abs >= Math.pow(10, 12)) {
number = (number / Math.pow(10, 12)).toFixed(1) + "T";
} else if (abs >= Math.pow(10, 9)) {
number = (number / Math.pow(10, 9)).toFixed(1) + "B";
} else if (abs >= Math.pow(10, 6)) {
number = (number / Math.pow(10, 6)).toFixed(1) + "M";
} else if (abs >= Math.pow(10, 3)) {
number = (number / Math.pow(10, 3)).toFixed(1) + "k";
} else {
number = number.toFixed(0);
}
return number;
}
return {
loadFile: loadFile,
formatNumberPostfix: formatNumberPostfix
};
})();
+6 -2
View File
@@ -12,6 +12,9 @@ var ObjectStorage = (function() {
},
load: function(key) {
return JSON.parse(_s.getItem(key));
},
clear: function() {
_s.clear();
}
};
} catch (e) {
@@ -19,7 +22,8 @@ var ObjectStorage = (function() {
+ ' If you refresh the page, all progress will be lost');
return {
save: function(key, item) {},
load: function(key) { return null; }
load: function(key) { return null; },
clear: function() {}
};
};
});
})();
+56 -32
View File
@@ -1,13 +1,64 @@
$(function() {
var h = $(window).height();
$('.scrollable').height(h - 50 + 'px');
'use strict';
$(window).resize(function() {
/** Define UI specific stuff.
*/
var UI = (function () {
/** Resize the scrollable containers and make sure they are resized whenever
* the window is resized. */
$(function() {
var h = $(window).height();
$('.scrollable').height(h - 50 + 'px');
$(window).resize(function() {
var h = $(window).height();
$('.scrollable').height(h - 50 + 'px');
});
});
});
/** Show a bootstrap modal with dynamic content. */
var showModal = function(title, text) {
var $modal = $('#infoBox');
$modal.find('#infoBoxLabel').html(title);
$modal.find('.modal-body').html(text);
$modal.modal({show: true});
};
var showUpdateValue = function(ident, num) {
var formatted = Helpers.formatNumberPostfix(num);
if (num != 0) {
var insert;
if (num > 0) {
insert = $("<div></div>")
.attr("class", "update-plus")
.html("+" + num);
} else {
insert = $("<div></div>")
.attr("class", "update-minus")
.html(num);
}
showUpdate(ident, insert);
}
}
var showUpdate = function(ident, insert) {
var elem = $(ident);
elem.append(insert);
insert.animate({
"bottom":"+=30px",
"opacity": 0
}, { duration: 500, complete: function() {
$(this).remove();
}});
}
return {
showModal: showModal,
showUpdateValue: showUpdateValue
}
})();
// I don't know what this is for, so I leave it here for the moment...
(function() {
var hidden = "hidden";
@@ -41,30 +92,3 @@ $(function() {
detector.visible = !this[hidden];
}
})();
function showUpdateValue(ident, num) {
if (num != 0) {
if (num > 0) {
insert = $("<div></div>")
.attr("class", "update-plus")
.html("+" + num);
} else {
insert = $("<div></div>")
.attr("class", "update-minus")
.html(num);
}
showUpdate(ident, insert);
}
}
function showUpdate(ident, insert) {
elem = $(ident);
elem.append(insert);
insert.animate({
"bottom":"+=30px",
"opacity": 0
}, { duration: 500, complete: function() {
$(this).remove();
}});
}