Add 3rd dimension, use sprite instead of circle

3rd dimension (z value) is not used right now, but indices were updated to
support it. I should really make a Point class...

Using a sprite image instead of drawCircle noticeably improves performance.
This commit is contained in:
Tyler Hallada 2017-08-10 01:07:09 -04:00
parent d787cc306b
commit 20168d1dc4
2 changed files with 49 additions and 26 deletions

BIN
img/node.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -27,6 +27,7 @@ var click = null;
var hover = null; var hover = null;
var lastHover = null; var lastHover = null;
var clickEnd = false; var clickEnd = false;
var sprites = [];
// global configurable vars // global configurable vars
var resolution = 1; // scaling for PIXI renderer var resolution = 1; // scaling for PIXI renderer
@ -97,6 +98,8 @@ var hoverMaxDistStart = 75; // initial value for the effect radius of a hover: p
var hoverMaxDistMax = 1000; // maximum value of hoverMaxDist var hoverMaxDistMax = 1000; // maximum value of hoverMaxDist
var hoverMaxDist = hoverMaxDistStart; var hoverMaxDist = hoverMaxDistStart;
var hoverTweeningFn = 5; // specific tweening function to assign to points in effect radius var hoverTweeningFn = 5; // specific tweening function to assign to points in effect radius
var zRange = 10; // maximum value for the range of possible z values for a point (unused right now)
var nodeImg = 'img/node.png'; // image file location for representing every point
/* TWEENING FUNCTIONS */ /* TWEENING FUNCTIONS */
@ -354,18 +357,29 @@ function relativeCounter (counter, targetStart) {
return relCounter; return relCounter;
} }
function createSprite () {
return new window.PIXI.Sprite(
window.PIXI.loader.resources[nodeImg].texture
);
}
/* POINT OPERATION FUNCTIONS */ /* POINT OPERATION FUNCTIONS */
function getRandomPoints (numPoints, maxX, maxY, tweeningFns) { function getRandomPoints (numPoints, maxX, maxY, maxZ, tweeningFns) {
var i, x, y, color, cycleStart, easingFn; var i, x, y, z, color, cycleStart, easingFn, sprite;
var points = []; var points = [];
for (i = 0; i < numPoints; i++) { for (i = 0; i < numPoints; i++) {
x = randomInt(0, maxX - 1); x = randomInt(0, maxX - 1);
y = randomInt(0, maxY - 1); y = randomInt(0, maxY - 1);
z = randomInt(0, maxZ - 1); // TODO: do something with the 3rd dimension
cycleStart = randomInt(0, cycleDuration - 1); cycleStart = randomInt(0, cycleDuration - 1);
color = randomColor(); color = randomColor();
easingFn = tweeningFns[Math.floor(Math.random() * tweeningFns.length)]; easingFn = tweeningFns[Math.floor(Math.random() * tweeningFns.length)];
points[i] = [x, y, cycleStart, color, easingFn]; // save PIXI Sprite for each point in array
sprite = createSprite();
sprites.push(sprite);
stage.addChild(sprite);
points[i] = [x, y, z, cycleStart, color, easingFn];
} }
return points; return points;
} }
@ -373,11 +387,11 @@ function getRandomPoints (numPoints, maxX, maxY, tweeningFns) {
function shiftPoints (points, maxShiftAmt, counter, tweeningFns) { function shiftPoints (points, maxShiftAmt, counter, tweeningFns) {
var i, shiftX, shiftY, candidateX, candidateY; var i, shiftX, shiftY, candidateX, candidateY;
for (i = 0; i < points.original.length; i++) { for (i = 0; i < points.original.length; i++) {
if (points.target[i][2] >= cycleDuration) { if (points.target[i][3] >= cycleDuration) {
// cycleDuration was reduced and now this point's cycle is out of bounds. Randomly pick a new valid one. // cycleDuration was reduced and now this point's cycle is out of bounds. Randomly pick a new valid one.
points.target[i][2] = randomInt(0, cycleDuration - 1); points.target[i][3] = randomInt(0, cycleDuration - 1);
} }
if (points.target[i][2] === counter) { if (points.target[i][3] === counter) {
points.original[i] = points.target[i].slice(); points.original[i] = points.target[i].slice();
shiftX = randomInt(maxShiftAmt * -1, maxShiftAmt); shiftX = randomInt(maxShiftAmt * -1, maxShiftAmt);
shiftY = randomInt(maxShiftAmt * -1, maxShiftAmt); shiftY = randomInt(maxShiftAmt * -1, maxShiftAmt);
@ -397,9 +411,9 @@ function shiftPoints (points, maxShiftAmt, counter, tweeningFns) {
} }
points.target[i][0] = candidateX; points.target[i][0] = candidateX;
points.target[i][1] = candidateY; points.target[i][1] = candidateY;
points.target[i][4] = tweeningFns[Math.floor(Math.random() * tweeningFns.length)]; points.target[i][5] = tweeningFns[Math.floor(Math.random() * tweeningFns.length)];
// FIXME: buggy, makes points jump around too fast // FIXME: buggy, makes points jump around too fast
// points.target[i][2] = shiftPointCounter(points.original[i][2], maxShiftAmt); // points.target[i][3] = shiftPointCounter(points.original[i][3], maxShiftAmt);
} }
} }
// clear pointShiftBiases now that they have been "used" // clear pointShiftBiases now that they have been "used"
@ -425,7 +439,7 @@ function pullPoints (points, clickPos, pullRate, inertia, maxDist, counter, rese
points.target[i][0] += Math.round((targetXDiff + (inertia * originXDiff)) * pullRate); // pull X points.target[i][0] += Math.round((targetXDiff + (inertia * originXDiff)) * pullRate); // pull X
points.target[i][1] += Math.round((targetYDiff + (inertia * originYDiff)) * pullRate); // pull Y points.target[i][1] += Math.round((targetYDiff + (inertia * originYDiff)) * pullRate); // pull Y
// shift the color of each point in effect radius by some configurable amount // shift the color of each point in effect radius by some configurable amount
points.target[i][3] = shiftColor(points.original[i][3], clickColorShiftAmt); points.target[i][4] = shiftColor(points.original[i][4], clickColorShiftAmt);
if (tweeningFn !== null) { if (tweeningFn !== null) {
// Also switch the tweening function for all affected points for additional effect // Also switch the tweening function for all affected points for additional effect
// The tweening function will be re-assigned at the start of the point's next cycle // The tweening function will be re-assigned at the start of the point's next cycle
@ -433,8 +447,8 @@ function pullPoints (points, clickPos, pullRate, inertia, maxDist, counter, rese
} }
} }
// If this point's cycle is near it's end, bump it up some ticks to make the animation smoother // If this point's cycle is near it's end, bump it up some ticks to make the animation smoother
if (relativeCounter(points.target[i][2]) > Math.roundcycleDuration - 10) { if (relativeCounter(points.target[i][3]) > Math.roundcycleDuration - 10) {
points.target[i][2] = (points.target[i][2] + Math.round(cycleDuration / 2)) % cycleDuration; points.target[i][3] = (points.target[i][3] + Math.round(cycleDuration / 2)) % cycleDuration;
} }
} }
} }
@ -448,8 +462,8 @@ function redistributeCycles (points, oldCycleDuration, cycleDuration) {
// cycleDuration goes back up, the values will remain the same, making the points appear to dance in sync. // cycleDuration goes back up, the values will remain the same, making the points appear to dance in sync.
var progress; var progress;
for (var i = 0; i < points.original.length; i++) { for (var i = 0; i < points.original.length; i++) {
progress = points.target[i][2] / oldCycleDuration; progress = points.target[i][3] / oldCycleDuration;
points.target[i][2] = Math.round(progress * cycleDuration); points.target[i][3] = Math.round(progress * cycleDuration);
} }
return points; return points;
} }
@ -457,11 +471,11 @@ function redistributeCycles (points, oldCycleDuration, cycleDuration) {
/* DRAW FUNCTIONS */ /* DRAW FUNCTIONS */
function drawPolygon (polygon, points, counter, tweeningFns) { function drawPolygon (polygon, points, counter, tweeningFns) {
var i, j, easingFn, relativeCount, avgColor, shadedColor, connectionCount, dist, connectivity; var i, j, easingFn, relativeCount, avgColor, shadedColor, connectionCount, dist, connectivity, scale;
// calculate vectors // calculate vectors
for (i = 0; i < points.original.length; i++) { for (i = 0; i < points.original.length; i++) {
easingFn = allTweeningFns[points.target[i][4]]; easingFn = allTweeningFns[points.target[i][5]];
relativeCount = relativeCounter(counter, points.target[i][2]); relativeCount = relativeCounter(counter, points.target[i][3]);
points.tweened[i][0] = easingFn(relativeCount, points.original[i][0], points.target[i][0] - points.original[i][0], cycleDuration); points.tweened[i][0] = easingFn(relativeCount, points.original[i][0], points.target[i][0] - points.original[i][0], cycleDuration);
points.tweened[i][1] = easingFn(relativeCount, points.original[i][1], points.target[i][1] - points.original[i][1], cycleDuration); points.tweened[i][1] = easingFn(relativeCount, points.original[i][1], points.target[i][1] - points.original[i][1], cycleDuration);
@ -487,12 +501,12 @@ function drawPolygon (polygon, points, counter, tweeningFns) {
connectivity = dist / connectionDistance; connectivity = dist / connectionDistance;
if ((j !== i) && (dist <= connectionDistance)) { if ((j !== i) && (dist <= connectionDistance)) {
// find average color of both points // find average color of both points
if ((points.tweened[i][2] === counter) || (points.tweened[j][2] === counter)) { if ((points.tweened[i][3] === counter) || (points.tweened[j][3] === counter)) {
// avgColor = shiftColor(avgColor, Math.round(colorShiftAmt * (1 - connectivity))); // avgColor = shiftColor(avgColor, Math.round(colorShiftAmt * (1 - connectivity)));
points.tweened[i][3] = weightedAverageColor(points.tweened[i][3], points.tweened[j][3], connectivity); points.tweened[i][4] = weightedAverageColor(points.tweened[i][4], points.tweened[j][4], connectivity);
points.tweened[j][3] = weightedAverageColor(points.tweened[j][3], points.tweened[i][3], connectivity); points.tweened[j][4] = weightedAverageColor(points.tweened[j][4], points.tweened[i][4], connectivity);
} }
avgColor = averageColor(points.tweened[i][3], points.tweened[j][3]); avgColor = averageColor(points.tweened[i][4], points.tweened[j][4]);
shadedColor = shadeColor(avgColor, connectivity); shadedColor = shadeColor(avgColor, connectivity);
polygon.lineStyle(1, rgbToHex(shadedColor), 1); polygon.lineStyle(1, rgbToHex(shadedColor), 1);
@ -503,12 +517,18 @@ function drawPolygon (polygon, points, counter, tweeningFns) {
} }
if (connectionCount === 0) { if (connectionCount === 0) {
points.tweened[i][3] = shiftColor(points.tweened[i][3], disconnectedColorShiftAmt); points.tweened[i][4] = shiftColor(points.tweened[i][4], disconnectedColorShiftAmt);
} }
// draw vectors // draw vectors
polygon.lineStyle(1, rgbToHex(points.tweened[i][3]), 1); polygon.lineStyle(1, rgbToHex(points.tweened[i][4]), 1);
polygon.drawCircle(points.tweened[i][0], points.tweened[i][1], 1); // TODO: numbers here should be derived from a configuration variable
scale = 0.03;
sprites[i].scale.x = scale;
sprites[i].scale.y = scale;
sprites[i].x = points.tweened[i][0] - 1.5;
sprites[i].y = points.tweened[i][1] - 1.5;
sprites[i].tint = rgbToHex(points.tweened[i][4]);
} }
} }
@ -633,13 +653,13 @@ function loopStart () {
connectionDistance = Math.min(Math.round(totalScreenPixels / 16), 75); connectionDistance = Math.min(Math.round(totalScreenPixels / 16), 75);
pointShiftDistance = Math.round(totalScreenPixels / 45); pointShiftDistance = Math.round(totalScreenPixels / 45);
polygon = new window.PIXI.Graphics(); polygon = new window.PIXI.Graphics();
startPoints = getRandomPoints(Math.round(totalScreenPixels / 6), screenWidth, screenHeight, tweeningFns); stage.addChild(polygon);
startPoints = getRandomPoints(Math.round(totalScreenPixels / 6), screenWidth, screenHeight, zRange, tweeningFns);
polygonPoints = { polygonPoints = {
original: startPoints, original: startPoints,
target: JSON.parse(JSON.stringify(startPoints)), target: JSON.parse(JSON.stringify(startPoints)),
tweened: JSON.parse(JSON.stringify(startPoints)) tweened: JSON.parse(JSON.stringify(startPoints))
}; };
stage.addChild(polygon);
fpsGraphic = new window.PIXI.Text('0', {font: '25px monospace', fill: 'yellow'}); fpsGraphic = new window.PIXI.Text('0', {font: '25px monospace', fill: 'yellow'});
fpsGraphic.x = 0; fpsGraphic.x = 0;
@ -656,7 +676,10 @@ function loopStart () {
window.requestAnimationFrame(loop); window.requestAnimationFrame(loop);
} }
window.onload = loopStart; // Use PIXI loader to load image and then start animation
window.PIXI.loader
.add(nodeImg)
.load(loopStart);
/* MOUSE AND TOUCH EVENTS */ /* MOUSE AND TOUCH EVENTS */