How do I "uniquely" repeat a function n times in javascript? - javascript

so I have some code that draws a path and a circle. the circle is animated across the path every single time the function is initiated. I simply want to create 10 paths, each with their own circle that animates across each path. When I simply execute the function 10 times, the paths are generated fine, however the circle all animate along the same, single path. what am I doing wrong here? Is the best method here to create a for(i=0) loop?
You can view my code on jfiddle, or take a look at it here:
function commerce() {
Raphael("commercebounce", function () {
var r = this;
function pathfade() {
var pa = .1,
pb = .4,
pc = [0, 2],
pd = [50, 300],
pe = [150, 800],
pf = [150, 350],
pg = pd[0] + Math.random() * (pd[1] - pd[0]),
ph = pe[0] + Math.random() * (pe[1] - pe[0]),
pi = pf[0] + Math.random() * (pf[1] - pf[0]),
bd = .1,
be = .9,
pathspot = bd + Math.random() * (be - bd),
colours = ["215,10,45", "115,115,115"],
stroke = ["", "- "];
opacity = pa + Math.random() * (pb - pa), colour = "rgb(" + colours[Math.round(Math.random())] + ")", strokeW = pc[Math.round(Math.random())];
pj = r.path("M 0 " + pg + " C 0 " + pg + " " + (ph - 100) + " " + pg + " " + ph + " 400 M " + ph + " 400 C " + ph + " 400 " + (ph + 100) + " " + pg + " 960 " + pi).attr({stroke: colour,"stroke-dasharray": stroke[Math.round(Math.random())],"opacity": 0});
bh = r.circle(0, 0, 7, 7).attr({"stroke-width": this.strokeW,stroke: colour,"stroke-opacity": this.opacity,fill: "none","fill-opacity": 0}).onAnimation(function() {
var t = this.attr("transform")})
leng = pj.getTotalLength();
r.customAttributes.along1 = function (v) {
var point = pj.getPointAtLength(v * leng);
return {
transform: "t" + [point.x, point.y] + "r" + point.alpha
}
};
return bh.attr({along1:0}), bh.animate({along1:pathspot},300), pj.animate({opacity:opacity},300), pj, bh
}
pathfade();//how do i repeat this function n times?
});
}
commerce();

As far as I can see a simple loop should be fine. If you're interested this is the fastest way to loop in JavaScript:
var i = 10; while (i--) {
//Your code..
}

You need to break the pathfade() function into multiple simple functions that do only a few task.
There are two main problems.
First, you're placing a semi-colon where there should be a comma during your variable declarations. Look at the stroke variable.
Second, pathfade is returning multiple values when javascript only supports one. Remember that once you return from a function the rest of the statements don't get executed.
And lastly, use a for, do-while, or while loop to repeat your function calls.
Here's the fix. Sorry I didn't have time to refactor.
function commerce() {
Raphael("commercebounce", function () {
var r = this;
function pathfade() {
var pa = 0.5,
pb = 0.9,
pc = [0, 2],
pd = [50, 300],
pe = [150, 800],
pf = [150, 350],
pg = pd[0] + Math.random() * (pd[1] - pd[0]),
ph = pe[0] + Math.random() * (pe[1] - pe[0]),
pi = pf[0] + Math.random() * (pf[1] - pf[0]),
bd = 0.1,
be = 0.9,
pathspot = bd + Math.random() * (be - bd),
colours = ["215,10,45", "115,115,115"],
stroke = ["", "- "],
opacity = pa + Math.random() * (pb - pa),
colour = "rgb(" + colours[Math.round(Math.random())] + ")",
strokeW = pc[Math.round(Math.random())],
pj = r.path("M 0 " + pg + " C 0 " + pg + " " + (ph - 100) + " " + pg + " " + ph + " 400 M " + ph + " 400 C " + ph + " 400 " + (ph + 100) + " " + pg + " 960 " + pi).attr({
stroke : colour,
"stroke-dasharray" : stroke[Math.round(Math.random())],
"opacity" : 0
}),
bh = r.circle(0, 0, 7, 7).attr({
"stroke-width" : this.strokeW,
stroke : colour,
"stroke-opacity" : this.opacity,
fill : "none",
"fill-opacity" : 0
}).onAnimation(function () {
var t = this.attr("transform")
}),
leng = pj.getTotalLength();
r.customAttributes.along1 = function (v) {
var point = pj.getPointAtLength(v * leng);
return {
transform : "t" + [point.x, point.y] + "r" + point.alpha
}
};
bh.attr({
along1 : 0
});
bh.animate({
along1 : pathspot
}, 300);
pj.animate({
opacity : opacity
}, 300);
}
var i = 10;
while( i-- ){
pathfade();
}
});
}
commerce();
Demo: http://jsfiddle.net/VEdwG/6/
Your should read "The Elements of C# Style".
http://www.amazon.com/The-Elements-Style-Kenneth-Baldwin/dp/0521671590/ref=cm_cr-mr-title

