Javascript: Why isn't my javascript running both animations? - javascript

I'm working on a video game for my project and i'm running into a animation problem. Basically i'm doing a Final Fantasy style game where your recharging your ATB bar and once its full, you can do a skill. So I have 3 functions here. The first one is clearing my ATB bar so that it resets. This code works. The second one is refilling the time-bar by moving a DIV block into place. This works as well. The third function is my attack skill function, which also works except for the fact that it does not do both of these animation functions in the order I placed them.
If you look below, you'll notice I have the code to first run the clear ATB function, and then run the time bar function, hoping that every time I click the button it would reset my ATB. The problem is, it completely ignores the FIRST function and runs the second one. I tried switching them and same thing occurs. So basically I'm stuck where my code will always ignore the first one and operate the 2nd one if both of my animation functions are in the code. So now I'm confused on how to fix this because I want BOTH codes to work. They work separately and independently as it stands now, but when I combine them, only the 2nd one registers.
// 5. ATB TIMEBAR FUNCTION
function clearTimeBar (el, color) { //Clears the bar
var elem = document.getElementById(el);
elem.style.transition = "width 0.0s, ease-in 0s";
elem.style.background = color;
elem.style.width = "0px"
}
function timeBar (el, color) { // Runs the animation
var elem = document.getElementById(el);
elem.style.transition = "width 6.0s, ease-in 0s";
elem.style.background = color;
elem.style.width = "289px";
}
// ATTACK SKILL
document.getElementById("attack").addEventListener('click', function(){
clearTimeBar('overlay','white'); // Clear the ATB bar
timeBar('overlay', 'blue'); // Run the ATB bar
var criticalRoll = Math.floor(Math.random() * 100 + 1);
var precisionRoll = Math.floor(Math.random() * cs.precision + 1);
var npcParryRoll = Math.floor(Math.random() * dragonstats.parry + 1);
var damage = Math.floor(Math.random() * cs.strength + 1);
if (precisionRoll < npcParryRoll) {
addMessage("The Dragon evaded your attack!");
return;
}
if (cs.critical >= criticalRoll) {
damage *= 2;
damage -= dragonstats.armor;
dragon.hp -= damage;
document.getElementById("npchp").innerHTML = dragon.hp;
addMessage("Critical Strike! Dragon suffers " + damage + " hp!")
}
else if (damage - dragonstats.armor <= 0) {
addMessage("Your opponents armor withstood your attack!");
}
else {
damage -= dragonstats.armor;
dragon.hp -= damage;
document.getElementById("npchp").innerHTML = dragon.hp;
addMessage("You hit the dragon for " + damage + " hp!");
}
});

Run your timeBar function after the clearTimeBar has completed taking place.
window.setTimeout(function() { timeBar('overlay', 'blue') }, 1000/60);
or
window.requestAnimationFrame(function() { timeBar('overlay', 'blue') });

Related

trying to increment simon game level in javaScript

