clearInterval after 10sec doesnt work - clearinterval

I created a little Game and that should create every 1sec a enemy till there are 10 enemy (10sec)
if i do it without clearInterval it creates the whole time enemys
so i want to stop when it reach 10
var initEnemy = function ()
{
//enemy div
for(var i = 0; i < 10; i++)
var timerid = null;
function IntervalFunction()
{
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
}
IntervalFunction();
setInterval(IntervalFunction,1000);
clearInterval(IntervalFunction),10000);
}

clearInterval doesn't take second argument.
And setTimeout is easier to wrap head around... A simple approach is to count how many enemies you've created so far and not run setTimeout when the limit is reached:
var initEnemies = function () {
var numEnemiesCreated = 0;
function createAnotherEnemy() {
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
numEnemiesCreated += 1;
if (numEnemiesCreated < 10)
setTimeout(createAnotherEnemy, 1000);
}
createAnotherEnemy();
}
And a version with for loop, it schedules function calls 0s, 1s, 2s, ... , 9s from now:
var initEnemies = function () {
function createEnemy() {
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
}
for (var i=0; i < 10; i++)
setTimeout(createEnemy, i * 1000);
}
update
Here's a version with setInterval and clearInterval. You still have to count how many enemies you've created so far, and you have to use interval id in clearInterval call. Haven't tested this, sorry!
var initEnemies = function () {
var numEnemiesCreated = 0;
var intervalId;
function createEnemy() {
var randomX = Math.floor(Math.random() * 190);
var randomY = Math.floor(Math.random() * 50);
enemy.push(new Enemy(randomX, randomY).create());
// Unschedule ourselves after 10th run
numEnemiesCreated += 1;
if (numEnemiesCreated == 10)
clearInterval(intervalId);
}
intervalId = setInterval(createEnemy, 1000);
}

Related

Creating a javascript array to localstorage not returning desired result

