setting timeout function within an object - javascript

I'm creating a game with one hero figure that his mission is to collect fruits all over the canvas.
the thing is that each fruit has it's own expiration time on the canvas.
For example, banana will appear 5 seconds, orange will appear 10 sec etc..
the thing im trying to do, is to create an object that each instance of this object has a timer that change a boolean value after selected time
my code looks like this :
function apple(timeToStay,score){
this.kind = "apple";
this.timeTostay = timeToStay;
this.score=score;
this.imgsrc = "images/apple.png";
this.x = 32 + (Math.random() * (canvas.width - 64));
this.y = 32 + (Math.random() * (canvas.height - 64));
this.removeMe = false;
setTimeout(function() { this.removeMe=true; }, timeToStay*1000);
return this;
}
as you can see i thought that setting a timeout with the instance will fire this after 5 seconds for example if i created it var obj = apple(5,5)
at the beginning obj.removeMe should be false but after 5 seconds it should turn into true.

This is happening because the function you're passing as parameter to the setTimeout method doesn't keep the same context, because of the Javascript's lexical scoping.
You can override that behavior by using Function.prototype.bind, e.g:
setTimeout(function() { this.removeMe=true; }.bind(this), timeToStay*1000);

This should work:
function apple(timeToStay,score){
this.kind = "apple";
this.timeTostay = timeToStay;
this.score=score;
this.imgsrc = "images/apple.png";
this.x = 32 + (Math.random() * (canvas.width - 64));
this.y = 32 + (Math.random() * (canvas.height - 64));
this.removeMe = false;
var base = this;
setTimeout(function() { base.removeMe=true; }, timeToStay*1000);
return this;
}

Related

can i reduce my code using loop for varaible or array