var n = 5; //or however much you want
for (var i = 0; i < n; i++){
pathfade();
}
The for loop method is the simplest option here.

Related

How can I rewrite innerHTML everytime function is called javascript

function he() {
var x = Math.floor((Math.random() * 100) + 1);
document.getElementById("res1").innerHTML = "Heroes have dealt " + x + " damage on villains.";
var vhp = villains - x;
document.getElementById("res2").innerHTML = "<br/>Villains have " + vhp + " hp left.";
vok();
}
function vok() {
var y = Math.floor((Math.random() * 100) + 1);
document.getElementById("res3").innerHTML = "<br/>Villains have dealt " + y + " damage on Heroes.";
var hhp = hero - y;
document.getElementById("res4").innerHTML = "<br/>Heroes have " + hhp + " hp left.";
he();
}
Here is the above code I made function he() is called when a button is clicked and vok function is called after execution of he() function but it's not going good currently i want to overwrite the innerHTML every time the function is runned how am I supposed to do so?

Math error in angularjs calculation

I am calculating the values and dividing the total by variable value (9).for example:
$scope.wald_costs = Math.round($scope.logistics_costs + $scope.refurbishment_costs + $scope.insurance_costs + $scope.priceful + $scope.t / $scope.$scope.sharable_with)
which will be
$scope.wald_costs = Math.round(1000 + 500 + 4500 + 45000 + 27000 / 9)
suppose to be $scope.wald_costs = 8666
but i am not getting the proper output when i print <b>{{wald_costs}}</b>.
Instead what i get in output is like this 6000450003375
$scope.t = 27000
$scope.logistics_costs = 1000
$scope.refurbishment_costs = 500
$scope.insurance_costs = 4500
$scope.priceful = 45000
$scope.sharable_with = 9
$scope.wald_costs = Math.round(($scope.logistics_costs + $scope.refurbishment_costs + $scope.insurance_costs + $scope.priceful + $scope.t / $scope.$scope.sharable_with))
how can i solve this?
Try this http://plnkr.co/edit/8ZZY2XtxB2EbB64hWYyn?p=preview
$scope.t = 27000;
$scope.logistics_costs = 1000;
$scope.refurbishment_costs = 500;
$scope.insurance_costs = 4500;
$scope.priceful = 45000;
$scope.sharable_with = 9;
$scope.wald_costs = Math.round(($scope.logistics_costs + $scope.refurbishment_costs + $scope.insurance_costs + $scope.priceful + $scope.t) / $scope.sharable_with);
alert($scope.wald_costs);
use
$scope.wald_costs = Math.round(($scope.logistics_costs + $scope.refurbishment_costs + $scope.insurance_costs + $scope.priceful + $scope.t) / $scope.$scope.sharable_with)

Trying to make loop exit , but it currently just continues looping for 100 times

