Issue with EaselJS - javascript

I developing TD game with EaselJS and faced with one problem.
When enemy come to castle he should should to start attack it with uniq delay.(for example witch:3 seconds, elemental:2 seconds e.t.c.)
How to set this delay with enabled ticker?
createjs.Ticker.on("tick", moveTick);
createjs.Ticker.setFPS(20);
console.log(mobs);
function moveTick(event) {
for (var i = 0; i < mobs.length; i++) {
if (mobs[i].y > stage.canvas.height - castle.castleHeight - mobs[i].elemSize) {
setTimeout(console.log("attacking"), 600000);
} else {
mobs[i].y = mobs[i].y + mobs[i].movementSpeed;
}
}
field.update(event);
}

Since you know how many seconds you want to have something wait before performing an action, and you know how many frames per second your program will run at, what you can do is count frames before performing an action.
A good way to count the frames would be to maintain a tick counter, and decrement the counter any time it is a positive number, and then performing an action once the counter hits 0. Here is a code example partially making use of your code of how this might work:
createjs.Ticker.on("tick", moveTick);
createjs.Ticker.setFPS(20);
console.log(mobs);
// note that enemy_ticker would probably be a property of your enemy object:
var enemy_ticker = -1;
function moveTick(event) {
if (event that causes enemy to attack soon) {
enemy_ticker = 60; // this gives us 3 seconds
}
if (enemy_ticker > 0) {
enemy_ticker--;
} else if (enemy_ticker = 0) {
enemy_ticker--;
// put your code to start your enemy's attack here
}
field.update(event);
}

Related

How to make the alert pop up after the spin results?

I'm making a very each game for school project, it should works like this:
User click spin, 3 cards will display elements
If all 3 cards matches, the balance will add $50, and pop up alert "you won!"
Otherwise, it will subtract $10 for each spin doesn't match.
If the balance fall below $10, pop up alert "you have less than $10.
I'm trying to make the alert pop up after the slots rendered and balance updated, however the alert always pop up ahead. Any idea how to fix it?
let slotsContainer = document.getElementById('slots');
let balanceContainer = document.getElementById("balance-container");
let tries = document.getElementById("tries");
const INITIAL_AMOUNT = 1000;
let values = ['❤', '🌞', '👻'];
let number_of_spinners = 3;
let spinCount = 0;
let slot_els = [];
let balance = INITIAL_AMOUNT;
balanceContainer.innerHTML = balance;
function render(result) {
slotsContainer.innerHTML = '';
for (var i = 0; i < number_of_spinners; i++) {
let spinner = document.createElement('div');
spinner.innerHTML = result[i];
slotsContainer.appendChild(spinner);
slot_els.push(spinner);
}
}
render(['?', '?', '?'])
function getOneRandomNumber() {
return Math.floor(Math.random() * values.length);
}
function spin_func() {
let firstRandomValue = getOneRandomNumber();
let secondRandomValue = getOneRandomNumber();
let thirdRandomValue = getOneRandomNumber();
render([values[firstRandomValue], values[secondRandomValue], values[thirdRandomValue]]);
if ((firstRandomValue === secondRandomValue) && (secondRandomValue === thirdRandomValue)) {
balance += 50;
balanceContainer.innerHTML = balance;
alert("you won!");
} else {
if (balance >= 10) {
balance -= 10;
balanceContainer.innerHTML = balance;
} else {
alert("You have less than $10");
}
}
console.log('spin!!!');
}
let spin_button = document.getElementById('spin');
spin_button.onclick = spin_func
The DOM is rendered asynchronously so you need to trigger the alert asynchronously.
Try replacing alert("xyz"); with setTimeout(alert, 0, "xyz"); where you are using it.
If you want the player to have time to read the result before triggering the alert, just increase the delay expressed in milliseconds from 0 to 2000 (2 seconds).
Ok. This is because the JS code runs so fast it spins but you don't see it.
This code
for (var i = 0; i < number_of_spinners; i++) {
let spinner = document.createElement('div');
spinner.innerHTML = result[i];
slotsContainer.appendChild(spinner);
slot_els.push(spinner);
}
Would need to be slowed down using a delay. The delay would need to be say 1/4 of a second per animation. Then the code would allow you to see it. Afterwhich the alert would fire and it would work as expected.
The problem here now is that you would need to make the code asynchronous.
Otherwise it still will not work.
Here is a Question of SO re a loop with a delay
How do I add a delay in a JavaScript loop?
You need to make this call your alert (finish) code when the loop completes otherwise, it still won't work.
The principle is:
run a loop that fires the animation
delay the next iteration by the animation speed say 600ms
call the alert/end code when the loop completes

