How to run function after event is run? - javascript

I am a beginner with all coding. Here is my general goal. I am running something relatively simple where I have 8 superheroes on the screen. I would like the user to eliminate the 4 DC superheroes from the screen and after all 4 of them are eliminated from the screen I want the system to alert the user that they have won the game. They don't have to do it in any order so I ran the superHero function each time a DC character was clicked to check if all four DC superheroes had been eliminated yet. Somebody please help me. I feel like it is something very simple I am messing up on. Thanks a ton in advance.
/*This is my jquery that shows all 8 of my superheroes*/
$('#heroes').show();
var flashHidden = !$('#greenlantern').is(':visible');
var greenHidden = !$('#greenlantern').is(':visible');
var batmanHidden = !$('#batman').is(':visible');
var supermanHidden = !$('#superman').is(':visible');
function superHero() {
if(flashHidden && batmanHidden && supermanHidden && greenHidden) {
alert ("Congratulations!!! You have won the game!! Please proceed forward and fill out a quick survey for the developers");
}
}
$('#flash').click(function(){
$('#flash').hide('slow',function(){
superHero();
});
});
$('#greenlantern').click(function(){
$('#greenlantern').hide('slow',function(){
superHero();
});
});
$('#batman').click(function(){
$('#batman').hide('slow',function(){
superHero();
});
});
$('#superman').click(function(){
$('#superman').hide('slow',function(){
superHero();
});
});
});
Right now the current thing that is happening is I will eliminate all of the correct superheroes and it will not alert me that the user has won. I've tried a lot of different things and the only other result I've gotten is to have the system alert the user every time they click on a superhero that they've won which is also incorrect.
EDIT
This has been solved by changing the scope of the variables to inside the function.

You should declare your variables i.e. flashHidden in your function. Currently you are setting then at the start.
function superHero() {
var flashHidden = !$('#flash').is(':visible');
var greenHidden = !$('#greenlantern').is(':visible');
var batmanHidden = !$('#batman').is(':visible');
var supermanHidden = !$('#superman').is(':visible');
if(flashHidden && batmanHidden && supermanHidden && greenHidden) {
alert ("Congratulations!!! You have won the game!! Please proceed forward and fill out a quick survey for the developers");
}
}
Additionally your click handler can be condensed into
$('#flash, #greenlantern, #batman, #superman').click(function(){
$(this).hide('slow',function(){
superHero();
});
});