I am new to javaScript and trying to create a simon game in jS and want to increase level everytime nextSequence() is called
var started = false; //toggler
var level = 0;
$(document).on("keydown", function() {
if (!started) {
$("h1").text("Level 0")
nextSequence()
started = true;
}
})
function nextSequence() {
var randomNumber = Math.random() * 4;
randomNumber = Math.floor(randomNumber);
var randomChosenColor = buttonColors[randomNumber] //any one color
gamePattern.push(randomChosenColor);
$("#" + randomChosenColor).fadeOut(100).fadeIn(100).fadeOut(100).fadeIn(100); // animate
level = level + 1
console.log(level)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Assuming you have all of the necessary variables set (buttonColors). The variable level should be increased by one every key down, if you want to display the score through the h1 you would need to incorporate the 'score' variable into the text
so change $("h1").text("Level 0") to $("h1").text("Level " + level)

Dom element infinitely incrementing

I'm in my first steps of creating an auto aim system for the enemy bot but I can't even seem to get him to shoot properly.
I create a div element, and move it in a direction. This happens every 4 seconds. I delete the div before the next one gets created. This works. But somehow it creates more and more elements over time and soon turns into a massive amount of divs all flying in the same direction.
** make the bullet here **
function makeBullet() {
if (player.enemy) {
if (player.enemyBullet.bulletInterval == true) {
console.log("working");
player.enemyBullet.bullet = document.createElement('div');
player.enemyBullet.bullet.className = 'bullet';
gameArea.appendChild(player.enemyBullet.bullet);
player.enemyBullet.bullet.x = player.enemy.x;
player.enemyBullet.bullet.y = player.enemy.y;
player.enemyBullet.bullet.style.left = player.enemyBullet.bullet.x + 'px';
player.enemyBullet.bullet.style.top = player.enemyBullet.bullet.y + 'px';
player.enemyBullet.bulletInterval = false;
setInterval(function () {
player.enemyBullet.bulletInterval = true;
}, 4000);
}
}
}
** Move Bullet **
function moveBullet() {
let bullets = document.querySelectorAll('.bullet');
bullets.forEach(function (item) {
item.x += 3;
item.y -= 3;
item.style.left = item.x + 'px';
item.style.top = item.y + 'px';
if(item.y < 200){
item.parentElement.removeChild(item);
player.enemyBullet.bullet = null;
}
})
}
** invoked in request Animation function **
function playGame() {
if (player.inplay) {
moveBomb();
moveBullet();
makeBullet();
window.requestAnimationFrame(playGame);
}
}
** Initiate interval boolean here **
let player = {
enemyBullet: {
bulletInterval: true
}
}
** LINK TO JS FIDDLE FULL PROJECT ** (click here to see what's happening)
https://jsfiddle.net/mugs17/j7f12a0n/
You are using setInterval like set timeout. However setInterval does not only execute one time. Once you've called setInterval the first time, calling it again makes a new different interval that also executes every 4 seconds.
So each time your function gets invoked its creating a new Interval which is why your div elements are increasing as time goes on
Instead wrap the entire create bullet code inside setInterval and make it execute only once by setting a boolean conditional and then immediately changing that conditional to false. Like this:
if (player.enemy) {
if (player.enemyBullet.bulletInterval == true) {
player.enemyBullet.bulletInterval = false;
console.log("working");
setInterval(function () {
player.enemyBullet.bullet = document.createElement('div');
player.enemyBullet.bullet.className = 'bullet';
gameArea.appendChild(player.enemyBullet.bullet);
player.enemyBullet.bullet.x = player.enemy.x;
player.enemyBullet.bullet.y = player.enemy.y;
player.enemyBullet.bullet.style.left = player.enemyBullet.bullet.x + 'px';
player.enemyBullet.bullet.style.top = player.enemyBullet.bullet.y + 'px';
}, 4000);
}
}
}

Using animate.css (link in description) how do I trigger an animation when a particular event is finished

I have an an image moving across the screen and out of viewport, when the image reaches a particular absolute position (right: - 200), I want to trigger the below animation. I am relatively new to programming, not sure how to track when a particular function is done so that I can trigger the below animation.
var $startLessonButton = $('.startLessonButtonUp');
$startLessonButton.mouseup(function() {
$(this).addClass('animated slideInLeft');
});
---------
var movingOutAnimationCounter = 2;
var movingOutCurrentPosition = window.innerWidth / 2 - 200
function moveTrumpOut() {
movingOutCurrentPosition -= 2;
trumpyWrapper.style.right = movingOutCurrentPosition + 'px';
if (movingOutAnimationCounter < 9 ) {
trumpy.src = '../images/trump_walking_out_' + movingOutAnimationCounter + '.png';
movingOutAnimationCounter += 1;
} else {
movingOutAnimationCounter = 1;
trumpy.src = '../images/trump_walking_out_' + movingOutAnimationCounter + '.png';
}
if (movingOutCurrentPosition > -200 ) {
requestAnimationFrame(moveTrumpOut);
}
}
All the best!
If you know time, when moving element is hidden, you can use this function:
setTimeout(function(){ $('.elem').addClass("animCssClass") }, 1000);
Last parameter, in this example: 1000 is time in ms, when function inside should execute. Run this function on mouseup when you adding class to moving element.

Reduce setTimeout time relative to time left

I'm making a random "spinner" that loops through 8 divs and add a class active like this:
https://jsfiddle.net/9q1tf51g/
//create random setTimeout time from 3sec to 5sec
var time = Math.floor(Math.random() * (5000 - 3000 + 1)) + 3000;
var exit = false;
function repeat(){
//my code
if(!exit){
setTimeout(repeat, 50);
}
}
My problem is, I want the function repeat to end slowly, to create more suspense. I think I can do this by raising the 50 from the timeout but how can I do this accordingly to the time left?
Thanks in advance!
You can try this.
$('button').on('click', function(){
var time = Math.floor(Math.random() * (5000 - 3000 + 1)) + 3000;
var anCounter = 1;
var anState = "positive";
var exit = false;
//var time1 = 50000;
setInterval(function(){time = time-1000;}, 1000);
function repeat(){
if(anCounter>7 && anState=="positive"){ anState="negative"}
if(anCounter<2 && anState=="negative"){ anState="positive"}
$('div[data-id="'+anCounter+'"]').addClass('active');
$('div').not('div[data-id="'+anCounter+'"]').removeClass('active');
if(anState=="positive"){anCounter++;}else{anCounter--;}
if(!exit){
if(time <1000)
setTimeout(repeat, 300);
else if(time< 2000)
setTimeout(repeat, 100);
else setTimeout(repeat, 50);
}
}
repeat();
setTimeout(function(){
exit=true;
},time);
});
Once you know that you need to exit the flow (exit is true ) you can trigger some animation by creating a dorm linear serials of you code. Usually this animation should not last more than 2 sec.
You were kind of on the right track but it'd be easier to check the time you've passed by and increment accordingly at a fixed rate. I set it to increase by 50ms every iteration but you could change that to whatever you like.
Fiddle Demo
Javascript
$('button').on('click', function() {
var time = Math.floor(Math.random() * (5000 - 3000 + 1)) + 3000;
var anCounter = 1;
var anState = "positive";
var elapsed = 0;
var timer;
function repeat(timeAdded) {
if (anCounter > 7 && anState == "positive") {
anState = "negative"
}
if (anCounter < 2 && anState == "negative") {
anState = "positive"
}
$('div[data-id="' + anCounter + '"]').addClass('active');
$('div').not('div[data-id="' + anCounter + '"]').removeClass('active');
if (anState == "positive") {
anCounter++;
} else {
anCounter--;
}
if (elapsed < time) {
timer = setTimeout(function() {
repeat(timeAdded + 50);
}, timeAdded);
elapsed += timeAdded;
}
else {
clearTimeout(timer);
}
}
repeat(0);
});
You can add a parameter called intTime to your function repeat and inside that function you can adjust the next timeout and call the repeat function with the new timeout. each time it gets called it will take 20 ms longer. however you adjust the increment by changing the 20 in
var slowDown=20; to a different number.
var slowDown=20;
setTimeout ("repeat",50);
function repeat(intTime){
//my code
if(!exit){
intTime=Math.floor (intTime)+slowDown;
setTimeout(repeat(intTime), intTime);
}
}
And then you will need to create another timeout for the exit.
var time = Math.floor(Math.random() * (5000 - 3000 + 1)) + 3000;
var exit = false;
setTimeout ("stopSpinning",time);
function stopSpinning(){
exit = true;
}
so the whole thing should look something like this
var slowDown=20;
var time = Math.floor(Math.random() * (5000 - 3000 + 1)) + 3000;
var exit = false;
setTimeout ("stopSpinning",time);
setTimeout ("repeat",50);
function repeat(intTime){
//my code
if(!exit){
intTime=Math.floor (intTime)+20;
setTimeout(repeat(intTime), intTime);
}
}
function stopSpinning(){
exit = true;
}
Fiddle Demo
Linear deceleration: //values are just an example:
add a var slowDown = 0; inside the click event handler
add slowDown += 1; inside the repeat function
pass 50+slowDown to setTimeout
Curved deceleration:
add a var slowDown = 1;and a var curveIndex = 1.05 + Math.random() * (0.2); // [1.05-1.25)inside the click event handler
add slowDown *= curveIndex; inside the repeat function
pass 50+slowDown to setTimeout

Proper deleting HTML DOM nodes

I'm trying to create a star shining animation.
function ShowStars()
{
//if ($('img.star').length > 5)
// return;
var x = Math.floor(Math.random() * gameAreaWidth) - 70;
var y = Math.floor(Math.random() * gameAreaHeight);
var star = document.createElement("img");
star.setAttribute("class", "star");
star.setAttribute("src", imagesPath + "star" + GetRandom(1, 3) + ".png");
star.style.left = x + "px";
star.style.top = y + "px";
gameArea.appendChild(star);
// Light.
setTimeout(function () { star.setAttribute("class", "star shown"); }, 0);
// Put out.
setTimeout(function () { star.setAttribute("class", "star"); }, 2000);
// Delete.
setTimeout(function () { gameArea.removeChild(star); }, 4000);
setTimeout(function () { ShowStars(); }, 500);
}
It works fine until I uncomment the following code which is supposed to regulate star count:
//if ($('img.star').length > 5)
// return;
Then it stops to work as if the created stars are not removed (the first 5 stars blink then nothing happens). Why do the jQuery selector select them after gameArea.removeChild(star);? Isn't it enough to remove them from the parent node?
Browser: Google Chrome 17.
Regards,
Change the commented out lines to
if ($('img.star').length > 5) {
setTimeout(function () { ShowStars(); }, 500);
return;
}
to keep the ShowStars recursion going.
I see a workaround: do not create stars dynamically, but insert them in HTML (<img id="star1">...<img id="starN">, where N is total count) then light and put out the existing nodes. Nevertheless, I'd like to understand, what's wrong with removing nodes in the question above.

Categories

Resources