Javascript move target around screen?

So I'm working on a basic shooter, part of which involves moving a target around the screen. I'm using babylon.js as the engine and my goal is to have the target appear for 0.75 seconds on the screen, then disappear for 0.5 seconds, then reappear at a different random location. The current code I have for that is this:
function moveTarget(canvas, scene){
setTimeout( function (){
scene.meshes[10].visibility = 0; //how I access the target object
randX = genRandNum(minX, maxX); //This is a separate function that works
randY = genRandNum(minY, maxY);
scene.meshes[10].position = new BABYLON.Vector3(randX, randY,
scene.meshes[10].position.z);
scene.meshes[10].visibility = 1;
x ++;
if (x < amount){
moveTarget(canvas, scene);
}
}, tarDuration * 1000)
}
which succeeds in everything except the 0.5 second delay between appearances of the target, ie currently it flashes from location to location with no space in between. I'm thinking that I need a second setTimeout but I'm not entirely sure how to include that or where it would go. Any pushes in the right direction would be much appreciated.
The way I would do this is to set a timeout for the full cycle time (0.75 s + 0.5 s) and then another timeout inside that for the 0.5 s delay.
function moveTarget(canvas, scene){
setTimeout( function (){
setTimeout( function(){
// Your other code
x ++;
if (x < amount){
moveTarget(canvas, scene);
}
}, yourDelayHere)
}, tarDuration * 1000)
}
Where yourDelayHere gives the desired 0.5 s delay. I created a Babylon.js playround which shows a simplified example here.

Delay logic for web automation chrome extension (Javascript)

I am making a chrome extension for web automation.The first step is to get a list of sites and instructions from a server in a delimiter-format.
Once the list is obtained it is divided into an array that i call "siteArray".
The site array is then divide into another array i call "instructionsArray"
and among those items in the array one of them is the duration spent on the site i.e instructionsArray[5] has the value of "10" seconds. {the duration is not the same for all the sites}
My question arises in how to delay(implementing duration)
One implementation I found is using a sleep function which turns out to be inefficient as it is just a long for loop
see code:
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
and then:
getlist();
for each(siteArray){
instructionsArray = siteArray[count].split(delimiter);
gotoUrl(instructionsArray[1]);
sleep(instructionsArray[5]);
count++;
}
Where
getlist() fetches a list of instructions and splits into the
siteArray .
gotoUrl() changes url.
sleep() runs the sleep function.
Is there a better way to implement a duration/wait/delay.
Rework the way you iterate over the array: process one entry, set a timer, repeat.
var count = 0;
processSite();
function processSite() {
if (count >= siteArray.length) {
console.log('all done!');
return;
}
var instructionsArray = siteArray[count].split(delimiter);
count++;
gotoUrl(instructionsArray[1]);
setTimeout(processSite, instructionsArray[5]);
}
After giving much thought into it I have solved the issue.
Using wOxxOm's idea I came up with this 'sub-idea' to create multiple timeouts i.e
for(index = 1;index<(siteArray.length);index++){
instructionsArray = siteArray[index].split(delimiter);
bigtime+=instructionsArray[5];
setTimeout(function(){processNext(count)},bigtime);
}
This code creates multiple timeout functions for each site.
similar to :
setTimeout(function(){processNext(count)},10 sec);
setTimeout(function(){processNext(count)},10+10 sec);
setTimeout(function(){processNext(count)},10+10+10 sec);
but in a dynamic way.
The count variable is change in the processNext function:
processNext(count){
instructionsArray = siteArray[count].split(delimiter);
visitUrl(instructionsArray[1]);
count++;
}
I give Thanks to wOxxOm for the insight.