You're setting...
var flashHidden = !$('#greenlantern').is(':visible');
...to start with. But you're not updating that variable later on when it gets hidden. So according to your check of:
if(flashHidden && batmanHidden && supermanHidden && greenHidden) {
...Flash is still visible. Even though, yes, on the page he's gone.
Try adding this:
$('#flash').click(function(){
$('#flash').hide('slow',function(){
flashHidden=true;
superHero();
});
});

Related

Phaser 2 buttons are needed to work text? What's happening?

I'm working on a dialogue system for my game. I have it almost finished, but I'm stuck on one weird bug. Here is the code for it in the update method. Assume everything with this in front of it was declared in the create method.
if ((this.checkCollision(this.p1, this.goodLamb) || this.checkCollision(this.p1, this.stiches)) && Phaser.Input.Keyboard.JustDown(this.keyT)) {
this.talking = true;
}
if (this.talking == true){
if (this.checkCollision(this.p1, this.goodLamb) || this.checkCollision(this.p1, this.stiches)) {
if (this.has("spool") && this.has("needleOne") && this.has("needleTwo")){
this.line1.setText('Good Lamb: Oh, thanks Peef! Now we can fix Stiches!');
this.line2.setText('Peef: Glad to help. I know how painful rips are.');
}
else if (!(this.has("spool")) || !(this.has("needleOne")) || !(this.has("needleTwo"))) {
this.line1.setText('Good Lamb: Help! Stiches ripped herself again! Can you get the sewing supplies?');
this.line2.setText('Peef: Oh gosh! Sit tight Stiches. Ill be back soon!');
}
}
if(this.keyA.isDown) {
this.p1.setVelocityX(0);
}
else if(this.keyD.isDown) {
this.p1.setVelocityX(0);
}
if(this.p1.body.touching.down && Phaser.Input.Keyboard.JustDown(this.keyW)) {
this.p1.body.setVelocityY(0);
}
if ((this.checkCollision(this.p1, this.goodLamb) || this.checkCollision(this.p1, this.stiches)) && Phaser.Input.Keyboard.JustDown(this.keyT)){
this.talking = false;
this.line1.setText('');
this.line2.setText('');
}
}
I admit this may be an outrageously overly complicated text system, but it's the only one I've gotten to work. When the player presses the talk button when touching an npc, the game checks for collision and sets the talking Boolean to true. If that Boolean is true, the game disables the player's movement and displays dialogue based on who the npc is and if they met the criteria for completing the associated quest, in this case gathering 2 needles and a spool of thread. For the player to continue, they have to press the talk button again, which turns the talking Boolean back to false, restores movement and makes the text disappear.
It's the last step that's not working. For some reason, when the player presses the talking button again, the talking Boolean doesn't change back and none of the associated actions happen.
The only solution I currently have is to change the button that makes the text disappear to a different button from the talking button. This lets things work as intended, but it's also an awkward button set up for the player.
Is there a solution, or am I just going to have to live with this issue?
If it helps, I'm using Phaser 3 in VSCode employing arcade physics.
No 1 Button is enough. What is happening, is hard to say, because your code is pretty complicated. In any case the main problem is that your if/else blocks are setup incorrect.
I cleaned it up and tried teh if/elseblocks in the correct order, so that they reflect, what you want to happen.
Although it is hard to say since, your code snippet covers only a small part of your update function.
if ((this.checkCollision(this.p1, this.goodLamb) || this.checkCollision(this.p1, this.stiches)) && Phaser.Input.Keyboard.JustDown(this.keyT)) {
if(this.talking == false){
this.talking = true;
if (this.has("spool") && this.has("needleOne") && this.has("needleTwo")) {
this.line1.setText('Good Lamb: Oh, thanks Peef! Now we can fix Stiches!');
this.line2.setText('Peef: Glad to help. I know how painful rips are.');
}
else if (!(this.has("spool")) || !(this.has("needleOne")) || !(this.has("needleTwo"))) {
this.line1.setText('Good Lamb: Help! Stiches ripped herself again! Can you get the sewing supplies?');
this.line2.setText('Peef: Oh gosh! Sit tight Stiches. Ill be back soon!');
}
/* this velocity blocks seem strange, but if it works for you why not */
if (this.keyA.isDown || this.keyD.isDown) {
this.p1.setVelocityX(0);
}
if (this.p1.body.touching.down && Phaser.Input.Keyboard.JustDown(this.keyW)) {
this.p1.body.setVelocityY(0);
}
} else {
this.talking = false;
this.line1.setText('');
this.line2.setText('');
}
}
Try to keep if/else nesting low, and try to group condition to avoid mistakes and performance issues (for example: multiple calculations / collision checks)
Update / Improvement:
Here the same code from above just more concise, and easier to understand / read
/* default text values is empty string */
let textLine1 = '';
let textLine2 = '';
/* I put "Phaser.Input.Keyboard..." first, for performance reasons */
if (Phaser.Input.Keyboard.JustDown(this.keyT) && (this.checkCollision(this.p1, this.goodLamb) || this.checkCollision(this.p1, this.stiches))) {
if(this.talking == false){
let hasAllItems = this.has("spool") && this.has("needleOne") && this.has("needleTwo");
if (hasAllItems) {
textLine1 = 'Good Lamb: Oh, ...';
textLine2 = 'Peef: Glad to help. ...';
} else {
textLine1 ='Good Lamb: Help! ...';
textLine2 = 'Peef: Oh gosh! ...';
}
/* just set the velocity always to 0, no if/else is needed */
this.p1.setVelocity(0);
}
// toggles: true <=> false
this.talking = !this.talking;
/* set the text's object in one place, no matter the text */
this.line1.setText(textLine1);
this.line2.setText(textLine2);
}

Prepending Old Chat Messages to Chat Box

I'm trying to prepend old messages to a chatbox when the user scrolls to the top. I'm using eventListeners as the code illustrates, but I'm running into an error where only the last chatbox is working properly. It seems that bodies[index].scrollTop and bodies[index].scrollHeight always returns 0 with the exception of bodies[lastIndex]. Why might this be? (logging bodies[index] correctly returns the div element)
document.querySelectorAll('.popup-messages').forEach((item, index) =>
{
item.addEventListener('scroll', async function()
{
if (chatReady[index] == true && bodies[index].scrollTop == 0)
{
chatReady[index] = false;
var previousHeight = bodies[index].scrollHeight;
await getMessages(item.id.replace(":body", ""));
var heightDiff = bodies[index].scrollHeight - previousHeight;
bodies[index].scrollTop += heightDiff;
}
})
})
Edit: If there's a different way to make multiple eventListeners dynamically, please share it with me as it would help a lot.
This problem was solved by replacing bodies[index] with item. Perhaps there was a bug that occurs when more than one variable is associated with an element.

Winner Detection in TicTacToe

How to get winner detection?
My code isn't working right now i only need the winner detection if someone can help me then do this .
$(document).ready(function() {
var xoro = 1;
$('#reset').on("click", function() {
$('img').attr("src", "blank.png");
});
$('img').on("click", function() {
var tmp = $(this).attr("src");
if (tmp == "blank.png" && xoro == 1) {
$(this).attr("src", "x.png");
xoro = 0;
} else if (tmp == "blank.png" && xoro == 0) {
$(this).attr("src", "o.png");
xoro = 1;
}
});
});
With your code you cant really determine a winner.
Options you have are :
Give your images ids . like
Let say we have this 3x3 field and we say its a 2dimensional array. Then the top left field is [0][0] and your bottom right is [3][3]
Your HTML code should be somethig like this
<img src="x.png" id="0-0"></img><img src="blank.png" id="0-1"></img>...
And so on.
After youve eine that you have to Start writing a huge if statement with all the winning Casey where you check if the SRC are all "x.PNG" or so.
EG: if ID 0-0,0-1 and 0-2 all have the SRC x.PNG x wins .
Best is to put these into a function named checkForWinner() and then just call this Funktion after every click or so
I hope i could help you out.
This question has already been answered here (in Java language though but the idea is the same). For that I suggest you store every move in a matrix which you can the use to determine the winner.
In addition, you have to make the images identifiable (as zeropublix suggested) so that you can actually capture the user's input and fill the matrix.

syntax issues with js/jquery assignment - Quiz questions in an object

I'm trying to work through an assignment to further my understanding of js but I'm running into some issues that are keeping me from final code. The code executes a short quiz- inputs from radio buttons are taken in and matched to an object containing answers, then outputting a final score.
code at http://jsfiddle.net/8ax9A/3/
issues I'm aware of now :
my $response variable doesn't seem to work.
var $response = $('[name=rad]:checked').val();
counter is listening for clicks through questions. After the last question, I want to report final score. I can't get counter to reach the end of questions + 1, and I cant get an accurate final score listener reported (var finalScore).
if ($response == parseInt(questions[counter].answer, 10)) {
finalScore++;
}
Those are just snippets so check out the fiddle for full code. I'd love some suggestions on how to understand where I'm going wrong.
Here is one way you could do it:
//Initialization
var counter=0;
var score=0;
loadQuestion();
$('#next').on('click',answer);
//functions
function answer(){
// if the user did not answer
if ($('input:radio:checked').length == 0){
alert('You have to answer!');
return;
}
var currentQ=questions[counter];
// if answer is correct
if($('[name=rad]:checked').val()==currentQ.answer){score++;}
counter++;
// if there are no questions left
if(counter >= questions.length) {displayResults(); return;}
loadQuestion();
}
function loadQuestion(){
// clear the radio buttons
$("input:checked").removeAttr("checked");
var currentQ=questions[counter];
// display the question
$('h1').text(currentQ.question);
$('#a1').text(currentQ.choices[0]);
$('#a2').text(currentQ.choices[1]);
$('#a3').text(currentQ.choices[2]);
}
function displayResults(){
$("h1").text("You've finished with a score of " + score + "!");
$('[name=rad], #a1, #a2, #a3, #next').remove();
}
JS Fiddle

display message javascript while a calculation is being made

I have been looking around and I cannot seem to figure out how to do this, although it seems like it would be very simple.(mobile development)
What I am trying to do is display a message (kind of like an alert, but not an alert, more like a dialog) while a calculation is being made. Simply like a Loading please wait. I want the message to appear and stay there while the calculation is being done and then be removed. I just cannot seem to find a proper way of doing this.
The submit button is pressed and first checks to make sure all the forms are filled out then it should show the message, it does the calculation, then hides the message.
Here is the Calculation function.
function scpdResults(form) {
//call all of the "choice" functions here
//otherwise, when the page is refreshed, the pulldown might not match the variable
//this shouldn't be a problem, but this is the defensive way to code it
choiceVoltage(form);
choiceMotorRatingVal(form);
getMotorRatingType();
getProduct();
getConnection();
getDisconnect();
getDisclaimer();
getMotorType();
//restore these fields to their default values every time submit is clicked
//this puts the results table into a known state
//it is also used in error checking in the populateResults function
document.getElementById('results').innerHTML = "Results:";
document.getElementById('fuse_cb_sel').innerHTML = "Fuse/CB 1:";
document.getElementById('fuse_cb_sel_2').innerHTML = "Fuse/CB 2:";
document.getElementById('fuse_cb_result').innerHTML = "(result1)";
document.getElementById('fuse_cb_res_2').innerHTML = "(result2)";
document.getElementById('sccr_2').innerHTML = "<b>Fault Rating:</b>";
document.getElementById('sccr_result').innerHTML = "(result)";
document.getElementById('sccr_result_2').innerHTML = "(result)";
document.getElementById('contactor_result').innerHTML = "(result)";
document.getElementById('controller_result').innerHTML = "(result)";
//Make sure something has been selected for each variable
if (product === "Choose an Option." || product === "") {
alert("You must select a value for every field. Select a Value for Product");
**************BLAH************
} else {
//valid entries, so jump to results table
document.location.href = '#results_a';
******This is where the message should start being displayed***********
document.getElementById('motor_result').innerHTML = motorRatingVal + " " + motorRatingType;
document.getElementById('voltage_res_2').innerHTML = voltage + " V";
document.getElementById('product_res_2').innerHTML = product;
document.getElementById('connection_res_2').innerHTML = connection;
document.getElementById('disconnect_res_2').innerHTML = disconnect;
if (BLAH) {
}
else {
}
populateResults();
document.getElementById('CalculatedResults').style.display = "block";
} //end massive else statement that ensures all fields have values
*****Close out of the Loading message********
} //scpd results
Thank you all for your time, it is greatly appreciated
It is a good idea to separate your display code from the calculation code. It should roughly look like this
displayDialog();
makeCalculation();
closeDialog();
If you are having trouble with any of those steps, please add it to your question.
Computers are fast. Really fast. Most modern computers can do several billion instructions per second. Therefore, I'm fairly certain you can rely on a a setTimeout function to fire around 1000ms to be sufficient to show a loading message.
if (product === "Choose an Option." || product === "") {
/* ... */
} else {
/* ... */
var loader = document.getElementById('loader');
loader.style.display = 'block';
window.setTimeout(function() {
loader.style.display = 'none';
document.getElementById('CalculatedResults').style.display = "block";
}, 1000);
}
<div id="loader" style="display: none;">Please wait while we calculate.</div>
You need to give the UI main thread a chance to render your message before starting your calculation.
This is often done like this:
showMessage();
setTimeout(function() {
doCalculation();
cleanUp()
}, 0);
Using the timer allows the code to fall through into the event loop, update the UI, and then start up the calculation.
You're already using a section to pop up a "results" page -- why not pop up a "calculating" page?
Really, there are 4,000,000 different ways of tackling this problem, but why not try writing a "displayCalculatingMessage" function and a "removeCalculatingMessage" function, if you don't want to get all object-oriented on such a simple thing.
function displayCalculatingMessage () {
var submit_button = getSubmitButton();
submit_button.disabled = true;
// optionally get all inputs and disable those, as well
// now, you can either do something like pop up another hidden div,
// that has the loading message in it...
// or you could do something like:
var loading_span = document.createElement("span");
loading_span.id = "loading-message";
loading_span.innerText = "working...";
submit_button.parentElement.replaceChild(loading_span, submit_button);
}
function removeCalculatingMessage () {
var submit_button = getSubmitButton(),
loading_span = document.getElementById("loading-message");
submit_button.disabled = false;
loading_span.parentElement.replaceChild(submit_button, loading_span);
// and then reenable any other disabled elements, et cetera.
// then bring up your results div...
// ...or bring up your results div and do this after
}
There are a billion ways of accomplishing this, it all comes down to how you want it to appear to the user -- WHAT you want to have happen.

Categories