I'm trying to create an array to localstorage containing some gear box values, witch I then need again to do some more calculations with specific array[?].value.
The problem I'm encountering is that the created entry returns only 2 array entries, although all entries are there but the " is at the beginning and then at the second last entry and then before and after the last entry.
These are the values generated.
spd_Dev = ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"]
When I used to use a fixed array I've entered it as:
var spd_Dev = [202.391, 172.876, 120.451, 102.601, 85.173, 72.664, 61.701, 52.706, 45.116, 38.510, 32.326, 27.407, 22.910, 19.536, 16.585, 14.195, 12.228, 10.401];
So my question is how to write this values to localstorage and read again from localstorage so that I can use this values as an array.
This is what I'm trying to work.
var D_RatioId = data.truck.make + data.truck.model + "D_Ratio"
var G_RatioId = data.truck.make + data.truck.model + "G_Ratio"
var fGr = data.truck.forwardGears;
var gr = data.truck.displayedGear;
var Rpm = data.truck.engineRpm * 100;
var spd = data.truck.speed;
var T_Dia = 1008.3;
if (localStorage.getItem(G_RatioID) == undefined) {
localStorage.setItem(G_RatioID, '');
var fG_Rat = [localStorage.getItem(G_RatioID)];
} else {
var fG_Rat = [localStorage.getItem(G_RatioID)];
}
var spd_Dev = localStorage.getItem(Spd_DevId);
spd_Dev = spd_Dev ? spd_Dev.split(', ') : [];
if (localStorage.getItem("i") == undefined) {
localStorage.setItem("i", 1);
var i = localStorage.getItem("i");
} else {
var i = localStorage.getItem("i");
}
if (i <= fGr && spd > 0.5) {
if (i <= fGr + 1) {
if (i == gr) {
if (RPM > 1450) {
var G_Ratio = Math.abs(Rpm / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / spd / 1000, 2).toFixed(2);
var spd_D = Math.abs(RPM / (RPM / G_Ratio / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / 1000) * 0.821932).toFixed(3);
fG_Rat.push(G_Ratio);
spd_Dev.push(spd_D);
i++;
localStorage.setItem("i", i);
var G_RatioValue = fG_Rat;
var Spd_DevValue = spd_Dev;
SetG_Ratio(G_RatioID, G_RatioValue);
SetSpd_Dev(Spd_DevId, Spd_DevValue);
localStorage.setItem("spd_Dev", JSON.stringify(Spd_DevValue));
}
}
}
}
function SetG_Ratio(G_RatioID, G_RatioValue) {
localStorage.setItem(G_RatioID, G_RatioValue);
console.log(G_RatioID, G_RatioValue);
}
function SetSpd_Dev(Spd_DevId, Spd_DevValue) {
localStorage.setItem(Spd_DevId, Spd_DevValue.toString());
console.log(Spd_DevId, Spd_DevValue, Spd_DevValue.length);
}
if (spd >= 0) {
var spd_Dev = [localStorage.getItem(Spd_DevId)];
var spD_D = JSON.parse(spd_Dev);
for (i = 1; i < (fGr + 1); i++) { // Some more code dependant on the above results //
why don't you use LSM.js? it will make everything simpler. you can put the array as an array so that it will return the full array only, you will not need to use split(),
https://github.com/kevinj045/LSM_js
var lsm = new LSM("G_RatioID");
var G_RatioValue ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"];
lsm.set("G_RatioID",G_RatioValue);
console.log(lsm.get("G_RatioID")); // it will return the full array

Question About Order of Execution of Functions in React

In the following code, why is the sleep function executed before the startClock function?
handleClick = () => {
this.startClock();
this.sleep(5000);
}
startClock = () => {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
// add a zero in front of numbers<10
m = this.checkTime(m);
s = this.checkTime(s);
document.getElementById("txt").innerHTML = h + ":" + m + ":" + s;
console.log(h + ":" + m + ":" + s);
var t = setTimeout(function(){this.startClock()}.bind(this), 1000);
};
checkTime = (i) => {
if (i < 10) {
i = "0" + i;
}
return i;
};
sleep = (timeout) => {
var begin = new Date();
while (new Date() - begin < timeout) {
}
};
I would expect the startClock function to execute first but the sleep function executes first and then the startClock function.
I think what is actually happening here is the startClock function is executed first but since the time specified in setTimeout is 1000ms, the sleep function starts before the GUI is updated and therefore the GUI is not updated until sleep is finished.

async function not waiting to move on

I have a react app, in which im hiding and showing buttons instead of moving across pages, before I show the next button I want to make sure the function the button was meant to call has completed. Here is what I have so far:
This is the Async function:
async handleTransferFromEthereum(){
parseAddress(this.state.sc)
this.setState(prevState => ({
isEthTransferVisible: !prevState.isEthTransferVisible,
isGoDeployedVisible: !prevState.isGoDeployedVisible
}));
}
and this would be the function im calling:
import ERC20ABI from './blockchain/ERC20ABI.js';
import ethweb3 from './blockchain/ethweb3.js';
import _ from 'lodash';
var addressesValues = [];
var uniqueAddresses = [];
var values = [];
var count = 0;
var map = {};
var address =[];
var amounts=[];
var choppedAdrresses = [];
export function parseAddress(_smartcontract){
console.log("Scanning blockchain")
var contractObj = new ethweb3.eth.Contract(ERC20ABI,_smartcontract);
contractObj.getPastEvents(
'Transfer' || 'allEvents',
{
fromBlock: 0,
toBlock: 'latest'
},
function(err,res){
for(var i =1; i< res.length; i++){
if (uniqueAddresses.includes(res[i].returnValues.from)===false) {
uniqueAddresses[count] = res[i].returnValues.from;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
if (uniqueAddresses.includes(res[i].returnValues.to)===false){
uniqueAddresses[count] = res[i].returnValues.to;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
}
for(var j = 0; j< res.length; j++){
map[res[j].returnValues.from] -= parseInt(res[j].returnValues.value);
map[res[j].returnValues.to] += parseInt(res[j].returnValues.value);
}
for(var x = 0; x < uniqueAddresses.length; x++){
addressesValues.push([uniqueAddresses[x], parseInt(map[res[x].returnValues.to])])
}
for(var y=0; y < addressesValues.length; y++){
address.push(addressesValues[y][0]);
amounts.push(addressesValues[y][1]);
}
var choppedAdrresses=_.chunk(address, 100);
var choppedValue=_.chunk(amounts, 100);
var tokenSum = amounts.reduce((a, b) => a + b, 0);
sessionStorage.setItem("addresses", JSON.stringify(address))
sessionStorage.setItem("tokenSum", JSON.stringify(tokenSum))
sessionStorage.setItem("choppedAdrresses", JSON.stringify(choppedAdrresses))
sessionStorage.setItem("choppedValue", JSON.stringify(choppedValue))
}
);
}
Any pointers would really help.
You need to wait on a promise, but since the getPastEvents function works in a callback pattern, you could create a custom promise and return it from parseAddress method
export function parseAddress(_smartcontract){
console.log("Scanning blockchain")
return new Promise(function(resolve, reject) {
var contractObj = new ethweb3.eth.Contract(ERC20ABI,_smartcontract);
contractObj.getPastEvents(
'Transfer' || 'allEvents',
{
fromBlock: 0,
toBlock: 'latest'
},
function(err,res){
if (err) {
reject(err);
}
for(var i =1; i< res.length; i++){
if (uniqueAddresses.includes(res[i].returnValues.from)===false) {
uniqueAddresses[count] = res[i].returnValues.from;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
if (uniqueAddresses.includes(res[i].returnValues.to)===false){
uniqueAddresses[count] = res[i].returnValues.to;
values[count] = parseInt(0);
map[uniqueAddresses[count]] = values[count];
count+=1
}
}
for(var j = 0; j< res.length; j++){
map[res[j].returnValues.from] -= parseInt(res[j].returnValues.value);
map[res[j].returnValues.to] += parseInt(res[j].returnValues.value);
}
for(var x = 0; x < uniqueAddresses.length; x++){
addressesValues.push([uniqueAddresses[x], parseInt(map[res[x].returnValues.to])])
}
for(var y=0; y < addressesValues.length; y++){
address.push(addressesValues[y][0]);
amounts.push(addressesValues[y][1]);
}
var choppedAdrresses=_.chunk(address, 100);
var choppedValue=_.chunk(amounts, 100);
var tokenSum = amounts.reduce((a, b) => a + b, 0);
sessionStorage.setItem("addresses", JSON.stringify(address))
sessionStorage.setItem("tokenSum", JSON.stringify(tokenSum))
sessionStorage.setItem("choppedAdrresses", JSON.stringify(choppedAdrresses))
sessionStorage.setItem("choppedValue", JSON.stringify(choppedValue))
resolve();
}
);
});
}
After this, you can use await like
async handleTransferFromEthereum(){
await parseAddress(this.state.sc)
this.setState(prevState => ({
isEthTransferVisible: !prevState.isEthTransferVisible,
isGoDeployedVisible: !prevState.isGoDeployedVisible
}));
}
However if its possible try to convert getPastEvents so that it returns a promise instead of using a callback
The promise starts when you create it and await will wait for it to resolve. But the code in the middle of these two statements will run before the promise ends. If you don't need any result of the promise you can put code in that zone to paralelize the execution of it with the promise.
const timeBomb = (resolve, reject) => {
const msleft = Math.random() * 700 + 200;
console.log("Countdown started!");
console.log("Only "+(Math.round(msleft)/1000)+" seconds left!!");
setTimeout(resolve, msleft);
};
waiter = async (p) => {
console.log("I will hurry to do my last wish before dying");
const result = await p;
console.log("It Exploded!");
}
waiter(new Promise(timeBomb));

Chain Reaction with Arrays and Distance

I want to make a program in which mines will appear on the screen after a user inputs the number of mines. Then, the user will click on one mine and set off a chain reaction that explodes the nearest two mines.
So far, my code can prompt the user for the number of mines, and then display them. The mines are buttons in which, when clicked, will be removed and an explosion will appear.
However, I am stuck with how I can handle the chain reaction. I am relatively new to coding in AS3 and therefore am stumped with no clue on how to approach this part of my program.
Code:
package
{
import flash.display.MovieClip;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.events.*;
public class Minefield extends MovieClip
{
var integer:int;
var iField:TextField = new TextField();
var button:iButton = new iButton();
var i:int;
var mines:Array = new Array();
public function Minefield()
{
var explosion:iExplosion = new iExplosion();
iField.type = "input";
iField.height = 18;
iField.x = 460;
iField.y = 275;
iField.border = true;
iField.restrict = "0-9";
iField.maxChars = 2;
stage.focus = iField;
addChild(iField);
addChild(button);
button.x = 450;
button.y = 175;
button.buttonMode = true;
button.addEventListener(MouseEvent.CLICK, UponClick);
}
function AddMines()
{
for (i = 0; i < integer; i++)
{
CreatorOfMine();
mines[i].addEventListener(MouseEvent.CLICK, UponMineClick)
mines[i].buttonMode = true;
}
}
function CreatorOfMine()
{
mines[i] = new Mine();
MineLocation()
}
function MineLocation()
{
mines[i].x = Math.round(Math.random() * 925);
mines[i].y = Math.round(Math.random() * 525);
mines[i].rotation = Math.random() * 360;
addChild(mines[i]);
}
function UponClick(e:MouseEvent)
{
integer = int(iField.text);
RemoverOfChildren();
}
function RemoverOfChildren()
{
removeChild(button);
removeChild(iField);
AddMines();
}
function UponMineClick(event:MouseEvent){
var mineObject:Mine = Mine(event.currentTarget)
var expl:iExplosion = new iExplosion()
expl.x = mineObject.x
expl.y = mineObject.y
expl.rotation = mineObject.rotation
addChild(expl)
removeChild(mineObject)
}
}
}
}
Information you may need/want:
Stage size is 1024 x 600 (px)
Size of mine(s) is 40 x 40 (px)
Size of explosion is 40 x 40 (px)
Looks like a good case for recursion. Pseudo-code:
Function ExplodeMine(mine) {
mine.boooooooooom()
nearest = findNearestUnexplodedMines()
foreach(nextMine in nearest) {
ExplodMine(nextMine);
}
}
Just start ExplodeMine on the first mine that is clicked.

Issues with using setTimeout inside of a for loop with arrays

--- UPDATE ---
Here is another attempt... The issue seems to be that the animation only happens to the third item in the for loop array I'm assuming because of the setTimeout delay. How can I have the animation fire for each item (3) with a delay?
// Breadcrumb Animation
(function(){
var header = document.getElementById("header"),
header2 = document.getElementById("header-secondary"),
banner = document.getElementById("banner");
var bcLink = [header, header2, banner];
var myTime = '';
var myItem = '';
function delay() {
setTimeout(fadeIn, myTime);
function fadeIn() {
if( myItem.style.opacity !== '1' ) {
console.log(myItem);
setInterval(function(){
myItem.style.opacity = parseFloat(myItem.style.opacity) + 0.1;
}, 100);
}
}
}
var i, len=bcLink.length;
for(var i = 0; i < len; i++) {
bcLink[i].style.opacity = 0;
myItem = bcLink[i];
myTime = myTime = parseInt(myTime + 2000)
delay();
}
})();
--- END UPDATE ---
The code below works but I was trying to optimize my code by creating a foor loop that will loop through each of the items (my attempt is commented out). I'm currently using 3 items on my page (header, header2, banner) that will load one after the other, but the second should not start until the first loads, the third should not start until the second item loads, and so on. This code will eventually be used for breadcrumbs where the amount of items will be uncertain but they will still load one after the other. Any help is greatly appreciated.
(function(){
var header = document.getElementById("header"),
header2 = document.getElementById("header-secondary"),
banner = document.getElementById("banner");
var bcLink = [header, header2, banner];
var myTime = '';
function fadeIn(name, speed) {
if( name.style.opacity !== '1' ) {
setInterval(function(){
name.style.opacity = parseFloat(name.style.opacity) + 0.1;
}, speed);
}
}
function delay(funct, time) {
setTimeout(function() {funct}, time);
}
bcLink[0].style.opacity = 0;
bcLink[1].style.opacity = 0;
bcLink[2].style.opacity = 0;
setTimeout(function(){fadeIn(bcLink[0], 100)}, 0);
setTimeout(function(){fadeIn(bcLink[1], 100)}, 1000);
setTimeout(function(){fadeIn(bcLink[2], 100)}, 2000);
// for(var i = 0; i < bcLink.length; i++) {
// bcLink[i].style.opacity = 0;
// delay(fadeIn(bcLink[i],100), i + 000);
// }
})();
use jQuery animation queue, not timeout.
http://blog.bigbinary.com/2010/02/02/understanding-jquery-effects-queue.html
Try changing:
delay(fadeIn(bcLink[i],100), i + 000);
to:
setTimeout(function(){fadeIn(bcLink[i], 100)}, i * 1000);

Resources