JavaScript Automated Clicking

So, here's my issue.
I need to write a script to be run in the console (or via Greasemonkey) to automate clicking of certain links to check their output.
Each time one of these links is clicked, they essentially generate an image in a flash container to the left. The goal here is to be able to automate this so that the QC technicians do not have to click each of these thumbnails themselves.
Needless to say, there needs to be a delay between each "click" event and the next so that the user can view the large image and make sure it is okay.
Here is my script thus far:
function pausecomp(ms) {
ms = ms + new Date().getTime();
while (new Date() < ms){}
}
var itemlist, totalnumber, i;
itemlist = document.getElementsByClassName("image");
totalnumber = parseInt(document.getElementById("quickNavImage").childNodes[3].firstChild.firstChild.nodeValue.replace(/[0-9]* of /, ""));
for(i = 0; i < totalnumber; i = i + 1) {
console.log(i);
itemlist[i].childNodes[1].click();
pausecomp(3000);
}
Now, totalnumber gets me the total number of thumbnails, obviously, and then itemlist is a list of get-able elements so I can access the link itself.
If I run itemlist[0].childNodes[1].click() it works just fine. Same with 1, 2, 3, etc. However, in the loop, it does nothing and it simply crashes both Firefox and IE. I don't need cross-browser capability, but I'm confused.
There is a built-in JS function "setInterval(afunction, interval)" that keeps executing a given function every "interval" miliseconds (1000 = 1s).
This fiddle shows how to use setTimeout to work through an array. Here is the code:
var my_array = ["a", "b", "c", "d"];
function step(index) {
console.log("value of my_array at " + index + ":", my_array[index]);
if (index < my_array.length - 1)
setTimeout(step, 3000, index + 1);
}
setTimeout(step, 3000, 0);
Every 3 seconds, you'll see on the console something like:
value of my_array at x: v
where x is the index in the array and v is the corresponding value.
The problem with your code is that your pausecomp loop is a form of busy waiting. Let's suppose you have 10 items to go through. Your code will click an item, spin for 3 seconds, click an item, spin for 3 seconds, etc. All your clicks are doing is queuing events to be dispatched. However, these events are not dispatched until your code finishes executing. It finishes executing after all the clicks are queued and (roughly) 30 seconds (in this hypothetical scenario) have elapsed. If the number of elements is greater that's even worse.
Using setTimeout like above allows the JavaScript virtual machine to regain control and allows dispatching events. The documentation on setTimeout is available here.
People were correct with SetInterval.
For the record, here's the completed code:
/*global console, document, clearInterval, setInterval*/
var itemlist, totalnumber, i, counter;
i = 0;
function findmepeterpan() {
"use strict";
console.log("Currently viewing " + (i + 1));
itemlist[i].scrollIntoView(true);
document.getElementById("headline").scrollIntoView(true);
itemlist[i].style.borderColor = "red";
itemlist[i].style.borderWidth = "thick";
itemlist[i].childNodes[1].click();
i = i + 1;
if (i === totalnumber) {
clearInterval(counter);
console.log("And we're done! Hope you enjoyed it!");
}
}
function keepitup() {
"use strict";
if (i !== 0) {
itemlist[i - 1].style.borderColor = "transparent";
itemlist[i - 1].style.borderWidth = "medium";
}
findmepeterpan();
}
itemlist = document.getElementsByClassName("image");
totalnumber = parseInt(document.getElementById("quickNavImage").childNodes[3].firstChild.firstChild.nodeValue.replace(/[0-9]* of /, ""), 10);
counter = setInterval(keepitup, 1500);

HTML5 Canvas performance - calculating loops/frames per second

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);

Categories

Resources