on a onscroll command I have a function which checks the scroll position and then waits 200ms and then checks it again, even tho' I have put the if function to stop it repeating the function the alert tells me that the xy[1] and ye are the same.
function dothescroll() {
if (scrolling == false) {
scrolling = true;
var xy = getScrollXY();
var ye = xy[1];
setTimeout(function(){
alert(xy[1] + " + " + ye);
if (xy[1] > ye) {
scrollup();
} else {
scrolldown();
}
},200);
}
}
Any ideas??
Thankss.x
You need to call getScrollXY() again to get the new coordinates:
setTimeout(function(){
xy = getScrollXY();
alert(xy[1] + " + " + ye);
if (xy[1] > ye) {
scrollup();
} else {
scrolldown();
}
},200);
Related
I have an image gallery I'm using for a webpage. Currently, the gallery images change when the user scrolls, but I'd like to change it so that the images change on a time interval, and are on a loop instead of an up scroll to go back and a down scroll to go forward. I'm pretty new to Javascript, so I'm now sure how to change the below script from scrolling to timed.
<script>
$(document).ready(function() {
var curPage = 1;
var numOfPages = $(".skw-page").length;
var animTime = 1000;
var scrolling = false;
var pgPrefix = ".skw-page-";
function pagination() {
scrolling = true;
$(pgPrefix + curPage).removeClass("inactive").addClass("active");
$(pgPrefix + (curPage - 1)).addClass("inactive");
$(pgPrefix + (curPage + 1)).removeClass("active");
setTimeout(function() {
scrolling = false;
}, animTime);
};
function navigateUp() {
if (curPage === 1) return;
curPage--;
pagination();
};
function navigateDown() {
if (curPage === numOfPages) return;
curPage++;
pagination();
};
$(document).on("mousewheel DOMMouseScroll", function(e) {
if (scrolling) return;
if (e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) {
navigateUp();
} else {
navigateDown();
}
});
$(document).on("keydown", function(e) {
if (scrolling) return;
if (e.which === 38) {
navigateUp();
} else if (e.which === 40) {
navigateDown();
}
});
});
</script>
Just call setInterval, change what happens when navigateDown is called once all pages have been cycled through, and remove the scroll/keydown listeners.
$(document).ready(function() {
var curPage = 1;
var numOfPages = $(".skw-page").length;
var animTime = 1000;
var scrolling = false;
var pgPrefix = ".skw-page-";
function pagination() {
scrolling = true;
$(pgPrefix + curPage)
.removeClass("inactive")
.addClass("active");
$(pgPrefix + (curPage - 1)).addClass("inactive");
$(pgPrefix + (curPage + 1)).removeClass("active");
if (curPage === 1) $(pgPrefix + numOfPages).addClass("inactive");
setTimeout(function() {
scrolling = false;
}, animTime);
}
function navigateDown() {
if (curPage === numOfPages) curPage = 0;
curPage++;
console.log(curPage);
pagination();
}
setInterval(navigateDown, 5000); // 5000 ms == 5 s
});
.active {
color: purple;
}
.inactive {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p class="skw-page skw-page-1 active">Page 1</p>
<p class="skw-page skw-page-2 inactive">Page 2</p>
<p class="skw-page skw-page-3 inactive">Page 3</p>
<p class="skw-page skw-page-4 inactive">Page 4</p>
</div>
You can use setInterval, also inside setInterval you should not call both the navigateUp and navigateDown functions, since this will nullify their pagination changes as defined in your code.
Also, since in your original code, the trigger to fire either of navigateDown and nvaigateUp functions depends on event passed from keydown and DOMmouseScroll, you will need to tweak my example code to fit your html. I can not give a complete example since your html part is missing here.
$(document).ready(function() {
var curPage = 1;
var numOfPages = $(".skw-page").length;
var animTime = 1000;
var scrolling = false;
var pgPrefix = ".skw-page-";
function pagination() {
scrolling = true;
$(pgPrefix + curPage).removeClass("inactive").addClass("active");
$(pgPrefix + (curPage - 1)).addClass("inactive");
$(pgPrefix + (curPage + 1)).removeClass("active");
setTimeout(function() {
scrolling = false;
}, animTime);
}
function navigateUp() {
if (curPage === 1) return;
curPage--;
pagination();
}
function navigateDown() {
if (curPage === numOfPages) return;
curPage++;
pagination();
}
setInterval(function() {
navigateUp();
/*
or call
navigateDown();
*/
}, animTime);
});
When you run this script it shows the HP for both of the pokemon when you press 1 and click enter it subtracts your attack hit points to the enemies hit points. When you or the ememy hits 0 or less than 0 hit points it is supposed to stop and just show who won in the console log. Instead it takes an extra hit to for it to show the message.
So if you are at -10 hp it takes one more hit.
let firstFight = false;
while (!firstFight) {
let fightOptions = prompt("1. Fight, 2.Items, 3.Potions " + wildPokemon[0].name + ":" + wildPokemon[0].hp + " " + pokeBox[0].name + ":" + pokeBox[0].hp);
if (fightOptions == 1) {
if (!firstFight) {
if (wildPokemon[0].hp <= 0) {
console.log("You have won!");
firstFight = true;
} else {
let attack1 = wildPokemon[0].hp -= pokeBox[0].attack.hp;
console.log(wildPokemon[0].hp);
}
if (pokeBox[0].hp <= 0) {
console.log(wildPokemon[0] + " has killed you");
firstFight = true;
} else {
let attack2 = pokeBox[0].hp -= wildPokemon[0].attack.hp;
console.log(pokeBox[0].hp);
}
}
} else if (fightOptions == 2) {
} else if (fightOptions == 3) {
} else {
}
}
Are there any ways I can make this code more efficient?
you can simply add another if condition to check whether life of the player is still greater then '0' or less then '0' in the same turn like this.
in this way you don't have to go for next turn to check for the players life plus it rids off the extra conditional statements...
if (fightOptions == 1) {
let attack1 = wildPokemon[0].hp -= pokeBox[0].attack.hp;
console.log(wildPokemon[0].hp);
if (wildPokemon[0].hp <= 0) {
console.log("You have won!");
firstFight = true;
}
if (!firstFight){
let attack2 = pokeBox[0].hp -= wildPokemon[0].attack.hp;
console.log(pokeBox[0].hp);
if (pokeBox[0].hp <= 0) {
console.log(wildPokemon[0] + " has killed you");
firstFight = true;
}
}
}
The problem is, the points are getting subtracted after you check if they are equal to or below zero. Here is a way you can check before:
let firstFight = false;
while (!firstFight) {
let fightOptions = prompt("1. Fight, 2.Items, 3.Potions " + wildPokemon[0].name + ":" + wildPokemon[0].hp + " " + pokeBox[0].name + ":" + pokeBox[0].hp);
if (fightOptions == 1) {
wildPokemon[0].hp -= pokeBox[0].attack.hp;
if (wildPokemon[0].hp <= 0) {
console.log("You have won!");
firstFight = true;
} else {
console.log(wildPokemon[0].hp);
}
pokeBox[0].hp -= wildPokemon[0].attack.hp;
if (!firstFight && pokeBox[0].hp <= 0) {
console.log(wildPokemon[0] + " has killed you");
firstFight = true;
} else {
console.log(pokeBox[0].hp);
}
} else if (fightOptions == 2) {
} else if (fightOptions == 3) {
} else {
}
}
While loops stops when the condition is false, in you case, you set it to not false, it is not stopping because you did not explicitly determine it. There are 2 ways you can do.
1st:
while(!firstFight == false)
2nd:
var firstFight = true;
while(firstFight)
then set the firstFight to false inside your if else statements.
I have making a text-based space rpg game. In the battle system, the player and AI take turns firing at each other. I can't figure out how to make the system loop with a while loop without making the browser crash via infinite loop. Here is my code:
function battle(enemy) {
var battleOver = false;
console.log(enemy.name + " appears!");
//problem loop here.
while(battleOver === false){
console.log("This enemy has " + enemy.health + " health.");
for (var i = 0; i < userWeapons.length; i++) {
var ibumped = i + 1;
console.log("Press " + ibumped + " to fire the " + userWeapons[i].name + ".");
}
var weaponChosen;
setTimeout(function() {
var weaponChoice = prompt("Which weapon do you choose?");
switch (weaponChoice) {
case 1:
weaponChosen = userWeapons[0];
console.log(userWeapons[0].name + " chosen.");
break;
case 2:
weaponChosen = userWeapons[1];
console.log(userWeapons[1].name + " chosen.");
break;
default:
weaponChosen = userWeapons[0];
console.log(userWeapons[0].name + " chosen.");
};
}, 1000);
setTimeout(function() {
if (enemy.shields > 0 && weaponChosen.ignoreShield === false) {
enemy.shields = enemy.shields - weaponChosen.damage;
weaponChosen.fire(enemy);
if (enemy.shields < 0) {
enemy.health = enemy.health + enemy.shields;
console.log("Enemy shields destroyed and enemy took " + -1 * enemy.shields + " damage!")
} else {
console.log("Enemy shields have been reduced to " + enemy.shields + ".");
}
} else {
enemy.health = enemy.health - weaponChosen.damage;
weaponChosen.fire(enemy);
console.log("Enemy takes " + weaponChosen.damage + " damage!");
}
if (enemy.health <= 0 && battleOver === false) {
console.log("Enemy destroyed!");
battleOver = true;
}
}, 3000);
setTimeout(function() {
if (enemy.health > 0 && battleOver === false) {
if (enemy.weapons != null) {
console.log(enemy.weapons.name + " fired at you.");
health = health - enemy.weapons.damage;
console.log("You have " + health + " health left.");
if (health <= 0) {
console.log("Game over... You were destroyed");
battleOver = true;
}
} else {
console.log("The enemy did nothing...");
}
};
}, 5000);
}
}
All help is appreciated!
Things start getting very tricky when you use setTimeout. Most games will have a "main game loop" that runs 60 times a second.
Try using a main game loop and cooldowns.
Here's an example of how you could restructure the program.
var timeForOneFrame = 1000/60 // 60 Frames per second
var enemy;
var battleOver;
function initGame() {
/*
Initialize the enemy etc.
*/
}
function gameLoop() {
battle(enemy);
}
function battle(enemy) {
/*
Do all the battle stuff, this function is called 60 times a second-
there's no need for setTimeout!
*/
// If you want an enemy to only be able to attack every 2 seconds, give them
// a cooldown...
if (enemy.cooldown <= 0) {
// Attack!
enemy.cooldown += 2000
} else {
enemy.cooldown -= timeForOneFrame
}
if (enemy.health <= 0 && battleOver === false) {
console.log("Enemy destroyed!");
battleOver = true;
clearInterval(gameLoopInterval)
}
}
initGame();
var gameLoopInterval = setInterval(gameLoop, timeForOneFrame);
A while loop blocks the whole page until it ends, and as your loop never exits its infinite. You may replace it with a high speed interval:
const loop = setInterval( function(){
if( battleOver ) return clearInterval(loop);
console.log("This enemy has " + enemy.health + " health.");
for (var i = 0; i < userWeapons.length; i++) {
console.log("Press " + (i + 1) + " to fire the " + userWeapons[i].name + ".");
}
},10);
I would take that loop out and use a recursive call on the end of the interactions.
Let's say:
function battle(enemy) {
//All your code here
if (HeroAlive) {
battle(enemy);
}
}
I have a timer that starts counting up when the page is loaded. I want it to stop when the user scrolls to the bottom of the page. Here is the jQuery I've written:
function timerTick(time, stop)
{
if(stop == false)
{
setInterval(function ()
{
time += 1;
var displayTime = time/10;
if(displayTime % 1 != 0)
{
$('.time').text(displayTime.toString());
}
else
{
$('.time').text(displayTime.toString() + ".0");
}
}, 100);
}
else //behavior is the same if i remove the else block
{
return;
}
}
$(document).ready(function () {
var time = 0;
var stop = false;
timerTick(time, stop);
//check if we're at the bottom
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
stop = true;
}
});
});
The timer counts up perfectly, the problem is I can't get it to stop. If I replace the stop = true; line with alert('abc');, the alert shows up when the user reaches the bottom. So all of the pieces are working, just for some reason setting stop to true doesn't stop the timerTick function from going into the if(stop == false) block.
Can someone tell me what I'm doing wrong?
Edit: I made a jsFiddle.
You have to clear interval as soos as user reach the end of page. Otherwise it will continue executing.
Try:
var intervalId;
function timerTick(time, stop)
{
if(stop == false)
{
intervalId=setInterval(function () //Set the interval in a var
{
time += 1;
var displayTime = time/10;
if(displayTime % 1 != 0)
{
$('.time').text(displayTime.toString());
}
else
{
$('.time').text(displayTime.toString() + ".0");
}
}, 100);
}
else //behavior is the same if i remove the else block
{
return;
}
}
$(document).ready(function () {
var time = 0;
var stop = false;
timerTick(time, stop);
//check if we're at the bottom
$(window).scroll(function() {
if($(window).scrollTop() + $(window).height() == $(document).height()) {
stop = true;
clearInterval(intervalId);//HERE clear the interval
}
});
});
DEMO
to determine bottom of the page you could try this
if(window.innerHeight + document.body.scrollTop >= document.body.offsetHeight) {
stop = true;
}
Update:
you need to make your variable stop global, declare it outside of documnet.ready function.
setInterval function returns number that you can later pass into clearInterval to stop the timer.
Declare
var Timeout=0;
check
if(stop == false)
inside the setInterval function
like
Timeout=setInterval(function ()
{
if(stop == false)
{
time += 1;
var displayTime = time/10;
if(displayTime % 1 != 0)
{
$('.time').text(displayTime.toString());
}
else
{
$('.time').text(displayTime.toString() + ".0");
}
}
else
{
clearInterval(Timeout);
}
}, 100);
i'm doing a game with javascript only using function, i know it's not the best method but i'm still learning prototypes before steping in to use them. So, to the point, i have a request animatation frame that calls him self so my function keep executing. The problem is when the player dies i want to stop the enemys to be created , basicaly, stop the functions execution. Better show you some code.
This is my animation function:
function animate() {
if (endGame() == true) {
return;
}
requestAnimationFrame(animate);
if(theBird == null && canContinue == true) {
theBird = getBird(); // variavel com a div do bird
setTimeout(createDrake(), Math.round(Math.random() * 800));
setTimeout(createBrick(), Math.round(Math.random() * 3000));
setTimeout(createBoss(), Math.round(1000 + Math.random() * 15000));
setTimeout(createPowerUp(), Math.round(Math.random() * 15000));
document.addEventListener('keydown', onKeyPressed);
document.addEventListener('keyup', onKeyReleased);
}
else {
updateBirdLocation();
updateBirdSpeed();
flyDrakes();
flyBrick();
flyBullets();
flyPowerUp();
flyBoss();
checkBulletCollisions();
checkBulletCollisionsBricks()
checkShipCollision();
checkShipCollisionBricks();
checkShipCollisionBonusP();
checkShipCollisionBoss();
checkBulletCollisionsBoss();
updateScores();
checkEnemyBulletCollisions();
MoveArrayX(bullets2, -10);
MoveArrayX(bullets3, -10);
removePassingElements();
}
}
And this one is my function stopGame that is beeing called everytime player looses:
function endGame() {
Rbutton.style.visibility= "visible";
var RestartDiv = document.createElement("div");
RestartDiv.id = "RestartDiv";
gameDiv.appendChild(RestartDiv);
document.getElementById('RestartDiv').innerHTML += "You scored" + " " + mobHits + " " + "points!";
canContinue = false;
return true;
}
My attemp to stop this was the 1st part of animate :
function animate() {
if (endGame() == true) {
return;
}
but if i do this my game stops ( like i want ) but before the player dies.
I do not have endGame beeing executed anywhere besides the functions where the player dies. How can i solve this ?
Thank you
EDIT: This is an example how i detect a player died:
function checkShipCollisionBoss() {
for (var k=0; k<bossArray.length; k++) {
if ((isCollide(BirdsDiv, bossArray[k]) ) == true){
endGame();
}
}
}
isCollide is a function that detects the collision.
Then do like this,
function endGame() {
if(isCollide()) // return a boolean from this function
{
Rbutton.style.visibility= "visible";
var RestartDiv = document.createElement("div");
RestartDiv.id = "RestartDiv";
gameDiv.appendChild(RestartDiv);
document.getElementById('RestartDiv').innerHTML += "You scored" + " " + mobHits + " " + "points!";
canContinue = false;
return true;
}
return false;
}
Also remember this, if you are going to check a boolean you can simple give
if(true) or if (false)
Example,
var bool = true;
if(bool)
// your stuff
Your endGame function always return true, so endGame() == true
Then in animate function:
function animate() {
if (endGame() == true) {
return;
}
...
}
which is:
function animate() {
if (true == true) {
return;
}
...
}
which is:
function animate() {
if (true) {
return;
}
...
}
which is:
function animate() {
return;
...
}
So it always return