My goal is to write a mini-game using canvas, one of the task is to create "bug" object entering the scene between every 1-3 seconds. I did try functions like setTimeOut,setInterval but I couldn't get it right. Here is my attempt
bugs =[];
function addBug(){
var bug = createBug();
bugs.push(bug);
}
function createRandomNumber(max){
return Math.floor((Math.random() * max) + 1);
};
var enterBug = setInterval(addBug,createRandomNumber(10)*1000);
currently I got it spawning at constant rate but don't know how to change it to every 1-3.Any suggestion? thanks in advance.
Currently, you are only setting the rate once at initial setInterval call. You would likely need to use setTimeout like this:
...
function addBug(){
...
bugTimeout = setTimeout(addBug, createRandomNumber(10)*1000);
}
...
bugTimeout = setTimeout(addBug, createRandomNumber(10)*1000);
You also may think about your random number generation if you want to get more randomness. Right now you can only get exact second values 1-10 since you are multiplying by 1000 to convert to seconds AFTER the random generation is done. If you want something more random you might use:
function createRandomNumber(maxSeconds){
minSeconds = 1;
if (maxSeconds < minSeconds) {
maxSeconds = minSeconds;
}
interval = maxSeconds - minSeconds;
return (Math.floor(Math.random() * interval) + minSeconds) * 1000;
};
You of course would not need to multiply by 1000 anymore when setting timeout.
bugTimeout = setTimeout(addBug, createRandomNumber(10))
Related
I am making a simple reaction time game for a final project.
We are using javascript to power the functions in the game, most of my code is in working order, but I have an if conditional statement that's giving me trouble.
Here's the code
function fireTime() {
setTimeout(ShotsFired, time);
function ShotsFired() {
fire.style.visibility = "visible";
createdTime = Date.now();
console.log(createdTime);
EnemyTime = Math.floor((Math.random() * 1000) + 400);
setTimeout(EnemyShoot, EnemyTime)
function EnemyShoot() {
console.log(EnemyTime);
gameplay();
}
function gameplay() {
reactionTime = -(createdTime - clickedTime);
var EnemyTime;
console.log(reactionTime);
if (reactionTime < EnemyTime) {
alert("Wow you beat him! Congrats!");
fire.style.visibility = "hidden";
clickedTime = 0;
createdTime = 0;
reactionTime = 0;
scavnumber++;
BGnumber++;
DesertBG.src = "images/Desert" + BGnumber + ".png";
scav.src = "images/scav" + scavnumber + ".png";
fireTime();
} else {
EndScreen.style.visibility = "visible";
}
}
This is not the entire code, just the function that should progress the game to the next level.
For whatever reason, even though reactionTime is less than EnemyTime, the EndScreen becomes visible.
Anyone know what could cause this?
Use floating point for your enemy time maths, i.e. 400.0 , else you are getting 0/1 seconds and not using milliseconds, and it is useing Math integer. Specifically cast your enemyTime as a float number, for the moment, if you print it it's probably an integer. its a MAJOR js coding detail that you will cost you hours of bughunting in the future if you think that 101/50 = 2.05, it isn't it equals 2, so divide by 50.0 and same with all second/ms tasks.
Use EnemyTime as a global variable for all scripts, at the moment, the code things you have a different function called EnemyTime in all scripts, the latter one has no value.
Use print to see when your else conditions work, specify a print in both an print the enemyTime value.
That's how you are supposed to resolve the issue, by printing the variables that are confusing.
I'm in the process of creating an incremental game in JavaScript (like CookieClicker, if you've ever played it).
To use CookieClicker as an example, you generate a certain number of cookies every second. If you're making 700 cookies per second, the counter increments by 1 cookie 700 times a second (or appears to).
Currently in my game, if you are making 700 "cookies" per second, the counter will increment by 700 "cookies" once per second, rather than increasing smoothly by a fixed amount.
I'm at a loss on how to do this. I've made a function that calculates the number of "cookies" you make per second, and I tried using that number to make the time parameter of window.setInterval() a variable, but I'm not even sure if that's possible let alone practical.
I'm pretty sure this isn't the right approach but I'll post the relevant code anyway:
function getManaPerSecond(){
manaPerSecond = earthEssence + (windEssence * 5) + (waterEssence * 10) +
(fireEssence * 150);
};
window.setInterval(function(){
getManaPerSecond();
}, 1000);
window.setInterval(function(){
if(manaPerSecond>0){
incrementalMana++;
document.getElementById('incrementalMana').innerHTML = incrementalMana;
}
}, (1000/manaPerSecond));
Whenever the frequency changes, you need to stop the old interval function and start a new one.
var manaCounter;
var oldManaPerSecond = 0;
function restartManaCounter(manaPerSecond) {
if (manaPerSecond != oldManaPerSecond) {
clearInterval(manaCounter);
oldManaPerSecond = manaPerSecond;
if (manaPerSecond > 0) {
manaCounter = setInterval(function() {
incrementalMana++;
document.getElementById('incrementalMana').innerHTML = incrementalMana;
}, 1000/manaPerSecond);
}
}
}
function getManaPerSecond(){
var manaPerSecond = earthEssence + (windEssence * 5) + (waterEssence * 10) + (fireEssence * 150);
return manaPerSecond;
};
window.setInterval(function() {
restartManaCounter(getManaPerSecond());
}, 1000);
I am trying to create a function that continuously adds the same number to itself. Or simply displays multiples of one number every so many seconds with the setInterval method.
For now, let's just say I want to display multiples of ten.
I know how to get a regular while loop to simply display multiples of ten in a row, but what I want to do here is continually replace the previous text every time the function is called. I am trying to create a game and this is going to be the experience calculator. So it needs to display the total experience earned over the given time.
I was trying something along the lines of this:
window.setInterval(
function writeExp ()
{
var j;
while (rounded > 0)
{
var i = w*10;
var j = j + i;
}
document.getElementByID("exp").innerHTML=j;
}, experience)
This seems logical enough to me, but obviously something is wrong, as it does not work. I have tried googling various things like how to sum numbers in javascript or continuously sum, among others, but it is somewhat difficult to word to get it more centered to my needs. So this is the best way to get my questions answered.
There are lot of undefineds in your code, but general example would be
var interval = 1000,
result = 0,
elem = document.getElementByID("exp");
window.setInterval(function () {
result *= 10;
elem.innerHTML = result;
}, interval);
or without global variables
var interval = 1000,
multiply = function (elem) {
var result = 0;
return function () {
result *= 10;
elem.innerHTML = result;
}
};
window.setInterval(multiply(document.getElementByID("exp")), interval);
I have a for loop that is running a timeout function that needs dynamic numbers but instead I'm getting the end result instead of the increments in some cases.
Here's my code (p.s. yes I realize setting 'start' variable inside for loop is not ideal):
var new_answer_start = 0;
var seconds = 0;
for (start=0; start<50; start++) {
new_answer_start = new_answer_start + 50;
seconds = seconds + 10000; //10 seconds
setTimeout(function(){reloadXMLDoc(xmlurl, new_answer_start);},seconds);
}
What I'm trying to accomplish is that increasing every 10 seconds the function will run with the new_answer_start equaling increments of 50. Instead I'm getting every 10 seconds the function is outputting each time starting at 2500 (the last set of numbers after 50 loops). I've had a similar issue before, something to do with closures and I used "let" to fix it then. However when I tried:
let new_answer_start = new_answer_start + 50;
I started getting NaN (not a number) errors. I thought it was weird that the timeout would increment in seconds (10, 20, 30, etc) but not the variable sent to the function. I'm assuming that's because once the function goes to run 10 seconds later, the variable increment has completed to the end. So how do I send the 'fixed' number to the function?
After doing research on similar questions here, I also tried putting the number into a closure:
setTimeout(function(){reloadXMLDoc(xmlurl, (new_answer_start));},seconds);
But this still start outputting at 2500.
Try using an actual closure:
setTimeout((function (new_answer_start) {
return function () {
reloadXMLDoc(xmlurl, new_answer_start);
};
})(new_answer_start), seconds);
window.new_answer_start = 0;
var interval = setInterval(function() {
window.new_answer_start = window.new_answer_start + 50;
}, 10000);
I know a few questions have been asked like this one before, such as this: Check FPS in JS? - which did work to some degree, I was able to find out how long each loop took to complete.
What I am looking for though is something more readable and controllable. I want to be able to set the refresh rate for the FPS counter to make it slow so it is human readable or as fast as the application can run, so I can use it on some kind of speedometer.
Anyway so here is the code I have right now:
var lastLoop = new Date().getTime();
function updateStage()
{
clearCanvas();
updateStageObjects();
drawStageObjects();
var thisLoop = new Date().getTime();
var fps = (thisLoop - lastLoop);
$('#details').html(fps);
lastLoop = thisLoop;
iteration = setTimeout(updateStage, 1);
}
Am I right to be setting the setTimeout function to a speed of 1 millisecond? I was thinking this will just make it loop as fast as it possibly can.
Should I count every 100 frames or so, find out how many milliseconds it took to run 100 frames then make a calculation to find out how many frames it would have done if the milliseconds were 1000? What would this calculation be?
To make the result more accurate I am guessing I need to display averages as one frame can vary a significant amount, how should I do this?
Any tips are greatly appreciated.
Thanks.
Note that the faster you update your output, the more you will affect your measurement. Although minimal, I try to update my fps output once per second or less unless it's necessary to go faster.
I like to have a low-pass filter on my results so that a temporary hiccup doesn't affect the values too strongly. This is easier to compute and write than a moving average, and doesn't have the problem of an overall average where your 'current' readings are affected by total performance over the entire run (e.g. anomalous readings during startup).
Put together, here's how I usually measure FPS:
var fps = 0, now, lastUpdate = (new Date)*1;
// The higher this value, the less the FPS will be affected by quick changes
// Setting this to 1 will show you the FPS of the last sampled frame only
var fpsFilter = 50;
function drawFrame(){
// ... draw the frame ...
var thisFrameFPS = 1000 / ((now=new Date) - lastUpdate);
if (now!=lastUpdate){
fps += (thisFrameFPS - fps) / fpsFilter;
lastUpdate = now;
}
setTimeout( drawFrame, 1 );
}
var fpsOut = document.getElementById('fps');
setInterval(function(){
fpsOut.innerHTML = fps.toFixed(1) + "fps";
}, 1000);
Ive tried something out,
If you change the
lastUpdate = now
to
lastUpdate = now * 1 - 1;
Your NaN problem is solved! This is also used where the lastUpdate is defined. Probably because it is not able to convert the date to unix timestamp.
The new result will be:
var fps = 0, now, lastUpdate = (new Date)*1 - 1;
// The higher this value, the less the FPS will be affected by quick changes
// Setting this to 1 will show you the FPS of the last sampled frame only
var fpsFilter = 50;
function drawFrame(){
// ... draw the frame ...
var thisFrameFPS = 1000 / ((now=new Date) - lastUpdate);
fps += (thisFrameFPS - fps) / fpsFilter;
lastUpdate = now * 1 - 1;
setTimeout( drawFrame, 1 );
}
var fpsOut = document.getElementById('fps');
setInterval(function(){
fpsOut.innerHTML = fps.toFixed(1) + "fps";
}, 1000);
I've taken the solution(s) posted and enhanced them a little. Have a look here - http://jsfiddle.net/ync3S/
I fixed that NaN error by using Date.now() instead of constructing a new date object each time and trying to reference it. This also prevents some garbage collection necessity.
I neatened up the variable and function names a bit and added some extra commenting - not necessary but nice to have.
I included some drawing code for testing.
I added fpsDesired as a test var for the engine loop.
I started fpsAverage at fpsDesired so with the fpsFilter it doesn't work up from 0 to the real FPS, rather starting at the desired FPS and adjusting from there.
Drawing now blocks incase it already was drawing, and this can be used for pausing and other control functions.
The main block is as follows:
var fpsFilter = 1; // the low pass filter to apply to the FPS average
var fpsDesired = 25; // your desired FPS, also works as a max
var fpsAverage = fpsDesired;
var timeCurrent, timeLast = Date.now();
var drawing = false;
function fpsUpdate() {
fpsOutput.innerHTML = fpsAverage.toFixed(2);
}
function frameDraw() {
if(drawing) { return; } else { drawing = true; }
timeCurrent = Date.now();
var fpsThisFrame = 1000 / (timeCurrent - timeLast);
if(timeCurrent > timeLast) {
fpsAverage += (fpsThisFrame - fpsAverage) / fpsFilter;
timeLast = timeCurrent;
}
drawing = false;
}
setInterval(fpsUpdate, 1000);
fpsUpdate();
setInterval(frameDraw, 1000 / fpsDesired);
frameDraw();
Going to have a tinker and see if I can come up with something smoother, as this thread is near the top in Google results.
Let's see what we can all come up with as a team, and I think it's always neat to not use 3rd party libraries, making the code portable for anyone :)
-Platima
Just set a interval that is resetting the fps counter every second.
var fpsOut, fpsCount;
var draw = function () {
fpsCount++;
..Draw To Canvas..
..Get the fps value: fpsOut
requestAnimationFrame(draw);
};
setInterval(function () {
fpsOut = fpsCount;
fpsCount = 0;
}, 1000);
draw();
If you want real-time updates, consider making it loop again and again in real time. To make it affect the performance less, only update the controlled variable, in this case, the FPS. You can have optional Frame Latency, which I will put here, just in case. Just copy, paste and tweak the code to your needs.
Take note that a single frame lasts for 16.66 miliseconds.
setInterval(function(){var latencybase1 = parseFloat(new Date().getTime());
var latencybase2 = parseFloat(new Date().getTime());
var latency = latencybase2-latencybase1;
var fps = Math.round(1000/latency);
if (latency<16.66)
{document.getElementById("FPS").innerHTML = fps+"
FPS";}
else {document.getElementById("FPS").innerHTML = ""+fps+" FPS";}
document.getElementById("Latency").innerHTML = latency+" ms";}, 0);