开发者

Backbone.js - Loading views programmatically

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 display create 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