Firefly animation, browser gets slower after a while - javascript

I was checking out the demo of greensock. You can see that the result is a firefly animation, unfortunately the more time passes the slower the browser gets. Even if set to a total of 15-30 dots.
Is there any efficient way to stop the script from accumulating somehow?
function RN(x){
return Math.random()*x;
}
var total = 100 ;
var w = window.innerWidth;
var h = window.innerHeight;
var target = document.getElementById('container');
for (i=0; i<total; i++){
var e = document.createElement('div');
e.className = "dot";
e.opacity = 0;
e.style.left = RN(w)+'px';
e.style.top = RN(h)+'px';
target.appendChild(e);
animm(e);
}
function animm(elm){
TweenMax.killTweensOf(elm);
TweenMax.to(elm, (RN(80))+40, {
bezier:{
curviness:3,
values:[
{left:RN(w), top:RN(h)},
{left:RN(w), top:RN(h)}
]
},
onComplete:function(){
TweenMax.delayedCall(RN(2), animm, [elm]);
}
});
TweenMax.to(elm, (RN(4)+2),{
force3D:true,
opacity:RN(.7)+.1,
repeat:-1,
scale:RN(1.25)+.25,
yoyo:true,
ease:Bounce.easeInOut
});
};
http://codepen.io/maelfyn/pen/GgRLbg

Animate only X and Y properties, which are cheap for browser to render, not left and right. X and Y do not trigger recalculation of layout. Best solution would be proper redistribution of memory usage between CPU and GPU. Use CSS3 animations/transitions, which consume GPU instead of CPU (CPU is standardly used by javascript animations).

