I have recently started learning javascript with Codecademy. To extend my knowledge and just for fun, I followed HTML5 game tutorials by Gyrostorm: http://www.youtube.com/playlist?list=PL290A4D2398C97186/.
Now I completed the tutorial to make my version of his game, but I want it to be so that when you hold the spacebar, bullets fire at a certain rate. Currently, you have to keep pressing the spacebar to fire. I have a Jet.shoot function and a Jet.checkShoot function but after trying many times to setIntervals and setTimeouts nothing would work! Please help!
Jet.prototype.checkShooting = function() {
if(this.isSpacebar && !this.isShooting) {
this.isShooting = true;
this.bullets[this.currentBullet].fire(this.noseX, this.noseY)
this.currentBullet++;
if(this.currentBullet >= this.bullets.length) {
this.currentBullet = 0;
}
} else if(!this.isSpacebar) {
this.isShooting = false;
}
};
Jet.prototype.shoot = function() {
this.isShooting = true;
this.bullets[this.currentBullet].fire(this.noseX, this.noseY);
this.currentBullet++;
if(this.currentBullet >= this.bullets.length) {
this.currentBullet = 0;
}
}
Here is a live version of what I have so far: https://googledrive.com/host/0B2Xb6VzofFX-OGxEcnV3OUNTdFU/index.html
Thanks!
If you want to have a given fire-rate, you need to handle the time. So best thing is to have a game-time, but anyway you need to implement a solution like this (i used real-world time (Date.now()) for this example) :
if(this.isSpacebar && Date.now()>this.shootPossibleTime) {
this.shootPossibleTime =Date.now()+this.reloadTimeForThisWeapon;
this.bullets[this.currentBullet].fire(this.noseX, this.noseY)
this.currentBullet++;
if(this.currentBullet >= this.bullets.length) {
this.currentBullet = 0;
}
}
Related
I am using Qualtrics to make a survey, and I need to do a bit of JS to make a timer. Unfortunately, I'm constantly running into "cannot set innerHTML property of null" for element "s5".
I've read the other thread about this issue (albeit the OP doesn't seem to be using qualtrics), and thought that perhaps changing "Qualtrics.SurveyEngine.addOnload" to "Qualtrics.SurveyEngine.addReady" might do the trick, but it doesn't, and I've already tried changing the id's quite a few times to no avail. Could someone help me find where my error is?
I got marked previously for the same question (as something that's already been answered), but that thread didn't help me at all. I've tried ready() as shown in the commented out section in the first code snippet, but that only gave me a "startThinkingTimer is not defined" error. When I tried it the second way in the second code snippet, I didn't get any errors, but my timer wasn't visible/working at all either. I can't move script or use defer b/c Qualtrics does not have all the HTML/CSS/JS in one file, but has different sections for them and honestly I'm not sure how they connect the different files. Regarding using .on(), I'm not sure which event to use here, and would really like some help.
I've tried replacing all the document.getElementById for element "s5" with something like this:
$("s5").innerHTML="10";
but this doesn't work, either.
(Should I try to move the html code inside the JS portion (esp. the div timeShower part)? I'm not too sure how to do that though, so if someone could help me do that, that'd be awesome.)
window.thinkingTimer_;
window.typingTimer_;
Qualtrics.SurveyEngine.addOnload(function(){
that = this;
var thinkingTimeLimit = 15;
var typingTimeLimit = 10;
jQuery(".InputText").hide();
$('NextButton').hide();
document.getElementById("instructions5").innerHTML = "You have 15 seconds to think about the prompt and come up with your two most favourite fruits, either from the list or from your previous choices. Textboxes will appear when the time is up.";
function startTypingTimer() {
that.enableNextButton();
typingTimer_ = setInterval( function(){
if (typingTimeLimit > 0) {
document.getElementById("s5").innerHTML=pad(--typingTimeLimit%60);
document.getElementById("minutes5").innerHTML=pad(parseInt(typingTimeLimit/60,10));
}
if (typingTimeLimit == 0) {
clearInterval(typingTimer_);
jQuery("#NextButton").click();
}
}, 1000);
}
/*
$(function startThinkingTimer() {
that.disableNextButton();
thinkingTimer_ = setInterval( function(){
if (thinkingTimeLimit >0) {
document.getElementById("s5").innerHTML=pad(--thinkingTimeLimit%60);
document.getElementById("minutes5").innerHTML=pad(parseInt(thinkingTimeLimit/60,10));
}
if (thinkingTimeLimit == 0) {
clearInterval(thinkingTimer_);
document.getElementById("s5").innerHTML="10";
document.getElementById("minutes5").innerHTML="00";
jQuery(".InputText").show();
document.getElementById("instructions5").innerHTML = "You now have 10 seconds to type in the two fruits. The page will automatically move on to the next page once time is up.";
startTypingTimer();
}
}, 1000);
});
*/
function startThinkingTimer() {
that.disableNextButton();
thinkingTimer_ = setInterval( function(){
if (thinkingTimeLimit >0) {
document.getElementById("s5").innerHTML=pad(--thinkingTimeLimit%60);
document.getElementById("minutes5").innerHTML=pad(parseInt(thinkingTimeLimit/60,10));
}
if (thinkingTimeLimit == 0) {
clearInterval(thinkingTimer_);
document.getElementById("s5").innerHTML="10";
document.getElementById("minutes5").innerHTML="00";
jQuery(".InputText").show();
document.getElementById("instructions5").innerHTML = "You now have 10 seconds to type in the two fruits. The page will automatically move on to the next page once time is up.";
startTypingTimer();
}
}, 1000);
}
function pad (val) {
return val > 9 ? val : "0" + val;
}
startThinkingTimer();
});
<div id="instructions5"> </div>
<div id="timeShower1">time: <span id="minutes5">00</span>:<span id="s5">15</span></div>
window.thinkingTimer_;
window.typingTimer_;
Qualtrics.SurveyEngine.addOnload(function(){
that = this;
var thinkingTimeLimit = 15;
var typingTimeLimit = 10;
jQuery(".InputText").hide();
$('NextButton').hide();
document.getElementById("instructions5").innerHTML = "You have 15 seconds to think about the prompt and come up with your two most favourite fruits, either from the list or from your previous choices. Textboxes will appear when the time is up.";
function startTypingTimer() {
that.enableNextButton();
typingTimer_ = setInterval( function(){
if (typingTimeLimit > 0) {
document.getElementById("s5").innerHTML=pad(--typingTimeLimit%60);
document.getElementById("minutes5").innerHTML=pad(parseInt(typingTimeLimit/60,10));
}
if (typingTimeLimit == 0) {
clearInterval(typingTimer_);
jQuery("#NextButton").click();
}
}, 1000);
}
$(function () {
that.disableNextButton();
thinkingTimer_ = setInterval( function(){
if (thinkingTimeLimit >0) {
document.getElementById("s5").innerHTML=pad(--thinkingTimeLimit%60);
document.getElementById("minutes5").innerHTML=pad(parseInt(thinkingTimeLimit/60,10));
}
if (thinkingTimeLimit == 0) {
clearInterval(thinkingTimer_);
document.getElementById("s5").innerHTML="10";
document.getElementById("minutes5").innerHTML="00";
jQuery(".InputText").show();
document.getElementById("instructions5").innerHTML = "You now have 10 seconds to type in the two fruits. The page will automatically move on to the next page once time is up.";
startTypingTimer();
}
}, 1000);
});
/*
function startThinkingTimer() {
that.disableNextButton();
thinkingTimer_ = setInterval( function(){
if (thinkingTimeLimit >0) {
document.getElementById("s5").innerHTML=pad(--thinkingTimeLimit%60);
document.getElementById("minutes5").innerHTML=pad(parseInt(thinkingTimeLimit/60,10));
}
if (thinkingTimeLimit == 0) {
clearInterval(thinkingTimer_);
document.getElementById("s5").innerHTML="10";
document.getElementById("minutes5").innerHTML="00";
jQuery(".InputText").show();
document.getElementById("instructions5").innerHTML = "You now have 10 seconds to type in the two fruits. The page will automatically move on to the next page once time is up.";
startTypingTimer();
}
}, 1000);
}*/
function pad (val) {
return val > 9 ? val : "0" + val;
}
//startThinkingTimer();
});
So, I have a 'mini-game' in Vue.js which let's you 'fight'.
I am trying to make it that after someone 'dies' the game declares the winner and then asks if you want to play again.
All good until there,but when i'm trying to make it so after you clicked that you want to play again, to reset your health and 'monster\'s' health back to 100, it just doesn't work.
Here's my code, where i reset everything, it runs, i've put console logs but it does nothing:
checkWinner: function() {
if(this.mHp <= 0) {
if (confirm('You won! Play again?')) {
this.startGame();
} else {
this.gameIsActive = false;
}
return true;
} else if (this.pHp <= 0) {
if (confirm('You lost! Play again?')) {
this.startGame();
} else {
this.gameIsActive = false;
}
return true;
}
return false;
}
}
Also, here's the full code if you wanna take a look. I'd be thankful if someone could explain to me why it doesn't work. Thanks in advance !
http://jsfiddle.net/y5mn61qf/
The issue is in your startGame() function, where your pHp and mHp variables are not being set with this.
You have:
pHp = 100;
mHp = 100;
Which should be:
this.pHp = 100;
this.mHp = 100;
I found this by using console.log() which helped me to determine that startGame() was firing, and then upon closer inspection led me to notice that your data was not being updated properly.
In your startGame method you are setting the properties to a new value but forgot this. for the livespan values (pHp, mHp)
I think it should work after adding 'this' before your hp parameters.
startGame: function() {
this.gameIsActive = true;
this.pHp = 100;
this.mHp = 100;
},
Currently my code is like so. As is, what this feature does, is when clicked, it turns an SVG element to a certain color depending upon what conditions are met (in this instance, sting.state.mi === 'und').
After that click, the SVG item it is linked to changes color, as seen in m[geography.id]. However, if I spam this button enough times then I can get the wrong colors to show up.
I would like to avoid users spamming my click button.
Using datamap.svg.select('.datamaps-subunit.MI).disabled = true does not really do the trick. However, I hope it gets the point across.
Below is my code.
datamap.svg.select('.datamaps-subunit.MI').on('click', function(geography) {
var m = {};
if (sting.state.mi === 'und'){
datamap.svg.select('.datamaps-subunit.MI').disabled = true;
sting.setState({trumpnums: sting.state.trumpnums + 12});
sting.setState({mi: 'right'});
m[geography.id] = 'tomato';
datamap.svg.select('.datamaps-subunit.MI').disabled = false;
}
});
This example uses Reactjs and Datamaps, though I don't imagine that's entirely relevant.
A simple flag should do the trick:
var waiting = false;
datamap.svg.select('.datamaps-subunit.MI').on('click', function(geography) {
// only run the logic if it isn't already being run
if (!waiting) {
waiting = true;
var m = {};
if (sting.state.mi === 'und'){
datamap.svg.select('.datamaps-subunit.MI').disabled = true;
sting.setState({trumpnums: sting.state.trumpnums + 12});
sting.setState({mi: 'right'});
m[geography.id] = 'tomato';
datamap.svg.select('.datamaps-subunit.MI').disabled = false;
waiting = false;
}
}
});
Also, you can set all of your state at once and setState will call a supplied callback once it's complete:
if (sting.state.mi === 'und'){
sting.setState({
trumpnums: sting.state.trumpnums + 12,
mi: 'right'
}, function() {
m[geography.id] = 'tomato';
waiting = false;
});
}
Im a JQuery noob trying to write a simple jQuery code to get a text to blink three times. My initial code was as follows:
$("#welcome").click(function () {
var i = 1;
while (++i < 10) {
$("#welcome").fadeOut("slow", function () { $("#welcome").fadeIn("slow"); })();
}
});
But since I probably meddled in forces I could not comprehend, the above code made the text blink only once. I read up on closures and got convinced that the below code could make a change. Unfortunately, it doesnt.
$("#welcome").click(function () {
var i = 1;
while (++i < 10) {
(function (i) {
$("#welcome").fadeOut("slow", function () { $("#welcome").fadeIn("slow"); })();
})(i);
}
});
Can anyone tell me whats going on here?
You need make use of the animation queue
var $welcome = $("#welcome").click(function () {
var i = 1;
//clear previous animations
$welcome.stop(true, true);
while (++i < 10) {
$welcome.fadeOut("slow").fadeIn("slow");
}
});
Demo: Fiddle
Fading in and out takes some time, and you have to wait for your animation to be over before you can run the next one.
The provided answers solve your problem since jQuery is clever enough to bufferize your animation queue, but it may creates even more confusion for begginers, and also if you want to do something else between the fading animations, you can't rely on it anymore.
You then have to write your code on what is called an asynchronous recursive way (woah). Simply trying to understand that snippet may help you a lot with javascript general programming.
function blink(nbBlinks) {
// Only blink if the nbBlinks counter is not zero
if(nbBlinks > 0) {
$('#welcome').fadeOut('slow', function() {
// Do stuff after the fade out animation
$(this).fadeIn('slow', function() {
// Now we're done with that iteration, blink again
blink(nbBlinks-1);
})
});
}
}
// Launch our blinking function 10 times
blink(10);
This works perfectly. Demo http://jsfiddle.net/X5Qy3/
$("#welcome").click(function () {
for (var x = 0; x < 3; x += 1) {
$("#welcome").fadeOut("slow");
$("#welcome").fadeIn("slow");
}
});
Also, if you know how many times you want to do something. You should use a For Loop. While Loops are for when you don't know how many times you want it to run.
Set in queue
$("#welcome").click(function () {
var i = 1;
//clear animations whcih are running at that time
$(this).stop(true, true);
while (++i < 10) {
$(this).fadeOut("slow").fadeIn("slow");
}
});
You can not use jQuery delay function inside a looping/iteration hence you have to user closures:
$(document).ready(function(){
$(".click1").click(function () {
for (i=0;i<=10;i++) {
setTimeout(function(x) {
return function() {
$("#wrapper").fadeOut("slow", function () { $("#wrapper").fadeIn("slow"); })();
};
}(i), 1000*i);
}
});
});
<div id="wrapper"></div><div class="click1">click</div>
You can later change the count how many times you want to blink the <div>.
I am trying to make a form validation in 2 steps. One client side, one server side. I managed to get some parts of the client check working. I am experiencing peculiar bugs... The code:
//global vars
var form, cegnev, cegnevInfo, cegcim, cegcimInfo, cegemail, cegemailInfo, cegkapcs, cegkapcsInfo, cegbeosz, cegbeoszInfo;
form = $("#jelentkezes");
cegnev = $("#ceg_nev");
cegnevInfo = $("#ceg_nevInfo");
cegcim = $("#ceg_cim");
cegcimInfo = $("#ceg_cimInfo");
cegemail = $("#ceg_cim");
cegemailInfo = $("#ceg_emailInfo");
cegkapcs = $("#ceg_kapcs");
cegkapcsInfo = $("#ceg_kapcsInfo");
cegbeosz = $("#ceg_beosz");
cegbeoszInfo = $("#ceg_beszInfo");
(function () {
"use strict";
// this function is strict...
$(document).ready(function () {
function validateCegemail() {
//testing regular expression
var a = $("#ceg_email").val(), filter = /^(([^<>()\[\]\\.,;:\s#\"]+(\.[^<>()\[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
//if it's valid email
if (filter.test(a)) {
cegemail.removeClass("elizelte");
cegemailInfo.removeClass("elizelte");
cegemailInfo.text("Jó!");
cegemail.addClass("lotto");
cegemailInfo.addClass("lotto");
return true;
} else {
//if it's NOT valid
cegemail.removeClass("lotto");
cegemailInfo.removeClass("lotto");
cegemail.addClass("elizelte");
cegemailInfo.text("E-mail formátuma nem megfelelő! pl: valaki#vhalahol.hu");
cegemailInfo.addClass("elizelte");
return false;
}
}
function validateCegnev() {
//if it's NOT valid
if (cegnev.val().length < 7) {
cegnev.removeClass("lotto");
cegnevInfo.removeClass("lotto");
cegnev.addClass("elizelte");
cegnevInfo.text("Cég névnek több mint 7 betűből kell állnia!");
cegnevInfo.addClass("elizelte");
return true;
} else {
//if it's valid
cegnev.removeClass("elizelte");
cegnevInfo.removeClass("elizelte");
cegnevInfo.text("Jó!");
cegnev.addClass("lotto");
cegnevInfo.addClass("lotto");
return false;
}
}
function validateCegbeosz() {
//if it's NOT valid
if (cegbeosz.val().length < 4) {
cegbeosz.removeClass("lotto");
cegbeoszInfo.removeClass("lotto");
cegbeosz.addClass("elizelte");
cegbeoszInfo.text("Beosztás minimum 4 betűből kell, hogy álljon!");
cegbeoszInfo.addClass("elizelte");
return true;
} else {
//if it's valid
cegbeosz.removeClass("elizelte");
cegbeoszInfo.removeClass("elizelte");
cegbeoszInfo.text("Jó!");
cegbeosz.addClass("lotto");
cegbeoszInfo.addClass("lotto");
return false;
}
}
function validateCegkapcs() {
//if it's valid
var a = $("#ceg_kapcs").val(), filter = /^(\b[a-zA-Z.-]+\b.*){2,4}$/;
if (filter.test(a)) {
cegkapcs.removeClass("elizelte");
cegkapcsInfo.removeClass("elizelte");
cegkapcsInfo.text("Jó!");
cegkapcs.addClass("lotto");
cegkapcsInfo.addClass("lotto");
return true;
} else {
//Ha if it's NOT valid
cegkapcs.removeClass("lotto");
cegkapcsInfo.removeClass("lotto");
cegkapcs.addClass("elizelte");
cegkapcsInfo.text("Kis és nagybetű, szóköz és kőtőjel csak a megengedett!");
cegkapcsInfo.addClass("elizelte");
return false;
}
}
//On blur
cegnev.blur(validateCegnev);
cegemail.blur(validateCegemail);
cegkapcs.blur(validateCegkapcs);
cegbeosz.blur(validateCegbeosz);
//On key press
cegnev.keyup(validateCegnev);
cegemail.keyup(validateCegemail);
cegkapcs.keyup(validateCegkapcs);
cegbeosz.keyup(validateCegbeosz);
I don't know whats appropriate or not posting the whole code, or just the parts I have a genuine problem with, excuse me for not knowing that. My problem is that 2 validations work flawlessly. One that does "cegnev" and one that does "cegkapcs". The other two screw themselfs up, but differently. The cegemail does NOT work at ALL. cegbeosz does work to an extent but does NOT change the text.
The "testing" website can be checked at www.tudatoskommunikacio.hu/gergo if u want to check out the html part of it. I am quite new to javascript, and I do beleive that is causing the erros. I tried to narrow down my mistakes by using Jlint, but beside a few problems, that I read across the web I can live with, nothing stands out as a mayor flaw. Thanks for the help, I am quite desperate here...
It's just a copy-paste error by the look of it. At the top of your code:
cegcim = $("#ceg_cim");
cegcimInfo = $("#ceg_cimInfo");
cegemail = $("#ceg_cim");
cegemailInfo = $("#ceg_emailInfo");
You are selecting the ceg_sim id for the cegemail variable
Your other issue is also just a trivial spelling mistake:
cegbeosz = $("#ceg_beosz");
cegbeoszInfo = $("#ceg_beszInfo");
You're missing an "o".
I strongly recommend using a javascript debugger in future to catch these trivial mistakes.