I've been working on a simple script I can use for a JavaScript/HTML RPG game, but when building the battle script, I no getting any console output. I have tried everything I can think of but still no luck and I started to wonder if I've made a coding error somewhere.
var player = {hp:100, attack:10, defence:10, speed:20};
var enemy = {hp:100, attack:10, defence:10, speed:20};
function playeratk(){
console.log("enemy " + enemy.hp);
var pAtk = Math.floor(Math.random() * player.attack) + 1;
console.log(pAtk);
enemy.hp = enemy.hp - pAtk;
console.log("enemy " + enemy.hp);
console.log("-----");
}
function enemyatk(){
console.log("player " + player.hp);
var eAtk = Math.floor(Math.random() * enemy.attack) + 1;
console.log(eAtk);
player.hp = player.hp - eAtk;
console.log("player " + player.hp);
console.log("-----");
}
function battle() {
if (player.hp < 1) {
console.log("Enemy wins");
}
else if (enemy.hp < 1){
console.log("Player Wins");
}
else {
var pSpeed = Math.floor(Math.random() * player.speed) + 1;
var eSpeed = Math.floor(Math.random() * enemy.speed) + 1;
if (player.speed > enemy.speed){
playeratk();
enemyatk();
battle();
}
else if(enemy.speed > player.speed){
enemyatk();
playeratk();
battle();
}
else {
playeratk();
enemyatk();
battle();
}
}
}
You have to call the battle() function at least once outside of itself. Maybe at the end of the script.
Related
I am struggling all day with this one. I need to call function scoreGrade in order to get grade as a number. Could you tell me what do I need to correct? I tried with this code, but I can't figure out the rest. :/
function endQuiz() {
var grade = scoreGrade();
if (myAnswers[(lengthofobject-1)] {
var output = "<div class='output'>Резултат<br>";
var questionResult = "NA";
//console.log('Quiz Over');
for (var i = 0; i < myAnswers.length; i++ || "ten-countdown"<1)) {
if (data.quizcontent[i].correct == myAnswers[i]) {
questionResult = '<span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>';
correct++;
} else {
questionResult = '<span class="glyphicon glyphicon-remove-circle" aria-hidden="true"></span>';
}
output = output + '<p>Питање ' + (i + 1) + ' ' + questionResult + '</p> ';
}
var grade = scoreGrade(correct, lengthofobject)
document.getElementById("ocena").innerHTML = grade;
function scoreGrade(){
let score = (correct / lengthofobject) * 100;
let grade;
if (score>=85) {grade ='5'}
else if (score>=70) {grade ='4'}
else if (score>=55) {grade ='3'}
else if (score>=40) {grade ='2'}
else {grade ='1'}
return grade;
}
clearInterval(endTime);
output = output + '<p>Имате ' + correct + ' од ' + lengthofobject + ' тачних одговора.</p></div> ';
document.getElementById("quizContent").innerHTML = output;
} else {
//console.log('not answered');
}
I'm guessing your issue is inside the scoreGrade function, which does not return anything. Let's modify it like so:
function scoreGrade(correct, questions.length) {
let score = (correct/questions.length) * 100;
if (score>=85) { return (<h4>Vaša ocena je 5.</h4>); }
else if (score>=70) { return (<h4>Vaša ocena je 4.</h4>); }
else if (score>=55) { return (<h4>Vaša ocena je 3.</h4>); }
else if (score>=40) { return (<h4>Vaša ocena je 2.</h4>); }
else { return (<h4>Vaša ocena je 1.</h4>); }
}
This function would work, but not with vanilla js. Returning html in js is a jsx practice. If you're not using jsx consider just returning the grade value as a string or integer.
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 made a basic 'Lucky Prizes' game in Javascript and yet cannot work out how to stop it from infinitely looping. Is there anything I am obviously doing wrong as I am a beginner and the help would be appreciated.
var winNumber = 0;
var lossNumber = 0;
while (lossNumber < 10);
{
var randomNumber = Math.floor(Math.random() * 100);
if (randomNumber > 20 && randomNumber < 40) {
var winNumber = winNumber + 1;
} else
{
var lossNumber = lossNumber + 1;
}
}
console.log('Number of wins: ' + winNumber);
console.log('Number of losses: ' + lossNumber);
Many thanks
Actually, your entire problem is due to an errant semicolon in while (lossNumber < 10);
This causes the rest of the condition to not be evaluated so the loop never ends. Using var again inside the loops isn't necessary but it's also not the cause of your problem, the semicolon is.
var winNumber = 0;
var lossNumber = 0;
while (lossNumber < 10)
{
var randomNumber = Math.floor(Math.random() * 100);
if (randomNumber > 20 && randomNumber < 40) {
var winNumber = winNumber + 1;
} else
{
var lossNumber = lossNumber + 1;
}
}
console.log('Number of wins: ' + winNumber);
console.log('Number of losses: ' + lossNumber);
You redeclared the variables winNumber and lossNumber again.
Try this:
var winNumber = 0;
var lossNumber = 0;
while (lossNumber < 10)
{
var randomNumber = Math.floor(Math.random() * 100);
if (randomNumber > 20 && randomNumber < 40) {
winNumber = winNumber + 1;
}
else {
lossNumber = lossNumber + 1;
}
}
console.log('Number of wins: ' + winNumber);
console.log('Number of losses: ' + lossNumber);
I have a large number issue here. I'm using the nFormatter for large numbers in javascript but i have no idea how to use it with my existing code.
Here is the formatter im using.
function nFormatter(num) {
if (num >= 1000000000000) {
return (num / 1000000000000).toFixed(1).replace(/\.0$/, '') + 'Trillion';
}
if (num >= 1000000000) {
return (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'Billion';
}
if (num >= 1000000) {
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'Million';
}
if (num >= 1000) {
return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'Thousand';
}
return num;
}
nFormatter;
I need to add this code to my other code but i am not sure how i am going to do this.
Here is my current code.
var gameProfit = 5000;
var tinyOwned = 0;
var tinyCost = 5000;
var tinyIncome = 0;
function tinyGamePlay() {
if (gameProfit >= tinyCost) {
tinyOwned++;
gameProfit -= tinyCost;
tinyIncome = 15000 * tinyOwned;
tinyCost = 5000 * tinyOwned;
document.getElementById('tiny-owned').innerHTML = tinyOwned;
document.getElementById('tiny-income').innerHTML = "Income : $ " + tinyIncome;
document.getElementById('tiny-cost').innerHTML = "Next Cost : $ " + tinyCost;
document.getElementById('currentProfit').innerHTML = "Profit : $ " + gameProfit;
}
}
tinyGamePlay;
So all of the my variable will be more than 1000 at one point so the formatter needs to be used on all my variables.
I dont mind using a JS plugin either if anyone knows of something that could help,
Can anyone help please?
You just need to call this nFormatter function when you are printing the output, see snipped below, for bigger numbers you can use http://jsfromhell.com/classes/bignumber :
function nFormatter(num) {
if (num >= 1000000000000) {
return (num / 1000000000000).toFixed(1).replace(/\.0$/, '') + ' Trillion';
}
if (num >= 1000000000) {
return (num / 1000000000).toFixed(1).replace(/\.0$/, '') + ' Billion';
}
if (num >= 1000000) {
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + ' Million';
}
if (num >= 1000) {
return (num / 1000).toFixed(1).replace(/\.0$/, '') + ' Thousand';
}
return num;
}
var gameProfit = 5100;
var tinyOwned = 0;
var tinyCost = 5000;
var tinyIncome = 0;
function tinyGamePlay() {
if (gameProfit >= tinyCost) {
tinyOwned++;
gameProfit -= tinyCost;
tinyIncome = 15000 * tinyOwned;
tinyCost = 5000 * tinyOwned;
console.log(tinyCost);
document.getElementById('tiny-owned').innerHTML = nFormatter(tinyOwned);
document.getElementById('tiny-income').innerHTML = "Income : $ " + nFormatter(tinyIncome);
document.getElementById('tiny-cost').innerHTML = "Next Cost : $ " + nFormatter(tinyCost);
document.getElementById('currentProfit').innerHTML = "Profit : $ " + nFormatter(gameProfit);
}
}
tinyGamePlay();
<p id="tiny-owned"></p>
<p id="tiny-income"></p>
<p id="tiny-cost"></p>
<p id="currentProfit"></p>