I am trying to make so when the looping of 100 hits on the character exits the loop when the life dice rolls to 0. How it currently is is all gets looped 100 times. I am not quite sure how I need to go about solving this, any tips would be helpful. My code is below.
function addChar(fname, lname, speed, agility, wep, outfit, mood) {
this.fname = fname;
this.lname = lname;
this.speed = speed;
this.agility = agility;
this.wep = wep;
this.outfit = outfit;
this.mood = mood;
this.special = function(specialMove) {
specialMove();
}
this.jumpKick = function() {
var jmpkckTimes = Math.floor(Math.random() * (100 - 33 + 1)) + 33;
document.write("He jumpkicks " + jmpkckTimes + " times. ");
if (jmpkckTimes > 70) {
document.write("He enters rage mode! ");
} else {
document.write("He does not have enough kicks for rage mode. ");
}
}
this.hits = function() {
var allHits = Math.floor(Math.random() * (100 - 33 + 1)) + 33;
document.write(" He gets attacked for " + allHits + " HP.");
}
this.lifes = function() {
var life = Math.floor(Math.random() * (3 - 0 + 1)) + 0;
if (life > 0) {
document.write(" The life dice rolls a " + life + ". You have survived! For now...");
} else {
document.write(" The life dice rolls a " + life + ". You have died!");
}
}
}
var myChar = new addChar('Johhny', 'Kicker', 10, 7, 'Ancient Greataxe', 'Barrows', 'angry');
document.write(myChar.fname + " " + myChar.lname + "'s speed is " + myChar.speed + "<br>");
document.write(myChar.fname + " " + myChar.lname + "'s agility is " + myChar.agility + "<br>");
document.write(myChar.fname + " " + myChar.lname + "'s weapon of choice is: " + myChar.wep + "<br>");
document.write(myChar.fname + " " + myChar.lname + " feels " + myChar.mood + "<br>");
document.write(myChar.fname + " " + myChar.lname + " attempts his special: ");
myChar.special(myChar.jumpKick)
for (i = 1; i < 101; i++) {
myChar.hits(myChar.allHits)
myChar.lifes(myChar.lifes)
}
function myOutfit() {
document.getElementById("demo").innerHTML = ("He is wearing " + myChar.outfit)
}
var start = Date.now();
var response = prompt("Do you think my character has what it takes?", "");
var end = Date.now();
var elapsed = (end - start) / 1000;
console.log("You took " + elapsed + " seconds" + " to type: " + response);
You need to have a way to communicate outside of the object, of what is happening inside the object.
For example, when something happens in a function, like lifes() or hits(), you should assign a value to a variable on the object to retain state. That way you can access the state from the for loop.
Example:
this.isAlive = true; // starting condition
this.lifes = function() {
var life = Math.floor(Math.random() * (3 - 0 + 1)) + 0;
this.isAlive = (life > 0);
if (this.alive) {
document.write('you survived');
} else {
document.write('you died');
}
Now in your for loop, you can access isAlive:
// loop until 100 attempts or you die, which ever comes first
for (i = 1; i < 101 && myChar.isAlive; i++) {
myChar.hits(myChar.allHits)
myChar.lifes(myChar.lifes)
}
well in general you can break out of foor loops aswell as prevent further execution of a foor loop and continue the next iteration:
for (var i = 0; i < 10; i++) {
if (i == 4) continue;
if (i == 8) break;
console.log(i);
}
this will basically print: 0, 1, 2, 3, 5, 6, 7
(as you can see it kind of skipped 4)
(it will also work in while / do while loops)
so in your case you could check if the return value of one of your functions is true or false or do some other kind of conditional checking in order to break out of the loop.
or similar to how Rob Brander wrote in his answer:
var maxTurns = 100;
var turns = 0;
while (myChar.isAlive && ++turns <= maxTurns) {
myChar.hits();
myChar.lifes();
}
console.log("character is: " + myChar.isAlive ? "alive" : "dead");
console.log("after: " + turns + " turns.");

JQuery SVG not working

I am trying to create a circular page with tabs around it and the SVG path are not being appended to the html.
Any help would be grateful. I have not worked with JS in a long time since I have moved on to Java so my skills are rusty.
var tabs = 10;
var radius = 500;
var xcords = [];
for (var i = 1; i <= tabs; i++) {
xcords[xcords.length] = radius + Math.cos(36 * i + 18) * radius;
}
var ycords = [];
for (var i = 1; i <= tabs; i++) {
ycords[ycords.length] = radius + Math.sin(36 * i + 18) * radius;
}
$(document).ready(function(){
for (var i = 1; i < tabs; i++) {
$(".svg").prepend("<path class='piece' />");
$(".piece").attr({
"d" : "M" + xcords[i] + "," + ycords[i] + "L500,500 L" + xcords[i + 1] + "," + ycords[i + 1] " A500,500 0 0,0 " + xcords[i] + "," + ycords[i] + " Z"
});
}
$(".piece").mouseenter(function() {
$(this).fadeTo(100, 0.7);
});
$(".piece").mouseleave(function() {
$(this).fadeTo(100, 1);
});
$(".piece").click(function() {
$(".center").attr("fill",$(this).attr("fill"));
});
});
I know that the array id not large enough to get xcords[11] but a solution to it would be helpful.

Math.Random is not so random

I am making a basic game with popup boxes.
My problem is that if you look at the goblinAttack function it will repeat till the goblin is dead but the damage is random.
For example, I hit the goblin 6 damage every time until it dies instead of it being a random number between 1 and 25 and the goblin does 4 damage on me every time it hits. Its boring. I wanted it to be random each hit but repeating the function seems to not give a random number each time.
//VARIABLES
var dmgMultiply = Math.floor(Math.random() * 10 + 1);
var dmg = 10;
var armour = 0;
var hp = 100;
//ENEMY VARIABLES
var dmgGoblin = Math.floor(Math.random() * 10 + 1);
var goblinHP = 100;
//ARRAYS
var choiceArray = ["Type 'sword' equip your sword.",
"Type 'run' if you're scared.",
"Type 'stats' to see your stats."];
var answerArray = ["sword", "run", "stats"];
var outcomeArrayOne = ["You equip your sword.",
"You run away. Game Over."];
var outcomeArrayTwo = ["Sword Equipped."]
//GAME CHOICE
function choice(a, b, c, x, y, z, aa, bb)
{
var answer = prompt(a + "\n" + b + "\n" + c);
if(answer == x)
{
alert(aa);
swordEquipped(outcomeArrayTwo[0]);
}
if(answer == y)
{
alert(bb);
}
if(answer == z)
{
displayStats();
}
}
//EQUIPPED SWORD
function swordEquipped(a)
{
dmg = 25;
dmgMultiply = Math.floor(Math.random() * 25 + 1);
alert(a + "\n" + "DMG : " + dmg);
goblinCombatStart("goblin");
}
//GOBLIN COMBAT START
function goblinCombatStart(g)
{
alert("A wild " + g + " appears!" + "\n" + "The " + g + " has 100 HP!");
goblinAttack("goblin")
}
function goblinAttack(g)
{
alert("The " + g + " swings his axe at you!" + "\n" + "The " + g + " does " + dmgGoblin + " damage to you!");
hp -= dmgGoblin;
var attack = prompt("Type 'attack' to swing your sword at the " + g + "\n" + "HP : " + hp);
if(attack == "attack")
{
alert("You swing your sword at the " + g + "\n" + "You did " + dmgMultiply + " to the " + g);
goblinHP -= dmgMultiply;
alert("The " + g + " is on " + goblinHP + "HP");
if(goblinHP < 0)
{
goblinDead();
}
if(goblinHP > 0)
{
goblinAttack("goblin");
}
}
else
{
alert("You dropped your sword an shouted " + "'" + attack + "'" + " in the goblins face. It wasn't very effective and the goblin choppped your head off");
}
}
function goblinDead()
{
alert("You have slain the puny goblin with only a few scratches!");
}
//GAME START
choice(choiceArray[0], choiceArray[1], choiceArray[2],
answerArray[0], answerArray[1], answerArray[2],
outcomeArrayOne[0], outcomeArrayOne[1]);
//STATISTICS
function displayStats()
{
var statCheck = confirm("HP : " + hp + "\n" +
"ARMOUR : " + armour + "\n" +
"DMG : " + dmg + "\n" +
"Press OK to continue");
if(statCheck == true)
{
choice(choiceArray[0], choiceArray[1], choiceArray[2],
answerArray[0], answerArray[1], answerArray[2],
outcomeArrayOne[0], outcomeArrayOne[1]);
}
}
Instead of computing the random damage value only once at the beginning of your script, compute them whenever you need them. That would probably be in your attack function.
Maybe you are misunderstand something here: Math.random doesn't return some special magical value which changes every time it's read. It returns a number and that number doesn't change.
If you want multiple random values, you have to call Math.random multiple times. If you want a different random value whenever the goblin attacks, you have to call Math.random when it attacks.
The problem here is that you're initializing your variables at the beginning as random.
That means that, on every move, it will use the same random number that was generated at the beginning.
If you want it to be random for each time, you have to call Math.random() on every move.
As it stands, dmgMultiply and dmgGoblin are computed randomly once and use the same value on each turn, so you end up getting the same amount of damage taken and dealt each time.
Declare your variables at the beginning:
var dmgMultiply;
var dmgGoblin;
Then, set them to a random number within your attack function so that it computes a random number each turn:
function goblinAttack(g)
{
dmgMultiply = Math.floor(Math.random() * 10 + 1);
dmgGoblin = Math.floor(Math.random() * 10 + 1);
...
}
Demo

Categories