diff --git a/Gruntfile.js b/Gruntfile.js index 09b7192c..758fe134 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -11,7 +11,7 @@ module.exports = function (grunt) { compile_dir: 'dist', src: { phaser: [ - 'build/p2.js', + 'build/p2.js', 'src/Intro.js', 'src/pixi/Pixi.js', 'src/Phaser.js', diff --git a/build/p2.js b/build/p2.js index 50b2e2d7..509e018d 100644 --- a/build/p2.js +++ b/build/p2.js @@ -1068,6 +1068,7 @@ Polygon.prototype.getCutEdges = function() { */ Polygon.prototype.decomp = function(){ var edges = this.getCutEdges(); + console.log('decomp', edges); if(edges.length > 0) return this.slice(edges); else diff --git a/examples/wip/graphics.js b/examples/wip/graphics.js new file mode 100644 index 00000000..f7a82dc6 --- /dev/null +++ b/examples/wip/graphics.js @@ -0,0 +1,69 @@ +var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { create: create, update: update }); + +var graphics; +var sprite; + +function create() { + + graphics = game.add.graphics(0, 0); + // we don't need it to render, we're just using it as a texture + graphics.visible = false; + + // set a fill and line style + graphics.beginFill(0xFF3300); + graphics.lineStyle(10, 0xffd900, 1); + + // draw a shape + graphics.moveTo(0,50); + graphics.lineTo(250, 50); + graphics.lineTo(100, 100); + graphics.lineTo(250, 220); + graphics.lineTo(50, 220); + graphics.lineTo(0, 50); + graphics.endFill(); + + // set a fill and line style again + graphics.lineStyle(10, 0xFF0000, 0.8); + graphics.beginFill(0xFF700B, 1); + + // draw a second shape + graphics.moveTo(210,300); + graphics.lineTo(450,320); + graphics.lineTo(570,350); + graphics.lineTo(580,20); + graphics.lineTo(330,120); + graphics.lineTo(410,200); + graphics.lineTo(210,300); + graphics.endFill(); + + // draw a rectangle + graphics.lineStyle(2, 0x0000FF, 1); + graphics.drawRect(50, 250, 100, 100); + + sprite = game.add.sprite(100, 100, graphics.generateTexture()); + + // graphics.inputEnabled = true; + // graphics.events.onInputDown.add(clicked, this); + +} + +function clicked() { + + console.log('boom'); + + // draw a circle + graphics.lineStyle(0); + graphics.beginFill(0xFFFF0B, 0.5); + graphics.drawCircle(470, 200,100); + + graphics.lineStyle(20, 0x33FF00); + graphics.moveTo(30,30); + graphics.lineTo(600, 300); + +} + +function update() { + + + +} \ No newline at end of file diff --git a/examples/wip/tilemap1.js b/examples/wip/tilemap1.js index b7e746ee..1aa30616 100644 --- a/examples/wip/tilemap1.js +++ b/examples/wip/tilemap1.js @@ -9,19 +9,23 @@ function preload() { game.load.image('walls_1x2', 'assets/tilemaps/tiles/walls_1x2.png'); game.load.image('tiles2', 'assets/tilemaps/tiles/tiles2.png'); game.load.image('player', 'assets/sprites/phaser-dude.png'); + game.load.image('box', 'assets/sprites/ufo.png'); + game.load.image('ship', 'assets/sprites/thrust_ship2.png'); } +var ship; var map; var tileset; var layer; var p; var b; var cursors; +var box2; function create() { - // game.stage.backgroundColor = '#787878'; + game.stage.backgroundColor = '#787878'; map = game.add.tilemap('map'); @@ -29,39 +33,59 @@ function create() { map.addTilesetImage('walls_1x2'); map.addTilesetImage('tiles2'); - // layer = map.createLayer('Tile Layer 1'); + layer = map.createLayer('Tile Layer 1'); + layer.resizeWorld(); - // layer.resizeWorld(); - p = game.add.sprite(32, 32, 'player'); - b = game.add.sprite(600, 400, 'player'); - b.physicsEnabled = true; + + + + ship = game.add.sprite(200, 200, 'ship'); + // ship.physicsEnabled = true; + + + + // p = game.add.sprite(32, 32, 'player'); + + // b = game.add.sprite(300, 300, 'player'); + // b.physicsEnabled = true; + // b.body.static = true; + // b.body.mass = 1; + // b.body.data.motionState = 2; + + // b.body.kinematic = true; // b.body.clearShapes(); - b.body.addLine(32, 0, 0, 0.2); + // b.body.addLine(64, 0, 0, 0); + // b.body.fixedRotation = true; + // b.body.static = true; - var ox = 192; - var oy = 352; - var data = [0,0 , 0, -32 , 32, -64 , 64, -64 , 64,-96, 128,-96, 160,-128, 192,-128, 192,-96, 160,-64, 96,-64, 96,-32, 32,-32, 32,0, 0,0]; - var output = []; + var data = [[0,0] , [0, -32] , [32, -64] , [64, -64] , [64,-96], [128,-96], [160,-128], [192,-128], [192,-96], [160,-64], [96,-64], [96,-32], [32,-32], [32,0]]; - for (var i = 0; i < data.length; i += 2) - { - output.push(ox + data[i]); - output.push(oy + data[i+1]); - } + // "x":192, + // "y":352 - console.log(output); + b = game.physics.createBody(192, 352, 0, true, {}, data); - // var re = b.body.addPolygon({}, output); + // console.log(output); - console.log(data.length); + // var re = b.body.addPolygon({removeCollinearPoints:true}, data); + // var re = b.body.addPolygon({removeCollinearPoints:true}, data); + + // console.log(data.length); // console.log(re); - console.log(output); - console.log(b.body.data.shapes[0].vertices); + // console.log(output); + // console.log(b.body.data.shapes[0].vertices); + box2 = game.add.sprite(200, 200, 'box'); + box2.name = 'bob'; + box2.anchor.set(0.5); + box2.physicsEnabled = true; + // box2.body.mass = 1; + // box2.body.data.motionState = 1; + box2.body.fixedRotation = true; - game.camera.follow(p); + // game.camera.follow(p); cursors = game.input.keyboard.createCursorKeys(); @@ -69,20 +93,71 @@ function create() { function update() { + // if (cursors.left.isDown) + // { + // p.x -= 4; + // } + // else if (cursors.right.isDown) + // { + // p.x += 4; + // } + if (cursors.left.isDown) { - p.x -= 4; + box2.body.moveLeft(400); } else if (cursors.right.isDown) { - p.x += 4; + box2.body.moveRight(400); } + else if (!cursors.left.isDown && !cursors.right.isDown) + { + box2.body.data.force[0] = 0; + } + + if (cursors.up.isDown) + { + box2.body.moveUp(400); + } + else if (cursors.down.isDown) + { + box2.body.moveDown(400); + } + +/* if (cursors.left.isDown) + { + ship.body.rotateLeft(100); + } + else if (cursors.right.isDown) + { + ship.body.rotateRight(100); + } + else + { + ship.body.setZeroRotation(); + } + + if (cursors.up.isDown) + { + ship.body.thrust(400); + } +*/ + } function render() { // game.debug.renderCameraInfo(game.camera, 420, 320); - game.debug.renderPhysicsBody(b.body); + + game.debug.renderText(box2.body.velocity.x, 32, 32); + game.debug.renderText(box2.body.velocity.y, 32, 64); + + // game.debug.renderText(b.body.velocity.x, 32, 32); + // game.debug.renderText(b.body.velocity.y, 32, 64); + + game.debug.renderPhysicsBody(b); + // game.debug.renderPhysicsBody(ship.body); + } diff --git a/src/gameobjects/BitmapText.js b/src/gameobjects/BitmapText.js index da069969..8dd30244 100644 --- a/src/gameobjects/BitmapText.js +++ b/src/gameobjects/BitmapText.js @@ -12,8 +12,8 @@ * @classdesc BitmapText objects work by taking a texture file and an XML file that describes the font layout. * * On Windows you can use the free app BMFont: http://www.angelcode.com/products/bmfont/ -* * On OS X we recommend Glyph Designer: http://www.71squared.com/en/glyphdesigner +* For Web there is the great Littera: http://kvazars.com/littera/ * * @constructor * @param {Phaser.Game} game - A reference to the currently running game. diff --git a/src/gameobjects/Graphics.js b/src/gameobjects/Graphics.js index af9dc12f..0c88d7e8 100644 --- a/src/gameobjects/Graphics.js +++ b/src/gameobjects/Graphics.js @@ -47,16 +47,6 @@ Phaser.Graphics = function (game, x, y) { */ this.world = new Phaser.Point(x, y); - /** - * @property {Phaser.Events} events - The Events you can subscribe to that are dispatched when certain things happen on this Sprite or its components. - */ - this.events = new Phaser.Events(this); - - /** - * @property {Phaser.InputHandler|null} input - The Input Handler for this object. Needs to be enabled with image.inputEnabled = true before you can use it. - */ - this.input = null; - /** * @property {Phaser.Point} cameraOffset - If this object is fixedToCamera then this stores the x/y offset that its drawn at, from the top-left of the camera view. */ @@ -202,42 +192,6 @@ Object.defineProperty(Phaser.Graphics.prototype, 'angle', { }); -/** -* By default a Graphics object won't process any input events at all. By setting inputEnabled to true the Phaser.InputHandler is -* activated for this object and it will then start to process click/touch events and more. -* -* @name Phaser.Graphics#inputEnabled -* @property {boolean} inputEnabled - Set to true to allow this object to receive input events. -*/ -Object.defineProperty(Phaser.Graphics.prototype, "inputEnabled", { - - get: function () { - - return (this.input && this.input.enabled); - - }, - - set: function (value) { - - if (value) - { - if (this.input === null) - { - this.input = new Phaser.InputHandler(this); - this.input.start(); - } - } - else - { - if (this.input && this.input.enabled) - { - this.input.stop(); - } - } - } - -}); - /** * An Graphics that is fixed to the camera uses its x/y coordinates as offsets from the top left of the camera. These are stored in Graphics.cameraOffset. * Note that the cameraOffset values are in addition to any parent in the display list. diff --git a/src/gameobjects/Sprite.js b/src/gameobjects/Sprite.js index ed1d4a81..7e100c84 100644 --- a/src/gameobjects/Sprite.js +++ b/src/gameobjects/Sprite.js @@ -854,7 +854,7 @@ Object.defineProperty(Phaser.Sprite.prototype, "physicsEnabled", { { if (this.body === null) { - this.body = new Phaser.Physics.Body(this); + this.body = new Phaser.Physics.Body(this.game, this, this.x, this.y, 1); this.anchor.set(0.5); } } diff --git a/src/physics/Body.js b/src/physics/Body.js index 927cb7a2..5630f162 100644 --- a/src/physics/Body.js +++ b/src/physics/Body.js @@ -5,7 +5,7 @@ */ /** -* The Physics Body is linked to a single Sprite and defines properties that determine how the physics body is simulated. +* The Physics Body is typically linked to a single Sprite and defines properties that determine how the physics body is simulated. * These properties affect how the body reacts to forces, what forces it generates on itself (to simulate friction), and how it reacts to collisions in the scene. * In most cases, the properties are used to simulate physical effects. Each body also has its own property values that determine exactly how it reacts to forces and collisions in the scene. * By default a single Rectangle shape is added to the Body that matches the dimensions of the parent Sprite. See addShape, removeShape, clearShapes to add extra shapes around the Body. @@ -13,20 +13,29 @@ * @class Phaser.Physics.Body * @classdesc Physics Body Constructor * @constructor -* @param {Phaser.Sprite} sprite - The Sprite object this physics body belongs to. +* @param {Phaser.Game} game - Game reference to the currently running game. +* @param {Phaser.Sprite} [sprite] - The Sprite object this physics body belongs to. +* @param {number} [x=0] - The x coordinate of this Body. +* @param {number} [y=0] - The y coordinate of this Body. +* @param {number} [mass=1] - The default mass of this Body (0 = static). */ -Phaser.Physics.Body = function (sprite) { +Phaser.Physics.Body = function (game, sprite, x, y, mass) { + + sprite = sprite || null; + x = x || 0; + y = y || 0; + if (typeof mass === 'undefined') { mass = 1; } + + /** + * @property {Phaser.Game} game - Local reference to game. + */ + this.game = game; /** * @property {Phaser.Sprite} sprite - Reference to the parent Sprite. */ this.sprite = sprite; - /** - * @property {Phaser.Game} game - Local reference to game. - */ - this.game = sprite.game; - /** * @property {Phaser.Point} offset - The offset of the Physics Body from the Sprite x/y position. */ @@ -36,7 +45,7 @@ Phaser.Physics.Body = function (sprite) { * @property {p2.Body} data - The p2 Body data. * @protected */ - this.data = new p2.Body({ position:[this.px2p(sprite.position.x), this.px2p(sprite.position.y)], mass: 1 }); + this.data = new p2.Body({ position:[this.px2p(x), this.px2p(y)], mass: mass }); this.data.parent = this; /** @@ -53,9 +62,11 @@ Phaser.Physics.Body = function (sprite) { // this.onRemoved = new Phaser.Signal(); // Set-up the default shape - this.setRectangleFromSprite(sprite); - - this.game.physics.addBody(this.data); + if (sprite) + { + this.setRectangleFromSprite(sprite); + this.game.physics.addBody(this.data); + } }; @@ -220,7 +231,8 @@ Phaser.Physics.Body.prototype = { */ moveLeft: function (speed) { - this.data.velocity[0] = this.px2p(-speed); + // this.data.velocity[0] = this.px2p(-speed); + this.data.force[0] += this.px2p(-speed); }, @@ -233,7 +245,8 @@ Phaser.Physics.Body.prototype = { */ moveRight: function (speed) { - this.data.velocity[0] = this.px2p(speed); + // this.data.velocity[0] = this.px2p(speed); + this.data.force[0] += this.px2p(speed); }, @@ -246,7 +259,8 @@ Phaser.Physics.Body.prototype = { */ moveUp: function (speed) { - this.data.velocity[1] = this.px2p(-speed); + // this.data.velocity[1] = this.px2p(-speed); + this.data.force[1] += this.px2p(-speed); }, @@ -259,7 +273,8 @@ Phaser.Physics.Body.prototype = { */ moveDown: function (speed) { - this.data.velocity[1] = this.px2p(speed); + // this.data.velocity[1] = this.px2p(speed); + this.data.force[1] += this.px2p(speed); }, @@ -744,10 +759,16 @@ Object.defineProperty(Phaser.Physics.Body.prototype, "static", { if (value && this.data.motionState !== Phaser.STATIC) { this.data.motionState = Phaser.STATIC; + this.mass = 0; } else if (!value && this.data.motionState === Phaser.STATIC) { this.data.motionState = Phaser.DYNAMIC; + + if (this.mass === 0) + { + this.mass = 1; + } } } @@ -771,10 +792,16 @@ Object.defineProperty(Phaser.Physics.Body.prototype, "dynamic", { if (value && this.data.motionState !== Phaser.DYNAMIC) { this.data.motionState = Phaser.DYNAMIC; + + if (this.mass === 0) + { + this.mass = 1; + } } else if (!value && this.data.motionState === Phaser.DYNAMIC) { this.data.motionState = Phaser.STATIC; + this.mass = 0; } } @@ -802,6 +829,7 @@ Object.defineProperty(Phaser.Physics.Body.prototype, "kinematic", { else if (!value && this.data.motionState === Phaser.KINEMATIC) { this.data.motionState = Phaser.STATIC; + this.mass = 0; } } @@ -999,6 +1027,11 @@ Object.defineProperty(Phaser.Physics.Body.prototype, "mass", { { this.data.mass = value; this.data.updateMassProperties(); + + if (value === 0) + { + // this.static = true; + } } } diff --git a/src/physics/World.js b/src/physics/World.js index 86dada14..863f2778 100644 --- a/src/physics/World.js +++ b/src/physics/World.js @@ -232,3 +232,37 @@ Phaser.Physics.World.prototype.destroy = function () { this.game = null; }; + +/** +* @method Phaser.Physics.World.prototype.createBody +* @param {number} x - The x coordinate of Body. +* @param {number} y - The y coordinate of Body. +* @param {number} mass - The mass of the Body. A mass of 0 means a 'static' Body is created. +* @param {boolean} [addToWorld=false] - Automatically add this Body to the world? (usually false as it won't have any shapes on construction). +* @param {object} options - An object containing the build options: +* @param {boolean} [options.optimalDecomp=false] - Set to true if you need optimal decomposition. Warning: very slow for polygons with more than 10 vertices. +* @param {boolean} [options.skipSimpleCheck=false] - Set to true if you already know that the path is not intersecting itself. +* @param {boolean|number} [options.removeCollinearPoints=false] - Set to a number (angle threshold value) to remove collinear points, or false to keep all points. +* @param {(number[]|...number)} points - An array of 2d vectors that form the convex or concave polygon. +* Either [[0,0], [0,1],...] or a flat array of numbers that will be interpreted as [x,y, x,y, ...], +* or the arguments passed can be flat x,y values e.g. `setPolygon(options, x,y, x,y, x,y, ...)` where `x` and `y` are numbers. +*/ +Phaser.Physics.World.prototype.createBody = function (x, y, mass, addToWorld, options, data) { + + if (typeof addToWorld === 'undefined') { addToWorld = false; } + + var body = new Phaser.Physics.Body(this.game, null, x, y, mass); + + if (data) + { + body.addPolygon(options, data); + } + + if (addToWorld) + { + this.addBody(body.data); + } + + return body; + +}; diff --git a/src/utils/Debug.js b/src/utils/Debug.js index 05a19d4a..9a1a8b9d 100644 --- a/src/utils/Debug.js +++ b/src/utils/Debug.js @@ -712,14 +712,29 @@ Phaser.Utils.Debug.prototype = { this.start(0, 0, color); - var i = body.data.shapes.length; + var shapes = body.data.shapes; + var shapeOffsets = body.data.shapeOffsets; + var shapeAngles = body.data.shapeAngles; + + var i = shapes.length; var x = this.game.math.p2px(body.data.position[0]); var y = this.game.math.p2px(body.data.position[1]); var angle = body.data.angle; while (i--) { - this.renderShape(body.data.shapes[i], x, y, angle); + if (shapes[i] instanceof p2.Rectangle) + { + this.renderShapeRectangle(shapes[i], x, y, angle); + } + else if (shapes[i] instanceof p2.Line) + { + this.renderShapeLine(x, y, shapes[i], shapeOffsets[i], shapeAngles[i]); + } + else if (shapes[i] instanceof p2.Convex) + { + this.renderShapeConvex(x, y, shapes[i], shapeOffsets[i], shapeAngles[i]); + } } this.stop(); @@ -733,7 +748,7 @@ Phaser.Utils.Debug.prototype = { * @param {number} y - The y coordinate of the Body to translate to. * @param {number} angle - The angle of the Body to rotate to. */ - renderShape: function (shape, x, y, angle) { + renderShapeRectangle: function (shape, x, y, angle) { var w = this.game.math.p2px(shape.width); var h = this.game.math.p2px(shape.height); @@ -756,6 +771,64 @@ Phaser.Utils.Debug.prototype = { this.context.stroke(); this.context.restore(); + }, + + /** + * @method Phaser.Utils.Debug#renderShape + * @param {number} x - The x coordinate of the Body to translate to. + * @param {number} y - The y coordinate of the Body to translate to. + * @param {p2.Shape} shape - The shape to render. + * @param {number} offset - + * @param {number} angle - + */ + renderShapeLine: function (x, y, shape, offset, angle) { + + // var w = this.game.math.p2px(shape.width); + // var h = this.game.math.p2px(shape.height); + // var points = shape.vertices; + + this.context.beginPath(); + this.context.save(); + this.context.translate(x, y); + this.context.rotate(angle); + this.context.lineWidth = 0.5; + // this.context.moveTo(this.game.math.p2px(points[0][0]), this.game.math.p2px(points[0][1])); + this.context.moveTo(0, 0); + this.context.lineTo(this.game.math.p2px(shape.length), 0); + this.context.closePath(); + this.context.stroke(); + this.context.restore(); + + }, + + /** + * @method Phaser.Utils.Debug#renderShape + * @param {p2.Shape} shape - The shape to render. + * @param {number} x - The x coordinate of the Body to translate to. + * @param {number} y - The y coordinate of the Body to translate to. + * @param {number} angle - The angle of the Body to rotate to. + */ + renderShapeConvex: function (x, y, shape, offset, angle) { + + var points = shape.vertices; + + this.context.beginPath(); + this.context.save(); + this.context.translate(x + this.game.math.p2px(offset[0]), y + this.game.math.p2px(offset[1])); + this.context.rotate(angle); + this.context.lineWidth = 0.5; + + this.context.moveTo(this.game.math.p2px(points[0][0]), this.game.math.p2px(points[0][1])); + + for (var i = 1; i < points.length; i++) + { + this.context.lineTo(this.game.math.p2px(points[i][0]), this.game.math.p2px(points[i][1])); + } + + this.context.closePath(); + this.context.stroke(); + this.context.restore(); + } };