forked from martindrapeau/backbone-game-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
1860 lines (1759 loc) · 116 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<title>Backbone Game Engine</title>
<meta name="description" content="Elementary HTML5 Canvas Game Engine based on Backbone. Specialized for 2D platformers, and optimized for mobile.">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="apple_touch_icon.png" rel="apple-touch-icon" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="docs/jquery.min.js" type="text/javascript"></script>
<script src="docs/bootstrap.min.js" type="text/javascript"></script>
<link href="docs/bootstrap.min.css" rel="stylesheet" type="text/css" charset="utf-8">
<link href="docs/docs.css" rel="stylesheet" type="text/css" charset="utf-8">
</head>
<body data-spy="scroll" data-target="#sidebar" data-offset="100">
<header class="navbar navbar-inverse" role="banner">
<div class="navbar-header">
<button type="button" class="navbar-toggle pull-left" data-toggle="collapse" data-target="#navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html" title="Elementary HTML5 Canvas Game Engine based on Backbone."><img src="apple_touch_icon.png" /> Backbone Game Engine</a>
</div>
<div id="navbar-collapse" class="collapse navbar-collapse" role="navigation">
<ul class="nav navbar-nav">
<li><a href="index.html">Documentation</a></li>
<li><a href="examples.html">Examples</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="github-icon"><a href="https://github.com/martindrapeau/backbone-game-engine" title="Fork me on Github"><img src="docs/github.png" />Github</a></li>
</ul>
</div>
</header>
<div class="container">
<div class="row">
<div class="col-md-9">
<div id="introduction" class="row">
<div class="col-md-12">
<h1>HTML5 Canvas & Backbone</h1>
</div>
</div>
<div class="row">
<div class="col-md-6 col-xs-6">
<p>
An elementary HTML5 Canvas game engine built on Backbone. Specialized for 2D platformers, and optimized for mobile.
</p>
<h4>Examples</h4>
<ul>
<li>Real game: <a href="http://www.ludosquest.com" target="_blank">Ludo's Quest</a> - <a href="https://itunes.apple.com/ca/app/ludos-quest/id1047863228" target="_blank">launched on iOS</a> using <a href="https://www.cocoon.io" target="_blank">Cocoon.io</a></li>
<li>Test game: <a href="http://www.mariocraft.club" target="_blank">Mariocraft</a></li>
<li>Advanced: <a href="super-mario-bros/index.html" target="_blank">Super Mario Bros, level 1-1</a></li>
<li>Elementary: <a href="ball/index.html" target="_blank">Bouncing ball</a></li>
<li>Basic: <a href="mario/index.html" target="_blank">Mario in an empty world</a></li>
<li>Basic: <a href="gui/index.html" target="_blank">GUI</a></li>
<li>Basic: <a href="frog/index.html" target="_blank">Hoppy frog</a></li>
</ul>
<p>
These examples are on <a href="https://github.com/martindrapeau/backbone-game-engine">Github</a>.
</p>
</div>
<div class="col-md-3 col-xs-6">
<p>
<div class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
<a class="item active" href="super-mario-bros/index.html" target="_blank">
<img src="docs/super-mario-bros-level-1-1.png" alt="" class="img-responsive" alt="Super Mario Bros level 1-1" title="Super Mario Bros level 1-1" />
<span class="carousel-caption">Click to play</span>
</a>
</div>
</div>
</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h4>CocoonJS Example</h4>
<p>
Backbone Game Engine was written to run inside of CocoonJS Canvas+, so you can turn your HTML5 game into a native application on iOS or Android. If you have the CocoonJS launcher loaded on your iOS or Android device, you can load Super Mario Bros level 1-1 via this URL:
</p>
<pre>
http://martindrapeau.github.io/cocoon-mario/cocoon-mario.zip
</pre>
</div>
</div>
<div id="features" class="row">
<div class="col-md-12">
<h3>Features:</h3>
<ul>
<li><strong>Built on Backbone</strong>. Events, models, collections, inheritance and RESTful persistence. Why reinvent the wheel?</li>
<li><strong>HTML5 canvas only</strong>. No jQuery, as little DOM manipulations as possible.</li>
<li><strong>Mobile optimized</strong>. Build to run on mobile devices with transparent touch and viewport support. Everything is optimized for maxium frames per seconds (FPS).</li>
<li><strong>Go Native with CocoonJS.</strong>. Built to run in Ludei's <a href="http://support.ludei.com/hc/en-us/articles/200767118-Canvas-development-Guide" target="_blank">CocoonJS canvas+</a>. Deploy native on iOS and Android.</li>
<li><strong>2D platformer</strong>. Built with side-scrollers in mind. Built-in classes for sprites, sprite sheets, characters, hero, quad-tree collision detection, world and editor.</li>
<li><strong>No compilation</strong>. You don't need to install node, grunt or whatever else. Just code and press F5 to run.</li>
<li><strong>No server required</strong>. Fork this repo and your Github site is up and going. Create your own game and point your friends to it. Rebase to pull in latest engine updates.</li>
<li><strong>Built for mobile</strong>. Conceived to run on tablets. Share your URL with Mom so she can add it to the home screen of her iPad.</li>
<li><strong>Take if offline</strong>. With HTML5 Application Cache, your game runs offline. Perfect for taking it on the road or on a fishing trip.</li>
<li><strong>Save state</strong>. With HTML5 Local Storage, save where you are.</li>
<li><strong>World editor</strong>. Conceived for tile-based games, comes with a world editor. Place your tiles and characters, then hit play to try it out. Hit save to save your world.</li>
</ul>
</div>
</div>
<div id="dependencies" class="row">
<div class="col-md-12">
<h3>Dependencies</h3>
<ul>
<li><a href="http://underscorejs.org/" target="_blank">Underscore</a> </li>
<li><a href="http://backbonejs.org/" target="_blank">Backbone</a> </li>
<li><a href="https://github.com/inkling/backbone.native/" target="_blank">backbone.native</a>. To drop jQuery.</li>
<li><a href="https://github.com/asaarinen/qtree/" target="_blank">simple-quadtree</a></li>
</ul>
<p>
All included in the <code>3rd</code> folder. That and nothing else.
</p>
<h3>Why Backbone?</h3>
<p>
Backbone implements <a href="http://backbonejs.org/#Events" target="_blank">events</a>, <a href="http://backbonejs.org/#Model" target="_blank">models</a>, <a href="http://backbonejs.org/#Collection" target="_blank">collections</a>, <a href="http://backbonejs.org/#Model-extend" target="_blank">inheritance</a> and <a href="http://backbonejs.org/#Sync" target="_blank">persistence</a>. Models implement getters and setters for object attributes. Models and Collections have an <code>extend</code> function to easily do inheritance. They implement methods for persistence (RESTful JSON by default). They can also trigger events and bind to them. Everything you need to build a great extensible game engine. Plus, Backbone is now widely used and provides these features in a standard fashion with a huge community to support them. I hope this project can make game programming accessible to developers already familiar with Backbone.
</p>
<h3>Using and Contributing</h3>
<p>
Backbone Game Engine was built to get you going fast. <a href="https://github.com/martindrapeau/backbone-game-engine">Fork this repository</a>, and your own Github page will be ready in minutes. You can then create your own games by simply creating a new directory, and putting files in it.
</p>
<p>
The default branch is <code>gh-pages</code> so that any changes get published automatically to the Github page. Changes typically take only a few seconds to get published. This allows you to develop, test, document and deploy rapidly. It is a double-edge sword though. Any untested code you push to your fork on that branch will be felt by your users. It is therefore a good practice to create and work on another branch, and fast-forward merge to the <code>gh-pages</code> branch when done.
</p>
<p>
To report a bug, use <a href="https://github.com/martindrapeau/backbone-game-engine/issues" target="_blank">Github issues</a>. To contribute improvements, bug fixes or new examples, make changes to your fork and do a pull request. For anyone looking to help, here is a short to-do list:
</p>
<ul>
<li>Implement vertical panning in Backbone.Camera.</li>
<li>Revamp collision detection: optimize lookup and better functions.</li>
<li>Implement sound.</li>
<li>Add missing behaviors in Super Mario: character death, break brick, etc.</li>
</ul>
<br/>
</div>
</div>
<!-- Documentation -->
<div id="getting-started" class="row">
<div class="col-md-12">
<h1>Getting Started</h1>
</div>
</div>
<div id="documentation-Backbone" class="row">
<div class="col-md-12">
<h3>Backbone</h3>
<p>
The engine is based on Backbone so it is essential to understand its core structure: a <a href="http://backbonejs.org/#Model" target="_blank">Backbone.Model</a>. A model has hash of <code>attributes</code> that are changed via getter and setter methods <code>get</code> and <code>set</code>. These attributes should only contain state information as it is those attributes which get saved and restored. A model is a Javascript object. Hence behaviour can be stored as properties and methods directly on the object. For example a sprite sheet points to an image. Attribute <code>img</code> contains the <code>Image</code> object or DOM selector (by id) for retrieving the Image object. Property <code>img</code> contains reference to the Image object. It is automatically set when the sprite sheet model is initialized.
<pre>
var spriteSheet = new Backbone.SpriteSheet({
id: "mario",
img: "#mario",
tileWidth: 32,
tileHeight: 64,
tileColumns: 21,
tileRows: 6
});
spriteSheet.get("img"); // attribute
// #mario
spriteSheet.img; // property
// <img id="mario" src="../super-mario-bros/super-mario-2x.png" style="display:none;">
spriteSheet.img.width
//672
spriteSheet.img.height
//384
</pre>
</p>
<p>
In fact, a model stores its attributes in the object property <code>attributes</code>. Methods <code>get</code>, <code>set</code> and <code>toJSON</code> operate on that property. Just remember that state date like sprite coordinates, velocity, etc go in there. However references to other objects do not.
</p>
<div class="alert alert-info">
Note on nomenclature: The word <strong>attribute</strong> is used to define state data (get and set stored in obejct property attributes) while the word <strong>property</strong> is used to define behavioural data stored directly on the object.
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3 id="documentation-no-jQuery">Living without jQuery</h3>
<p>
Backbone Game Engine does not use jQuery. Instead, it depends on <a href="https://github.com/inkling/backbone.native/" target="_blank">backbone.native</a> which re-creates the ubiquitous <code>$</code> function/object with only essentials required by Backbone. As such, you are limited to simple DOM selectors enabled by <a href="https://developer.mozilla.org/en/docs/Web/API/Document.querySelectorAll" target="_blank">querySelectorAll</a> and events. Since the framework is for canvas-based games, avoid HTML manipulations. Canvas-based only allows for easier wrapping with CocoonJS. Consult the documentation of backbone.native to understand limitations.
</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3 id="documentation-Structure">Directory structure</h3>
<p>
To create a new example (or game), create an empty directory at the same level as <code>super-mario-bros</code>. Then, add some files. Here is the recommended file structure:
</p>
<pre>
3rd/
src/
...
super-mario-bros/
my-game/
index.html
main.js
</pre>
<p>
<code>index.html</code> is the HTML document which loads your assets, and defines your canvas. File <code>main.js</code> is where you instantiate the game engine and sprites. It must get loaded last.
</p>
<h3 id="documentation-HTML">index.html</h3>
<p>
The HTML document (usually named <code>index.html</code> in its own folder) declares the assets to be loaded and the <code>canvas</code> element. Javascript assets are declared in the <code>HEAD</code> element. Images are loaded via <code>IMG</code> elements. They must be hidden with inline CSS. Everything is bootstrap-loaded as declared in the HTML file. There is no asynchronous loading.
</p>
<p>
Here is an example HTML file taken from the example <a href="mario/index.html" target="_blank">Mario</a>.
</p>
<pre>
<!doctype html>
<html style="touch-action: none;">
<head>
<title>Mario - Backbone Game Engine</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../favicon.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../apple_touch_icon.png" rel="apple-touch-icon" />
<meta name="viewport" content="width=960, user-scalable=no"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<script src="../3rd/underscore.js" type="text/javascript"></script>
<script src="../3rd/backbone.native.js" type="text/javascript"></script>
<script src="../3rd/backbone.js" type="text/javascript"></script>
<script src="../src/shapes.js" type="text/javascript"></script>
<script src="../src/core.js" type="text/javascript"></script>
<script src="../src/input.js" type="text/javascript"></script>
<script src="../src/hero.js" type="text/javascript"></script>
<script src="../src/world.js" type="text/javascript"></script>
<script src="main.js" type="text/javascript"></script>
<style>
body {
margin: 0;
background-color: #000;
}
canvas {
position: fixed;
top: 0;
left: 0;
}
</style>
</head>
<body>
<img id="mario" src="../super-mario-bros/super-mario-2x.png" style="display:none;" />
<canvas id="foreground" width="960" height="700">
Your browser does not support canvas element.
</canvas>
</body>
</html>
</pre>
<p>
Some important notes:
</p>
<ul>
<li>HTML meta tags <code>viewport</code>, <code>apple-mobile-web-app-capable</code>, <code>mobile-web-app-capable</code> and <code>apple-mobile-web-app-status-bar-style</code> ensure the canvas is properly sized and styled on iPads and other mobile devices. The width specified there should be the same as the canvas elements. On <a href="#mobile-devices">mobile devices</a>, an orientation change will recalculate and change the width to fit the canvas in the viewport. </li>
<li>Style <code>touch-action: none;</code> on the <code>HTML</code> tag disables touch behaviors, like pan and zoom for IE10.</li>
<li>Elements must all have ids since we use the native <code>getElementById</code> Javascript function to retrieve the <code>Canvas</code> and <code>Image</code> objects from their respective DOM elements.</li>
</ul>
<h3 id="documentation-main">main.js</h3>
<p>
File <code>main.js</code> is where you declare and initialize your objects. It is recommended that you wrap that code in a function which gets executed once the document and all assets are loaded (i.e. window.onload event). You can use for example <code>$(window).on("load", function() {});</code>.
</p>
<p>
Other files use a simple anonymous function instead since they contain class declarations mainly. However in <code>main.js</code> is where <code>Canvas</code> and <code>Image</code> objects are retrieved from the DOM elements. So they must first be loaded. This keeps things simple. Assets are as a consequence always loaded synchronously.
</p>
<p>
Here is a sample <code>main.js</code> file, taken from the <a href="mario/index.html" target="_blank">Mario</a> example.
</p>
<pre>
$(window).on("load", function() {
// Mario alone in an empty world. Control him with the touchpad.
Backbone.Mario = Backbone.Hero.extend({
defaults: _.extend({}, Backbone.Hero.prototype.defaults, {
name: "mario",
spriteSheet: "mario"
})
});
var canvas = document.getElementById("foreground");
var spriteSheets = new Backbone.SpriteSheetCollection([{
id: "mario",
img: "#mario",
tileWidth: 32,
tileHeight: 64,
tileColumns: 21,
tileRows: 6
}]).attachToSpriteClasses();
var debugPanel = new Backbone.DebugPanel();
var input = new Backbone.Input({
drawTouchpad: true,
drawPause: true
});
var mario = new Backbone.Mario({
x: 400, y: 400, floor: 500
}, {
input: input
});
var world = new Backbone.World({
width: 30, height: 18,
tileWidth: 32, tileHeight: 32,
backgroundColor: "rgba(66, 66, 255, 1)",
viewportBottom: 156
});
world.add(mario);
var engine = new Backbone.Engine({}, {
canvas: canvas,
debugPanel: this.debugPanel,
input: input
});
engine.add([
world,
input,
debugPanel
]);
// Expose things as globals - easier to debug
_.extend(window, {
canvas: canvas,
engine: engine
});
// Ensure the canvas is always visible and centered
adjustViewport(canvas, canvas.width, canvas.height);
});
</pre>
</div>
</div>
<div id="documentation" class="row">
<div class="col-md-12">
<h1>Reference</h1>
<p>
Backbone Game Engine defines classes in the <code>Backbone</code> namespace. Most are sub-classed from <code>Backbone.Model</code> or <code>Backbone.Collection</code>.
</p>
</div>
</div>
<div id="documentation-Engine" class="row">
<div class="col-md-12">
<h3>Backbone.Engine</h3>
<pre>new Backbone.Engine([attributes], [options])</pre>
<p>
<code>Backbone.Engine</code> is a Backbone model that holds a <a href="http://backbonejs.org/#Collection" target="_blank">Backbone collection</a> of sprite models.
It uses HTML5's <a href="https://developer.mozilla.org/en/docs/Web/API/window.requestAnimationFrame" target="_blank">requestAnimationFrame</a> to provide a 60 frames per second game loop.
</p>
<p>
The sprite collection is stored in property <code>sprites</code>. You may directly access it however for convenience, methods <code>add</code>, <code>remove</code> and <code>reset</code> exist as proxy the engine.
</p>
<h4>Attributes</h4>
<ul>
<li><code>clearOnDraw</code>: Optional. Boolean to ask for a clear of the canvas before redraw. Defaults to false. Note that this is an expensive call. Better to only clear the area that changed.</li>
<li><code>tapDetectionDelay</code>: Optional. The delay in ms before a tap gestured is detected. Defaults to 50ms</li>
<li><code>tapMoveTolerance</code>: Optional. The amount of pixel move tolerated to detect a tap gesture. Defaults to +/-5 pixels. Beyond that, a drag gesture will be trigerred.</li>
</ul>
<h4>Options</h4>
<p>
Upon instantiation, these options can be passed. They will be stored as properties on the <code>Backbone.Engine</code> model instance.
</p>
<ul>
<li><code>canvas</code>: The canvas to draw upon. Drawing is on its 2d context.</li>
<li><code>input</code>: Optional. The user control input instance. If passed and the pause button is enabled, will stop/start then engine when pressed.</li>
<li><code>debugPanel</code>: Optional. A <a href="#documentation-DebugPanel">Backbone.DebugPanel</a> instance. If passed <code>fps</code> and <code>cycleTime</code> are output.</li>
</ul>
<h4>Methods</h4>
<ul>
<li><code>add()</code>: Adds one or multiple models delegating to the sprite collection's <code>add</code> method.</li>
<li><code>remove()</code>: Removes one or multiple models delegating to the sprite collection's <code>remove</code> method.</li>
<li><code>reset()</code>: Clears or sets the sprites collection delegating to the <code>reset</code> method.</li>
<li><code>isRunning()</code>: Returns true if the engine is running, or false if not.</li>
<li><code>start(), stop()</code>: Starts or stops the engine.</li>
<li><code>toggle()</code>: Toggle start/stop the engine.</li>
</ul>
<h4>Events</h4>
<ul>
<li><code>tap</code>: Trigerred when the user clicks or taps on the canvas. A tap is defined when the user presses/clicks on a position without moving for more than <code>tapDetectionDelay</code> ms. The event callback function is passed the DOM event object, with these extra properties attached: <code>canvas</code>, <code>canvasX</code> and <code>canvasY</code>. In addition, property <code>canvasHandled</code> is provided as a mechanism to stop propagation (see below). </li>
<li><code>key</code>: Trigerred when the user types in a key. The event callback function is passed the DOM event object, with additional property <code>canvas</code>.</li>
<li><code>dragstart</code>, <code>dragmove</code> and <code>dragend</code>: Trigerred when a drag gesture occurs. This happens when the user presses/clicks and holds and moves. When these events are trigerred, the <code>tap</code> event does not get trigerred.</li>
</ul>
<div class="alert alert-info">
Note: The <code>tap</code> and <code>drag*</code> events are broadcasted to whomever is listening. Event property <code>canvasHandled</code> is used to to prevent propagation to many overlapping objects. At first it is set to <code>false</code>. The first object to intercept and handle the event should set it to <code>true</code>. Subsequent objects intercepting the event should look at this property and return without action when <code>true</code>. <code>Backbone.Button</code> and <code>Backbone.WorldEditor</code> implement this behavior.
</div>
<h4>How it works</h4>
<p>During every animation frame, the engine performs these things:</p>
<ul>
<li>Loop through models (in order), and calls their <code>update</code> method. Passing <code>dt</code>, the time in milliseconds since the last call to update. The update method must return <code>true</code> to ask for a redraw, or <code>false</code> not to.</li>
<li>Loop through all models that requested a redraw, and call their <code>draw</code> method passing <code>context</code>, the canvas 2d context. Perform whatever magic you like in the draw method.</li>
<li>Call itself again upon the next animation frame.</li>
</ul>
<div class="alert alert-info">Note: By default the engine does not clear the canvas before redraw. You can set the <code>clearOnDraw</code> option to do so however it is an expensive call. Better to do it only when required. See class <a href="#documentation-World">Backbone.World</a> for an example.</div>
<p>
The <code>update</code> method is used to update the model position, animation, detect collisions, or whatever you like. If it requests a redraw, the engine will then call its <code>draw</code> method. The engine ensures that models are updated and drawn in the order they are sorted in the collection. You can define the sort order by defining a <a href="http://backbonejs.org/#Collection-comparator" target="_blank">comparator</a>.
</p>
<p>
Models added to the collection receive an <code>attach</code> event and have property <code>engine</code> set as backreference. When removed, they receive a <code>detach</code> event.
</p>
<p>
To measure performance, two properties are set: <code>fps</code> and <code>cycleTime</code>. If you passed option <code>debugPanel</code>, they will be drawn on screen.
</p>
<p>
The engine can be started and stopped. When running, will perform an update/draw sequence 60 times per second. Use methods <code>start</code>, <code>stop</code> or <code>toggle</code>. Use method <code>isRunning</code> to determine if the engine is running. If you passed option <code>input</code>, the engine will bind to the <em>pause</em> button (or the <em>p</em> key) to toggle start/stop.
</p>
<h4>Usage</h4>
<pre>
var canvas = document.getElementById("foreground");
var debugPanel = new Backbone.DebugPanel();
var ball = new Backbone.Ball({
x: 100, y: 100, color: "blue"
});
var engine = new Backbone.Engine({
clearOnDraw: true
}, {
canvas: canvas,
debugPanel: debugPanel
});
engine.add([
ball,
debugPanel
]);
</pre>
<p>
Taken from the <a href="ball/index.html" target="_blank">Bouncing Ball</a> example. Draws two models: the debug panel and a bouncing ball.
</p>
</div>
</div>
<div id="documentation-SpriteSheet" class="row">
<div class="col-md-12">
<h3>Backbone.SpriteSheet</h3>
<pre>new Backbone.SpriteSheet([attributes], [options]);</pre>
<p>
<code>Backbone.SpriteSheet</code> is a Backbone model which breaks an image into frames used for animation.
</p>
<h4>Attributes</h4>
<ul>
<li><code>img</code>: The <code>Image</code> object or element id selector of the image to find in the DOM (i.e. <code>#icons</code>). A pointer to the Image object is then stored in property <code>img</code>.</li>
<li><code>tileWidth, tileHeight</code>: Size of tiles in pixels.</li>
<li><code>tileColumns, tileRows</code>: Number of tiles in the image.</li>
</ul>
<h4>Properties</h4>
<ul>
<li><code>frames</code>: Array of animation frames. Automatically set when model is instantiated.</li>
<li><code>img</code>: Pointer to <code>Image</code> object. Automatically set when model is instantiated.</li>
</ul>
<p>
When a sprite sheet is instantiated, an array of frames is built and stored in property <code>frames</code>. A frame object contains the coordinates of the frame. It consists of <code>{x, y, width, height}</code> representing the pixel position and size of the frame. These will be passed to the <a href="https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D#drawImage()" target="_blank">HTML5 canvas drawImage</a> function as arguments <code>sx, sy, sw, sh</code> by the <code>draw</code> method.
</p>
<p>
Sprite sheets are not generally created on their own, but rather in a <code>Backbone.SpriteSheetCollection</code>. See below for usage.
</p>
</div>
</div>
<div id="documentation-SpriteSheetCollection" class="row">
<div class="col-md-12">
<h3>Backbone.SpriteSheetCollection</h3>
<pre>new Backbone.SpriteSheetCollection([models], [options]);</pre>
<p>
<code>Backbone.SpriteSheetCollection</code> is a Backbone collection of <code>Backbone.SpriteSheet</code> models.
</p>
<h4>Methods</h4>
<ul>
<li><code>attachToSpriteClasses()</code>: Attaches sprite sheets to sprite class prototypes. Does so by finding all defined sprite classes (<code>Backbone.*</code>) with default attribute <code>spriteSheet</code> matching a sprite sheet id in the collection. Then sets their <code>spriteSheet</code> property to point to the correct sprite sheet in the collection.</li>
</ul>
<h4>Usage</h4>
<p>
Define your sprite sheets by creating a collection as such:
</p>
<pre>
this.spriteSheets = new Backbone.SpriteSheetCollection([{
id: "mario",
img: "#mario",
tileWidth: 32,
tileHeight: 64,
tileColumns: 21,
tileRows: 2
}, {
id: "tiles",
img: "#tiles",
tileWidth: 32,
tileHeight: 32,
tileColumns: 29,
tileRows: 28
}]).attachToSpriteClasses();
</pre>
<p>
<img src="docs/super-mario-sprite.png" class="img-responsive" alt="Backbone.Input" />
</p>
<p>
Here two sprite sheets are created <code>mario</code> and <code>tiles</code>. Their graphics are in <code>Image</code> objects found in the DOM. The attribute <code>img</code> is the selector to retrieve them.
</p>
<p>
Calling method <code>attachToSpriteClasses</code> will attach the sprite sheets to each sprite class found in the <code>Backbone</code> namespace.
</p>
</div>
</div>
<div id="documentation-Sprite" class="row">
<div class="col-md-12">
<h3>Backbone.Sprite</h3>
<pre>new Backbone.Sprite([attributes], [options]);</pre>
<p>
<code>Backbone.Sprite</code> is a <a href="http://backbonejs.org/#Model" target="_blank">Backbone Model</a> which implements the required <code>update</code> and <code>draw</code> methods to animate a sprite, frame by frame.
</p>
<h4>Attributes</h4>
<ul>
<li><code>x, y</code>: The coordinates in pixels.</li>
<li><code>width, height</code>: Size of the sprite in pixels.</li>
<li><code>paddingLeft, paddingRight, paddingTop, paddingBottom</code>: Optional. Internal padding to account for empty space inside the tile of a sprite. Useful to specify empty zones for collision detection.</li>
<li><code>sequenceIndex</code>: The current animation sequence frame. Automatically set.</li>
<li><code>state</code>: The current animation.</li>
<li><code>spriteSheet</code>: Sprite sheet id. </li>
<li><code>collision</code>: Optional. For use with <a href="#documentation-World">Backbone.World</a>.</li>
<li><code>static</code>: Optional. For use with <a href="#documentation-World">Backbone.World</a>.</li>
<li><code>visible</code>: Optional boolean. If true, the sprite is not drawn. Default is false.</li>
<li><code>zIndex</code>: Optional. Specifies the drawing order. Higher value is drawn above sprites with lower values. Default is 0.</li>
</ul>
<div class="alert alert-info">
Note: <code>zIndex</code> is only used in <code>Backbone.World</code>. Currently, it is partially implemented - only 0 and 1 values are recognized.
</div>
<h4>Properties</h4>
<ul>
<li><code>animations</code>: Hash of animations of the sprite. Described further below.</li>
<li><code>spriteSheet</code>: Instance of the <code>Backbone.SpriteSheet</code> holding the images to animate. This is automatically set when you define your sprite sheet collection. See <a href="#documentation-SpriteSheetCollection">Backbone.SpriteSheetCollection</a> for details.</li>
<li><code>saveAttributes</code>: Attributes serialized for persistence. Defaults to <code>["name", "state", "sequenceIndex", "x", "y"]</code>.</li>
</ul>
<h4>Methods</h4>
<ul>
<li><code>toSave()</code>: Serializes attributes for persistence. Attributes to be serialized are specified in the <code>saveAttributes</code> property.</li>
<li><code>update(dt)</code>: Called by then engine 60 times a second. Updates sprite attribues and implements behavior. Returns true to ask for a redraw, or false for none.</li>
<li><code>onUpdate(dt)</code>: Not defined by default. If you define it, it is called at the end of <code>update</code>. Useful for extending the behavior of a sprite without having to overload metod <code>update</code>. Note that <code>draw</code> is called based on the Boolean return value of this method to decide whether to draw or not. It must therefore return <code>true</code> to perform a draw, or <code>false</code> not to.</li>
<li><code>draw(context, options)</code>: Called by the engine after <code>update</code>, if a redraw was asked. Takes care of rendering the sprite, and its proper animation at the correct position. Argument <code>options</code> can be used by a model serving as proxy. For example it is passed when drawn by a <code>Backbone.World</code>instance. It will contain <code>offsetX</code> and <code>offsetY</code> to transform <code>x</code> and <code>y</code> from world coordinates to canvas coordinates.</li>
<li><code>onDraw(context, options)</code>: Not defined by default. If defined, it is called at the end of <code>draw</code>. Useful for extending the rendering of a sprite without having to overload metod <code>draw</code>.</li>
<li><code>getAnimation([state])</code>: Returns the current animation based on argument <code>state</code>. If argument <code>state</code> is omitted, the attribute is used instead.</li>
<li><code>overlaps(x, y):</code>: Checks to see if the sprite overlaps with the passed coordinates. Returns a Boolean.</li>
<li><code>getLeft(withPadding), getRight(withPadding), getTop(withPadding), getBotttom(withPadding)</code>: Returns the left, right, top or bottom-most position of a sprite. Argument withPadding is a boolean specifying whether to include the padding or not. Defaults to false.</li>
<li><code>bbox(withPadding)</code>: Returns the bounding box of the sprite as an object <code>{x1, y1, x2, y2}</code>. Argument <code>withPadding</code> is a boolean specifying whether to include the padding or not. Defaults to false.</li>
<li><code>getCenterX(withPadding)</code>: Returns the center <code>x</code> of the sprite. Argument <code>withPadding</code> is a boolean specifying whether to include the padding or not. Defaults to false.</li>
<li><code>getCenterX(withPadding)</code>: Returns the center <code>y</code> of the sprite. Argument <code>withPadding</code> is a boolean specifying whether to include the padding or not. Defaults to false.</li>
</ul>
<h4>Events</h4>
<ul>
<li><code>attach</code>: Triggered when the sprite is attached to the engine.</li>
<li><code>detach</code>: Triggered when the sprite is detached to the engine.</li>
</ul>
<p>
The <code>attach</code> and <code>detach</code> events can be used to start/stop listening to events. For example, the <code>Backbone.Hero</code> sprite starts listening to user input when attached, and stops when detached.
</p>
<h4>Sprite and sprite sheets</h4>
<p>
Graphics are obtained from a <a href="#documentation-SpriteSheet">Backbone.SpriteSheet</a> model. In attribute <code>spriteSheet</code>, specify the sprite sheet id you previously defined in a <code>Backbone.SpriteSheetCollection</code> instance. The collection will automatically attach it to the sprite by setting property <code>spriteSheet</code> as back reference. Building on the example above:
</p>
<pre>
var spriteSheets = new Backbone.SpriteSheetCollection([{
id: "mario",
img: "#mario",
tileWidth: 32,
tileHeight: 64,
tileColumns: 21,
tileRows: 2
}]).attachToSpriteClasses();
var mario = new Backbone.Mario({
spriteSheet: "mario"
});
mario.get("spriteSheet");
// mario
spriteSheets.get("mario");
// child {cid: "c2", attributes: Object, collection: child, _changing: false, _previousAttributes: Object…}
mario.spriteSheet;
// child {cid: "c2", attributes: Object, collection: child, _changing: false, _previousAttributes: Object…}
</pre>
<h4>Inheritance</h4>
<p>
Instantiating a <code>Backbone.Sprite</code> model is not very useful by itself. You must first extend the <code>Backbone.Sprite</code> class to provide your own animations and a pointer to the sprite sheet. For example this defines a sprite with 3 animations <code>idle</code>, <code>walk-left</code> and <code>walk-right</code>. It points to the sprite sheet id <code>mario</code>.
</p>
<pre>
Backbone.MySprite = Backbone.Sprite.extend({
defaults: _.extend(_.deepClone(Backbone.Sprite.prototype.defaults), {
x: 400,
y: 400,
spriteSheet: "mario",
state: "idle",
sequenceIndex: 0,
static: false,
collision: true
}),
animations: {
idle: {
sequences: [0]
},
"walk-right": {
sequences: [1, 2, 3, 2],
delay: 200
},
"walk-left": {
sequences: [1, 2, 3, 2],
scaleX: -1,
delay: 200
}
}
});
</pre>
<p>
Above, the <code>Backbone.Sprite</code> was sub-classed using <code>extend</code> method. <code>defaults</code> are the default attributes to give any new <code>Backbone.MySprite</code> instance. They extend the Sprite class' defaults.
</p>
<p>
If you want to reuse parts of <code>defaults</code> or <code>animations</code> from a parent class, make sure to make a copy. You can use the helper function <code>_.deepClone</code> for that purpose (<code>_.clone</code> only goes one level deep). Otherwise you may change the parent class behavior. For example the <code>Backbone.PennieUg</code> class reuses the <code>Backbone.Pennie</code> class' properties <code>defaults</code> and <code>animations</code> by first creating copies.
</p>
<pre>
Backbone.PennieUg = Backbone.Pennie.extend({
defaults: _.extend(_.deepClone(Backbone.Pennie.prototype.defaults), {
name: "pennie-ug"
}),
animations: _.deepClone(Backbone.Pennie.prototype.animations)
});
Backbone.PennieUg.prototype.animations.idle.sequences = [168, 168, 169, 170, 169, 168];
</pre>
<div class="alert alert-info">
Helper function <code>deepClone</code> was created as a mixin of <code>underscore</code>. When it makes sense, make general functions available that way. Look at the end of <code>src/core.js</code> for all mixins.
</div>
<h4>Animations</h4>
<p>
Sprite property <code>animations</code> contains a hash of animations. Each animation contains a sequence of frames and a delay between frames for animation. For example:
</p>
<pre>
animations: {
idle: {
sequences: [0, 1],
delay: 200
}
}
</pre>
<p>
This defines an animation of two frames, alternating at an interval of 200ms. Values 0 and 1 in array <code>sequences</code> are frame indices defined in the sprite sheet. Sprite attributes <code>state</code> and <code>sequenceIndex</code> control which animation and sequence are currently used. The <code>sequenceIndex</code> is automatically incremented (and reset to 0) by the sprite's draw function. Attribute <code>state</code> determines the current animation. It must be set to <code>idle</code> in the above example (as there is only one).
</p>
<p>
Extra animation options are available. Here is a complete list:
</p>
<ul>
<li><code>sequences</code>: Array of frame indices, or squence objects. A sequence object looks like this: <code>{frame: 52, x: 0, y: -32, scaleX: 1.00, scaleY: 1}</code>. It allows you to specify an offset to apply when the sprite is drawn, and a scaling factor.</li>
<li><code>scaleX, scaleY</code>: Optional. Scaling factors. Set <code>scaleX</code> to -1 to flip horizontally. Defaults to 1 if omitted.</li>
<li><code>delay</code>: Optional. The time to change to the next sequence. No need to specify if there is only one frame (as there is no animation). You can also define a sprite method <code>sequenceDelay</code> to programmatically return the delay. It will be passed the current animation.</li>
</ul>
<p>
For detailed examples of animations, look at file <code>artifacts.js</code> in the <code>super-mario-bros</code> folder. Class <code>Backbone.Pennie</code> implements a basic animation sequence using frame indices, while <code>Backbone.FlyingPennie</code> implements a more complex animation with sequence objects.
</p>
<pre>
Backbone.Pennie = Backbone.AnimatedTile.extend({
...
animations: {
idle: {
sequences: [52, 52, 53, 54, 53, 52],
delay: 50
}
},
...
Backbone.FlyingPennie = Backbone.Sprite.extend({
...
animations: {
anim: {
sequences: [
{frame: 52, x: 0, y: -32, scaleX: 1.00, scaleY: 1},
{frame: 52, x: 0, y: -64, scaleX: 0.50, scaleY: 1},
{frame: 53, x: 0, y: -90, scaleX: 0.50, scaleY: 1},
{frame: 53, x: 0, y: -128, scaleX: 1.00, scaleY: 1},
{frame: 53, x: 0, y: -128, scaleX: 0.50, scaleY: 1},
{frame: 52, x: 0, y: -112, scaleX: 0.50, scaleY: 1},
{frame: 52, x: 0, y: -90, scaleX: 1.00, scaleY: 1},
{frame: 52, x: 0, y: -80, scaleX: 0.50, scaleY: 1},
{frame: 53, x: 0, y: -80, scaleX: 0.50, scaleY: 1}
],
delay: 50
}
},
...
</pre>
</div>
</div>
<div id="documentation-Input" class="row">
<div class="col-md-12">
<h3>Backbone.Input</h3>
<pre>new Backbone.Input([attributes], [options]);</pre>
<p>
<code>Backbone.Input</code> class is a model which captures user input events and stores them as model attributes. For example pressing the left arrow, sets the <code>left</code> attribute to <code>true</code>. Depressing sets it to <code>false</code>. Bind to on the attribute change event to be notified.
</p>
<p>
<code>Backbone.Input</code> supports keyboard, mouse and touch events. It can draw a touchpad on screen with left and right arrow keys, an A (red) button and a B (blue) button.
</p>
<p>
<img src="docs/input.png" class="img-responsive" alt="Backbone.Input" />
</p>
<div class="alert alert-info">
Note: The Backbone.Input model only captures input when attached to a Backbone.Engine.
</div>
<h4>Attributes</h4>
<p>This attribute can be passed when creating the model, to configure the input.</p>
<ul>
<li><code>drawTouchpad</code>: Optional. Boolean or string "auto" to indicate whether to draw the touchpad. When "auto", the touchpad will be drawn only on touch devies. Defaults to "auto".</li>
</ul>
<p>The following model attributes are set by the model. They should not be set externally.</p>
<ul>
<li><code>touchEnabled</code>: Boolean set to true if the device is touch enabled.</li>
<li><code>left</code>: Boolean set to true when the left touchpad arrow or left keyboard arrow key is pressed.</li>
<li><code>right</code>: Boolean set to true when the right touchpad arrow or right keyboard arrow key is pressed.</li>
<li><code>buttonA</code>: Boolean set to true when the A touchpad button is pressed, or when the z keyboard key is pressed.</li>
<li><code>buttonB</code>: Boolean set to true when the B touchpad button is pressed, or when the x keyboard key is pressed.</li>
</ul>
<h4>Methods</h4>
<ul>
<li><code>hasTouchpad()</code>: Returns true if the touchpad is drawn.</li>
<li><code>leftPressed()</code>: Returns true if the left button is pressed.</li>
<li><code>rightPressed()</code>: Returns true if the right button is pressed.</li>
<li><code>buttonAPressed()</code>: Returns true if button A is pressed.</li>
<li><code>buttonBPressed()</code>: Returns true if button B is pressed.</li>
</ul>
<h4>Events</h4>
<ul>
<li><code>attach</code>: Triggered when the input is attached to the engine. Will start listening to user input.</li>
<li><code>detach</code>: Triggered when the input is detached to the engine. Will stop listening to user input.</li>
</ul>
<p>
You can add or remove a <code>Backbone.Input</code> model from the engine on the fly. In the Super Mario Bros example, the <code>Backbone.Input</code> and the <code>Backbone.WorldEditor</code> are swapped when moving from play to edit modes.
</p>
<h4>Usage</h4>
<pre>
var input = new Backbone.Input();
var engine = new Backbone.Engine();
engine.add(input);
input.bind("change:left", function(input) {
if (input.leftPressed())
console.log("left pressed:)");
else
console.log("left depressed:(");
});
</pre>
</div>
</div>
<div id="documentation-World" class="row">
<div class="col-md-12">
<h3>Backbone.World</h3>
<pre>new Backbone.World([attributes], [options])</pre>
<p>
<code>Backbone.World</code> is model which contains a collection of sprites that interact with each other. A world is an environment composed of tiles and characters. The world extends beyond the canvas however the viewport, the visible portion, is constrained within its prescribed limits. <code>Backbone.World</code> is similar to a sprite; it implements the <code>update</code> and <code>draw</code> methods required by the <code>Backbone.Engine</code> collection.
</p>
<h4>Attributes</h4>
<ul>
<li><code>x, y</code>: Origin of top-left corner in pixels.</li>
<li><code>width, height</code>: Size of world in tiles.</li>
<li><code>tileWidth, tileHeight</code>: Size of a tile in pixels.</li>
<li><code>viewportLeft, viewportRight, viewportTop, viewportBottom</code>: Defines an area in the canvas the world is constrained to. Each value provides gutter regions in pixels. Anything drawn by the world will be clipped in the area. Useful for drawing a menu bar or buttons on the same canvas. In provided demos for example, <code>viewportBottom</code> is set to 156 pixels to make room the the touchpad.</li>
<li><code>sprites</code>: Array of sprite models for persistence.</li>
<li><code>backgroundColor</code>: Background color of the world.</li>
<li><code>backgroundImage</code>: Id attribute of an image element in the DOM to show as background.</li>
<li><code>state</code>: Persisted state either play or pause.</li>
</ul>
<div class="alert alert-info">
Note: Setting a viewport different than the canvas size uses canvas clipping. Avoid using if you can as clipping the is expensive and can introduce performance issues.
</div>
<h4>Options</h4>
<ul>
<li><code>backgroundImage</code>: Optional. Pass to use a background image instead of a background color. Anchored to the origin.</li>
<li><code>input</code>: Input instance to control the hero.</li>
<li><code>camera</code>: Camera instance to keep the hero in the viewport.</li>
<li><code>debugPanel</code>: Optional.</li>
</ul>
<h4>Methods</h4>
<p>
A <code>Backbone.World</code> is a model that wraps a collection stored in property <code>sprites</code>. To prevent outside direct access to this collection, it provides these two methods:
</p>
<ul>
<li><code>add(models, [options])</code>: Add one or many models. Adds <code>world</code> to options and delegates to the <code>sprites</code> collection's <code>add</code> method. Then sets the <code>world</code> property as back-reference on the new model(s). Returns the new model(s).</li>
<li><code>remove(models, [options])</code>: Removes one or many models. Delegates to the <code>sprites</code> collection's <code>remove</code> method. Deletes the <code>world</code> back-reference and returns the model(s).</li>
</ul>
<p>
In addition to standard <code>Backbone.Model</code> methods, it also exposes these:
</p>
<ul>
<li><code>spawnSprites()</code>: Resets the sprites collection by retrieving the <code>sprites</code> attribute from the model. This is called after the world is loaded.</li>
<li><code>update(dt)</code>: Update function called by the engine. Will in turn call the update method of all sprites.</li>
<li><code>draw(context)</code>: Draw function called by the engine. Will in turn call the draw method of all sprites.</li>
<li><code>cloneAtPosition(sprite, x, y)</code>: Clones the sprite model and places the new instance at the specified coordinates. Will pass <code>world</code> to the <code>options</code> payload when created. Will also set property <code>world</code> as back-reference. If the sprite name matches that of the world attribute <code>hero</code> it will also pass option <code>input</code>, and if a <code>Backbone.Camera</code> exists, it will be tied to it. This function also acts as a toggle when placing a sprite over a tile where another exists. The existing one is removed. This ensures only one tile (static sprite) exists at one location.</li>
<li><code>width(), height()</code>: Return the size of the world in pixels.</li>
<li><code>getWorldIndex(object)</code>: Calculates the index position of a tile based on coordinates. Argument <code>object</code> must contain <code>x</code> and <code>y</code>, or be a model with those attributes. The index is calculated with formula <code>height * x/tileWidth + y/tileHeight</code>. This method is used to set the <code>id</code> of tile sprites.</li>
<li><code>getWorldCol(x), getWorldRow(y)</code>: Returns the tile position in columns or rows of a coordinate.</li>
<li><code>findAt(x, y, [type], [exclude], [collision])</code>: Finds the first sprite at the specified coordinate. Use for collision detection. Optional arguments allow you to filter what to look for. Set <code>type</code> to <code>character</code> to find moving sprites, or <code>tile</code> to find tiles. Set <code>exclude</code> to the id of the sprite you want to exclude from the search. In a collision detection scheme, this is usually the id of the sprite you are checking against. Set <code>collision</code> to true to find only tiles that have their <code>collision</code> flag set.</li>
<li><code>filterAt(x, y, [type], [exclude], [collision])</code>: Same as <code>findAt</code> but returns the list of all matching sprites instead of the first.</li>
<li><code>findCollidingAt(x, y)</code>: Finds a colliding tile. Just like calling <code>findAt(x, y, "tile", null, true)</code>.</li>
<li><code>findCollisions()</code>: Finds collisions for a given set of collision map.</li>
</ul>
<h4>Events</h4>
<ul>
<li><code>attach</code>: Triggered when the sprite is attached to the engine. Will trigger the <code>attach</code> method of all sprites in the world.</li>
<li><code>detach</code>: Triggered when the sprite is detached to the engine. Will trigger the <code>detach</code> event of all sprites in the world.</li>
<li><code>tap</code>:
Trigerred when the user taps or clicks on the canvas. The callback will be passed the DOM event extended with these properties: <code>canvas</code>, <code>canvasX</code>, <code>canvasY</code>, <code>world</code>, <code>worldX</code> and <code>worldY</code>.
</li>
<li><code>key</code>: Trigerred on a keyup event. The event callback will be passed the DOM event as argument.</li>
</ul>
<h4>How it works</h4>
<p>
Sprites can be added and removed via methods <code>add</code> and <code>remove</code>. Sprites are automatically attached to the <a href="#documentation-Engine" target="_blank">Backbone.Engine</a> the world is attached to. Sprites then have properties <code>engine</code> and <code>world</code> set as back-reference. In each request frame, the same mechanics apply as for sprites attached directly to an engine; methods <code>update</code> and <code>draw</code> are called for each sprite. The exception is for static sprites which are only updated/redrawn when required (see below).
</p>
<p>
Internally, the world keeps sprites into a collection stored in property <code>sprites</code>. It further splits sprites into 2 collections for faster lookup:
</p>
<ul>
<li><code>staticSprites</code>: Background sprites that have no animation. These are usually same-sized tiles. Sprites that have their <code>static</code> attribute set to <code>true</code> will be put in this collection. Sprites are given an <code>id</code> determined by their position (column and row). The collection is ordered and indexed on <code>id</code> allowing for fast lookup on a pair of x/y coordinates. In addition, these sprites are drawn on a background canvas only drawn when required (i.e. world is panned).</li>
<li><code>dynamicSprites</code>: Animated tiles and characters. Their <code>static</code> attribute must be set to <code>false</code> to fall in this collection. These sprites are given unique <code>id</code> attributes based on their name (i.e. <code>mario.1</code>). They are not indexed therefore lookup has an order of N. Keep the number of sprites here to a minimum.</li>
</ul>
<p>
A world is measured in tiles via attributes <code>width</code>, <code>height</code>, <code>tileWidth</code> and <code>tileHeight</code>. Call methods <code>width</code> and <code>height</code> to get the size in pixels. Attributes <code>x</code> and <code>y</code> determine the origin in pixels (top-left corner) and allow the world to be panned consequently changing the viewport.
</p>
<div class="alert alert-info">
Note: If you define an animated tile, make sure its <code>static</code> attribute is set to false to prevent redraws every animation frame. Also ensure the width of tile sprites match that of world attributes <code>tileWidth</code> and <code>tileHeight</code>.
</div>
<h4>Sprites</h4>
<p>
When the world is created, sprites are instantiated in method <code>spawnSprites</code>. Each sprite instance is attached to the engine. Sprites then have properties <code>engine</code> and <code>world</code> set pointing to those respective objects.
</p>
<p>
Sprites can be categorized with attribute <code>type</code> as to identify one another when they interact with each other. Sprites of type <code>tile</code> are usually static and obstacles. Sprites of type <code>character</code> are usually dynamic and moving sprites.
</p>
<p>
You can add sprites with method <code>add</code> which delegates to the <code>sprites</code> collection's <code>add</code> method. It takes care of passing the <code>world</code> as option.
</p>
<p>
You can also use method <code>cloneAtPosition(sprite, x, y)</code>. It takes as argument an existing sprite, and coordinates. It will clone the sprite and place it at the specified coordinates passing <code>world</code> and <code>input</code> as options. If the sprite has its <code>hero</code> attribute set to <code>ture</code>, and if a <code>Backbone.Camera</code> exists, it will be tied to it. Backbone.WorldEditor</code> uses this function for instance.
</p>
<p>
Methods <code>getWorldIndex</code>, <code>getWorldCol</code> and <code>getWorldRow</code> can be used to find the position of a sprite. A sprite's <code>x</code> and <code>y</code> attributes determine their position relative to the world origin.
</p>
<h4>Background and Tiles</h4>
<p>
The background of a world is composed of same-size tiles defined by attributes <code>tileWidth</code> and <code>tileHeight</code>. A tile is usually a non-animated sprite with its <code>static</code> attribute set to true. The model <code>id</code> is the position of the sprite on screen (column and row). As such, there can only be one tile per location.
</p>
<h4>Character Sprites</h4>
<p>
Characters are sprites that interact with their environment. <a href="#documentation-Character">Backbone.Character</a> and <a href="#documentation-Hero">Backbone.Hero</a> are character sprites. Character sprite models usually have teir <code>type</code> attribute set to <code>character</code>. You are free to use attribute <code>type</code> to classify your sprites.
</p>
<h4>Collision detection</h4>
<p>Internally sprite positions are stored in a <a href="https://github.com/asaarinen/qtree" target="_blank">QuadTree</a>. As a sprite moves, its position in the QuadTree is updated.
</p>
<p>Three methods exist to detect collisions.</p>
<ul>
<li><code>findAt(x, y, [type], [exclude], [collision])</code>:
Find the first sprite touching the given point or <code>null</code> if none are found. Optional arguments can be passed for limiting the lookup:
<ul>
<li><code>type</code>: Optional. If set, will only lookup sprites matching that type. Typical values are <code>character</code> or <code>tile</code>.</li>
<li><code>exlcude</code>: Optional. The sprite model's <code>id</code> to exclude in lookup.</li>
<li><code>collision</code>: Optional. Boolean indicating whether to only include sprites that have the <code>collision</code> attribute explicitly set to <code>true</code>.
</ul>
</li>
<li><code>filterAt(x, y, [type], [exclude], [collision])</code>: Same as a above but finds all sprites touching the given point. Returns an array of sprites.</li>
<li><code>findCollisions(map, [type], [exclude], [collision])</code>:
Detects collisions on sprites for a set of named coordinates.
Optional arguments are the same as above. Argument <code>map</code> is an array of objects that is passed in, and passed out. A map object must contain:
<ul>
<li><code>x</code> and <code>y</code>: Coordinates to detect the collision.</li>
<li><code>dir</code>: The lookout direction: <code>top</code>, <code>right</code>, <code>bottom</code> or <code>left</code>.</li>
<li><code>sprites</code>: Array of detected colliding sprites. Reset/initialized to [] every call.</li>
<li><code>sprite</code>: The closest sprite based on the lookout direction.</li>
</ul>
</li>
</ul>
<p>
Look at the code in <code>Backbone.Character</code> and <code>Backbone.Hero</code> classes for examples on how to perform collision detection.
</p>
<h4>Persistence</h4>
<p>
The world model attributes contain all that is necessary to persist the state of the world to disk, or in the cloud. Calling the <code>save</code> method first serializes the sprite collection from the <code>sprites</code> property into the <code>sprites</code> attribute. It calls the <code>toSave</code> method on each sprite to save their position and state. It then delegates to the backbone model's <code>save</code> method to save to a server or local storage in JSON format. See the Backbone documentation for details.
</p>
<p>
The world can be restored by calling <code>spawnSprites</code> passing as argument a saved world in JSON format. For example, file <code>super-mario-world/level-1-1.js</code> contains the level in JSON format. It is set in global variable <code>_world</code>. The world can be restarted anytime with this line of code:
</p>
<pre>world.set(window._world).spawnSprites();</pre>
<h4>Usage</h4>
<pre>
var mario = new Backbone.Mario({
x: 400, y: 400, floor: 500
});
var world = new Backbone.World({
width: 30, height: 18,
tileWidth: 32, tileHeight: 32,
backgroundColor: "rgba(66, 66, 255, 1)"
});
world.add(mario);
var engine = new Backbone.Engine();
engine.add(world);
</pre>
<p>
A sprite (mario) is first created and added it the world. The world is then added to the engine. This is taken from file <code>mario/main.js</code> for the Mario example.
</p>
</div>
</div>
<div id="documentation-WorldEditor" class="row">
<div class="col-md-12">
<h3>Backbone.WorldEditor</h3>
<pre>new Backbone.WorldEditor([attributes], [options])</pre>
<p>
<code>Backbone.WorldEditor</code> is a model which displays a palette of sprites and allows the user to edit a <code>Backbone.World</code> instance by placing and removing sprites. Also allows the user to pan the world. In the Super Mario Bros demo, an editor is drawn at the bottom of the world replacing the <a href="#documentation-Input">Backbone.Input</a>. Like sprites and world, it must be added to the <code>Backbone.Engine</code> to render. The palette will page automatically if there are too many sprites.
</p>
<p>
<img src="docs/world-editor.png" class="img-responsive" alt="Backbone.Input" />
</p>
<h4>Attributes</h4>
<ul>
<li><code>x, y</code>: Top-left placement position in pixels of the editor on the canvas.</li>
<li><code>width, height</code>: Size of editor in pixels.</li>
<li><code>tileWidth, tileHeight</code>: Size of sprites drawn in the palette.</li>
<li><code>padding</code>: Padding in pixels around sprites.</li>
<li><code>backgroundColor</code>: Background color of the editor.</li>
<li><code>selectColor</code>: Background and outline color of a selected sprite.</li>
<li><code>selected</code>: The name of the cuurrently selected sprite.</li>
<li><code>spriteNames</code>: Ordered array of sprite names in the palette.</li>
</ul>
<h4>Options</h4>
<ul>
<li><code>world</code>: The Backbone.World to edit.</li>
<li><code>debugPanel</code>: Optional. If passed will output mouse coordinates.</li>
</ul>
<h4>Events</h4>
<ul>
<li><code>attach</code>: Triggered when the sprite is attached to the engine. Will start listening to user input.</li>
<li><code>detach</code>: Triggered when the sprite is detached to the engine. Will stop listening to user input.</li>
</ul>
<h4>How it works</h4>
<p>
The palette is drawn as a series of tiles left to right, top to bottom. Each tile is a sprite. The sprite may be bigger than the specified tile size, in which case it will be resized to fit the <code>tileWidth</code> and <code>tileHeight</code> attributes.
</p>
</div>
</div>
<div id="documentation-Character" class="row">
<div class="col-md-12">
<h3>Backbone.Character</h3>
<pre>new Backbone.Character([attributes], [options])</pre>
<p>
The <code>Backbone.Character</code> is a sub-classed <code>Backbone.Sprite</code> which implements an animated character with elementary AI (artificial intelligence) and physics. AI is limited to moving left, right, jumping/gravity and dying. Direction changes occur with collisions against an obstacle; either a tile or another character. You are free to extend the AI by subclassing it.
</p>
<div class="alert alert-info">
A <code>Backbone.Character</code> must live inside a <code>Backbone.World</code>.
</div>
<h4>Attributes</h4>
<ul>
<li><code>x, y</code>: Position of the sprite.</li>
<li><code>floor</code>: Set this value to prevent the character to fall outisde of the world due to gravity. By default it is null meaning the character will be removed from the world if it falls below the bottom of the world.</li>