now the repeating code problem has been solved but when executed the if condition function of moveHorse is being executed repeteadly. please help.
function moveHorse(horseId)
);
interval=setInterval(function(){moveHorse('horseID');},20);
}
now the repeating code problem has been solved but when executed the if condition function of moveHorse is being executed repeteadly. please help.
Pass in the element ID as the function parameter, then you can refactor the code to -
// TODO: rename your local variable name because now it doesn't need to be horse4, right?
function horseUp(horseElementId) {
var horse = document.getElementById(horseElementId);
// do the rest
}
function horseDown(horseElementId) {
var horse = document.getElementById(horseElementId);
// do the rest
}
function horseleft(horseElementId) {
var horse = document.getElementById(horseElementId);
// do the rest
}
To use the function, pass in the element Id
horseUp('horse4');
horseLeft('horse2');
and so on
Since the only part that appears to be different is the horse being changed, just pass that in. For example:
var horse4 = document.getElementById('horse4');
function horseUp(horse, moving) {
var horseTop = horse.offsetTop;
var random = Math.random() * 2.7 + 2;
horse.style.top = horseTop - 0.5 * random + 'px';
if (horseTop <= window.innerHeight * 0.05) {
clearInterval(interval4);
interval4 = setInterval(moving, 10);
}
}
There's a few other variables like interval4 that you'll need to figure out, but this should give you the general idea.
May use OOP:
function Horse(id) {
this.el = document.getElementById(id);
}
Horse.prototype={
move(x,y){
this.el.offsetTop+=(this.y=typeof y !=="undefined"?y:this.y);
this.el.offsetLeft+=(this.x=typeof x !== "undefined"?x:this.x);
},
up(){
this.move(0,0.5*Math.random() * 2.7 + 2* + 'px';
},
down(){ this.move(0,- 0.5* Math.random() * 2.4 + 2);},
left(){ this.move(0.5* Math.random() * 2.4 + 2,0);},
right(){ this.move(- 0.5* Math.random() * 2.4 + 2,0);},
setInterval(){
this.interval=setInterval(_=>this.move(),10);
}
}
use like this:
var horse4=new Horse("horse4");
horse4.setInterval();
horse4.left();

Pomodoro clock canvas ring not registering

Good evening everyone. I'm having some trouble with this bit of code and have been at it for a few hours. If you take a look in the constructor at this.drawArc and then in the prototype, I've logged to the console a couple things. You can see this.count logs a value, but this.drawArc does not. Obviously, this.minutes and this.toSeconds work, or the timer wouldn't start, but why does the drawArc not register the values?? I had this(the status ring) working before placing it in a constructor, but for some reason, it no longer registers any values. I have attached a fiddle.
NOTES: this is not complete - currently you have to re-run if you want to enter a new value into the input field. Once a value has been entered into the input(the small circle above the button) you can hover over the canvas(the larger circle) to view the countdown. The reason it is on hover is for those that don't want to see the ticking clock and prefer just the visual of the status ring. Any ideas??? I've been stuck for a few hours. Thank you in advance
https://jsfiddle.net/asthewaterfalls/szn0mch1/9/
function Pomodoro(userInput) {
this.minutes = userInput;
this.toSeconds = 60 * this.minutes;//seconds - actual
this.cout = this.toSeconds; //for timer
this.seconds = 0; //display
this.count = 0; //for status ring
this.circleStart = Math.PI * 1.5;
this.drawArc = (2 / this.toSeconds) * this.count;
}
Pomodoro.prototype.statusRing = function () {
if(this.count <= this.toSeconds) {
dom.canv.beginPath();
dom.canv.arc(125, 125, 121, this.circleStart, Math.PI * (1.5 + this.drawArc), false);
dom.canv.stroke();
this.count++;
console.log(this.count, this.drawArc);
const timeout = setTimeout(() => this.statusRing(), 1000 );
}
};
I took a look at your fiddle. With two small changes I got some animation into the blue ring around the clock. I did not check the ratios or angeles.
I made drawArg a function, calculating with the current value as argument and this.toSeconds as max value:
this.drawArc = function(arg){ return (2 / this.toSeconds) * arg; };
Second, I calld the function in dom.conv.arc():
dom.canv.arc(/*...*/, Math.PI * (1.5 + this.drawArc(this.count)), /*...*/);
Here is the complete example:
function Pomodoro(userInput) {
this.minutes = userInput;
this.toSeconds = 60 * this.minutes;//seconds - actual
this.cout = this.toSeconds; //for timer
this.seconds = 0; //display
this.count = 0; //for status ring
this.circleStart = Math.PI * 1.5;
this.drawArc = function(arg){ return (2 / this.toSeconds) * arg; };
}
Pomodoro.prototype.statusRing = function () {
if(this.count <= this.toSeconds) {
dom.canv.beginPath();
dom.canv.arc(125, 125, 121, this.circleStart, Math.PI * (1.5 + this.drawArc(this.count)), false);
dom.canv.stroke();
this.count++;
console.log(this.count, this.drawArc);
const timeout = setTimeout(() => this.statusRing(), 1000 );
}
};
Please let me know, if this helps ;)

Howto run function every few seconds that has return values?

How can I run this every few second , without blocking the rest of the pagefrom loading.
function Create() {
var SomeArray = [];
for ( var i=0; i<=1 ; i ++) {
SomeArray[i] = (Math.random() * 10) + 1;
//alert(arr[0]);
}
return SomeArray;
}
var x = Create();
alert(x[0] + x[1]);
I was trying this var timer = setInterval(Create, 5000); it prevent loading rest of the page.
i want to get new values every few seconds
A basic example would be:
var counter = 0;
var timerRef;
var increment = function() {
counter += 1;
console.log(counter);
timerRef = setTimeout(increment, 1000);
}
setTimeout(increment, 1000);
// clearTimeout(timerRef);
Please avoid document.write refer the screencast for further details.
setInterval() can be configured to repeatedly call any function you designate at whatever time interval you request. But, you can't retrieve a return value from that function. Instead, you need to process the results from within the callback that you pass to setInterval() or call some other function and pass the results you generate inside the callback. This is how asynchronous functions work in JavaScript. I've provided several examples below of your options:
If you just want to generate two random decimal values between 1 and 10 (inclusive) every 5 seconds, you can do that like this:
var interval = setInterval(function() {
var rand1 = (Math.random() * 10) + 1;
var rand2 = (Math.random() * 10) + 1;
// now insert code here to do something with the two random numbers
}, 5000);
If you wanted the random values to be integers (which is more common), then you would do this:
var interval = setInterval(function() {
var rand1 = Math.floor(Math.random() * 10) + 1;
var rand2 = Math.floor(Math.random() * 10) + 1;
// now insert code here to do something with the two random numbers
}, 5000);
If you want to call a function and pass it those two random numbers, you can do this:
function processRandoms(r1, r2) {
// code here to do something with the two random numbers
}
var interval = setInterval(function() {
var rand1 = Math.floor(Math.random() * 10) + 1;
var rand2 = Math.floor(Math.random() * 10) + 1;
processRandoms(rand1, rand2);
}, 5000);
You can then stop the recurring interval at any time with this:
clearInterval(interval);

