Javascript & jQuery: how to make function infinite through animate callback? - javascript

have an object of a class Abon and then i want this object to move around the page.
a = new Abon();
a.init();
a.move();
the method move() contains:
function abon_move () {
var x = this.x;
var y = this.y;
var direction_x = Math.random()*5 - 5;
var direction_y = Math.random()*5 - 5;
var x_new = x + direction_x * this.movement_rate;
var y_new = y + direction_y * this.movement_rate;
console.log(x_new+" "+y_new)
$(".abonent."+this.id).animate( {
left:+x_new,
top:+y_new
}, 'slow', "linear", function() { this.move() });
}
All i want is that the method move (represented as function abon_move()) repeated again and again, after the animate stops. But the problem is that this.move() shown in callback has no connection to my object, because this in that place points to the HTML element, selected by jQuery.
UPD:
function Abon(id) {
...
this.move = abon_move;
...
}
Abon.prototype.move = abon_move;
And the actual method is the same, but with no callback in animate
then i try doing the following:
setInterval( a[0].move , 300); //doesn't work - says `this` members are undefined
setInterval( a[0].move() , 300); //works only one time and stops
Thank you for any help!

Try this :
function abon_move () {
var x = this.x;
var y = this.y;
var class = this;
...
}
Then, inside your jQuery animate, your can refer to your class using the variable class

Wrap the function abon_move() in a setTimeout call, as such: setTimeout(abon_move, 300); so it will run every 300 ms.

Related

Change properties of a class from time to time

I have two functions. In the first one I increase a variable by adding 100 to it and I put a setInterval so the funcion repeats itself after some time. The other function is a class, a contrusctor to create an object. I want this.x_origen to get increased by adding aumento to it after some time and repeat it. However what I'm getting here is that the first function increases aument and then it finishes and then the second function starts. How can I solve this?
var aument = 0;
function aumento(){
aument = aument + 100;
return aument;
}
setInterval(function () {aumento()}, 1000/50);
function create_class_brick (x_origen_in, y_origen_in, x_final_in, y_final_in, mi_estado, mi_velocidad, mi_id){
this.x_origen = x_origen_in + aumento();
this.y_origen = y_origen_in;
this.x_final = x_final_in + aumento();
this.y_final = y_final_in;
this.estado = mi_estado;
this.velocidad = mi_velocidad;
this.id_elemento = mi_id;
this.DESPLAZAR_LADRILLO = desplazar_ladrillo;
this.F0 = f0;
this.F2 = f2;
this.crear_ladrillo = crear_ladrillo;
this.obtener_x_origen_ladrillo = obtener_x_origen_ladrillo;
this.obtener_y_origen_ladrillo = obtener_y_origen_ladrillo;
this.obtener_x_final_ladrillo = obtener_x_final_ladrillo;
this.obtener_y_final_ladrillo = obtener_y_final_ladrillo;
}
An example on how to wait for the initial call:
function brick (x_origen_in){
this.x_origen = x_origen_in;
}
function aumento(brick){
console.log(brick.x_origen);
brick.x_origen += 100;
setTimeout(aumento.bind(this, brick), 500);
}
var brick = new brick(100);
aumento(brick);
http://jsfiddle.net/x6c08u39/
You can use Object.defineProperty to dynamically generate the value whenever it is accessed.
First, lets simplify the auto-incrementing of aument:
var aument = 0;
function aumento(){
aument += 100;
}
// The first argument for setInterval is the function to execute
// No need to figure out the interval value at runtime as there are no dynamic values
setInterval(aumento, 20); // 1000/50 === 20
Now lets make an object that will have a the correct value:
function create_class_brick (x_origen_in, y_origen_in, x_final_in, y_final_in, mi_estado, mi_velocidad, mi_id){
Object.defineProperty(this, 'x_origen', {
get: function () { return x_origen_in + aument; }
});
// Other stuff
// ...
}
A quick test:
> aument
34100
> var obj = new create_class_brick(23);
undefined
> obj.x_origen
161523
> obj.x_origen
167223
> obj.x_origen
172423

Troubleshooting an infinite loop error

