Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*:
- * @plugindesc v1.00 Extension, that comes with predefined zones for use by some behaviours.
- * @author Iavra
- *
- * @help
- * To use one of the zones included in this plugin, provide it as an argument to behaviours requiring a zone argument:
- *
- * new IAVRA.PARTICLE.B.Position(new IAVRA.PARTICLE.Z.Point(100, 100));
- *
- * This example will create a "Position" behaviour with a "Point" zone, that will cause particles to spawn at the
- * point (100, 100).
- *
- * The following zones are contained in the IAVRA.PARTICLE.Z / IAVRA.PARTICLE.ZONE namespace:
- *
- * Multi(...zone) Can be used to merge multiple zones, which are weighted depending on
- * their area.
- *
- * Point(x, y) Defines a single point at the position (x, y).
- *
- * Line(x1, y1, x2, y2) Creates a line from the start point (x1, y1) to the end point (x2, y2).
- *
- * Circle(center, outerRadius, innerRadius) Creates a center around the given center point with the given radius.
- * The "innerRadius" parameter can be used to turn the circle into a ring.
- *
- * Rect(x, y, width, height) Defines a rectangle parallel to the axes with the given upper left edge
- * (x, y), as well as the given width an height.
- *
- * Image(imageData, x, y, skip) Creates a zone, that contains all non-transparent pixels from the given
- * image data, offset by the given x and y values, The parameter skip can
- * be used to skip pixels, which speeds up the creation of this zone.
- *
- * Regarding the Image zone, there are multiple ways to aquire an image data object. The following describes how to do
- * it using PIXI.RenderTexture:
- *
- * var sprite = PIXI.Sprite.fromImage('img/imageToBeUsed.png'); // Make sure, that this is loaded, before continuing.
- * var render = new PIXI.RenderTexture(sprite.width, sprite.height);
- * var imageData = render.getCanvas.getContext('2d').getImageData(0, 0, render.width, render.height);
- */
- (function($, undefined) {
- "use strict";
- if(!$.PARTICLE) { throw new Error("This plugin depends on 'Iavra Particle - Core'."); }
- /**
- * Extends a given object with all properties from another given object. Mainly used to simplify subclassing.
- * @param {Object} base - Base object to be extended.
- * @param {Object} extend - Object containing the properties to be appended to the given base object.
- * @returns {Object} The base object, after it has been extended.
- */
- var _extend = function(base, extend) {
- for(var key in extend) { base[key] = extend[key]; }
- return base;
- };
- /**
- * Returns a random floating point number between the given minimum (inclusive) and maximum (exclusive).
- * @param {number} min - Minimum number to be generated (inclusive).
- * @param {number} max - Maximum number to be generated (exclusive).
- * @returns {number} A random number between the given minimum and maximum numbers.
- */
- var _random = function(min, max) {
- return min + (max - min) * Math.random();
- };
- /**
- * Constructs a polar vector with the given radius and angle (in radians) and returns its cartesian representation.
- * @param {number} radius - Radius component of the polar vector, which defines the resulting vector's length.
- * @param {number} angle - Angle component of the polar vector, in radians.
- * @returns {number[]} An array containing the cartesian representation of the polar vector.
- */
- var _polarVector = function(radius, angle) {
- return [radius * Math.cos(angle), -radius * Math.sin(angle)]
- };
- //=============================================================================
- // IAVRA.PARTICLE.ZONE
- //=============================================================================
- $.PARTICLE.ZONE = $.PARTICLE.Z = {
- Multi: function(zone) { this._initialize.apply(this, arguments); },
- Point: function(x, y) { this._initialize(x, y); },
- Line: function(x1, y1, x2, y2) { this._initialize(x1, y1, x2, y2); },
- Circle: function(center, outerRadius, innerRadius) { this._initialize(center, outerRadius, innerRadius); },
- Rect: function(x, y, width, height) { this._initialize(x, y, width, height); },
- Image: function(imageData, x, y, skip) { this._initialize(imageData, x, y, skip); }
- };
- //=============================================================================
- // IAVRA.PARTICLE.ZONE.Multi
- //=============================================================================
- /**
- * A Multi zone contains of multiple zones, which are balanced according to their area, when determining a random
- * point inside of them.
- */
- $.PARTICLE.ZONE.Multi.prototype = _extend(Object.create($.PARTICLE.Zone.prototype), {
- /**
- * Initializes the zone.
- * @param {...IAVRA.PARTICLE.Zone} zone - One of more zones to be used inside the multi zone.
- */
- _initialize: function(zone) {
- this._zones = Array.prototype.slice.call(arguments);
- this.refresh();
- },
- /**
- * Needs to be called every time one of the supplied zone's area changes, since it's cached.
- */
- refresh: function() {
- this._areas = [];
- this._totalArea = 0;
- for(var i = 0, max = this._zones.length, area; i < max; ++i) {
- area = this._zones[i].getArea();
- this._areas.push(area);
- this._totalArea += area;
- }
- },
- /**
- * Tests, whether a given point is located inside the zone.
- * @param {number} x - X coordinate of the point to be tested.
- * @param {number} y - Y coordinate of the point to be tested.
- * @returns {boolean} True, if the given coordinates are located inside the zone. False, otherwise.
- */
- contains: function(x, y) {
- for(var i = 0, max = this._zones.length; i < max; ++i) {
- if(this._zones[i].contains(x, y)) { return true; }
- }
- return false;
- },
- /**
- * Returns a random point inside the zone. This can be used to create a random particle spread inside an area.
- * @returns {PIXI.Point} A random point inside this zone.
- */
- getPoint: function() {
- var select = Math.random() * this._totalArea;
- for(var i = 0, max = this._zones.length; i < max; ++i) {
- if((select -= this._areas[i]) <= 0) { return this._zones[i].getPoint(); }
- }
- return this._zones.length ? this._zones[0].getPoint() : new PIXI.Point();
- },
- /**
- * Returns the area of this zone. This may be used to balance multiple zones in regard to their areas.
- * @returns {number} This zone's area.
- */
- getArea: function() {
- return this._totalArea;
- },
- /**
- * Handles collision between the given particle and this zone.
- * @param {IAVRA.PARTICLE.Particle} particle - Particle instance to test for collision with this zone.
- * @param {number} [bounce=1] - Bounce coefficient. Values between 0 and 1 cause the particle to lose energy,
- * while values higher than 1 cause it to gain energy. Values lower than 0 might lead to unpredictable results.
- * @returns {boolean} True, if a collision was handled. False, otherwise.
- */
- collide: function(particle, bounce) {
- var collide = false;
- for(var i = 0, max = this._zones.length; i < max; ++i) {
- collide = this._zones[i].collide(particle, bounce) || collide;
- }
- return collide;
- }
- });
- //=============================================================================
- // IAVRA.PARTICLE.ZONE.Point
- //=============================================================================
- /**
- * A Point zone describes a single point and is mostly used to create particles there. The internal point can be
- * changed, which effectively moves the "emitter".
- */
- $.PARTICLE.ZONE.Point.prototype = _extend(Object.create($.PARTICLE.Zone.prototype), {
- /**
- * Initializes the zone.
- * @param {number} [x=0] - X coordinate of the point.
- * @param {number} [y=0] - Y coordinate of the point.
- */
- _initialize: function(x, y) {
- this._point = new PIXI.Point(x, y);
- },
- /**
- * Tests, whether a given point is located inside the zone.
- * @param {number} x - X coordinate of the point to be tested.
- * @param {number} y - Y coordinate of the point to be tested.
- * @returns {boolean} True, if the given coordinates are located inside the zone. False, otherwise.
- */
- contains: function(x, y) {
- return x === this._point.x && y === this._point.y;
- },
- /**
- * Returns a random point inside the zone. This can be used to create a random particle spread inside an area.
- * This also doubles, as the returned point is the internal representation of this zone, so it can be changed
- * to effectively move the zone around.
- * @returns {PIXI.Point} A random point inside this zone.
- */
- getPoint: function() {
- return this._point;
- },
- /**
- * Returns the area of this zone. This may be used to balance multiple zones in regard to their areas.
- * @returns {number} This zone's area.
- */
- getArea: function() {
- return 1;
- },
- /**
- * Handles collision between the given particle and this zone.
- * @param {IAVRA.PARTICLE.Particle} particle - Particle instance to test for collision with this zone.
- * @param {number} [bounce=1] - Bounce coefficient. Values between 0 and 1 cause the particle to lose energy,
- * while values higher than 1 cause it to gain energy. Values lower than 0 might lead to unpredictable results.
- * @returns {boolean} True, if a collision was handled. False, otherwise.
- */
- collide: function(particle, bounce) {
- var relPrevX = particle.oldPosition.x - this._point.x, relPrevY = particle.oldPosition.y - this._point.y;
- var dot = relPrevX * particle.velocity.x + relPrevY * particle.velocity.y;
- if(dot >= 0) { return false; }
- var relX = particle.position.x - this._point.x, relY = particle.position.y - this._point.y;
- var radius = particle.radius * particle.scale.x;
- dot = relX * particle.velocity.x + relY * particle.velocity.y;
- if(dot <= 0) {
- if(relX > radius || relX < -radius) { return false; }
- if(relY > radius || relY < -radius) { return false; }
- if(relX * relX + relY * relY > radius * radius) { return false; }
- }
- var frameVelX = relX - relPrevX, frameVelY = relY - relPrevY;
- var a = frameVelX * frameVelX + frameVelY * frameVelY;
- var b = 2 * (relPrevX * frameVelX + relPrevY * frameVelY);
- var c = relPrevX * relPrevX + relPrevY * relPrevY - radius * radius;
- var sq= b * b - 4 * a * c;
- if(sq < 0) { return false; }
- var srt = Math.sqrt(sq), t1 = (-b + srt) / (2 * a), t2 = (-b - srt) / (2 * a), t = [];
- if(t1 > 0 && t1 <= 1) { t.push(t1); }
- if(t2 > 0 && t2 <= 1) { t.push(t2); }
- if(!t.length) { return false; }
- var time = (t.length === 1) ? t[0] : Math.min(t1, t2);
- var cx = relPrevX + time * frameVelX + this._point.x, cy = relPrevY + time * frameVelY + this._point.y;
- var nx = cx - this._point.x, ny = cy - this._point.y, d = Math.sqrt(nx * nx + ny * ny);
- nx /= d;
- ny /= d;
- var n = frameVelX * nx + frameVelY * ny;
- frameVelX -= 2 * nx * n;
- frameVelY -= 2 * ny * n;
- particle.position.x = cx + (1 - time) * frameVelX;
- particle.position.y = cy + (1 - time) * frameVelY;
- var normalVel = particle.velocity.x * nx + particle.velocity.y * ny;
- particle.velocity.x -= (1 + bounce) * nx * normalVel;
- particle.velocity.y -= (1 + bounce) * ny * normalVel;
- return true;
- }
- });
- //=============================================================================
- // IAVRA.PARTICLE.ZONE.Line
- //=============================================================================
- /**
- * A Line zone describes a line from a given start to end point.
- */
- $.PARTICLE.ZONE.Line.prototype = _extend(Object.create($.PARTICLE.Zone.prototype), {
- /**
- * Initializes the zone.
- * @param {number} x1 - X coordinate of the line's starting point.
- * @param {number} y1 - Y coordinate of the line's starting point.
- * @param {number} x2 - X coordinate of the line's end point.
- * @param {number} y2 - Y coordinate of the line's end point.
- */
- _initialize: function(x1, y1, x2, y2) {
- this._start = new PIXI.Point(x1, y1);
- this._end = new PIXI.Point(x2, y2);
- this._length = new PIXI.Point(this._end.x - this._start.x, this._end.y - this._start.y);
- var length = Math.sqrt(this._length.x * this._length.x + this._length.y * this._length.y);
- this._parallel = new PIXI.Point(this._length.x / length, this._length.y / length);
- this._normal = new PIXI.Point(this._parallel.y, -this._parallel.x);
- },
- /**
- * Tests, whether a given point is located inside the zone.
- * @param {number} x - X coordinate of the point to be tested.
- * @param {number} y - Y coordinate of the point to be tested.
- * @returns {boolean} True, if the given coordinates are located inside the zone. False, otherwise.
- */
- contains: function(x, y) {
- if ((x - this._start.x) * this._length.y - (y - this._start.y) * this._length.x !== 0) { return false; }
- return (x - this._start.x ) * (x - this._end.x) + (y - this._start.y) * (y - this._end.y) <= 0;
- },
- /**
- * Returns a random point inside the zone. This can be used to create a random particle spread inside an area.
- * @returns {PIXI.Point} A random point inside this zone.
- */
- getPoint: function() {
- var scale = Math.random();
- return new PIXI.Point(this._start.x + this._length.x * scale, this._start.y + this._length.y * scale);
- },
- /**
- * Returns the area of this zone. This may be used to balance multiple zones in regard to their areas.
- * @returns {number} This zone's area.
- */
- getArea: function() {
- return Math.sqrt(this._length.x * this._length.x + this._length.y + this._length.y);
- },
- /**
- * Handles collision between the given particle and this zone.
- * @param {IAVRA.PARTICLE.Particle} particle - Particle instance to test for collision with this zone.
- * @param {number} [bounce=1] - Bounce coefficient. Values between 0 and 1 cause the particle to lose energy,
- * while values higher than 1 cause it to gain energy. Values lower than 0 might lead to unpredictable results.
- * @returns {boolean} True, if a collision was handled. False, otherwise.
- */
- collide: function(particle, bounce) {
- var radius = particle.radius * particle.scale.x;
- var prevDist = (particle.oldPosition.x - this._start.x) * this._normal.x +
- (particle.oldPosition.y - this._start.y) * this._normal.y;
- var velDist = particle.velocity.x * this._normal.x + particle.velocity.y * this._normal.y;
- if(prevDist * velDist >= 0) { return false; }
- var distance = (particle.position.x - this._start.x) * this._normal.x +
- (particle.position.y - this._start.y) * this._normal.y;
- if(distance * prevDist > 0 && (distance > radius || distance < -radius)) { return false; }
- var offsetX = this._normal.x * radius, offsetY = this._normal.y * radius;
- if(prevDist >= 0) {
- offsetX *= -1;
- offsetY *= -1;
- }
- var thenX = particle.oldPosition.x + offsetX, thenY = particle.oldPosition.y + offsetY;
- var nowX = particle.position.x + offsetX, nowY = particle.position.y + offsetY;
- var startX = this._start.x - this._parallel.x * radius, startY = this._start.y - this._parallel.y * radius;
- var endX = this._end.x + this._parallel.x * radius, endY = this._end.y + this._parallel.y * radius;
- var den = 1 / ((nowY - thenY) * (endX - startX) - (nowX - thenX) * (endY - startY));
- var u = den * ((nowX - thenX) * (startY - thenY) - (nowY - thenY) * (startX - thenX));
- if(u < 0 || u > 1) { return false; }
- var v = -den * ((endX - startX) * (thenY - startY) - (endY - startY) * (thenX - startX));
- if(v < 0 || v > 1) { return false; }
- particle.position.x = particle.oldPosition.x + v * (particle.position.x - particle.oldPosition.x);
- particle.position.y = particle.oldPosition.y + v * (particle.position.y - particle.oldPosition.y);
- var normalSpeed = this._normal.x * particle.velocity.x + this._normal.y * particle.velocity.y;
- var factor = (1 + bounce) * normalSpeed;
- particle.velocity.x -= factor * this._normal.x;
- particle.velocity.y -= factor * this._normal.y;
- return true;
- }
- });
- //=============================================================================
- // IAVRA.PARTICLE.ZONE.Circle
- //=============================================================================
- /**
- * A Circle zone describes a circle around a given center with an optional inner radius to turn it into a ring.
- */
- $.PARTICLE.ZONE.Circle.prototype = _extend(Object.create($.PARTICLE.Zone.prototype), {
- /**
- * Initializes the zone.
- * @param {PIXI.Point} center - Center point of the circle. If this parameter is cached somewhere, it can be
- * modified to move the circle around.
- * @param {number} [outerRadius=0] - Radius of the circle.
- * @param {number} [innerRadius=0] - Can be used to turn the circle in a ring. Can't be bigger than the
- * outer radius.
- */
- _initialize: function(center, outerRadius, innerRadius) {
- this._center = center;
- this._outerRadius = outerRadius || 0;
- this._innerRadius = innerRadius || 0;
- if(this._outerRadius < this._innerRadius) { throw new Error("Invalid radius values."); }
- this._outerSq = this._outerRadius * this._outerRadius;
- this._innerSq = this._innerRadius * this._innerRadius;
- },
- /**
- * Tests, whether a given point is located inside the zone.
- * @param {number} x - X coordinate of the point to be tested.
- * @param {number} y - Y coordinate of the point to be tested.
- * @returns {boolean} True, if the given coordinates are located inside the zone. False, otherwise.
- */
- contains: function(x, y) {
- x -= this._center.x;
- y -= this._center.y;
- var distSq = x * x + y * y;
- return distSq <= this._outerSq && distSq >= this._innerSq;
- },
- /**
- * Returns a random point inside the zone. This can be used to create a random particle spread inside an area.
- * @returns {PIXI.Point} A random point inside this zone.
- */
- getPoint: function() {
- var rand = Math.random();
- var vector = _polarVector(this._innerRadius + (1 - rand * rand) * (this._outerRadius - this._innerRadius),
- Math.random() * Math.PI * 2);
- return new PIXI.Point(vector[0] + this._center.x, vector[1] + this._center.y);
- },
- /**
- * Returns the area of this zone. This may be used to balance multiple zones in regard to their areas.
- * @returns {number} This zone's area.
- */
- getArea: function() {
- return Math.PI * (this._outerSq - this._innerSq);
- },
- /**
- * Handles collision between the given particle and this zone.
- * @param {IAVRA.PARTICLE.Particle} particle - Particle instance to test for collision with this zone.
- * @param {number} [bounce=1] - Bounce coefficient. Values between 0 and 1 cause the particle to lose energy,
- * while values higher than 1 cause it to gain energy. Values lower than 0 might lead to unpredictable results.
- * @returns {boolean} True, if a collision was handled. False, otherwise.
- */
- collide: function(particle, bounce) {
- var outerLimit, innerLimit, outerLimitSq, innerLimitSq, distanceSq, distance, pdx, pdy, pDistanceSq;
- var adjustSpeed, positionRatio, epsilon = 0.001, radius = particle.radius * particle.scale.x;
- var dx = particle.position.x - this._center.x, dy = particle.position.y - this._center.y;
- var dot = particle.velocity.x * dx + particle.velocity.y * dy;
- if(dot < 0) {
- outerLimit = this._outerRadius + radius;
- if(Math.abs(dx) > outerLimit || Math.abs(dy) > outerLimit) { return false; }
- distanceSq = dx * dx + dy * dy;
- outerLimitSq = outerLimit * outerLimit;
- if(distanceSq > outerLimitSq) { return false; }
- pdx = particle.oldPosition.x - this._center.x, pdy = particle.oldPosition.y - this._center.y;
- pDistanceSq = pdx * pdx + pdy * pdy;
- if(pDistanceSq > outerLimitSq) {
- adjustSpeed = (1 + bounce) * dot / distanceSq;
- particle.velocity.x -= adjustSpeed * dx;
- particle.velocity.y -= adjustSpeed * dy;
- distance = Math.sqrt(distanceSq);
- positionRatio = (2 * outerLimit - distance) / distance + epsilon;
- particle.position.x = this._center.x + dx * positionRatio;
- particle.position.y = this._center.y + dy * positionRatio;
- return true;
- }
- if(this._innerRadius !== 0 && this._innerRadius !== this._outerRadius ) {
- innerLimit = this._innerRadius + radius;
- if(Math.abs(dx) > innerLimit || Math.abs(dy) > innerLimit) { return false; }
- innerLimitSq = innerLimit * innerLimit;
- if(distanceSq > innerLimitSq) { return false; }
- if(pDistanceSq > innerLimitSq) {
- adjustSpeed = (1 + bounce) * dot / distanceSq;
- particle.velocity.x -= adjustSpeed * dx;
- particle.velocity.y -= adjustSpeed * dy;
- distance = Math.sqrt(distanceSq);
- positionRatio = (2 * innerLimit - distance) / distance + epsilon;
- particle.position.x = this._center.x + dx * positionRatio;
- particle.position.y = this._center.y + dy * positionRatio;
- return true;
- }
- }
- return false;
- } else {
- outerLimit = this._outerRadius - radius;
- pdx = particle.oldPosition.x - this._center.x, pdy = particle.oldPosition.y - this._center.y;
- if(Math.abs(pdx) > outerLimit || Math.abs(pdy) > outerLimit) { return false; }
- pDistanceSq = pdx * pdx + pdy * pdy;
- outerLimitSq = outerLimit * outerLimit;
- if(pDistanceSq > outerLimitSq) { return false; }
- distanceSq = dx * dx + dy * dy;
- if(this._innerRadius !== 0 && this._innerRadius !== this._outerRadius) {
- innerLimit = this._innerRadius - radius;
- innerLimitSq = innerLimit * innerLimit;
- if(pDistanceSq < innerLimitSq && distanceSq >= innerLimitSq) {
- adjustSpeed = (1 + bounce) * dot / distanceSq;
- particle.velocity.x -= adjustSpeed * dx;
- particle.velocity.y -= adjustSpeed * dy;
- distance = Math.sqrt(distanceSq);
- positionRatio = (2 * innerLimit - distance) / distance - epsilon;
- particle.position.x = this._center.x + dx * positionRatio;
- particle.position.y = this._center.y + dy * positionRatio;
- return true;
- }
- }
- if(distanceSq >= outerLimitSq) {
- adjustSpeed = (1 + bounce) * dot / distanceSq;
- particle.velocity.x -= adjustSpeed * dx;
- particle.velocity.y -= adjustSpeed * dy;
- distance = Math.sqrt(distanceSq);
- positionRatio = (2 * outerLimit - distance) / distance - epsilon;
- particle.position.x = this._center.x + dx * positionRatio;
- particle.position.y = this._center.y + dy * positionRatio;
- return true;
- }
- return false;
- }
- return false;
- }
- });
- //=============================================================================
- // IAVRA.PARTICLE.ZONE.Rect
- //=============================================================================
- /**
- * A Rect zone describes a rectangle parallel to the axes.
- */
- $.PARTICLE.ZONE.Rect.prototype = _extend(Object.create($.PARTICLE.Zone.prototype), {
- /**
- * Initializes the zone.
- * @param {number} x - X coordinate of the rect's upper left point.
- * @param {number} y - X coordinate of the rect's upper left point.
- * @param {number} width - Width of the rect.
- * @param {number} height - Height of the rect.
- */
- _initialize: function(x, y, width, height) {
- this._left = x;
- this._top = y;
- this._right = x + width;
- this._bottom = y + height;
- this._width = width;
- this._height = height;
- },
- /**
- * Tests, whether a given point is located inside the zone.
- * @param {number} x - X coordinate of the point to be tested.
- * @param {number} y - Y coordinate of the point to be tested.
- * @returns {boolean} True, if the given coordinates are located inside the zone. False, otherwise.
- */
- contains: function(x, y) {
- return x >= this._left && x <= this._right && y >= this._top && y <= this._bottom;
- },
- /**
- * Returns a random point inside the zone. This can be used to create a random particle spread inside an area.
- * @returns {PIXI.Point} A random point inside this zone.
- */
- getPoint: function() {
- return new PIXI.Point(this._left + Math.random() * this._width, this._top + Math.random() * this._height);
- },
- /**
- * Returns the area of this zone. This may be used to balance multiple zones in regard to their areas.
- * @returns {number} This zone's area.
- */
- getArea: function() {
- return this._width * this._height;
- },
- /**
- * Handles collision between the given particle and this zone.
- * @param {IAVRA.PARTICLE.Particle} particle - Particle instance to test for collision with this zone.
- * @param {number} [bounce=1] - Bounce coefficient. Values between 0 and 1 cause the particle to lose energy,
- * while values higher than 1 cause it to gain energy. Values lower than 0 might lead to unpredictable results.
- * @returns {boolean} True, if a collision was handled. False, otherwise.
- */
- collide: function(particle, bounce) {
- var position, prevPosition, intersect, collision = false, radius = particle.radius * particle.scale.x;
- if(particle.velocity.x > 0) {
- position = particle.position.x + radius, prevPosition = particle.oldPosition.x + radius;
- if(prevPosition < this._left && position >= this._left) {
- intersect = particle.oldPosition.y + (particle.position.y - particle.oldPosition.y) *
- (this._left - prevPosition) / (position - prevPosition);
- if(intersect >= this._top - radius && intersect <= this._bottom + radius) {
- particle.velocity.x *= -bounce;
- particle.position.x += 2 * (this._left - position);
- collision = true;
- }
- } else if(prevPosition <= this._right && position > this._right) {
- intersect = particle.oldPosition.y + (particle.position.y - particle.oldPosition.y) *
- (this._right - prevPosition) / (position - prevPosition);
- if(intersect >= this._top - radius && intersect <= this._bottom + radius) {
- particle.velocity.x *= -bounce;
- particle.position.x += 2 * (this._right - position);
- collision = true;
- }
- }
- } else if (particle.velocity.x < 0) {
- position = particle.position.x - radius, prevPosition = particle.oldPosition.x - radius;
- if(prevPosition > this._right && position <= this._right) {
- intersect = particle.oldPosition.y + (particle.position.y - particle.oldPosition.y) *
- (this._right - prevPosition) / (position - prevPosition);
- if(intersect >= this._top - radius && intersect <= this._bottom + radius) {
- particle.velocity.x *= -bounce;
- particle.position.x += 2 * (this._right - position);
- collision = true;
- }
- } else if(prevPosition >= this._left && position < this._left) {
- intersect = particle.oldPosition.y + (particle.position.y - particle.oldPosition.y) *
- (this._left - prevPosition) / (position - prevPosition);
- if(intersect >= this._top - radius && intersect <= this._bottom + radius) {
- particle.velocity.x *= -bounce;
- particle.position.x += 2 * (this._left - position);
- collision = true;
- }
- }
- }
- if (particle.velocity.y > 0) {
- position = particle.position.y + radius, prevPosition = particle.oldPosition.y + radius;
- if(prevPosition < this._top && position >= this._top) {
- intersect = particle.oldPosition.x + (particle.position.x - particle.oldPosition.x) *
- (this._top - prevPosition) / (position - prevPosition);
- if(intersect >= this._left - radius && intersect <= this._right + radius) {
- particle.velocity.y *= -bounce;
- particle.position.y += 2 * (this._top - position);
- collision = true;
- }
- } else if(prevPosition <= this._bottom && position > this._bottom) {
- intersect = particle.oldPosition.x + (particle.position.x - particle.oldPosition.x) *
- (this._bottom - prevPosition) / (position - prevPosition);
- if(intersect >= this._left - radius && intersect <= this._right + radius) {
- particle.velocity.y *= -bounce;
- particle.position.y += 2 * (this._bottom - position);
- collision = true;
- }
- }
- } else if (particle.velocity.y < 0) {
- position = particle.position.y - radius, prevPosition = particle.oldPosition.y - radius;
- if(prevPosition > this._bottom && position <= this._bottom) {
- intersect = particle.oldPosition.x + (particle.position.x - particle.oldPosition.x) *
- (this._bottom - prevPosition) / (position - prevPosition);
- if(intersect >= this._left - radius && intersect <= this._right + radius) {
- particle.velocity.y *= -bounce;
- particle.position.y += 2 * (this._bottom - position);
- collision = true;
- }
- } else if(prevPosition >= this._top && position < this._top) {
- intersect = particle.oldPosition.x + (particle.position.x - particle.oldPosition.x) *
- (this._top - prevPosition) / (position - prevPosition);
- if(intersect >= this._left - radius && intersect <= this._right + radius) {
- particle.velocity.y *= -bounce;
- particle.position.y += 2 * (this._top - position);
- collision = true;
- }
- }
- }
- return collision;
- }
- });
- //=============================================================================
- // IAVRA.PARTICLE.ZONE.Image
- //=============================================================================
- /**
- * An Image zone describes all non-transparent pixels inside the given image data.
- */
- $.PARTICLE.ZONE.Image.prototype = _extend(Object.create($.PARTICLE.Zone.prototype), {
- /**
- * Initializes the zone.
- * @param {ImageData} imageData - The data of a given image. How to aquire such an object is described in this
- * plugin's help section.
- * @param {number} [x=2] - X offset used for the zone.
- * @param {number} [y=2] - Y offset used for the zone.
- * @param {number} [skip=2] - Skips pixels, when reading image data. Using this greatly reduces the time needed
- * to setup this zone. Shouldn't be set much higher than 10, or you will skip too many pixels or even run the
- * risk to read outside the image data.
- */
- _initialize: function(imageData, x, y, skip) {
- this._imageData = imageData;
- this._x = x || 0;
- this._y = y || 0;
- this._skip = skip === undefined ? 2 : skip;
- this._vectors = [];
- this._setupVectors();
- },
- /**
- * Sets up the vectors used for this zone. This happens synchronous, but might take time, depending on the
- * given image's size, so it might be a good idea to initialize the zone inside a scene's "create" function.
- */
- _setupVectors: function() {
- for (var i = 0, width = this._imageData.width; i < width; i += this._skip) {
- for (var j = 0, height = this._imageData.height; j < height; j += this._skip) {
- if(this._imageData.data[(((j|0) * width + (i|0)) * 4) + 3] > 0) {
- this._vectors.push({ x: i + this._x, y: j + this._y });
- }
- }
- }
- },
- /**
- * Tests, whether a given point is located inside the zone.
- * @param {number} x - X coordinate of the point to be tested.
- * @param {number} y - Y coordinate of the point to be tested.
- * @returns {boolean} True, if the given coordinates are located inside the zone. False, otherwise.
- */
- contains: function(x, y) {
- return this._imageData.data[(((y|0) * width + (x|0)) * 4) + 3] > 0;
- },
- /**
- * Returns a random point inside the zone. This can be used to create a random particle spread inside an area.
- * @returns {PIXI.Point} A random point inside this zone.
- */
- getPoint: function() {
- return this._vectors[(this._vectors.length * Math.random())|0];
- },
- /**
- * Returns the area of this zone. This may be used to balance multiple zones in regard to their areas.
- * @returns {number} This zone's area.
- */
- getArea: function() {
- return this._vectors.length;
- },
- /**
- * Collision has been disabled for the Image zone, since it would be sketchy at best, seeing that it's
- * impossible to account for all possible images.
- */
- collide: function(particle, bounce) {
- throw new Error('Image zone doesn\'t support collision.');
- }
- });
- })(this.IAVRA || (this.IAVRA = {}));
Add Comment
Please, Sign In to add comment