Html5 canvas how to generate multiple images

Im making a simple zombie game in html5 canvas and wanted to know how to create a zombie every x seconds in a random place? so far i have
var zombies = new Array();
function SummonZombies (){
TotalZombies++;
zombies[TotalZombies] = new Image();
zombies[TotalZombies].src = 'images/monster.png';
ctx.drawImage(zombies[TotalZombies], zombie_x, zombie_y);
}
Only one zombie is being created with this? how would i get it to generate more.
First of all, where are you declaring the variable TotalZombies?
Try something like this :
var zombies = new Array();
for (var i = 0; i < 100; i++) {
var zombie = new Image();
zombie.src = 'images/monster.png';
ctx.drawImage(zombie, Math.floor((Math.random()*100)+1), Math.floor((Math.random()*100)+1));
zombies.push(zombie);
}
This will create 100 zombies, with random x and y positions between 1 and 100. It will add each zombie to the zombies array after they have been instantiated.
You should iterate through zombies array, and invoke drawImage() on everyone.
Extra tip: remember to change x and y after all iteration.
You must separate a Zombi from your zombies :
create a class that will describe what a Zombi is, and only after you will define a collection of such lovely guys and girls :
// This Class defines what a Zombi is.
function Zombi(x,y) {
this.x = x;
this.y = y;
}
var ZombiImage = new Image();
ZombiImage.src = "images/monster.png";
// image of a zombi is shared amongst all zombies, so it is
// defined on the prototype
Zombi.prototype.image = ZombiImage;
// draw the zombi on provided context
Zombi.prototype.draw = function(ctx) {
ctx.drawImage(this.image, this.x, this.y);
}
Now for the collection :
// This class defines a collection of Zombies.
function Zombies() {
this.zombies = [];
}
// summons a zombi at a random place. returns the summoned zombi.
myZombies.prototype.summon() {
var randX = Math.random()*100;
var randY = Math.random()*100;
return this.summonAt(randX, randY);
}
// summons a zombi at x,y. returns the summoned zombi.
myZombies.prototype.summonAt = function (x,y) {
var newZombi = new Zombi(x,y);
this.zombies.push();
return newZombi;
}
// draws all zombies on provided context.
myZombies.prototype.drawAll = function (ctx) {
var i=0;
var __zombies = this.zombies;
for (;i<__zombies.length; i++) {
__zombies[i].draw(ctx);
}
}
// collection of all zombies for your game.
var zombies = new Zombies();
// here you can call zombies.summon(); or zombies.drawAll();
// and even zombies.summonAt(x,y);
In fact the code above is simplified : you must handle the onload event of the image to start the game only after the image was loaded.
But you should get the idea : separate the issues (handle ONE zombi vs a collection of zombies) will get you faster to your goal.
With this -simple- design, you'll be able to easily add-up behaviour to your zombies.
Just one more example in which i will add the seekBrain and walk behaviour :
// This Class defines what a Zombi is.
function Zombi(x,y) {
this.x = x;
this.y = y;
this.dirX = 0 ; // direction X
this.dirY = 0; // direction Y
this.speed = 0.1; // common speed for all zombies
}
// have the zombi seek the brain located at (x,y)
Zombi.prototype.seekBrain = function (x,y) {
this.dirX = (x - this.x );
this.dirY = (y - this.y );
// normalize direction
var norm = Math.sqrt( this.dirX*this.dirX + this.dirY*this.dirY );
this.dirX/=norm;
this.dirY/=norm;
}
// Have the zombi walk in its current direction
Zombi.prototype.walk = function() {
this.x += this.dirX * this.speed;
this.y += this.dirY * this.speed;
}
// image and draw remains the same
And now you might want for your collection :
// makes all zombies walk.
Zombies.walkAll = function() {
var i=0;
var __zombies = this.zombies;
for (;i<__zombies.length; i++) {
__zombies[i].walk();
}
}
// constructor, summon, summonAt, and drawAll remains the same.
So to summon a zombi at random place every xxx ms, do something like :
// summons a zombi at a random place every 2 seconds (==2000 ms)
setTimeInterval(2000, function() { zombies.summon(); } );
now, if hero.x and hero.y are what we guess, you can do :
// Have a random zombi hunt for hero's brain every 2 seconds
setTimeInterval(2000, function() {
var which = Math.floor(zombies.zombies.length * Math.random());
zombies.zombies[which].seekBrain(hero.x, hero.y);
} );
provided you call to zombies.walkAll(); and zombies.drawAll(); on a regular basis, you've got the start of a game ! (i love so much zombies :-) )

