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
Related
I am trying to measure how many times i can make "count = count + 1" in one second. But this function breaks browser. Anyone can say why is it happening or have a better method to calculate it?
function counter(){
var count = 0;
var trs = true;
while(trs){
count = count + 1;
setTimeout(() => {trs = false;}, 1000);
}
console.log(count);
}
The reason it crashes is because of infinite loop. JavaScript is event driven + single threaded and in JavaScript execution model, the function must finish before it yields control to another function. Thus, the code while (trs) {...} never yields control to the function defined in setTimeout because it never finishes. trs is always true.
Nice visualization on how the JavaScript execution model works: https://blog.avenuecode.com/understanding-the-javascript-concurrency-model
Here's a better way to do it:
function counter() {
var count = 0
var start = Date.now()
var end = start + 1000
while (Date.now() <= end) {
count = count + 1
}
console.log(count)
}
There is an infinite loop over there. Now, since javascript is single-threaded, the browser will get stuck performing that infinite loop, which may cause the cache filling up very quickly and cause a crash (or not re-render anything).
First, generally speaking, it is better to create the setTimeout only once, before you call while:
var count = 0;
var trs = true;
setTimeout(() => {trs = false;}, 1000);
while(trs){
count = count + 1;
}
console.log(count);
However, this will also cause a crash.
You can try to measure the operations differently, measure how much time it takes for a single count = count + 1 operation to run, then find how many of these can be executed in a second (Although it is not the same as running X consecutive operations, which another parameters could influence the result, but I am assuming you care about a single operation or single function you want to measure).
var count = 0;
var t0 = performance.now()
count = count + 1;
var t1 = performance.now()
console.log(1000/(t1 - t0));
If you want it to be inside a loop, you can also include the value check (with if), which the while does before executing its block.
var count = 0;
var trs=true;
var t0 = performance.now()
if(trs==true){
count = count + 1;
}
var t1 = performance.now()
console.log(1000/(t1 - t0));
I have this idea to prove a theory of mine.
So what I want to happen is when I run the program it will rapidly test a random chance. So, when I launched it it would rapidly test yes or no and there is a 1/1000000000 chance of "yes" and if it was yes, It would count one number up.
I browsed Stack Overflow and I found this:
<html>
<script>
// Greetings
var words = ['Hello', 'Hey', 'What\'s up!?'];
function randomAlert() {
// Index for picking the greeting you want to show
var alertIndex;
// Generates a number between 0 and 1
var randomValue = Math.random();
// 50% chance of 'Yes'
if (randomValue < 0.5) {
alertIndex = 0;
}
// 50% chance of 'No'
else if(randomValue < 0.5) {
alertIndex = 1;
}
alert(words[alertIndex])
}
</script>
<button onClick="randomAlert()">Click me!</button>
</html>
But what happens is it makes the button and does what I want (does not work in stack overflow and i'm not sure why. It works when I run it as a file on my comp), but it does not count every time it comes out as "yes" and it has to be done manually. (That is why I have to make the chances so large)
I just read what I wrote and it sounds like I'm asking for a favor rather than asking to learn how to code it. Please, do not take this as a "job". I would like what functions to use to make a random value and rapidly test it. THNX
If you want to do more than 1 draw, then you'll need a loop.
A for is the simplest, a while is also possible.
Also you'll need to have counters for each 'low or high' outcome.
I have made those changes, with a slightly different chance setting to keep it from running forever, with this result:
<script type="text/javascript">
function randomCount() {
var countLow = 0;
var countHigh = 0;
var cutOff = 1 / 1000;
var totalTries = 10000;
for (var i = 0; i < totalTries; i++) {
var randomValue = Math.random();
if (randomValue < cutOff)
countLow++;
else
countHigh++;
}
console.log("Result: countLow = " + countLow + ", countHigh = " + countHigh + ".");
}
</script>
<button onClick="randomCount()">Click me!</button>
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);
}
I am trying to make a game. There are blocks falling and a main block which the user commands that is trying to avoid them. There is a point system that is supposed to add 10points each time the red cube touches one of the extremities. The problem is that it adds 10 points per each 10 milliseconds that the cube stays in the extremity. How can I solve this??
You just need a flag that you set and then clear whenever you touch the side.
Since the box starts touching the side, i initialized already_touched to true.
var already_touched = true;
Then your logic below becomes:
if (mySprite.x == 450 || mySprite.x == 0) {
if (!already_touched) {
already_touched = true;
count += 10;
}
var alert1 = document.getElementById("score");
alert1.innerHTML = "Score: " + count;
} else {
already_touched = false;
}
Working demo here: http://jsfiddle.net/KrZq9/
suppose I have this client-side code:
var d=document.createElement('div');
d.style.position='absolute';
d.style.width='1em';
d.style.height='1em';
d.style.background='red';
document.body.appendChild(d);
for(var i=1e7;i;--i);
It creates a red square and counts down in a loop. Now I have to wait for the countdown to be ready before I see the red square. What is the best way to show the square before the countdown starts? I thought of executing the countdown after a Timeout:
setTimeout(function(){
for(var i=1e7;i;--i);
},1);
Or is there a better way? I do not want to rebuild my code into WebWorkers. Only a simple way to show a message before I start some time consuming linear code.
My real life situation is that I have a huge calculation that takes some time and I want to display a message before it starts.
If it's a large calculation it may lockup your browser, causing a very poor experience for your users. If that's the case, you may consider looking at doing the calculation in a webworker and posting the completed message back to the user.
http://www.html5rocks.com/en/tutorials/workers/basics/
More simply, you do something using setTimetout or setInterval and just have the message show by default: http://jsfiddle.net/ZHDY4/1/
We wait for the DOM to be ready, show the red box with the corresponding wait message.
$(document).ready(function() {
var n = 99;
$("#counter").html("Please Wait");
// Some long calculation; the red box is showing
var a = 0;
for(var i = 0; i < 99999; ++i) {
for(var j = 0; j < 9999; j++) {
a++;
}
}
var counter = setInterval(function() {
$("#counter").html(n);
n--;
if(n <= 0) {
clearInterval(counter);
}
}, 1000);
});