Nell’iperspazio con Rocket: il Framework Web di Rust!
Modeling Patterns for JavaScript Browser-Based Games
1. Modeling Patterns for JavaScript Browser-Based Games JarodLong Ray Toal Loyola Marymount University Los Angeles, CA USA 2011-05-16
2. Topics Overview of Contributions Challenges for Browser-Based Games What’s new with JavaScript Patterns vs. Frameworks Contributions in Detail JavaScript and HTML5 Game Engines Summary
3. Contributions Development of JavaScript design patterns specifically for modules and types Note: patterns, not frameworks Patterns are independent of game engine Application of these patterns in a 2-D, physics-based, HTML5 game Survey of JavaScript game engines
4. Browser-Based Game Issues Rich domain models OOP was motivated by graphical applications Graphics and physics engines Can mix Canvas and the DOM don’t forget CSS! (esp. CSS3) Full source code visibility Ajax High score lists difficult to implement
5. JavaScript The most popular language for programming the client-side web (competes with Flash and Java) Created in 1996 but only “understood” in mid 2000s Recent Advances ECMAScript 5 V8 and other modern engines (>100x faster) Server-side (e.g., node.js) (BIG FUTURE IN THIS)
6. JavaScript Overview Array and object literals varx = [3, “true”, 2.2]; var point = {lat: 27.95, lon: -140.4}; A functional programming language -- closer to Scheme than C myArray.map(function (x) {return x * x;}); data.map(square).filter(isOdd).reduce(plus); Prototypes, not classes varmyCircle = Object.create(yourCircle); myCircle.color = “rgb(23,100, 122)”;
7. Software Modeling Games are naturally event-driven and feature an object-oriented architecture Modules and Types Common types: vector, sprite, fortress, level, weapon, enemy, projectile, … Common modules (singletons): math, world, camera, game, util, ui, input, contact, … How can these be represented in JavaScript?
8. JavaScript Prototypes varc = { x: 0, y: 0, radius: 1, color: black }; var c1 = Object.create(c); c1.x = 3; c1.color = "green"; var c2 = Object.create(c); c1.x = 4; c1.radius = 15; var c3 = Object.create(c); assert(c2.color === "black"); The prototype is NOT a "class" object
9. Shared Behavior in Prototypes varc = { x: 0, y: 0, radius: 1, color: black, area: function () {return this.radius * Math.PI * Math.PI;}, . . . }; Because we don't want separate function copies in each object
10.
11.
12. A Module Pattern <package>.M = (function () { var privatePropertyOrMethod1 = …; … var M = {}; M.publicProperty1 = …; M.publicMethod1 = function (…) {…}; … return M; }()); Already familiar to JavaScript professionals (We just prefer avoiding object literals)
13. Type Pattern <package>.T = (function () { var T = {}; ... T.create = function (…) { vart = Object.create(this); ... return t; } return T; }()); Instantiate with: varx = <package>.T.create(…); The "type" object and the prototype are one! Differs from operator new, which equates the type with the constructor (prototype separate) Shared properties and methods go here Assign the own properties here
14. Root Types <package>.GameObject = (function () { varGameObject = {}; GameObject.GameObject = GameObject; GameObject.create = function (id) { varg = Object.create(this); g.id = id; return g; } GameObject.update = function () { alert("Updating game object " + this.id); } return GameObject; }()); Self reference will allow multiple levels of "super" Of course we are going to override this on the next slide
15. Subtypes <package>.Projectile = (function () { var Projectile = Object.create(<package>.GameObject); Projectile.Projectile = Projectile; Projectile.create = function (id, name) { varp = <package>.GameObject.create.call(this, id); p.name = name; return p; } Projectile.update = function () { // override! this.GameObject.update.call(this); alert("Updating projectile " + this.name); } return Projectile; }()); Note use of "this" instead of the package name – it shows we are using an ancestor type
16. Subtypes, Slightly Cleaner <package>.Projectile = (function (supertype) { var Projectile = Object.create(supertype); Projectile.Projectile = Projectile; Projectile.create = function (id, name) { varp = supertype.create.call(this, id); p.name = name; return p; } Projectile.update = function () { // override! supertype.update.call(this); alert("Updating projectile " + this.name); } return Projectile; }(package.GameObject)); Or mention an ancestor type directly
17. How it all Looks Private data from closures not shown
19. Why is this Useful? No extra scripts to include No framework to learn No need to say "new Base" and ".extend" "Super" functionality is still available if needed Programmer can apply the pattern selectively It's real JavaScript Closures and Function.call are hardcore Maintains prototypal feel, even though class-like Type.create()
20. JavaScript Game Engines The Render Engine Impact Aves (Zynga Germany) Effect Isogenic gameQuery Rocket Engine (acquired by Disney) See engine lists and comparisons at https://github.com/bebraw/jswiki/wiki/Game-Engines and http://www.cssgalleries.com/2011/02/the-big-list-of-javascript-game-engines/
21. Summary Games benefit from an object-oriented, event-driven architecture Many approaches exist for modeling an OO software architecture in JavaScript We presented framework-free, engine independent modeling patterns Patterns were applied in a real HTML5, no-Flash application