I am trying to draw an array of images on canvas at random x,y but it gives me an infinite loop.... here is my code
var fruits = ["fruit1.png", "fruit2.png", "fruit3.png", "fruit4.png"];
var monsterReady1 = true;
var draw = function() {
for (var i = 0; i < fruits.length; i++) {
monsterImage1 = new Image();
monsterImage1.onload = function () {
monster1.x = (Math.random() * (canvas.width - 100));
monster1.y = (Math.random() * (canvas.height - 100));
ctx.drawImage(this, monster1.x, monster1.y);
};
monsterImage1.src = fruits[i];
}
};
var render = function() {
if (monsterReady1) {
draw();
}
var main = function () {
update();
render();
requestAnimationFrame(main);
};
You have recursive in main() function. This is normal behaviour of requestAnimationFrame(). It is normal to call that function infinite to draw canvas each frame.
There is also recursion when render() executes. You don't need to call render again and again. Pass out render call from render() body
var render = function(){
if (monsterReady1) {
draw();
}
var main = function () {
update();
render(); // THIS is error. You should not call render again
requestAnimationFrame(main); // This will call main function infinite loop. Expected.
}
};
//render(); // Better to call it here
By the way in code you provide there is a syntax error. You missed one closing bracket

Animating canvas with a javascript constructor

Hello stackoverflow community!
First I must say that I dont have much experience with constructors.
So. What I am trying to do, is to animate a parachutist to fly from top to bottom of the screen.
I thought I could use a constructor to set up a parachutist:
var parachute = function() {
this.height = 35;
this.width = 30;
this.speed = 50;
this.xPos = Math.round(Math.random() * (window.width - this.width));
this.animate = function() {
this.img = new Image();
this.yPos = 0;
this.img.onload = function() {
ctxPara.globalCompositeOperation = 'copy';
ctxPara.translate(0, this.yPos);
ctxPara.drawImage(this.img, this.xPos, 0);
};
this.img.src = 'para.png';
this.yPos++;
};
};
This constructor is used in a function called 'fly':
var fly = function() {
var newParachute = new parachute();
setInterval(newParachute.animate, newParachute.speed);
};
And this 'fly' function is triggered when the window loads:
window.onload = function() {
var canvasBg = document.getElementById('canvasBg');
// I splitt the Background and the parachutists in two canvas elements
// handling the problem (to erase content and draw new content) with
// the canvas animation.
var canvasPara = document.getElementById('canvasPara');
ctxPara = canvasPara.getContext('2d');
canvasPara.width = window.width;
canvasPara.height = window.height;
canvasBg.width = window.width;
canvasBg.height = window.height;
fly();
clouds(); // background is loading here
};
What you should see, is a Parachutist flying down the screen. But unfortunately you don't...
Now, after that Long text. (Iam very sorry that it is so long :-( ) My question is: Do you know what I am doing wrong? Is my constuctor correct? Is, what i am trying to do, supposed to be written like this? Any advices or suggestions for a succesfull opportunity? (I hope my english isn't that terrible I think it is :-) )
Oh i forgot to mention the error. It's a TypeMissMatchError.
That means 'this.img' is not an img element at this line:
ctxPara.drawImage(this.img, this.xPos, 0);
Now, I followed the example of markE.
Instead of showing me a parachutist. It shows me an error in this line: ctxPara.drawImage(this.img, this.xPos, this.yPos);
var fly = function () {
var newParachute = new parachute();
newParachute.img.load.call(newParachute);
setInterval(newParachute.animate.call(newParachute), newParachute.speed);
};
var parachute = function () {
this.height = 35;
this.width = 30;
this.speed = 25;
this.xPos = Math.round(Math.random() * (window.innerWidth - this.width));
this.img = new Image();
this.yPos = 0;
this.img.isLoaded = false;
this.img.load = function () {
this.img.isLoaded = true;
};
this.img.src = 'parachute.png';
this.animate = function () {
if (this.img.isLoaded) {
ctxPara.clearRect(0, 0, canvasPara.width, canvasPara.height);
ctxPara.drawImage(this.img, this.xPos, this.yPos); // ERROR: 'Unknown Error'.
this.yPos++;
console.log('animating');
}
};
};
I am stuck again. But now i don't even know the reason... Please help!?
Demo: http://jsfiddle.net/m1erickson/ym55y/
A couple of issues:
(1) To get the window width you can use:
window.innerWidth
(2) setInterval calls newParachute.animate.
setInterval(newParachute.animate, newParachute.speed);
But this inside animate the window object--not the Parachute object.
To give the correct this to animate you can use the call method like this:
var newParachute = new parachute();
setInterval(function(){newParachute.animate.call(newParachute);}, newParachute.speed);
(3) You need to deal with clearing previously drawn images or they will still show on your canvas.

javascript - can't change an image's position

I'm trying to change a position of a image that I have in HTML by using javascript. I can actually get it working if I have the following code:
function main()
{
var catOne = document.getElementById("cat1");
catOne.style.left = cat1.getX().toString() + "px";
catOne.style.top = cat1.getY().toString() + "px";
}
but when I change the code to this:
var catOne = new Cat("cat1", 300, 100);
function main()
{
catOne.setUp();
}
it doesn't work. and I dont know why, but it only gives me an error of "TypeError: Cannot read property 'style' of null"
This is my Cat class in javascript:
function Cat(id, x, y)
{
this.cat = document.getElementById(id);
this.x = x;
this.y = y;
}
Cat.prototype.setUp = function ()
{
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Cat.prototype.getX = function ()
{
return this.x;
};
Cat.prototype.getY = function ()
{
return this.y;
};
TypeError: Cannot read property 'style' of null means your catOne does not exist in the DOM tree.
You should instantiate the Cat class when the DOM is ready (or on window load).
I don't know why you need that main() function but when does it execute? It should also execute when the DOM is ready.
var catOne;
function main() {
catOne.setUp();
}
window.onload = function() {
catOne = new Cat("cat1", 300, 100);
main();
}
I also suggest that you set the position of your cat to absolute if you are positioning it like that in your setUp() function. (I think you are already doing this with your CSS):
Cat.prototype.setUp = function ()
{
this.cat.style.position = 'absolute';
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Here is the fiddle.
Other than that your code should work.
with:
var catOne = new Cat("cat1", 300, 100);
catOne.setUp();
works just fine.
I don't quite get it how You managed to get error You mentioned
link: http://jsfiddle.net/Z74mM/

javascript game: why return init: init?

I'm following a tutorial on how to make a javascript game, but i'm stuck on the return part. Why are is there { }, and what is the init: init for? Any help would be appreciated. Thanks.
var JS_SNAKE = {};
JS_SNAKE.game = (function () {
var ctx;
var xPosition = 0;
var yPosition = 0;
var frameLength = 500; //new frame every 0.5 seconds
function init() {
$('body').append('<canvas id="jsSnake">');
var $canvas = $('#jsSnake');
$canvas.attr('width', 100);
$canvas.attr('height', 100);
var canvas = $canvas[0];
ctx = canvas.getContext('2d');
gameLoop();
}
function gameLoop() {
xPosition += 2;
yPosition += 4;
ctx.clearRect(0, 0, 100, 100); //clear the canvas
ctx.fillStyle = '#fe57a1';
ctx.fillRect(xPosition, yPosition, 30, 50); //a moving rect
setTimeout(gameLoop, frameLength); //do it all again
}
return {
init: init
};
})();
$(document).ready(function () {
JS_SNAKE.game.init();
});
The {} is an object literal in JavaScript. The statement
return {
init: init
}
returns an object with one property. That property's key is init and value is whatever value the variable named init has (in this case, a function).
In case that syntax is confusing, this is equivalent and might be clearer:
JS_SNAKE.game = (function () {
// snip...
function performInitialization() {
// snip...
}
// snip ...
return {
init: performInitialization
};
})();
That is something that is called a module pattern - where you enclose your "class" (or represent it, if you will) with an anonymous function.
The function returns the JS object that can be used to access "class" methods and variables, but only those that are exposed (public) - such as init.
{} is object literal - it is used here to declare an empty JS_SNAKE object - which will serve as a namespace for the following "class" declaration.

Categories

Resources