so I'm not entirely sure I'm taking the correct approach with Backbone.js and what I'm trying to do but let me try to explain nonetheless.
I'm creating a mobile "game". The game is pretty simple, you connect to Facebook and "log in", select a level [Easy|Medium|Hard] and start the game.
The game consists of 6 Quests to find a particular area using geolocation (You should be within 15 metres to of the location to finish the quest).
You also get a few lifelines in order to help you find the location, in the style of "Who wants to be a Millionaire".
I digress. I'm using Backbone.js but its my first stab at Javascript MVC and I'm a little unsure of how I'm supposed to be using it.
When a player tells the app that they think the are at the location, I would like to be able to, after checking the location, move the player to the next Quest (provided they are not on the 6th and last quest) and simply开发者_如何学编程 update their score.
Each Quest shares the same View and I would like to populate the Quest Models via Ajax eventually.
My biggest problem is figuring out how to get from Quest 1 to Quest 2 gracefully.
I'm using jQuery & jQueryMobile with underscore and Backbone.
Here is my code so far:
$(document).bind("mobileinit", function() {
$.mobile.hashListeningEnabled = false;
$.mobile.ajaxEnabled = false;
var PROGRESS = 1;
var Quest = Backbone.Model.extend({
defaults: {
id: 0,
message: '',
points: 0,
latitude: '0',
longitude: '0',
clues: {}
},
initialize: function(){
},
addPoints: function(points) {
this.set({points: this.get('points') + points});
},
takePoints: function(points) {
this.set({points: this.get('points') - points});
}
});
var QuestsCollection = Backbone.Collection.extend({
model: Quest,
comparator: function(quest) {
return quest.get('id');
},
getFinalScore: function() {
var points = this.pluck('points');
var total = 0;
$.each(points, function(k, v) {
total += v;
});
return total;
}
});
var QuestView = Backbone.View.extend({
el: '#play',
tagName: 'div',
className: 'quest',
template: _.template($('#play-tpl').html()),
model: Quest,
quest: {},
questNumber: 1,
location: {latitude: 0, longitude: 0},
events: {
'click .amIWarm' : 'checkGeoWarmth',
'click .imThere' : 'complete',
'click .skipQuest' : 'skip'
},
initialize: function() {
this.questNumber = this.options.questNumber;
this.quest = this.options.quest;
},
checkGeoWarmth: function(event) {
console.log(event);
console.log('checkGeoWarmth');
},
complete: function(event) {
console.log('Check that the user is located within 30 metres of the target!');
console.log('If the user is actually at the location, move them on to the next quest and save their points.');
this.questNumber += 1;
PROGRESS += 1;
console.log(PROGRESS);
if (PROGRESS >= 6) {
console.log('Game Over!');
}
},
skip: function(event) {
console.log('Set points to 0');
console.log('Move on to the next quest.');
this.questNumber += 1;
if (this.questNumber >= 6) {
console.log('Game Over!');
}
},
render: function() {
$('.page').hide();
$(this.el).show();
console.log(this.quest);
$(this.el).html(this.template({quest: this.quest}));
}
});
var Game = Backbone.Router.extend({
routes: {
"": "welcome",
"/play/:quest": "play"
},
welcome: function() {
var SplashPage = new SplashView;
SplashPage.render();
},
selectLevel: function() {
console.log('Select Level');
},
play: function(quest) {
var thisQuest = Quests.get(quest);
var QuestPage = new QuestView({quest: thisQuest});
//console.log(QuestPage);
QuestPage.render();
},
gameOver: function() {
var score = Quests.getFinalScore();
// Score
console.log('Your Score is ' + score);
// Save Score
console.log('Send Ajax Request to [/score/save] with [{player_id: 1, facebook_id: 1234567890, score: 440}]')
// Share On Facebook
console.log('Share your score on Facebook?');
// Tweet?
console.log('Share your score on Twitter?');
},
leaderboard: function() {
// Model: Score
// Collection: Scores
// View: Score
}
});
var game = new Game;
Backbone.history.start();
});
My HTML is as follows:
<!DOCTYPE html>
<html>
<head>
<title>GeoQuest</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1; user-scalable=1;" />
<link type="text/css" rel="stylesheet" href="css/jquery.mobile.css" />
<link rel="stylesheet" type="text/css" href="css/geoquest.css" />
</head>
<body>
<div id="splash" class="page" data-role="page">
<script type="text/html" id="splash-tpl">
<a href="#/play/1">Play</a>
<button class="connect">Connect</button>
<button class="disconnect">Disconnect</button>
</script>
</div>
<div id="select-level" class="page" data-role="page">
</div>
<div id="play" class="page" data-role="page">
<script type="text/html" id="play-tpl">
<h1>Quest <%= quest.id %></h1>
<div class="quest-message">
<%= quest.message %>
</div>
<button class="skipQuest" data-role="button">Skip Quest</button>
<button href="/play/2" class="imThere" data-role="button">I'm There</button>
<button class="amIWarm" data-role="button">Am I Warm</button>
</script>
</div>
<div id="fb-root"></div>
<script type="text/javascript">
window.fbAsyncInit = function() {
FB.init({appId: '140750459345068', status: true, cookie: true, xfbml: true});
window.FB = FB;
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
</script>
<script type="text/javascript" src="js/jquery.js"> </script>
<script type="text/javascript" src="js/underscore.js"> </script>
<script type="text/javascript" src="js/backbone.js"> </script>
<script type="text/javascript" src="js/json2.js"> </script>
<script type="text/javascript" src="js/geoquest.js"> </script>
<script type="text/javascript" src="js/jquery.mobile.js"> </script>
</body>
</html>
Any help or advice is well appreciated.
Thanks!
I've been playing around with backbone also, and loving it so far.
Just a couple of points:
Should you replace 6 with QuestsCollection.length? That way you can add quests dynamically and have it adjust appropriately
On your QuestView, when you complete the quest,
have it call this.render() if it is not game over, and the next quest should displaycreate a new QuestView({next quest model}) and call the .render() function or redirect to /play/quest#?To add quests, it should be as straight forward as adding a new Quest into the collection: QuestsCollection.add({})
Here's my sample program/game, if you want to check it out. It is heavily based on the todo program on the official backbone.js site: http://rickcoder.com/bbtest/ (uses some html 5 local storage capabilities, so it only works on newer browsers)
The backbone related code is here http://rickcoder.com/bbtest/bbtest.js
I'mm looking into this as well at the moment so don't have a definitive answer.
However, have a look at this thread:
http://pinoytech.org/question/7172294/backbone-js-and-jquerymobile-routing-without-hack-or-other-router
You effectively want to call JQM's changePage yourself. There is also an article out next week you'll find useful:
http://msdn.microsoft.com/en-us/scriptjunkie/hh377172.aspx
精彩评论