Physics shape offset now finally working

This commit is contained in:
Richard Davey
2013-05-30 03:54:51 +01:00
parent 0fad46e04b
commit f2054f8a2a
12 changed files with 1545 additions and 1390 deletions
+59 -232
View File
@@ -1,5 +1,8 @@
/// <reference path="../Game.ts" />
/// <reference path="../core/Rectangle.ts" />
/// <reference path="../math/Vec2Utils.ts" />
/// <reference path="PhysicsManager.ts" />
/// <reference path="IPhysicsShape.ts" />
/**
* Phaser - Physics - AABB
@@ -7,253 +10,78 @@
module Phaser.Physics {
export class AABB {
export class AABB implements IPhysicsShape {
constructor(game: Game, sprite: Sprite, x: number, y: number, width: number, height: number) {
this.game = game;
this.world = game.world.physics;
this.sprite = sprite;
this.width = width;
this.height = height;
this.halfWidth = Math.round(width / 2);
this.halfHeight = Math.round(height / 2);
if (sprite !== null)
{
this.sprite = sprite;
this.scale = Vec2Utils.clone(this.sprite.scale);
}
else
{
this.sprite = null;
this.physics = null;
this.scale = new Vec2(1, 1);
}
this.position = new Vec2(x + this.halfWidth, y + this.halfHeight);
this.oldPosition = new Vec2(x + this.halfWidth, y + this.halfHeight);
this.newVelocity = new Vec2(0, 0);
//this.bounds = new Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height);
this.bounds = new Rectangle(x + Math.round(width / 2), y + Math.round(height / 2), width, height);
this.position = new Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight);
this.oldPosition = new Vec2(x + this.bounds.halfWidth, y + this.bounds.halfHeight);
this.offset = new Vec2(0, 0);
}
/**
* Local private reference to Game.
*/
public game: Game;
public world: PhysicsManager;
public sprite: Sprite;
public physics: Phaser.Components.Physics;
public position: Vec2;
public oldPosition: Vec2;
public width: number;
public height: number;
public halfWidth: number;
public halfHeight: number;
public offset: Vec2;
public scale: Vec2;
public bounds: Rectangle;
public oH: number;
public oV: number;
private _drag: number;
public preUpdate() {
public newVelocity: Vec2;
this.oldPosition.copyFrom(this.position);
if (this.sprite)
{
// Update position to sprite value
//console.log('a', this.position.x, this.position.y);
this.position.setTo((this.sprite.x + this.bounds.halfWidth) + this.offset.x, (this.sprite.y + this.bounds.halfHeight) + this.offset.y);
//console.log('b', this.position.x, this.position.y);
//this.position.setTo(this.sprite.x, this.sprite.y);
// Update scale / dimensions
if (Vec2Utils.equals(this.scale, this.sprite.scale) == false)
{
console.log('scaled');
this.scale.copyFrom(this.sprite.scale);
this.bounds.width = this.sprite.width;
this.bounds.height = this.sprite.height;
}
}
}
public update() {
if (this.sprite.physics.moves)
{
this.oldPosition.x = this.position.x;
this.oldPosition.y = this.position.y;
this.updateMotion();
this.collideWorld();
}
}
private updateMotion() {
public setSize(width: number, height: number) {
/*
var delta: number;
var velocityDelta: number;
velocityDelta = (this._game.motion.computeVelocity(this.angularVelocity, this.angularAcceleration, this.angularDrag, this.maxAngular) - this.angularVelocity) / 2;
this.angularVelocity += velocityDelta;
this._angle += this.angularVelocity * this._game.time.elapsed;
this.angularVelocity += velocityDelta;
*/
// move to temp vars
var delta;
var velocityDelta = (this.computeVelocity(this.sprite.physics.velocity.x, this.sprite.physics.acceleration.x, this.sprite.physics.drag.x) - this.sprite.physics.velocity.x) / 2;
this.sprite.physics.velocity.x += velocityDelta;
delta = this.sprite.physics.velocity.x * this.game.time.elapsed;
this.sprite.physics.velocity.x += velocityDelta;
this.position.x += delta;
var velocityDelta = (this.computeVelocity(this.sprite.physics.velocity.y, this.sprite.physics.acceleration.y, this.sprite.physics.drag.y) - this.sprite.physics.velocity.y) / 2;
this.sprite.physics.velocity.y += velocityDelta;
delta = this.sprite.physics.velocity.y * this.game.time.elapsed;
this.sprite.physics.velocity.y += velocityDelta;
this.position.y += delta;
}
/**
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
*
* @param {number} Velocity Any component of velocity (e.g. 20).
* @param {number} Acceleration Rate at which the velocity is changing.
* @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param {number} Max An absolute value cap for the velocity.
*
* @return {number} The altered Velocity value.
*/
public computeVelocity(velocity: number, acceleration: number = 0, drag: number = 0, max: number = 10000): number {
if (acceleration !== 0)
{
velocity += acceleration * this.game.time.elapsed;
}
else if (drag !== 0)
{
this._drag = drag * this.game.time.elapsed;
if (velocity - this._drag > 0)
{
velocity = velocity - this._drag;
}
else if (velocity + this._drag < 0)
{
velocity += this._drag;
}
else
{
velocity = 0;
}
}
if ((velocity != 0) && (max != 10000))
{
if (velocity > max)
{
velocity = max;
}
else if (velocity < -max)
{
velocity = -max;
}
}
return velocity;
}
private collideWorld() {
// Collide on the x-axis
var dx: number = this.world.bounds.x - (this.position.x - this.halfWidth);
if (0 < dx)
{
// Hit Left
this.oH = 1;
this.position.x += dx;
if (this.sprite.physics.bounce.x > 0)
{
this.sprite.physics.velocity.x *= -(this.sprite.physics.bounce.x);
}
else
{
this.sprite.physics.velocity.x = 0;
}
}
else
{
dx = (this.position.x + this.halfWidth) - this.world.bounds.right;
if (0 < dx)
{
// Hit Right
this.oH = -1;
this.position.x -= dx;
if (this.sprite.physics.bounce.x > 0)
{
this.sprite.physics.velocity.x *= -(this.sprite.physics.bounce.x);
}
else
{
this.sprite.physics.velocity.x = 0;
}
}
}
// Collide on the y-axis
var dy: number = this.world.bounds.y - (this.position.y - this.halfHeight);
if (0 < dy)
{
// Hit Top
this.oV = 1;
this.position.y += dy;
if (this.sprite.physics.bounce.y > 0)
{
this.sprite.physics.velocity.y *= -(this.sprite.physics.bounce.y);
}
else
{
this.sprite.physics.velocity.y = 0;
}
}
else
{
dy = (this.position.y + this.halfHeight) - this.world.bounds.bottom;
if (0 < dy)
{
// Hit Bottom
this.oV = -1;
this.position.y -= dy;
if (this.sprite.physics.bounce.y > 0)
{
this.sprite.physics.velocity.y *= -(this.sprite.physics.bounce.y);
}
else
{
this.sprite.physics.velocity.y = 0;
}
}
}
}
private processWorld(px, py, dx, dy, tile) {
// Velocity
//this.sprite.physics.velocity.x = this.position.x - this.oldPosition.x;
//this.sprite.physics.velocity.y = this.position.y - this.oldPosition.y;
// Optimise!!!
var dp: number = (this.sprite.physics.velocity.x * dx + this.sprite.physics.velocity.y * dy);
var nx: number = dp * dx;
var ny: number = dp * dy;
var tx: number = this.sprite.physics.velocity.x - nx;
var ty: number = this.sprite.physics.velocity.y - ny;
var bx, by, fx, fy;
if (dp < 0)
{
fx = tx * this.sprite.physics.friction.x;
fy = ty * this.sprite.physics.friction.y;
bx = (nx * (1 + this.sprite.physics.bounce.x));
by = (ny * (1 + this.sprite.physics.bounce.y));
//this.sprite.physics.velocity.x = bx;
//this.sprite.physics.velocity.y = by;
}
else
{
bx = by = fx = fy = 0;
}
this.position.x += px;
this.position.y += py;
this.oldPosition.x += px + bx + fx;
this.oldPosition.y += py + by + fy;
this.bounds.width = width;
this.bounds.height = height;
}
@@ -261,7 +89,7 @@ module Phaser.Physics {
context.beginPath();
context.strokeStyle = 'rgb(0,255,0)';
context.strokeRect(this.position.x - this.halfWidth, this.position.y - this.halfHeight, this.width, this.height);
context.strokeRect(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight, this.bounds.width, this.bounds.height);
context.stroke();
context.closePath();
@@ -273,8 +101,8 @@ module Phaser.Physics {
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.position.x - this.halfWidth, this.position.y - this.halfHeight);
context.lineTo(this.position.x - this.halfWidth, this.position.y + this.halfHeight);
context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight);
context.lineTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight);
context.stroke();
context.closePath();
}
@@ -282,8 +110,8 @@ module Phaser.Physics {
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.position.x + this.halfWidth, this.position.y - this.halfHeight);
context.lineTo(this.position.x + this.halfWidth, this.position.y + this.halfHeight);
context.moveTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight);
context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight);
context.stroke();
context.closePath();
}
@@ -292,8 +120,8 @@ module Phaser.Physics {
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.position.x - this.halfWidth, this.position.y - this.halfHeight);
context.lineTo(this.position.x + this.halfWidth, this.position.y - this.halfHeight);
context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y - this.bounds.halfHeight);
context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y - this.bounds.halfHeight);
context.stroke();
context.closePath();
}
@@ -301,13 +129,12 @@ module Phaser.Physics {
{
context.beginPath();
context.strokeStyle = 'rgb(255,0,0)';
context.moveTo(this.position.x - this.halfWidth, this.position.y + this.halfHeight);
context.lineTo(this.position.x + this.halfWidth, this.position.y + this.halfHeight);
context.moveTo(this.position.x - this.bounds.halfWidth, this.position.y + this.bounds.halfHeight);
context.lineTo(this.position.x + this.bounds.halfWidth, this.position.y + this.bounds.halfHeight);
context.stroke();
context.closePath();
}
}
}
+33
View File
@@ -0,0 +1,33 @@
/// <reference path="../Game.ts" />
/// <reference path="../core/Rectangle.ts" />
/// <reference path="PhysicsManager.ts" />
/**
* Phaser - Physics - IPhysicsShape
*/
module Phaser.Physics {
export interface IPhysicsShape {
game: Game;
world: PhysicsManager;
sprite: Sprite;
physics: Phaser.Components.Physics;
position: Vec2;
oldPosition: Vec2;
offset: Vec2;
bounds: Rectangle;
oH: number;
oV: number;
setSize(width: number, height: number);
preUpdate();
update();
render(context:CanvasRenderingContext2D);
}
}
+227 -26
View File
@@ -1,4 +1,5 @@
/// <reference path="../Game.ts" />
/// <reference path="IPhysicsShape.ts" />
/**
* Phaser - PhysicsManager
@@ -13,12 +14,12 @@ module Phaser.Physics {
constructor(game: Game, width: number, height: number) {
this._game = game;
this.game = game;
this.gravity = new Vec2(0, 0.2);
this.drag = new Vec2(1, 1);
this.bounce = new Vec2(0.3, 0.7);
this.friction = new Vec2(0.05, 0.05);
this.gravity = new Vec2;
this.drag = new Vec2;
this.bounce = new Vec2;
this.friction = new Vec2;
this.bounds = new Rectangle(0, 0, width, height);
@@ -29,9 +30,15 @@ module Phaser.Physics {
/**
* Local private reference to Game.
*/
private _game: Game;
public game: Game;
private _objects;
private _objects: IPhysicsShape[];
// Temp calculation vars
private _drag: number;
private _delta: number;
private _velocityDelta: number;
private _length: number = 0;
public bounds: Rectangle;
@@ -40,30 +47,23 @@ module Phaser.Physics {
public bounce: Vec2;
public friction: Vec2;
private minFriction: number = 0;
private maxFriction: number = 1;
// Add some sanity checks here + remove method, etc
public add(shape: IPhysicsShape): IPhysicsShape {
private minBounce: number = 0;
private maxBounce: number = 1;
this._objects.push(shape);
return shape;
private minGravity: number = 0;
private maxGravity: number = 1;
private _i: number = 0;
private _length: number = 0;
public add(o) {
this._objects.push(o);
this._length++;
return o;
}
public update() {
// iterate through the objects here, updating and colliding
for (this._i = 0; this._i < this._length; this._i++)
this._length = this._objects.length;
for (var i = 0; i < this._length; i++)
{
this._objects[this._i].update();
this._objects[i].preUpdate();
this.updateMotion(this._objects[i]);
this.collideWorld(this._objects[i]);
}
}
@@ -71,13 +71,214 @@ module Phaser.Physics {
public render() {
// iterate through the objects here, updating and colliding
for (this._i = 0; this._i < this._length; this._i++)
for (var i = 0; i < this._length; i++)
{
this._objects[this._i].render(this._game.stage.context);
this._objects[i].render(this.game.stage.context);
}
}
private updateMotion(obj: IPhysicsShape) {
if (obj.physics.moves == false)
{
return;
}
/*
velocityDelta = (this._game.motion.computeVelocity(this.angularVelocity, this.angularAcceleration, this.angularDrag, this.maxAngular) - this.angularVelocity) / 2;
this.angularVelocity += velocityDelta;
this._angle += this.angularVelocity * this._game.time.elapsed;
this.angularVelocity += velocityDelta;
*/
this._velocityDelta = (this.computeVelocity(obj.physics.velocity.x, obj.physics.gravity.x, obj.physics.acceleration.x, obj.physics.drag.x) - obj.physics.velocity.x) / 2;
obj.physics.velocity.x += this._velocityDelta;
this._delta = obj.physics.velocity.x * this.game.time.elapsed;
obj.physics.velocity.x += this._velocityDelta;
obj.position.x += this._delta;
this._velocityDelta = (this.computeVelocity(obj.physics.velocity.y, obj.physics.gravity.y, obj.physics.acceleration.y, obj.physics.drag.y) - obj.physics.velocity.y) / 2;
obj.physics.velocity.y += this._velocityDelta;
this._delta = obj.physics.velocity.y * this.game.time.elapsed;
obj.physics.velocity.y += this._velocityDelta;
obj.position.y += this._delta;
}
/**
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
*
* @param {number} Velocity Any component of velocity (e.g. 20).
* @param {number} Acceleration Rate at which the velocity is changing.
* @param {number} Drag Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param {number} Max An absolute value cap for the velocity.
*
* @return {number} The altered Velocity value.
*/
public computeVelocity(velocity: number, gravity: number = 0, acceleration: number = 0, drag: number = 0, max: number = 10000): number {
if (acceleration !== 0)
{
velocity += (acceleration + gravity) * this.game.time.elapsed;
}
else if (drag !== 0)
{
this._drag = drag * this.game.time.elapsed;
if (velocity - this._drag > 0)
{
velocity = velocity - this._drag;
}
else if (velocity + this._drag < 0)
{
velocity += this._drag;
}
else
{
velocity = 0;
}
velocity += gravity;
}
if ((velocity != 0) && (max != 10000))
{
if (velocity > max)
{
velocity = max;
}
else if (velocity < -max)
{
velocity = -max;
}
}
return velocity;
}
private collideWorld(obj:IPhysicsShape) {
// Collide on the x-axis
var dx: number = obj.world.bounds.x - (obj.position.x - obj.bounds.halfWidth);
if (0 < dx)
{
// Hit Left
obj.oH = 1;
obj.position.x += dx;
if (obj.sprite.physics.bounce.x > 0)
{
obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x);
}
else
{
obj.sprite.physics.velocity.x = 0;
}
}
else
{
dx = (obj.position.x + obj.bounds.halfWidth) - obj.world.bounds.right;
if (0 < dx)
{
// Hit Right
obj.oH = -1;
obj.position.x -= dx;
if (obj.sprite.physics.bounce.x > 0)
{
obj.sprite.physics.velocity.x *= -(obj.sprite.physics.bounce.x);
}
else
{
obj.sprite.physics.velocity.x = 0;
}
}
}
// Collide on the y-axis
var dy: number = obj.world.bounds.y - (obj.position.y - obj.bounds.halfHeight);
if (0 < dy)
{
// Hit Top
obj.oV = 1;
obj.position.y += dy;
if (obj.sprite.physics.bounce.y > 0)
{
obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y);
}
else
{
obj.sprite.physics.velocity.y = 0;
}
}
else
{
dy = (obj.position.y + obj.bounds.halfHeight) - obj.world.bounds.bottom;
if (0 < dy)
{
// Hit Bottom
obj.oV = -1;
obj.position.y -= dy;
if (obj.sprite.physics.bounce.y > 0)
{
obj.sprite.physics.velocity.y *= -(obj.sprite.physics.bounce.y);
}
else
{
obj.sprite.physics.velocity.y = 0;
}
}
}
}
/*
private processWorld(px, py, dx, dy, tile) {
// Velocity
//this.sprite.physics.velocity.x = this.position.x - this.oldPosition.x;
//this.sprite.physics.velocity.y = this.position.y - this.oldPosition.y;
// Optimise!!!
var dp: number = (this.sprite.physics.velocity.x * dx + this.sprite.physics.velocity.y * dy);
var nx: number = dp * dx;
var ny: number = dp * dy;
var tx: number = this.sprite.physics.velocity.x - nx;
var ty: number = this.sprite.physics.velocity.y - ny;
var bx, by, fx, fy;
if (dp < 0)
{
fx = tx * this.sprite.physics.friction.x;
fy = ty * this.sprite.physics.friction.y;
bx = (nx * (1 + this.sprite.physics.bounce.x));
by = (ny * (1 + this.sprite.physics.bounce.y));
//this.sprite.physics.velocity.x = bx;
//this.sprite.physics.velocity.y = by;
}
else
{
bx = by = fx = fy = 0;
}
this.position.x += px;
this.position.y += py;
this.oldPosition.x += px + bx + fx;
this.oldPosition.y += py + by + fy;
}
*/
}
}