I have four objects I want to appear, one after another, with one second in between. What's the standard way of doing time-based animation?
My idea is to to continually ask for the Ticker's time for a period of 5 seconds, and when the Ticker hits the 1-, 2-second marks, the objects get created:
startAnimationTime = Ticker.getTime();
while (Ticker.getTime()-startTime < 5000) {
if (Ticker.getTime() == 1000) {
// create first object
} else if (Ticker.getTime() == 2000) {
// create second object
} else if ...
Is there a more elegant way of doing this? Thanks!
You could use TweenJS for this. Other than animation, it makes a swell timer, mainly due to the chaining you can do with it.
var tween = createjs.Tween.get(this).wait(1);
for (var i=0; i<10; i++) {
tween.wait(2000).call(createObjectFunction, [i, otherArg], this);
}
tween.call(doneFunction, null, this); // Call something when done
This will run a function every 2 seconds, 10 times.
I would suggest using TweenMax/GSAP an awesome tweening engine with a timeline engine as well. You could do what you want in various ways. Simplest would be:
TweenMax.delayedCall(1, function(){//create first object });
TweenMax.delayedCall(2, function(){//create second object });
etc...
...or use TimelineMax or TimelineLite to properly control things.
Just realised it's basically exactly what #Lanny said but using a different tweening engine. The advantage of Lannys suggestion is tweenJS is already there in createJS, I just use TweenMax/GSAP because I'm used to it ;)
Related
I am trying to create a timer to limit the amount of time a player can use their jetpack in my phaser game. I've been following this(http://www.joshmorony.com/how-to-create-an-accurate-timer-for-phaser-games/) but I can't get anything to work. Is there a better way to implement this?
var use_jetpack;
jetpack_timer = game.time.events.add(
Phaser.Timer.SECOND * 1 /*change the 1 to however many seconds you want*/,
end_jetpack /*runs the function end_jetpack*/,
this);
function end_jetpack(){
use_jetpack = false;
//if you want a cool down, put it here. follow what was done in line 3.
}
if(use_jetpack){
//player can use jetpack
}else{
//player cannot use jetpack
}
Try this. I don't know what you couldn't get to work, but this is what my implementation would be. Of course you would need to put functions in update(), and the variable wherever you put those. This is just a quick demo. Also I had odd formatting for teaching purposes.
I have written javascript that takes 20-30 seconds to process and I want to show the progress by updating the progress bar on my webpage.
I have used setTimeout in an attempt to allow webpage to be re-drawn.
This is how my code looks like:
function lengthyFun(...){
for(...){
var progress = ...
document.getElementById('progress-bar').setAttribute('style',"width:{0}%".format(Math.ceil(progress)));
var x = ...
// Processing
setTimeout(function(x) { return function() { ... }; }(x), 0);
}
}
It does not work, I know why it does not work, but I don't know how to refactor my code to make it work.
As you probably know, the problem here is that you main process (the one that takes a lot of time), is blocking any rendering. That's because JavaScript is (mostly) mono-threaded.
From my point of view, you have two solutions to do this.
The first one is to cut down your main process into different parts and to do the rendering between each of them. I.e. you could have something like that (using Promises) :
var processParts = [/* array of func returning promises */];
function start(){
// call the first process parts
var firstPartPromise = (processParts.shift())();
// chain it with all the other process parts interspersed by updateDisplay
return processParts.reduce(function(prev, current){
return val.then(current).then(updateDisplay);
}, firstPartPromise);
}
You will probably need a polyfill for the promises (one here). If you use jQuery, they have a (bad non standard) implementation.
The second solution can be to use webworkers which allows you to create threads in JavaScript. It works on all modern browsers.
It is probably the best solution in your case.
I never used them but you are supposed to be able to do stuff like:
var process = new Worker("process.js");
worker.onmessage(function(event){
updateProgress(event.data.progress)
});
And the in process.js:
postMessage({progress: 0.1});
// stuff
postMessage({progress: 0.4});
// stuff
postMessage({progress: 0.7});
//etc
Try setting progress element attribute min to 0 , max to 20000 , value to 0 ; create function where if value less than max increment value by 1000 ; utilize setTimeout with duration set to 1000 to call function recursively until value reaches max
var p = document.querySelector("progress");
function redraw() {
if (p.value < p.max) {
p.value += 1000;
setTimeout("redraw()", 1000)
}
}
redraw()
<progress max="20000" min="0" value="0"></progress>
There are a couple of ways that I know of to trigger sequential HTML redraws through Javascript:
Incremental Timeout Period
Recursive Method Calls
The first and easiest way of doing this is by using a multiplier (such as the iterator) on the timeout interval in a loop. This method should be sufficient if the operation is independent of external variables and only needs to be run a finite and relatively few number of times. The more operations required/likely to occur, the greater the strain on resources - just for calculating intervals. Another drawback takes effect when the processing time exceeds the timeout interval, causing a knock-on to the interval of the observed redraws. The result of this can be that the web page freezes up entirely until all operations are done.
Example
for (var i=0, limit=n; i<limit; i++) {
setTimeout((function(params) {
return function() {
some_func(params);
}
})(param_values), i*1000);
}
The second method is a little more convoluted, but guarantees redraws between each operation, regardless of the timeout interval. Here, the timeout only affects the time between redraws ands resists the effects of consecutive operation variables. However, the processing time for the current operation is still a factor for the observed interval and will still freeze up a web page between redraws if the operation is computationally intensive.
Example
var limit = n;
var i = 0;
recursive_timeout();
function recursive_timeout() {
setTimeout((function(params) {
return function() {
some_func(params);
i++;
if (i<limit) {
recursive_timeout();
}
}
})(param_values, i, limit), 1000);
}
Refined Example (based off guest271314's answer)
var still_true = true;
recursive_timeout();
function recursive_timeout() {
some_func(params);
if (still_true) {
setTimeout(function() {recursive_timeout();}, 1000);
}
}
While the incremental method is fine for simple tasks, recursion will reliably perform redraws. If long processing times per operation is an issue, then it might be worth delving into asynchronous tasks in addition to using recursion in order to avoid rendering a web page temporarily unusable.
Anyway, hope this helps!
Ha! Just realised guest271314 put up a much more elegant example of the recursive method... Oh well, more info can't hurt.
Here is the problem, I've got a tree structure of html blocks, global container is of a fixed width(X) and height(Y). When i click one of the blocks on a level, all other blocks shrink to some size, while the clicked one gets enlarged to the leftover space, and the sublevels show up on it's place.
For all the shrinking i'm using default animate function with easing effect, when shrinking 1 level, to avoid enlargement bugs i have to do something like this:
$tabs.not($obj).animate({height:32<<$obj.getVerUp().length+"px"},{duration:300,
step:function() {
$obj.height(function(){
var sum = 0;
$tabs.not($obj).each(function(){
sum += $(this).height();
});
return $obj.getCont().height()-sum+"px";
});
}
});
$tabs are all the tabs of current level, $obj - is the one tab that i want to enlarge
The main problem is:
When i open up a tab that is on a deep level, i have to animate all the tabs of higher levels to shrink a little bit more, thus the $obj X and Y would change, so the current animation has to use new values, but if i call 3 different animations on different levels i'm bound to get a bug, when one of the animations on a deeper level finishes 1 step earlier, while the one on the level above, would enlarge the object by 5-10 more pixels and that space wouldn't be used up.
The second problem is that there has to be about 50 object animating with easing at the same time, which is a little bit overkill.
And the last problem is when i call step callback on animation as shown above, i have a strange feeling that it calls the step separately for each animation of the $tabs collection, while i need 1 step for all the tabs in the list (to avoid unnecessary scripts)
There might be some other way to fix all that, but i have yet to discover all jQuery functions, so from what i see the only way is to simulate easing, and do everything in one single animation.
I don't really want to use setInterval and determining when do i need to clear it plus calculating each of the easing values, if there is a simple way doing it.
Does jQuery has some sort of empty animation easing, e.g.
$().css("height":starth+"px").animate({height:endh},{duration:300,
step:function(fn) {
// all the animation actions here via fn end value
}
});
Thanks in advance.
What I need - is not a completely working solution in code, just some enlightenment in those subjects:
Is there a legal way to call one step function for a collection of animated elements, or, maybe, it does call step once when I use one .animate on collection.
I'd be really appreciated if someone would shed some light over how does jquery handle multiple .animate, would they be used in one global function that works on .setInterval? or would they be having massive number of those .setIntervals that are equivalent to setTimeout (which most browsers can't handle in large amounts);
Is there a way to simulate 'animate' easing, some function name maybe, or a special trick to achieve that (the only thing I see is a hidden element or 'window' property to change maybe)
Or some directed pushes with functions I should study, that could help me achieve my goals
Guess i pretty much found the answer to my questions:
http://james.padolsey.com/javascript/fun-with-jquerys-animate/
Here's the empty animation from the link above with 1 step function with desired values, going to post the result later on if it all works out.
var from = {property: 0};
var to = {property: 100};
jQuery(from).animate(to, {
duration: 100,
step: function() {
console.log( 'Currently # ' + this.property );
}
});
Yes it all worked great, no desynch, and a good speed, since only 1 animate, found making one universal function for the animation - waste of resourses, so it is pretty specific, but still, here it is:
animate: function($obj) {
var T = this;
...
T.arr = new Array();
// gathering the array
$obj.each(function(i){
var size;
T.arr[i] = {obj:$(this), rest:$(this).getSibl(), cont:$(this).getCont()}
if($(this).hasClass("vert"))
{
size = "height";
T.arr[i].to = yto;
}
else
{
size = "width";
T.arr[i].to = xto;
T.arr[i].children = $(this).getChld();
}
T.arr[i].rest.each(function(){
$(this).attr("from",$(this)[size]());
});
});
// animating prop
jQuery({prop:0}).animate({prop:1}, {
duration: 300,
step: function() {
var i;
var P = this;
var newval;
var sum;
var size;
for(i = 0; i < T.arr.length; i++)
{
size = T.arr[i].obj.hasClass("vert") ? "height":"width";
sum = 0;
T.arr[i].rest.each(function(){
// new value of width/height, determined by the animation percentage
newval = parseInt($(this).attr("from")) + (T.arr[i].to-$(this).attr("from"))*P.prop;
$(this)[size](newval);
sum += newval;
});
T.arr[i].obj[size](T.arr[i].cont[size]()-sum);
}
}
});
},
I have two instances of setInterval. Each is triggering a different function ( these two functions are title quarterNoteFunc & eighthNoteFunc ) at repeated intervals. The interval for quarterNoteFunc is 600 milliseconds. The interval for eighthNoteFunc is 300 milliseconds. Both of these functions each trigger a different audio file at repeat intervals hence creating a basic music rhythm. The rhythm between the two function calls eventually "drifts" in Google Chrome making the rhythm between the two sounds dissolve. My question is:
It seems that even though browser based timing is garbage their should be a way to create some kind of "hard" timing reference so that the sounds are locked even if the "global" timing gets offset hence keeping the sounds in sync. I thought assigning the same variable milliseconds (code below) would inhibit this - but I was wrong.
The (abbreviated) code looks like this
milliseconds = 600;
quarterNote = setInterval(quarterNoteFunc, milliseconds);
eighthNote = setInterval(eighthNoteFunc, milliseconds/2);
Probably the best way to do this is to have a single, always active 1/8 note interval, then call the quarter-note every other tick:
// wrapped in a closure to allow for a private tickCount variable
// alternatively, you could use a more advanced object with start/stop methods, etc.
(function() {
var tickCount = 0,
tick = function() {
eighthNoteFunc();
if(tickCount %2 == 0) {
quarterNoteFunc();
}
tickCount++;
};
setInterval(tick, 300);
})();
This ensures that the methods are always called on the same tick. You can also expand this to support half notes (tickCount % 4 == 0) and whole notes (tickCount % 8 == 0).
This interested me, so I decided to create a fully-working sample (except, using animated backgrounds instead of audio): http://jsfiddle.net/SycBm/
This allows you to see the eighth-, quarter-, and half- notes ticking in sync, as well as start & stop the timer, and independently enable or disable the notes.
Enjoy!
I have run in to a problem I do not know how to code in JavaScript really. The thing is I would like to be able to create a lot of objects added to an Array. when objects are created to be added to this array they will have a "lifetime". When this lifetime runs out this object should be removed from the array.
What Im trying to build here is a particle system where particles will vanish from being rendered after the particles lifetime in question have expired.
Anyone who have a good idea or example for this?
I have thought about using setTimeout, setInterval and clearInterval but not sure how this would be most effective.
Something like this?
Update for Felix Kling:
var a = [], next = function() {
a = a.slice(0,-1);
document.body.innerHTML += a.length + "<br />";
if (a.length != 0)
setTimeout(next, 100);
};
for (var i = 0; i < 100; i++) {
a.push({hi: 1});
}
setTimeout(next, 100);
You can use the code sample of micha. On every call of "next" function you can update the state of you particles (position, velocity, etc). Also you can track the time of the creation of the particles and on every "next" call check if the current time minus the creation time exceeds certain constant and if it does then remove the particles. Depending on the required quality of the animation you may want to reduce the time between timeouts, e.g. setTimeout(next, 25);
Good luck :)