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.
Related
I am coding a game that is currently in its very early stages for a project to try to learn more about coding. In my game, objects generate randomly (green squares), and the player (red square), avoids them. I am having trouble trying to get the green squares to generate from a random position on the x-axis. I already have a formula to generate a random number for X, but after it selects a number randomly, all the "projectiles" generate there, rather than all generating from a different area. How would I get all the "projectiles" to generate from different positions on the x-axis randomly?
var randomX = Math.floor(Math.random() * 480) + 15;
function updateGameArea() {
var x, y;
for (i = 0; i < projectiles.length; i += 1) {
if (player.crashWith(projectiles[i])) {
gameArea.stop();
return;
}
}
gameArea.clear();
gameArea.frameNo += 1;
if (gameArea.frameNo == 1 || everyinterval(150)) {
x = randomX;
y = gameArea.canvas.height;
projectiles.push(new component(40, 40, "green", x, y));
}
for (i = 0; i < projectiles.length; i += 1) {
projectiles[i].y += -1; // the shape is using its coordinates to build downward from its y position
projectiles[i].update();
}
player.newPos();
player.update();
}
function everyinterval(n) {
if ((gameArea.frameNo / n) % 1 == 0) {return true;}
return false;
Expected: Green squares generate in random positions on the x- axis every 3 seconds and move upwards
Actual: Green squares all generate from the same random position on the X-axis.
You should reset X every time you're adding a new projectile:
if (gameArea.frameNo == 1 || everyinterval(150)) {
randomX = Math.floor(Math.random() * 480) + 15;
x = randomX;
y = gameArea.canvas.height;
projectiles.push(new component(40, 40, "green", x, y));
}
Otherwise, the randomX value stays constant as the value originally evaluated on line 1 when the interpreter reached it.
Here's your problem:
var randomX = Math.floor(Math.random() * 480) + 15;
// Generates a random number and stores it to randomX
// Called using 'randomX'
You need to turn it into a function if you want it to run each time:
var randomX = function() { Math.floor(Math.random() * 480) + 15 };
// Returns a new number each time
// Called using 'randomX()'
Both shivashriganesh mahato and natelouisdev have, essentially responded to how to fix the issue but since you are learning coding here is a tip. When you code, the code will run in a particular order. If you want something to be reassigned repeatedly, in this case a randomized number being used, and you want it to occur only after an event, you need to make sure that it gets trigger within each event.
natelouisdev has a good approach because, by using it as a function, you can call your randomizer more cleanly in your code and make it reassign the value of x each time.
Since you are building a game, it is also a good idea to compartmentalize your code. It'll make it easier to keep your ideas in order for each event trigger.
Example:
function gameLoss(){} - Define event return upon game loss. You can
then create editable rules to reason for loss without having to edit
the loss
function gameActive(){} - Defines what is normal gameplay. everything that occurs during normal gameplay should be managed here.
function gameArea(){} - Defines game canvas that function more for UI than for gameplay (scores, lifes, size of screen, etc)
Had you created individual functions you'd realize you only need a randomized 'x' value upon regular play thus you'd assign it within the gameActive() function and not as a global variable. Then you'd call the gameActive() function as many times as needed within a time interval to ensure a unique value is created each time.
-Side note: Don't litter unnecessary global variables. It'll make a mess off of your code when debugging. -
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 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);
}
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);
I'm working on a HTML5 game, and currently trying to make a weapon that fires 3 projectiles a few seconds after each other. So basically, a 3 burst assault rifle.
I first did:
for(var i = 0; i < 3; i++){
player.bullets.push(bulletInstance);
}
player.shotBullet = true;
which worked, but of course, the projectiles where release at the same time, meaning there was no delay between each shot. So I tried to introduce a setTimeout function:
setTimeout(function (){
i++;
if(i < 3){
var b = new Rectangle( player.x + (player.width / 2) - 4, player.y + (player.height / 2) - 4, 8, 8);
player.bullets.push(bulletInstance);
}
}, 1000)
player.shotBullet = true;
This doesn't do the trick either. Could someone point out my problem here?
One easy way would be like this:
for(var i = 0; i < 3; i++){
window.setTimeout( function(){ player.bullets.push(bulletInstance); }, i * 1000 );
}
This will init 3 functions 1s apart, which each firing a bullet according to your logic.
You probably will have to create separate instances of bulletInstance.
If there are much more than 3 actions to be done, I'd suggest to switch to setInterval() instead. But in such low areas, setTimeout() should be fine.
Being more specific about what is not wouking would help. In your case, the problem is that setTimeout runs only once. You should either create a new settimeout call inside the handler or use setInterval instead (just remember to clearInterval when you are done so it stops)
You can use the delay() from jQuery.