Javascript: How do you enter in unknown variables? - javascript

I'm making a game where the player can pick 3 different characters. However I am running into a glaring problem, that being, when I create a function (like a attack function), it is linked to only 1 specific character.
I would rather have my code be written where when the person picks their character, all can use the same attack skill without me having to write 3 different ones. Also, the attack skills are linked to a button, so it must be diverse.
I can't have a designated attack button for X player. So how do I make my code so it can add all characters instead of just 1 specified character?
Example: Looking at my function below for the strike attack. I can set it to dwarf & angel which is fine. However what if the player picks a ELF character instead? Then the function will not work because it believes the character is a dwarf, fighting a angel. How can I fix this?
New=Object.create;
actor = {
primaryStats: function (level, hp, hpcap, balance, balancecap, exp){
this.level = level;
this.hp = hp;
this.hpcap = hpcap;
this.balance = balance;
this.balancecap = balancecap;
this.exp = exp;
},
player = New (actor),
monster = New (actor),
dwarf = New(player),
human = New(player),
elf = New(player),
angel = New(monster),
demon = New(monster),
dragon = New(monster);
//ATTACK SKILL ONE
dom.el("strike").onclick = function strike() {
playerHitCalc(dwarf, angel);
};
playerHitCalc = function(character, boss){
roll = Math.floor(Math.random() * character.accuracy + 1);
if (roll > boss.agility){
var hit = true;
}
else {
hit = false;
logMessage(boss.ID + " " + "has evaded your attack!")
}
playerDamCalc = function(){
if (hit == true){ //If you score a successful hit
var damage = Math.floor(Math.random() * character.strength + 1);
var totalDamage = damage - boss.armor; // Subtract Damage from Bosses Armor
if(totalDamage <= 0)totalDamage += boss.armor; // Add boss armor to prevent Negative Numbers
boss.hp -= totalDamage; // Subtract bosses HP from damage.
character.exp += totalDamage * 0.25; // Gain 1 exp point per 4 damage done
dom.setText("bosshealthcounter", boss.hp) // Update Bosses Health
logMessage("You hit " + boss.ID + " for " + totalDamage + " damage!");
}

You can use data attributes to link a dom element to particular characters. For example -
<button class="attack-btn" data-attacker="dwarf" data-target="angel">Attack</button>
Then in the on click handler, you can extract that particular element's attributes attacker and target instead of hardcoding the values.
Hope that helps!

One thing you are doing is creating Player and Monster from Actor and then specific player class from Player and the same for monster.
Problem lies in that now you have a specific handle for each type of player and each type of monster.
If we would want to edit current code, you would have to add currentPlayer and currentMonster variables that you would make equal to the Player and Monster you want to fight. Then you could avoid referencing specific player and specific monster and just use
playerHitCalc(currentPlayer, currentMonster);
But I would suggest changing things a little bit and create objects in a little different way.

Related

Making a high score (best time) localStorage in JavaScript

I'm having a little bit of trouble wrapping my head around using a localStorage for a high score. I have saved the variable for the high score but now getting it to refresh with a new high score has become the issue.
So I have reverted back to the start and I have just these lines:
localStorage.setItem('score', timeDiff.toFixed(3));
parseFloat(document.getElementById("best_score").innerHTML = "My best time is " + localStorage.getItem('score') + " s");
My plan is then, if that user scores a better time than all their other attempts, this is saved as their best time.
I realise I need to do an "if" statement. So, the best I can come up with at the moment is human speak not JavaScript.
If score is nothing, then just print the new score.
If the score is better than the current printed score, then print that one instead.
If the score isn't as good as the current score, then don't do anything at all.
And that is it!
Be grateful for anyone to push me in the right direction of how to write those if statements.
There's no reason for the parseFloat in your example, but you will probably want parseFloat as part of this solution.
The update would look something like this:
// Get the previous high score if any, or `NaN` if none
// `localStorage.score` will be `undefined` if you've never stored a high score
// at all (or a string otherwise). `parseFloat` will return `NaN` if you pass it
// `undefined`, so we check that later.
const lastHighScore = parseFloat(localStorage.score);
// Get the string version of this score
const scoreString = timeDiff.toFixed(3);
let message;
if (isNaN(lastHighScore) || timeDiff > lastHighScore) { // ** Perhaps < ? Hard to tell from the question
// New high score
message = "Your new best time is " + scoreString;
// Store the new score
localStorage.score = scoreString;
} else {
// Not a new high score
message = "Your time was " + scoreString + "; your best time was " + localStorage.score;
}
document.getElementById("best_score").textContent = message;
Given the starting point seems to have a value in timeDiff, I couldn't see how a score could be "nothing."
(If you want to use getItem() and setItem() instead, note that getItem() will return null [not undefined] if the item doesn't exist. But parseFloat(null) also gives you NaN, so...)
Okay, based on what you wrote in the comment, your problem is not actually the if statements, but how to structure it so it gets updated properly.
The answer to this is creating a function that does all of this for you.
Let's call it updateHighscore.
This function will take a new score, then see if it's a high score and if it is, update everything accordingly.
Whenever a game is finished now, you just call this method.
E.g. See the following:
function updateHighscore(newScore) {
// get current highscore
const oldHighscore = parseFloat(localStorage.getItem('score'))
if (oldHighscore == null // if it doesn't exist yet
|| oldHighscore < newScore) { // or if it's smaller than the new score (I assume bigger means better here)
// current highscore needs to be updated
localStorage.setItem('score', newScore)
// html needs to be updated
document.getElementById("best_score").innerHTML = "My best time is " + localStorage.getItem('score') + " s"
}
}
Now, whenever the game is finished and you have a new score, just call this method with the score and it should update everything accordingly.
You have to write it like this when user gets a new highscore:
localStorage.setItem('score', timeDiff.toFixed(3));
document.getElementById("best_score").innerHTML = "My best time is " + parseFloat(localStorage.getItem('score')) + " s";
to check the highscore, do like this:
var highScore = parseFloat(localStorage.getItem('score'));
highScore = highScore > currentScore ? highScore : currentScore;
localStorage.setItem('score', highScore);

How can I get a true random from an array? Or should I do something else entirely?

I would like to display a different madlib each time a user clicks the submit button. Only needs to be clicked 3 times. I am using the functions below, but it doesn't seem all that random. I also have a snippet of the dogLib function that creates three madlibs and then calls the function above it to generate a random madlib string.
//Class: madlibGenerator.js
//----- Private Helper Functions -----
//Get Random: word strings for randam madlib
//Get Random: madlib string to display
function getRandomString(array) {
for(var i = array.length - 1; i>0; i--){
var j = Math.floor(Math.random() * (i+1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return this.word = array.pop();
}
//Set: set user input word string arrays into the getRandomString(array)
//Get: a final array of words to add to the madLib display strings
function getFinalWordArray(){
var prpN = getRandomString(this.properNouns);
var adjt = getRandomString(this.adjectives);
var noun = getRandomString(this.nouns);
var vrb = getRandomString(this.verbs);
return finalWordArray = [prpN, adjt, noun, vrb];
}
//Get Random Dog Lib
function getDogLib() {
//Get Random Dog Words
var dogWordsArray = getFinalWordArray();
//DogLibs
var dogLibOne =
"What is that " + dogWordsArray[1] +
" sound!" +
" Hey! " + dogWordsArray[0] +
"! You come " + dogWordsArray[3] +
" you crazy " + dogWordsArray[2] +
"!";
var dogLibTwo =
dogWordsArray[0] + "!! " +
dogWordsArray[0] + "!! " +
"Come " + dogWordsArray[3] +
" and lay on my clean " + dogWordsArray[2] +
" while your treat is still " + dogWordsArray[1] + "!";
var dogLibThree =
"My human comes home and takes me for a " + dogWordsArray[3] +
" where I sit on a " + dogWordsArray[2] +
" and get my " + dogWordsArray[1] +
" belly rubbed!";
//Make array of DogLibs
var dogLibArray = [dogLibOne, dogLibTwo, dogLibThree];
//Pick random dogLib string to display
finalDogLib = getRandomString(dogLibArray);
}
//Display: Random MadLib to console for now
function displayMadlib(pDisplayIDValue) {
if(pDisplayIDValue == "dogLib"){
//display
getDogLib();
console.log(finalDogLib);
}else if(pDisplayIDValue == "loveLib"){
//display
getLoveLib();
console.log(finalLoveLib);
}else if(pDisplayIDValue == "funnyLib"){
//display
getFunnyLib();
console.log(finalFunnyLib);
}
}
The code above isn't broken, it just doesn't produce a true random.
//Preferred Result: the program displays a different madlib each time the user clicks the submit button. The user only needs to click the button 3 times to get different madlibs, the fourth click clears the form and starts the program fresh.
Thank you!
I am open to any idea to make this a truly random madlibGenerator. Maybe counting number of clicks from a submit button?
So true randomness is going to be tough to achieve. Math.Random() from the javascript library isn't truly random as you've guessed, it's pseudo-random, meaning there is a pattern to it over a large number of inputs. Computers inherently can't really do true randomness, because they are always going to have to take some number, perform some sort of algorithm on it (these are usually "Mersenne Twisters" - fun wikipedia read), and spit out the result.
That said, I don't know exactly how to improve on what you've put into place here. With PRNG, a really large number of possible inputs can help a lot. If you want absolutely true randomness, the easiest way would probably be to hook into random.org's API (https://api.random.org/dashboard - developer license is free, limited to 1000 requests per day). Hooking into an API might be more work than you were planning on, but random.org uses (if I remember right) atmospheric noise and barometric pressure from the Earth to create their random numbers, so it's about as close to true randomness as you can possibly get.
I hope this helps!

Score counter doesn't count scores properly

First off, I have to say that I am very new to Javascript and programming in general so it's possible that the issue is related to my (current) lack of knowledge.
I've tried to make a simple game where a computer thinks of a random number between 0 and 10 and the user tries to guess that number by typing his guess in the text field. If the number is correct, the user gets the message that they guessed the number correctly and otherwise, they get the message that the numbers are not correct.
The first part works as intended. The problem is the score counter.
So this is the part of the HTML code that I wrote for the counter:
<p id="points">Number of points: </p><span id="points-number">0</span>
And this is the code that I wrote in JS:
<script type="text/javascript">
document.getElementById("instructions").onclick = function() {
alert("You need to guess the number that your computer imagined. Viable numbers are between 0 and 10. Every time you guess the number, score increases by 1 and every time you miss, you will lose a point")
}
document.getElementById("guess-number").onclick = function() {
var ourNumber;
var randomNumber;
var pointsNumber = 0;
randomNumber = Math.floor(Math.random() * 10);
ourNumber = document.getElementById("input").value;
if (ourNumber == randomNumber) {
alert("The numbers are equal!");
pointsNumber+=1;
var result = document.getElementById("points-number");
result.innerHTML = pointsNumber;
} else {
alert("The numbers are not equal! The number that your computer imagined is:" + randomNumber + ", and our number is: " + ourNumber);
pointsNumber-=1;
var result = document.getElementById("points-number");
result.innerHTML = pointsNumber;
}
}
</script>
Now here's the problem...whenever the user misses the number, the number of points goes to -1. But if he misses the second time, it stays at -1, it doesn't decrease further. After the user guesses the number, the value changes from -1 to 1. But, if he guesses again, it doesn't increase to 2, it stays at 1. Then when he misses, it jumps back to -1 and vice versa.
So, I believe I am missing something here, what should I do to make the counter work as intended? In other words, to make the score increase by 1 every time the user guesses the random number and make it decrease by 1 every time he doesn't get it right?
Thanks in advance.
basically, you are always starting with
var pointsNumber = 0;
instead, you should use:
var pointsNumber = + document.getElementById("points-number").innerHTML;
bonus:
and yes instead of:
randomNumber = Math.floor(Math.random() * 10);
use:
randomNumber = Math.floor(Math.random() * 11);
because, Math.random() lies between 0 (inclusive) and 1 (EXCLUSIVE), so could never reach 10.
see more about Math.random() at: https://www.w3schools.com/js/js_random.asp
You need to declare pointsNumber outside of the function:
var pointsNumber = 0;
document.getElementById("guess-number").onclick = function() {
var ourNumber;
var randomNumber;
Otherwise, each time the onclick function is called, you declare pointsNumber and set it to 0. Then it gets +1 or -1 depending on the if/else, which explains the behavior you are observing.

Wrong results calculating EMA (exponential moving average) using Javascript, Nodejs

I'm trying to calculate the EMA with this script.
But it does not give me the correct EMA.
This could be of many reasons, but i'm not sure what it is.
I've tried different formulas for the EMA without any better results, I'm really not a professional coder nor mathematician and thus i can't see what I'm doing wrong.
How Is the EMA value calculated over time? For the first value I calculate the first EMA using the SMA, i guess that should work - right?
My EMA value = 0.033144798412698406
Real EMA value = 0.033084
Close = last closing price
Period = 20;
Multiplier = (2 / (period + 1));
function calculateEMA() {
if (EMA == 0) {
EMA = (Close - SMA) * multiplier + SMA;
calculateEMA();
} else {
for (a = 0; a < period; a++) {
EMA = (Close - previous_ema) * multiplier + previous_ema;
console.log(EMA + " ema");
previous_ema = EMA;
}
}
}
// UPDATE Added my whole script (which can be runned)- https://pastebin.com/91GEuATM
You need Nodejs and the binance node api installed (npm install node-binance-api --save) ; Keep in mind that this is just my "test script" hence all the weird variable names etc.
//UPDATE 2 Ticks sample data https://pastebin.com/AFzf7GwQ

Var won't exceed billion

EDIT
I tested something out, and apparently, this:
if(info.max.value == "") {maxdesiredvalue = 999999999999999999999}
Returns in the chrome console:
> maxdesiredvalue
< 999999999
So I believe the problem really comes from there... is there a maximum number of digits we can attribute to a variable?
I'm into javascript for a few months now, and I've made a program that generates random weapons for a tabletop rpg.
Every weapon generated has a price relative to it's attributes. My problem today is that this price won't exceed 9 digits (cannot reach billion), even though it can.
In my generator, it is possible to choose certain properties before generating the weapon. If I intentionally try to generate something worth over a billion gold, it will crash instantly. On the other hand, if there is any way the weapon can be generated without exceeding the billion, it will do so.
For example, the most expansive metal is the "Residuum". The only 2 weapons that can be generated in Residuum are the dart and the shuriken, since they only use 1/16 of an Ingot. Therefore if I set the metal to be Residuum, they will be the only 2 possible generated weapons. From this point, if I try to specify I want a Residuum Sword, it will simply crash as explained earlier.
In my generation options, I also have a text input for the user to choose a minimum value and/or a maximum value for the weapon. I set the default max value to Infinity, so it should'nt be a problem.
function desiredvalue(){
if(info.max.value == "") {maxdesiredvalue = Infinity}
else {maxdesiredvalue = parseInt(info.max.value)}
if(info.min.value == "") {mindesiredvalue = 0}
else {mindesiredvalue = parseInt(info.min.value)}
}
In my html:
Min price: <input type="text" name="min" value="" onchange="desiredvalue()">
Max price: <input type="text" name="max" value="" onchange="desiredvalue()">
I already tried to deactivate this function to see if it was the problem, but even without a specific max value, weapons still won't be generated if their value exceeds 9 digits.
Maybe the problem sets inside the value formula, so here it is, even though it might not be a big help since it is all made up from variables.
WeapValue = ((((IngotValue * Ingots) + CraftTime + (actualEnchantTime * 3) + (LS * 0.02) + (R * 0.05) + BS + (FTH * 0.03)) * (((BPArace + BPAstatus + BPAlevel + ((BPAcrit1 + 1) * BPAcrit2)) / 100) + 1)) + PAenchant + PAaugment1 + PAaugment2 + PAaugment3)
Also the value is modified afterwards to fit in gold, silver or copper...
WeapValue.toLocaleString('en-US', {minimumFractionDigits: 0});
WeapValue = WeapValue.toFixed(2);
if (WeapValue >= 2) {WeapValue2 = Math.ceil(WeapValue); goldtype = " GP"}
else if (WeapValue < 2 && WeapValue >= 1) {WeapValue2 = WeapValue * 10; goldtype = " SP"}
else if (WeapValue < 1 && WeapValue >= 0) {WeapValue2 = WeapValue * 100; goldtype = " CP"}
Nothing else in the script really change the value, and all the variables affecting it are defined earlier, and I don't really think they are the problem, since they actually seem to work (they simply make the price exceed 9 digits).
If you have any questions related to the script, I'm here to answer, but I can't put the full script since it is very, very long (2543 lines)...
If anyone has an idea of how I can deal with my problem, it would be so appreciated! Again, I'm not a javascript expert, but I did my best and looked a lot on the Internet for help, but I still can't get rid of this problem...
Thank you!

Categories

Resources