How to translate this bit of Python to idiomatic Javascript

My code so far:
// The q constant of the Glicko system.
var q = Math.log(10) / 400;
function Player(rating, rd) {
this.rating = rating || 1500;
this.rd = rd || 200;
}
Player.prototype.preRatingRD = function(this, t, c) {
// Set default values of t and c
this.t = t || 1;
this.c = c || 63.2;
// Calculate the new rating deviation
this.rd = Math.sqrt(Math.pow(this.rd, 2) + (Math.pow(c, 2) * t));
// Ensure RD doesn't rise above that of an unrated player
this.rd = Math.min(this.rd, 350);
// Ensure RD doesn't drop too low so that rating can still change
// appreciably
this.rd = Math.max(this.rd, 30);
};
Player.prototype.g = function(this, rd) {
return 1 / Math.sqrt(1 + 3 * Math.pow(q, 2) * Math.pow(rd, 2) / Math.pow(Math.PI, 2));
};
Player.prototype.e = function(this, p2rating, p2rd) {
return 1 / (1 + Math.pow(10, (-1 * this.g(p2rd) * (this.rating - p2rating) / 400)));
};
I'm working on a JS/HTML implementation of the Glicko rating system and am heavily borrowing from pyglicko -- which is to say, completely ripping it off.
It's rather short (probably less than 100 LoC without comments) but I'm having my misgivings about whether my translation will work because honestly, I have no idea how Javascript scoping and this actually work. You can see what I have at the link at the top.
But in specific I'm wondering how you would express this bit of Python code in Javascript. Basically _d2 is inside a class definition for Player.
def _d2(self, rating_list, RD_list):
tempSum = 0
for i in range(len(rating_list)):
tempE = self._E(rating_list[i], RD_list[i])
tempSum += math.pow(self._g(RD_list[1]), 2) * tempE * (1 - tempE)
return 1 / (math.pow(self._q, 2) * tempSum)
I've got the functions e and g defined like so, and q is a constant:
Player.prototype.e = function(this, ratingList, rdList) {
// Stuff goes here
}
In Javascript you don't need o pass the self explicitly (Python is the "weird" one here, actually)
Player.prototype.e = function(rating_list, RD_list){
//replace "self" with "this" here:
var tempSum = 0; //if you don't use the "var", tempSum will be a global
// instead of a local
for(var i=0; i<rating_list.length; i++){ //plain old for loop - no foreach in JS
var tempE = this._E( ... ); //note that in JS, just like in Python,
//variables like this have function scope and
//can be accessed outside the loop as well
tempSum += Math.pow( ... ) //the Math namespace is always available
//Javascript doesn't have a native module system
}
return (...);
}
This should work all right.
The only tricky thing you need to know about this is that it is very promiscuous. This means that is is determined by how you call the function:
obj.e(); //if you do a method-like call, the this will be set to obj
However, there is no magic binding behind the scenes. The following works in python but does not work in Javascript:
f = obj.e
f(); //looks like a normal function call. This doesn't point to obj

Categories

Resources