diff --git a/Gruntfile.js b/Gruntfile.js index fa13b88a3..5c2c62b7f 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -25,15 +25,16 @@ module.exports = function (grunt) { '* By Richard Davey http://www.photonstorm.com @photonstorm\n' + '*\n' + '* Phaser is a fun, free and fast 2D game framework for making HTML5 games \n' + -'* for desktop and mobile web browsers, supporting Canvas and WebGL rendering.\n' + +'* for desktop and mobile web browsers, supporting Canvas and WebGL.\n' + '*\n' + '* Phaser uses Pixi.js for rendering, created by Mat Groves http://matgroves.com @Doormat23\n' + -'* Phaser uses p2.js for physics, created by Stefan Hedman https://github.com/schteppe/p2.js @schteppe\n' + +'* Phaser uses p2.js for full-body physics, created by Stefan Hedman https://github.com/schteppe/p2.js @schteppe\n' + +'* Phaser contains a port of N+ Physics, converted by Richard Davey, original by http://www.metanetsoftware.com\n' + '*\n' + '* Many thanks to Adam Saltsman (@ADAMATOMIC) for releasing Flixel, from which both Phaser\n' + -'* and my love of framework development originate.\n' + +'* and my love of framework development can be traced.\n' + '*\n' + -'* Follow Phaser development progress at http://phaser.io\n' + +'* Follow development at http://phaser.io and on our forum\n' + '*\n' + '* "If you want your children to be intelligent, read them fairy tales."\n' + '* "If you want them to be more intelligent, read them more fairy tales."\n' + @@ -43,10 +44,6 @@ module.exports = function (grunt) { release_dir: 'build', compile_dir: 'dist', - p2: [ - 'src/p2.js' - ], - pixi: [ 'src/pixi/Intro.js', 'src/pixi/Pixi.js', @@ -186,21 +183,6 @@ module.exports = function (grunt) { 'src/physics/arcade/World.js', 'src/physics/arcade/Body.js', - 'src/physics/ninja/World.js', - 'src/physics/ninja/Body.js', - 'src/physics/ninja/AABB.js', - 'src/physics/ninja/Tile.js', - 'src/physics/ninja/Circle.js', - - 'src/physics/p2/World.js', - 'src/physics/p2/PointProxy.js', - 'src/physics/p2/InversePointProxy.js', - 'src/physics/p2/Body.js', - 'src/physics/p2/Spring.js', - 'src/physics/p2/Material.js', - 'src/physics/p2/ContactMaterial.js', - 'src/physics/p2/CollisionGroup.js', - 'src/particles/Particles.js', 'src/particles/arcade/ArcadeParticles.js', 'src/particles/arcade/Emitter.js', @@ -214,6 +196,26 @@ module.exports = function (grunt) { 'src/Outro.js' ], + p2: [ + 'src/physics/p2/p2.js' + 'src/physics/p2/World.js', + 'src/physics/p2/PointProxy.js', + 'src/physics/p2/InversePointProxy.js', + 'src/physics/p2/Body.js', + 'src/physics/p2/Spring.js', + 'src/physics/p2/Material.js', + 'src/physics/p2/ContactMaterial.js', + 'src/physics/p2/CollisionGroup.js', + ], + + ninja: [ + 'src/physics/ninja/World.js', + 'src/physics/ninja/Body.js', + 'src/physics/ninja/AABB.js', + 'src/physics/ninja/Tile.js', + 'src/physics/ninja/Circle.js', + ], + clean: ['<%= compile_dir %>'], concat: { @@ -230,7 +232,13 @@ module.exports = function (grunt) { dest: '<%= compile_dir %>/pixi.js' }, - // Phaser, stand-alone (no bundled libs) + // Our custom version of Ninja Physics + ninja: { + src: ['<%= ninja %>'], + dest: '<%= compile_dir %>/ninja.js' + }, + + // Phaser with no bundled libs phaser: { options: { banner: '<%= banner %>' @@ -244,7 +252,7 @@ module.exports = function (grunt) { options: { banner: '<%= banner %>' }, - src: ['<%= compile_dir %>/p2.js', '<%= compile_dir %>/pixi.js', '<%= compile_dir %>/phaser-no-libs.js'], + src: ['<%= compile_dir %>/pixi.js', '<%= compile_dir %>/phaser-no-libs.js', '<%= compile_dir %>/ninja.js', '<%= compile_dir %>/p2.js'], dest: '<%= compile_dir %>/phaser.js' } @@ -268,6 +276,14 @@ module.exports = function (grunt) { dest: '<%= compile_dir %>/pixi.min.js' }, + ninja: { + options: { + banner: '/* Ninja Physics for Phaser v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' + }, + src: ['<%= concat.ninja.dest %>'], + dest: '<%= compile_dir %>/ninja.min.js' + }, + phaser: { options: { banner: '/* Phaser (no libs) v<%= pkg.version %> - http://phaser.io - @photonstorm - (c) 2014 Photon Storm Ltd. */\n' @@ -301,6 +317,8 @@ module.exports = function (grunt) { { src: ['dist/phaser-no-libs.min.js'], dest: 'build/custom/phaser-no-libs.min.js' }, { src: ['dist/pixi.js'], dest: 'build/custom/pixi.js' }, { src: ['dist/pixi.min.js'], dest: 'build/custom/pixi.min.js' } + { src: ['dist/ninja.js'], dest: 'build/custom/ninja.js' }, + { src: ['dist/ninja.min.js'], dest: 'build/custom/ninja.min.js' } ] } }, diff --git a/README.md b/README.md index fc17b8537..cb1a5cdee 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ New features: * Group.xy(index, x, y) allows you to set the x and y coordinates of a Group child at the given index. * Group.reverse() reverses the display order of all children in the Group. * Tweens are now bound to their own TweenManager, not always the global game one. So you can create your own managers now (for you clark :) -* json is now the default tilemap format when not defined (thanks RyanDansie, #528) +* ScaleManager.fullScreenTarget allows you to change the DOM element that the fullscreen API is called on (feature request #526) Updates: @@ -175,6 +175,7 @@ Updates: * Keyboard.event now stores the most recent DOM keyboard event. * Animation.stop has a new parameter: dispatchComplete. If true it'll dispatch an Animation.onComplete event. * TileSprites now have a physics body property and call it in the pre and post updates. As with all physics bodies it's null by default. +* json is now the default tilemap format when not defined (thanks RyanDansie, #528) Bug Fixes: diff --git a/build/config.php b/build/config.php index aea27a63a..47f2ea798 100644 --- a/build/config.php +++ b/build/config.php @@ -6,7 +6,7 @@ echo << + diff --git a/src/core/ScaleManager.js b/src/core/ScaleManager.js index 4bfcc266e..0e36e9640 100644 --- a/src/core/ScaleManager.js +++ b/src/core/ScaleManager.js @@ -120,6 +120,14 @@ Phaser.ScaleManager = function (game, width, height) { */ this.hasResized = new Phaser.Signal(); + /** + * This is the DOM element that will have the Full Screen mode called on it. It defaults to the game canvas, but can be retargetted to any valid DOM element. + * If you adjust this property it's up to you to see it has the correct CSS applied, and that you have contained the game canvas correctly. + * Note that if you use a scale property of EXACT_FIT then fullScreenTarget will have its width and height style set to 100%. + * @property {any} fullScreenTarget + */ + this.fullScreenTarget = this.game.canvas; + /** * @property {Phaser.Signal} enterFullScreen - The event that is dispatched when the browser enters full screen mode (if it supports the FullScreen API). */ @@ -277,11 +285,11 @@ Phaser.ScaleManager.prototype = { if (this.game.device.fullscreenKeyboard) { - this.game.canvas[this.game.device.requestFullscreen](Element.ALLOW_KEYBOARD_INPUT); + this.fullScreenTarget[this.game.device.requestFullscreen](Element.ALLOW_KEYBOARD_INPUT); } else { - this.game.canvas[this.game.device.requestFullscreen](); + this.fullScreenTarget[this.game.device.requestFullscreen](); } }, @@ -292,7 +300,7 @@ Phaser.ScaleManager.prototype = { */ stopFullScreen: function () { - this.game.canvas[this.game.device.cancelFullscreen](); + this.fullScreenTarget[this.game.device.cancelFullscreen](); }, @@ -310,8 +318,8 @@ Phaser.ScaleManager.prototype = { { if (this.fullScreenScaleMode === Phaser.ScaleManager.EXACT_FIT) { - this.game.canvas.style['width'] = '100%'; - this.game.canvas.style['height'] = '100%'; + this.fullScreenTarget.style['width'] = '100%'; + this.fullScreenTarget.style['height'] = '100%'; this.width = window.outerWidth; this.height = window.outerHeight; @@ -334,8 +342,8 @@ Phaser.ScaleManager.prototype = { } else { - this.game.canvas.style['width'] = this.game.width + 'px'; - this.game.canvas.style['height'] = this.game.height + 'px'; + this.fullScreenTarget.style['width'] = this.game.width + 'px'; + this.fullScreenTarget.style['height'] = this.game.height + 'px'; this.width = this._width; this.height = this._height; diff --git a/src/p2.js b/src/physics/p2/p2.js similarity index 99% rename from src/p2.js rename to src/physics/p2/p2.js index cfd12f507..51ce51167 100644 --- a/src/p2.js +++ b/src/physics/p2/p2.js @@ -1953,6 +1953,33 @@ function Narrowphase(){ */ this.restitution = 0; + /** + * The stiffness value to use in the next contact equations. + * @property {Number} stiffness + */ + this.stiffness = 1e7; + + /** + * The stiffness value to use in the next contact equations. + * @property {Number} stiffness + */ + this.relaxation = 3; + + /** + * The stiffness value to use in the next friction equations. + * @property frictionStiffness + * @type {Number} + */ + this.frictionStiffness = 1e7; + + /** + * The relaxation value to use in the next friction equations. + * @property frictionRelaxation + * @type {Number} + */ + this.frictionRelaxation = 3; + + // Keep track of the colliding bodies last step this.collidingBodiesLastStep = { keys:[] }; }; @@ -2041,6 +2068,8 @@ Narrowphase.prototype.createContactEquation = function(bodyA,bodyB,shapeA,shapeB c.shapeB = shapeB; c.restitution = this.restitution; c.firstImpact = !this.collidedLastStep(bodyA,bodyB); + c.stiffness = this.stiffness; + c.relaxation = this.relaxation; c.enabled = true; if(bodyA.allowSleep && (bodyA.motionState == Body.DYNAMIC) && !(bodyB.motionState == Body.STATIC || bodyB.sleepState === Body.SLEEPY)) @@ -2068,6 +2097,8 @@ Narrowphase.prototype.createFrictionEquation = function(bodyA,bodyB,shapeA,shape c.frictionCoefficient = this.frictionCoefficient; c.relativeVelocity = this.surfaceVelocity; c.enabled = true; + c.frictionStiffness = this.frictionStiffness; + c.frictionRelaxation = this.frictionRelaxation; return c; }; @@ -5439,8 +5470,8 @@ ContactEquation.prototype.computeB = function(a,b,h){ Gq = 0; GW = (1/b)*(1+this.restitution) * this.computeGW(); } else { - GW = this.computeGW(); Gq = vec2.dot(n,penetrationVec); + GW = this.computeGW(); } var GiMf = this.computeGiMf(); @@ -6946,9 +6977,19 @@ function Body(options){ this.wlambda = 0; /** - * The angle of the body + * The angle of the body, in radians. * @property angle * @type {number} + * @example + * // The angle property is not normalized to the interval 0 to 2*pi, it can be any value. + * // If you need a value between 0 and 2*pi, use the following function to normalize it. + * function normalizeAngle(angle){ + * angle = angle % (2*Math.PI); + * if(angle < 0){ + * angle += (2*Math.PI); + * } + * return angle; + * } */ this.angle = options.angle || 0; @@ -8803,7 +8844,7 @@ GSSolver.prototype.solve = function(h,world){ lambda = this.lambda; if(!useGlobalParams){ for(var i=0, c; c = equations[i]; i++){ - if(h !== c.h) c.updateSpookParams(h); + c.updateSpookParams(h); Bs[i] = c.computeB(c.a,c.b,h); invCs[i] = c.computeInvC(c.eps); } @@ -9465,6 +9506,10 @@ function World(options){ */ this.defaultRestitution = 0.0; + this.defaultMaterial = new Material(); + + this.defaultContactMaterial = new ContactMaterial(this.defaultMaterial,this.defaultMaterial); + /** * For keeping track of what time step size we used last step * @property lastTimeStep @@ -9863,20 +9908,26 @@ World.prototype.internalStep = function(dt){ xj = bj.shapeOffsets[l], aj = bj.shapeAngles[l]; + /* var mu = this.defaultFriction, restitution = this.defaultRestitution, surfaceVelocity = 0; + */ + var cm = this.defaultContactMaterial; if(si.material && sj.material){ - var cm = this.getContactMaterial(si.material,sj.material); - if(cm){ + var tmp = this.getContactMaterial(si.material,sj.material); + if(tmp){ + cm = tmp; + /* mu = cm.friction; restitution = cm.restitution; surfaceVelocity = cm.surfaceVelocity; + */ } } - this.runNarrowphase(np,bi,si,xi,ai,bj,sj,xj,aj,mu,restitution,surfaceVelocity,glen); + this.runNarrowphase(np,bi,si,xi,ai,bj,sj,xj,aj,cm,glen); } } } @@ -10031,7 +10082,7 @@ World.integrateBody = function(body,dt){ * @param {Number} aj * @param {Number} mu */ -World.prototype.runNarrowphase = function(np,bi,si,xi,ai,bj,sj,xj,aj,mu,restitution,surfaceVelocity,glen){ +World.prototype.runNarrowphase = function(np,bi,si,xi,ai,bj,sj,xj,aj,cm,glen){ /* mu,restitution,surfaceVelocity */ if(!((si.collisionGroup & sj.collisionMask) !== 0 && (sj.collisionGroup & si.collisionMask) !== 0)) return; @@ -10051,8 +10102,8 @@ World.prototype.runNarrowphase = function(np,bi,si,xi,ai,bj,sj,xj,aj,mu,restitut var ajw = aj + bj.angle; // Run narrowphase - np.enableFriction = mu > 0; - np.frictionCoefficient = mu; + np.enableFriction = cm.friction > 0; + np.frictionCoefficient = cm.friction; var reducedMass; if(bi.motionState == Body.STATIC || bi.motionState == Body.KINEMATIC) reducedMass = bj.mass; @@ -10060,9 +10111,13 @@ World.prototype.runNarrowphase = function(np,bi,si,xi,ai,bj,sj,xj,aj,mu,restitut reducedMass = bi.mass; else reducedMass = (bi.mass*bj.mass)/(bi.mass+bj.mass); - np.slipForce = mu*glen*reducedMass; - np.restitution = restitution; - np.surfaceVelocity = surfaceVelocity; + np.slipForce = cm.friction*glen*reducedMass; + np.restitution = cm.restitution; + np.surfaceVelocity = cm.surfaceVelocity; + np.frictionStiffness = cm.frictionStiffness; + np.frictionRelaxation = cm.frictionRelaxation; + np.stiffness = cm.stiffness; + np.relaxation = cm.relaxation; var resolver = np[si.type | sj.type], numContacts = 0;