From 5b85c910cb63b097dd488ee927a78cd54d8afbeb Mon Sep 17 00:00:00 2001 From: photonstorm Date: Tue, 28 Jan 2014 17:13:07 +0000 Subject: [PATCH] New lineIntersectLine() function working nicely. --- examples/wip/create map polygon.js | 174 +++++++++++++++++++++ examples/wip/line intersection.js | 225 ++++++++++++++++++++++++++++ examples/wip/platform.js | 14 +- examples/wip/tilemap poly.js | 105 +++++++++++++ src/physics/arcade/ArcadePhysics.js | 4 +- src/physics/arcade/Body.js | 47 +++--- src/tilemap/Tile.js | 5 + src/utils/Debug.js | 7 + 8 files changed, 555 insertions(+), 26 deletions(-) create mode 100644 examples/wip/create map polygon.js create mode 100644 examples/wip/line intersection.js create mode 100644 examples/wip/tilemap poly.js diff --git a/examples/wip/create map polygon.js b/examples/wip/create map polygon.js new file mode 100644 index 00000000..cccc57a7 --- /dev/null +++ b/examples/wip/create map polygon.js @@ -0,0 +1,174 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }); + +function preload() { + + game.load.tilemap('map', 'assets/tilemaps/maps/platform.json', null, Phaser.Tilemap.TILED_JSON); + game.load.image('platformer_tiles', 'assets/tilemaps/tiles/platformer_tiles.png'); + game.load.spritesheet('gameboy', 'assets/sprites/gameboy_seize_color_40x60.png', 40, 60); + game.load.spritesheet('balls', 'assets/sprites/balls.png', 17, 17); + +} + +var map; +var layer; +var sprite; +var sprite2; +var balls; + +function create() { + + game.stage.backgroundColor = '#124184'; + + map = game.add.tilemap('map'); + + map.addTilesetImage('platformer_tiles'); + + map.setCollisionBetween(21, 53); + + layer = map.createLayer('Tile Layer 1'); + + // layer.debug = true; + + // var mapLayer = map.layers[0]; + + + + // var p = []; + // var direction = 'e'; + + // var x = 0; + // var y = 0; + + // for (var y = 0, h = mapLayer.height; y < h; y++) + // { + // for (var x = 0, w = mapLayer.width; x < w; x++) + // { + // var tile = mapLayer.data[y][x]; + + // if (tile) + // { + // if (tile.faceTop) + // tile.faceTop = false; + // tile.faceBottom = false; + // tile.faceLeft = false; + // tile.faceRight = false; + // } + // } + // } + + // sprite = game.add.sprite(270, 100, 'gameboy', 0); + // sprite.name = 'red'; + // sprite.body.collideWorldBounds = true; + // sprite.body.minBounceVelocity = 0.9; + // sprite.body.bounce.setTo(0.5, 0.9); + // sprite.body.friction = 0.5; + +} + + + +/*--------------------------------------------------------------------------- +Returns an Object with the following properties: +intersects -Boolean indicating if an intersection exists. +start_inside -Boolean indicating if Point A is inside of the polygon. +end_inside -Boolean indicating if Point B is inside of the polygon. +intersections -Array of intersection Points along the polygon. +centroid -A Point indicating "center of mass" of the polygon. + +"pArry" is an Array of Points. +----------------------------------------------------------------------------*/ +function lineIntersectPoly(A : Point, B : Point, pArry:Array):Object { + var An:int=1; + var Bn:int=1; + var C:Point; + var D:Point; + var i:Point; + var cx:Number=0; + var cy:Number=0; + var result:Object = new Object(); + var pa:Array=pArry.slice(); //Copy to prevent growing points when connecting ends. + pa.push(pa[0]); //Create line from last Point to beginning Point + result.intersects = false; + result.intersections=[]; + result.start_inside=false; + result.end_inside=false; + var n:int=pa.length-1; + while(n > -1){ + C=Point(pa[n]); + if(n > 0){ + cx+=C.x; + cy+=C.y; + D=Point(pa[n-1])||Point(pa[0]); + i=lineIntersectLine(A,B,C,D); + if(i != null){ + result.intersections.push(i); + } + if(lineIntersectLine(A,new Point(C.x+D.x,A.y),C,D) != null){ + An++; + } + if(lineIntersectLine(B,new Point(C.x+D.x,B.y),C,D) != null){ + Bn++; + } + } + n--; + } + if(An % 2 == 0){ + result.start_inside=true; + } + if(Bn % 2 == 0){ + result.end_inside=true; + } + result.centroid=new Point(cx/(pa.length-1),cy/(pa.length-1)); + result.intersects = result.intersections.length > 0; + return result; +} + + + + + + +function launch() { + + // sprite.body.velocity.x = -200; + // sprite.body.velocity.y = -200; + + sprite2.body.velocity.x = -200; + sprite2.body.velocity.y = -200; + +} + +function update() { + + // game.physics.collide(balls, layer); + // game.physics.collide(sprite, layer); + // game.physics.collide(sprite2, layer); + // game.physics.collide(sprite, sprite2); + +} + +function render() { + + // game.debug.renderBodyInfo(sprite2, 32, 32); + // game.debug.renderPhysicsBody(sprite2.body); + + + // game.debug.renderText(sprite2.body.left, 32, 30); + // game.debug.renderText(sprite2.body.right, 32, 50); + // game.debug.renderText(sprite2.body.top, 32, 70); + // game.debug.renderText(sprite2.body.bottom, 32, 90); + + + // for (var i = 0; i < balls._container.length; i++) + // { + + // } + + // if (sprite) + // { + // // game.debug.renderBodyInfo(sprite, 20, 30); + // game.debug.renderBodyInfo(sprite2, 20, 230); + // } + +} \ No newline at end of file diff --git a/examples/wip/line intersection.js b/examples/wip/line intersection.js new file mode 100644 index 00000000..b2278478 --- /dev/null +++ b/examples/wip/line intersection.js @@ -0,0 +1,225 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render }); + +function preload() { + + game.load.spritesheet('balls', 'assets/sprites/balls.png', 17, 17); + +} + +var lineA1; +var lineA2; +var lineB1; +var lineB2; + + +function create() { + + game.stage.backgroundColor = '#124184'; + + lineA1 = game.add.sprite(100, 100, 'balls', 0); + lineA1.inputEnabled = true; + lineA1.input.enableDrag(true); + + lineA2 = game.add.sprite(400, 300, 'balls', 0); + lineA2.inputEnabled = true; + lineA2.input.enableDrag(true); + + lineB1 = game.add.sprite(300, 300, 'balls', 1); + lineB1.inputEnabled = true; + lineB1.input.enableDrag(true); + + lineB2 = game.add.sprite(500, 500, 'balls', 1); + lineB2.inputEnabled = true; + lineB2.input.enableDrag(true); + + +} + + + +/*--------------------------------------------------------------------------- +Returns an Object with the following properties: +intersects -Boolean indicating if an intersection exists. +start_inside -Boolean indicating if Point A is inside of the polygon. +end_inside -Boolean indicating if Point B is inside of the polygon. +intersections -Array of intersection Points along the polygon. +centroid -A Point indicating "center of mass" of the polygon. + +"pArry" is an Array of Points. +----------------------------------------------------------------------------*/ + +// a = point +// b = point +// pArry = polygons array + +/* +function lineIntersectPoly(A, B, pArry) { + + var An =1; + var Bn =1; + var C = {x: 0, y: 0}; + var D = {x: 0, y: 0}; + var i = {x: 0, y: 0}; + var cx=0; + var cy=0; + var result = {}; + + var pa = pArry.slice(); //Copy to prevent growing points when connecting ends. + pa.push(pa[0]); //Create line from last Point to beginning Point + + result.intersects = false; + result.intersections=[]; + result.start_inside=false; + result.end_inside=false; + + var n = pa.length-1; + + while(n > -1){ + + C.x = pa[n].x; + C.y = pa[n].y; + + if(n > 0){ + + cx+=C.x; + cy+=C.y; + + D=Point(pa[n-1])||Point(pa[0]); + + i=lineIntersectLine(A,B,C,D); + + if(i != null){ + result.intersections.push(i); + } + if(lineIntersectLine(A,new Point(C.x+D.x,A.y),C,D) != null){ + An++; + } + if(lineIntersectLine(B,new Point(C.x+D.x,B.y),C,D) != null){ + Bn++; + } + } + n--; + } + if(An % 2 == 0){ + result.start_inside=true; + } + if(Bn % 2 == 0){ + result.end_inside=true; + } + result.centroid=new Point(cx/(pa.length-1),cy/(pa.length-1)); + result.intersects = result.intersections.length > 0; + return result; +} +*/ + +//--------------------------------------------------------------- +//Checks for intersection of Segment if as_seg is true. +//Checks for intersection of Line if as_seg is false. +//Return intersection of Segment AB and Segment EF as a Point +//Return null if there is no intersection +//--------------------------------------------------------------- + + +// a, b, e, f = point +// as_seg = bool (true) +// returns point + +// Adapted from code by Keith Hair +function lineIntersectLine(A, B, E, F, as_seg) { + + var ip = { x: 0, y: 0 }; + var a1 = B.y - A.y; + var a2 = F.y - E.y; + var b1 = A.x - B.x; + var b2 = E.x - F.x; + var c1 = (B.x * A.y) - (A.x * B.y); + var c2 = (F.x * E.y) - (E.x * F.y); + var denom = (a1 * b2) - (a2 * b1); + + if (denom === 0) + { + return null; + } + + ip.x = ((b1 * c2) - (b2 * c1)) / denom; + ip.y = ((a2 * c1) - (a1 * c2)) / denom; + + //--------------------------------------------------- + //Do checks to see if intersection to endpoints + //distance is longer than actual Segments. + //Return null if it is with any. + //--------------------------------------------------- + if (as_seg) + { + if (Math.pow((ip.x - B.x) + (ip.y - B.y), 2) > Math.pow((A.x - B.x) + (A.y - B.y), 2)) + { + return null; + } + + if (Math.pow((ip.x - A.x) + (ip.y - A.y), 2) > Math.pow((A.x - B.x) + (A.y - B.y), 2)) + { + return null; + } + + if (Math.pow((ip.x - F.x) + (ip.y - F.y), 2) > Math.pow((E.x - F.x) + (E.y - F.y), 2)) + { + return null; + } + + if (Math.pow((ip.x - E.x) + (ip.y - E.y), 2) > Math.pow((E.x - F.x) + (E.y - F.y), 2)) + { + return null; + } + } + + return ip; + +} + + + +var c = 'rgb(255,255,255)'; +var p = new Phaser.Point(); + +function update() { + + p = lineIntersectLine(lineA1.center, lineA2.center, lineB1.center, lineB2.center, true); + + if (p) + { + c = 'rgb(0,255,0)'; + } + else + { + c = 'rgb(255,255,255)'; + } + +} + +function render() { + + game.context.strokeStyle = c; + + game.context.beginPath(); + game.context.moveTo(lineA1.center.x, lineA1.center.y); + game.context.lineTo(lineA2.center.x, lineA2.center.y); + game.context.closePath(); + game.context.stroke(); + + game.context.beginPath(); + game.context.moveTo(lineB1.center.x, lineB1.center.y); + game.context.lineTo(lineB2.center.x, lineB2.center.y); + game.context.closePath(); + game.context.stroke(); + + if (p) + { + game.context.fillStyle = 'rgb(255,0,255)'; + game.context.fillRect(p.x - 2, p.y - 2, 5, 5); + game.debug.renderPointInfo(p, 32, 32); + } + + + +} \ No newline at end of file diff --git a/examples/wip/platform.js b/examples/wip/platform.js index 6b446394..1a95f279 100644 --- a/examples/wip/platform.js +++ b/examples/wip/platform.js @@ -32,6 +32,7 @@ function create() { game.physics.gravity.y = 150; +/* balls = game.add.group(); for (var i = 0; i < 30; i++) @@ -47,13 +48,14 @@ function create() { balls.setAll('body.bounce.y', 0.9); balls.setAll('body.minBounceVelocity', 0.9); balls.setAll('body.friction', 0.5); +*/ sprite2 = game.add.sprite(340, 250, 'gameboy', 2); sprite2.name = 'green'; sprite2.body.collideWorldBounds = true; // sprite2.body.bounce.setTo(0.5, 0.5); - sprite = game.add.sprite(300, 100, 'gameboy', 0); + sprite = game.add.sprite(270, 100, 'gameboy', 0); sprite.name = 'red'; sprite.body.collideWorldBounds = true; sprite.body.minBounceVelocity = 0.9; @@ -85,7 +87,7 @@ var flag = false; function update() { - game.physics.collide(balls, layer); + // game.physics.collide(balls, layer); game.physics.collide(sprite, layer); game.physics.collide(sprite2, layer); game.physics.collide(sprite, sprite2); @@ -95,7 +97,7 @@ function update() { function render() { game.debug.renderBodyInfo(sprite2, 32, 32); - // game.debug.renderPhysicsBody(sprite2.body); + game.debug.renderPhysicsBody(sprite2.body); // game.debug.renderText(sprite2.body.left, 32, 30); @@ -103,6 +105,12 @@ function render() { // game.debug.renderText(sprite2.body.top, 32, 70); // game.debug.renderText(sprite2.body.bottom, 32, 90); + + // for (var i = 0; i < balls._container.length; i++) + // { + + // } + // if (sprite) // { // // game.debug.renderBodyInfo(sprite, 20, 30); diff --git a/examples/wip/tilemap poly.js b/examples/wip/tilemap poly.js new file mode 100644 index 00000000..99f4a442 --- /dev/null +++ b/examples/wip/tilemap poly.js @@ -0,0 +1,105 @@ + +var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, render: render }); + +function preload() { + + game.load.image('phaser', 'assets/sprites/phaser1.png'); + game.load.spritesheet('arrows', 'assets/sprites/arrows.png', 23, 31); + +} + +var arrowStart; +var arrowEnd; +var sprite; + +function create() { + + game.stage.backgroundColor = '#2384e7'; + + // game.physics.setBoundsToWorld(true, true, false, false); + + // arrowStart = game.add.sprite(100, 100, 'arrows', 0); + // arrowEnd = game.add.sprite(400, 100, 'arrows', 1); + + // sprite = game.add.sprite(100, 164, 'phaser'); + sprite = game.add.sprite(300, 364, 'phaser'); + // sprite.anchor.setTo(0.5, 0.5); + sprite.inputEnabled = true; + sprite.body.collideWorldBounds = true; + sprite.body.bounce.setTo(1, 1); + sprite.alpha = 0.2; + + // sprite.body.allowRotation = true; + // sprite.body.polygon.translate(100, 0); + + + // sprite.body.setPolygon([new SAT.Vector(0,0), new SAT.Vector(60, 0), new SAT.Vector(100, 40), new SAT.Vector(60, 80), new SAT.Vector(0, 80)], -50, -40); + + sprite.body.setPolygon([new SAT.Vector(0,50), new SAT.Vector(100, 50), new SAT.Vector(100, 0), new SAT.Vector(150, 0), new SAT.Vector(150, 150), new SAT.Vector(100, 150), new SAT.Vector(100, 100), new SAT.Vector(0, 100), new SAT.Vector(0, 50)], -100, -100); + + + // sprite.body.setCircle(50); + // sprite.body.offset.setTo(50, 50); + + // console.log(sprite.body.x, sprite.body.y, sprite.body.shape.radius); + + sprite.events.onInputDown.add(move, this); + + // sprite.body.polygons.rotate(0.4); + // sprite.rotation = 0.4; + + // console.log(sprite.body.polygons); + +} + +function move() { + + console.log('move'); + + sprite.body.velocity.x = 200; + sprite.body.velocity.y = -200; + // sprite.body.angularVelocity = 2; + + // sprite.rotation = 0.4; + + // console.log(sprite.body.polygon.points); + + // to: function (properties, duration, ease, autoStart, delay, repeat, yoyo) { + + // game.add.tween(sprite).to( { angle: 359 }, 8000, Phaser.Easing.Linear.None, true, 0, 1000, false); + + // sprite.scale.setTo(2, 2); + + if (sprite.x === 100) + { + // Here you'll notice we are using a relative value for the tween. + // You can specify a number as a string with either + or - at the start of it. + // When the tween starts it will take the sprites current X value and add +300 to it. + + // game.add.tween(sprite).to( { x: '+300' }, 2000, Phaser.Easing.Linear.None, true); + } + else if (sprite.x === 400) + { + // game.add.tween(sprite).to( { x: '-300' }, 2000, Phaser.Easing.Linear.None, true); + } + +} + +function render() { + + if (sprite.x === 100 || sprite.x === 400) + { + // game.debug.renderText('Click sprite to tween', 32, 32); + } + + // game.debug.renderText('x: ' + arrowStart.x, arrowStart.x, arrowStart.y - 4); + // game.debug.renderText('x: ' + arrowEnd.x, arrowEnd.x, arrowEnd.y - 4); + + game.debug.renderText('sprite.x: ' + sprite.x + ' deltaX: ' + sprite.deltaX, 32, 32); + game.debug.renderText('sprite.y: ' + sprite.y + ' deltaY: ' + sprite.deltaY, 32, 48); + + game.debug.renderPhysicsBody(sprite.body); + + game.debug.renderPoint(sprite.center); + +} diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index 99e1edb2..cb6561d9 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -1063,8 +1063,8 @@ Phaser.Physics.Arcade.prototype = { body.x += body.overlapX; body.y += body.overlapY; - body.setBlockFlag(body.blocked.left, body.blocked.right, body.blocked.up, body.blocked.down, body.overlapX, body.overlapY); - body.reboundCheck(true, true, true); + // body.setBlockFlag(body.blocked.left, body.blocked.right, body.blocked.up, body.blocked.down, body.overlapX, body.overlapY); + // body.reboundCheck(true, true, true); return true; diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index ca2384c7..b1754ecd 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -441,26 +441,31 @@ Phaser.Physics.Arcade.Body.prototype = { this.updateBounds(); - if (this.blocked.left && this.blockFlags[0] !== this.left) - { - this.blocked.left = false; - } + // if (this.blocked.left && this.blockFlags[0] !== this.left) + // { + // this.blocked.left = false; + // } - if (this.blocked.right && this.blockFlags[1] !== this.right) - { - this.blocked.right = false; - } + // if (this.blocked.right && this.blockFlags[1] !== this.right) + // { + // this.blocked.right = false; + // } - if (this.blocked.up && this.blockFlags[2] !== this.top) - { - this.blocked.up = false; - } + // if (this.blocked.up && this.blockFlags[2] !== this.top) + // { + // this.blocked.up = false; + // } - if (this.blocked.down && this.blockFlags[3] !== this.bottom) - { - console.log('reset down block flag', this.blockFlags[3], this.bottom); - this.blocked.down = false; - } + // if (this.blocked.down && this.blockFlags[3] !== this.bottom) + // { + // console.log('reset down block flag', this.blockFlags[3], this.bottom); + // this.blocked.down = false; + // } + + this.blocked.left = false; + this.blocked.right = false; + this.blocked.up = false; + this.blocked.down = false; this.touching.none = true; this.touching.up = false; @@ -485,25 +490,25 @@ Phaser.Physics.Arcade.Body.prototype = { if (left) { this.blockFlags[0] = this.left + x; - console.log('left flag set to', this.blockFlags[0]); + // console.log('left flag set to', this.blockFlags[0]); } else if (right) { this.blockFlags[1] = this.right + y; - console.log('right flag set to', this.blockFlags[1]); + // console.log('right flag set to', this.blockFlags[1]); } if (up) { this.blockFlags[2] = this.top + y; // this.blockFlags[2] = this.top; - console.log('up flag set to', this.blockFlags[2]); + // console.log('up flag set to', this.blockFlags[2]); } else if (down) { this.blockFlags[3] = this.bottom + y; // this.blockFlags[3] = this.bottom; - console.log('down flag set to', this.blockFlags[3]); + // console.log('down flag set to', this.blockFlags[3]); } }, diff --git a/src/tilemap/Tile.js b/src/tilemap/Tile.js index fef0eeba..a17c9428 100644 --- a/src/tilemap/Tile.js +++ b/src/tilemap/Tile.js @@ -59,6 +59,11 @@ Phaser.Tile = function (layer, index, x, y, width, height) { */ this.properties = {}; + /** + * @property {boolean} walked - Has this tile been walked / turned into a poly? + */ + this.walked = false; + /** * @property {boolean} faceTop - Is the top of this tile an interesting edge? */ diff --git a/src/utils/Debug.js b/src/utils/Debug.js index f5549acc..9e476e5d 100644 --- a/src/utils/Debug.js +++ b/src/utils/Debug.js @@ -925,6 +925,10 @@ Phaser.Utils.Debug.prototype = { this.context.arc(x, y, body.shape.r, 0, Math.PI * 2, false); this.context.stroke(); this.context.closePath(); + + this.context.strokeStyle = 'rgb(0,0,255)'; + this.context.strokeRect(body.left, body.top, body.width, body.height); + this.stop(); } else @@ -953,6 +957,9 @@ Phaser.Utils.Debug.prototype = { this.context.fillRect(x + points[i].x - 2, y + points[i].y - 2, 5, 5); } + this.context.strokeStyle = 'rgb(0,0,255)'; + this.context.strokeRect(body.left, body.top, body.width, body.height); + this.stop(); }