The browser is handling this just fine. If you change the speed to 3 temporarily you can see that the animation speed is getting slower as the dots settle towards their final destination finally coming to a stop, before starting the next animation.
TweenMax.to(elm, 3, {
bezier:{
curviness:3,
values:[
{left:RN(w), top:RN(h)},
{left:RN(w), top:RN(h)}
]
}
You should try playing around with various settings to get the dots to have a more even speed throughout the animation.

Related

Matter.js: Method to count how many times that an object has rotated?

I am creating a project in which a body is picked up and thrown by the user (with a mouse constraint). The body is set so that it can pivot about the constrain point. I need to find out, from the moment that it is let go, how many times it fully rotates (+-360 degrees) before landing. Reading the documentation, the only thing that I could find regarding the rotation was Matter.Body.rotate() which actually just sets the rotation of a body instead of recording it. How should I go about this?
Basically: How can I count an objects rotations?
This worked for me tbh:
var rad = 6.28;
var nrad = -6.28;
Events.on(engine, "tick", function () {
if(boxA.angle > rad){
rad+=6.28;
nrad+=6.28;
hrt +=1;
//hrt is the rotation c0unter
}
if (boxA.angle < nrad){
nrad-=6.28;
rad-=6.28;
hrt +=1;
}
rnum.innerHTML = "Spins: " + hrt;
fnum.innerHTML = fcounter; });

Three js tween js performance lag with many simultaneous tweens

Long time first time and all that - I'm new to Three.js and Tween.js and was hoping to see if it's possible to simultaneously tween 200k Three.js vertices from one position to another. Please excuse my interchangeable use of the words pixels and vertices.
I would like to display 200k pixels in a grid. A user can decide to sort these 200k pixels in a number of ways causing them to rearrange in the grid. I would like all pixels to simultaneously tween between their initial position and final position. Currently, I have the vertices simultaneously moving with tweens but I'm having severe performance issues once the animation nears completion. I hope someone can help!
For each of the 200k vertices I have a tween object associated with them living in this list that I create after drawing vertices in the scene,
var scPartVerts = scene.children[0].geometry.vertices;
var dataSetLen = 200000;
tweenList = []
for (i=0; i<dataSetLen; i ++){
tweenList.push(new TWEEN.Tween(scPartVerts[i]))
}
Using D3 (just what I was familiar with for handling click events), I provide each tween with a new XY position to move to
d3.select("#key").on("click", function() {
for (i = 0; i < dataSetLen; i ++){
var newX = desiredXPostionList[i]; //grab the new X from presorted list
var newY = desiredYPositionList[i]; //grab the new Y from presorted list
tweenList[i].to( {
x: newX,
y: newY
}, 2500)
.start();
}
I then update the tweens while rendering,
function render() {
scene.children[0].geometry.verticesNeedUpdate = true;
TWEEN.update();
renderer.render( scene, camera );
}
The animation appears to run fine for ~75% of the tween and then it comes to a grinding, stuttering, 0 FPS, screeching halt for around 30 seconds once the vertices are close to their final positions. I tried to look at the animation timeline and it appears that all of that time is being dumped into updating the tweens.
Am I somehow supplying redundant tween updates using my d3.select method? (Does javascript register one click as 10 and try to update the tween 10x?) Or can tween.js not smoothly tween 200k positions simultaneously? Thank you so much for any help!
My approach from scratch is to use loops for vertices. The solution is not the ultimate truth, of course.
The plan: set duration and current time of animation,
var duration = 10; // seconds
var currentTime = 10;
var clock = new THREE.Clock();
remember the end position of a vertex, set a random start position for it, find the vector between those positions (direction),
fieldGeom = new THREE.PlaneGeometry(500, 500, 500, 500);
fieldGeom.vertices.forEach(function(vertex){
vertex.startPosition = new THREE.Vector3(THREE.Math.randInt(-500,500),THREE.Math.randInt(-500,500),THREE.Math.randInt(-500,500));
vertex.endPosition = vertex.clone();
vertex.direction = vertex.startPosition.clone().sub(vertex.endPosition);
vertex.copy(vertex.startPosition);
});
then in animation loop add the result vector, multiplied with proportion of currentTime / duration
var delta = clock.getDelta();
currentTime -= delta;
if (currentTime < 0) currentTime = 0;
fieldGeom.vertices.forEach(function(vertex){
vertex.addVectors(vertex.endPosition,vertex.direction.clone().multiplyScalar(currentTime / duration));
});
fieldGeom.verticesNeedUpdate = true;
jsfiddle example with 250K points.

JavaScript - Timer Initiation

I'm trying to make my enemy fire every second. Right now - it's every frame.
Within my enemy object, I have a piece of code that is initiated when the player is within range:
this.shotBullet = false;
var object = this;
object.Fire();
This is the enemy fire function:
this.Fire = function(){
console.debug("Firing | Shot: " + this.shotBullet);
if(!this.shotBullet){
if(this.weapon == "pistol")
PistolEnemy(this);
this.shotBullet = true;
}
};
And my PistolEnemy function:
PistolEnemy = function(operator){
var user = operator;
console.debug("user:" + user.tag);
var bulletDamage = 1;
var bulletSpeed = 20;
var b = new Rectangle( user.x + (user.width / 2) - 4, user.y + (user.height / 2) - 4, 8, 8);
var velocityInstance = new Vector2(0, 0);
velocityInstance.x = Math.cos(user.rotation) * bulletSpeed;
velocityInstance.y = Math.sin(user.rotation) * bulletSpeed;
var bulletInstance = new Bullet(velocityInstance, b, "Enemy", bulletDamage, "blue");
/*audioPistol.volume = 0.5;
audioPistol.currentTime = 0;
audioPistol.play();*/
user.bullets.push(bulletInstance);
user.shotBullet = true;
};
I've tried playing around with the 'setInterval', but it doesn't work well. Most of the times, it waits for a second, then sprays a load of bullets.
All I want it for a enemy bullet to initiate every second.
Thanks
var triggerID = window.setInterval(function(){firing_clock()},1000);
function firing_clock()
{
// this will execute once per second....sort of
}
Mozilla window.setInteral doc
So, one thing you should known is if your browser gets busy it will get 'late'. Mozilla used to have an extra non-standard parameter detailing "actual lateness", but it no longer does - but the point was that you are asking the browser to try to do something once per second, but if it gets busy it will get behind or skip a few rounds (how the browser handles it differs by browser).
Ideally what you would do here is register your enemy object with a list that firing_clock() would work through to dispatch firing commands to all live enemies. This cuts overhead by only using one global timer, rather than one timer per object on screen.
Try this with just one hard-coded enemy and see how it works. If it still doesn't work, then it's a bigger problem as there is no javascript "guaranteed accurate timer" that I'm aware of.
But it should work, so long as things don't get too intense on the client's CPU, and having one global timer for ship firing should allow you to have a good number of ships firing away without too much ill effect.

How to speed up this moving algorithm? In Javascript

I have an Array of 16 billiard balls in JS and want to move each ball smoothly with its direction and speed.
For that I set up a timer, calling UpdateThis() every 42ms (for 24 fps).
The problem is that UpdateThis() takes 53ms as firebug states.
Now UpdateThis iterates over every ball and calls UpdateBall(ball).
I assume that the problem lies there.UpdateBall looks like this:
function UpdateBall(ball)
{
if(ball.direction.x != 0 && ball.direction.y != 0) {
//ball moving!
for(var i = 0; i < balls.length; i++) {
//CheckCollision(ball, balls[i]); //even without this it takes 53 ms!
}
var ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Multiply Direction with speed and add to position!
if(ps.x < Bx || ps.y < By || ps.x > Bw || ps.y > Bh) { //Bounce off the wall!
ball.direction = VMul(ball.direction, -1); //Invert direction
ball.speed *= 1;
ps = VAdd(ball.position, VMul(ball.direction, ball.speed)); //Calc new position!
}
ball.position = ps;
ball.MoveTo(); //See explanation at the bottom.
ball.speed *= GRK; //Gravity
if(ball.speed < 0.05) {
ball.speed = 0;
}
}
}
it seems that the most time is spent in ball.MoveTo() which looks like this:
function()
{
this.image.style.left = this.position.x + "px";
this.image.style.top = this.position.y + "px";
}
-- UPDATE --
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
and onload looks like
nx = setInterval(function() { UpdateThis(); }, 42);
Does somebody have any ideas on how to speed this up?
-- UPDATE 2 --
You can download the folder with the HTML file here (the password is password)
What about separating the position updates from the drawing? So have something like this (untested code):
function DrawBall(ball)
{
ball.MoveTo(); //Take this line out of UpdateBall
}
-
function UpdateThis() {
for(var i = 0; i < balls.length; i++) {
var cur = balls[i];
UpdateBall(cur);
balls[i] = cur;
}
}
-
function DrawThis() {
for(var i = 0; i < balls.length; i++) {
DrawBall(balls[i]);
}
setTimeout(function() { DrawThis(); }, 42);
}
-
nx = setInterval(function() { UpdateThis(); }, 42);
setTimeout(function() { DrawThis(); }, 42);
If indeed it's the moving of the position that's slow, this way the logic update still happens at 42ms, and the framerate is no faster than 42ms but it can skip frames. (I haven't actually tried this, so this is all theoretical and you may need to tweak some stuff)
Why moving may be (and most probably is) slow?
Move functionality could be slow, because it has more things to do than simple variable assignment. It has to actually render some element to some other place. You could test this if you run this on IE9. I anticipate it should run faster since it uses hardware video acceleration.
As for the other routine I hope others will dissect it. :)
Questions for you
Can you please describe how do balls move? Sporadically? How do you call UpdateBall() for each ball? Do you queue those calls?
Provide VMul and VAdd functionality
Have you played with styling? Maybe relative positioning of balls' immediate parent may speed up rendering. And setting overflow:hidden on it as well. I don't know. Depends on how you've done it. Hence a JSFiddle would be very helpful.
A suggestion
Instead of using setInterval to call your function you should maybe just queue them and let them execute as fast as it gets. And just for the sake of it, provide a central setInterval with some watcher that they don't run too fast.
But I guess that it still utilizes your processor to 100% which isn't good anyway.
Very important note: Don't run you app while Firebug's enabled because it's a well known fact that Javascript executes much slower when Firebug is running.
That's tough, if MoveTo() is in fact your bottleneck, since there is not a whole lot going on there. About the only things I can think of, right off hand, are
1) Cache the style property of the image and position for faster lookups. Everytime you see a dot in the object chain it's requires stepping through the scope chain. Ideally you can cache this property at the time the parent of MoveTo() is constructed.
2) Are the 'px' strings required? It may result in an invalid CSS specification, but it may still work. I have a hard time believing 2 string concats would really change all that much though.
The main problem here is likely the fact that anytime you change the DOM, the browsers re-flows the entire page. Your only other option may be to refactor such that instead of changing the styles, you actually remove the previous contents, and replace it with the a document fragment describing the new state. This would result in only 2 re-flows for the entire step (1 for removal, 1 for addition), instead of 2 for each ball.
EDIT: Regarding #1 above, when I say cache, I don't mean just locally in the function call. But perhaps as a closure in the parent object. For example:
var Ball = function(img){
var style = img.style;
var posX;
var posY;
function MoveTo(){
style.left = posX + "px";
style.right = posY + "px";
}
};

How to optimize this js (now CPU is over 40% when the page is opened)

I have this piece of JavaScript on my page and it loads the CPU considerably. Is there any way to optimize the code? ( I'm using jQuery, so jQuery solutions will be fine )
function Particle() {
this.particleContainerWidth = $('#particle-container').width() - 100;
this.particleContainerHeight = $('#particle-container').height() - 100;
this.path = 'img/';
this.images = ['particle1.png', 'particle2.png', 'particle3.png', 'particle4.png'];
// Randomly Pick a Particle Model
this.image = this.images[randomInt(this.images.length)];
this.file = this.path + this.image;
// Create a Particle DOM
this.element = document.createElement('img');
this.speed().newPoint().display().newPoint().fly();
};
// Generate Random Speed
Particle.prototype.speed = function() {
this.duration = (randomInt(10) + 5) * 1100;
return this;
};
// Generate a Random Position
Particle.prototype.newPoint = function() {
this.pointX = randomInt(this.particleContainerWidth);
this.pointY = randomInt(this.particleContainerHeight);
return this;
};
// Display the Particle
Particle.prototype.display = function() {
$(this.element)
.attr('src', this.file)
.css('position', 'absolute')
.css('top', this.pointY)
.css('left', this.pointX);
$('#particle-container').append(this.element);
return this;
};
// Animate Particle Movements
Particle.prototype.fly = function() {
var self = this;
$(this.element).animate({
"top": this.pointY,
"left": this.pointX
}, this.duration, 'linear', function(){
self.speed().newPoint().fly();
});
};
function randomInt(max) {
// Generate a random integer (0 <= randomInt < max)
return Math.floor(Math.random() * max);
}
$(function(){
$('body').append('<div id="particle-container"></div>');
var total = 8;
var particles = [];
for (i = 0; i < total; i++){
particles[i] = new Particle();
}
});
You cannot make JavaScript consume less of your CPU. That is governed by the priority of the executing application in the OS kernel. The best you can hope for is to reduce execution time.
To improve your execution efficiency limit your usage of prototype and stop assigning values to properties. This method of coding has become popular because it is extremely clean and easy to read, but it horribly backwards to execute.
If you are capable of coding using only variables for assignment, if statements for decisions, and for loops for looping your code execution will be far faster. That will require you to write more code, however, and it will not be so pretty.
To improve output performance write all output segments each into an index of an array and use only a single join method when all output is created and a single innerHTML method to output this text to the page. This will reduce output execution by up to 4 times.
Have you thought about implementing this with a <canvas> version? It won't work in IE directly, of course, and off-hand I'm not sure whether it'd be faster or slower. You could also try it with Processing.
This would need a lot of changing and rewriting, but You can create a new easing function for jquery and post it to animate. Then every particle You have would just be once issued with animate() with Your easing function and the function has to be based on those:
random
current time (new Date()) modulo some number
a singleton holding individual directions
ideas:
Assuming You don't want to change Your code You can try setting the particle to fly with some random timeout when first running fly(). It could change the way it's all executed. No idea if it helps or makes it slower though ;)
Second thing is quality. jquery animate does it too smoothly. You can move Your particles instead of animating and just chande the distance to lower and increase speed and use setTimeout to make it move the same pace as now.

Categories