How to reset the variables of an object? - javascript

I am trying to reset the following objects inside a
draw = function() {...}
var Beaver = function(x, y) {
this.x = x;
this.y = y;
this.img = getImage("");
this.sticks = 0;
this.holes = 0;
this.npcs = 0;
};
var Stick = function(x, y) {
this.x = x;
this.y = y;
};
var Hole = function(x, y) {
this.x = x;
this.y = y;
};
var Npc = function(x, y) {
this.x = x;
this.y = y;
this.img = getImage("");
};
How to do that?

Related

Why are the two waves (or functions) interfering?

I was coding a function to plot graphs in JS. Here it goes:
var x = 0;
var y = 0;
var prevx = 0;
var prevy = 0;
var zoom = 25;
function plot(func) {
this.func = func;
this.x = x;
this.y = y;
this.prevx = prevx;
this.prevy = prevy;
function draw() {
c.beginPath();
c.moveTo(this.prevx * zoom, this.prevy * zoom);
c.lineTo(this.x * zoom, this.y * zoom);
c.strokeStyle = '#fff';
c.stroke();
this.prevx = this.x;
this.prevy = this.y;
this.x += 0.1;
this.y = func(this.x);
}
function animate() {
requestAnimationFrame(animate);
draw();
}
animate();
}
plot(Math.sin);
plot(Math.cos);
// plot(Math.tan);
Why are the two functions interfering even if i am using this keyword?
There are already many similar questions on this website itself still i can't get my answer, hence i have asked here.
Thanks in advance!
When you use "this" keyword within a function, it refers to the function itself. Here you want it to refer to the "plot" function while you are inside the "draw" function. You can do that by creating a new variable within the "plot" function and use that. i.e. "that".
var x = 0;
var y = 0;
var prevx = 0;
var prevy = 0;
var zoom = 25;
function plot(func) {
var that = this;
this.func = func;
this.x = x;
this.y = y;
this.prevx = prevx;
this.prevy = prevy;
function draw() {
c.beginPath();
c.moveTo(that.prevx * zoom, that.prevy * zoom);
c.lineTo(that.x * zoom, that.y * zoom);
c.strokeStyle = '#fff';
c.stroke();
that.prevx = that.x;
that.prevy = that.y;
that.x += 0.1;
that.y = func(that.x);
}
function animate() {
requestAnimationFrame(animate);
draw();
}
animate();
}
plot(Math.sin);
plot(Math.cos);
You can do the same by using the "bind" method when you call a function. This would change the "this" keyword in that function to refer to the object passed.
var x = 0;
var y = 0;
var prevx = 0;
var prevy = 0;
var zoom = 25;
function plot(func) {
this.func = func;
this.x = x;
this.y = y;
this.prevx = prevx;
this.prevy = prevy;
this.draw = () => {
c.beginPath();
c.moveTo(this.prevx * zoom, this.prevy * zoom);
c.lineTo(this.x * zoom, this.y * zoom);
c.strokeStyle = '#fff';
c.stroke();
this.prevx = this.x;
this.prevy = this.y;
this.x += 0.1;
this.y = func(this.x);
}.bind(this)
this.animate = () => {
requestAnimationFrame(this.animate);
this.draw();
}.bind(this)
this.animate();
}
plot(Math.sin);
plot(Math.cos);

How to make a prototype function use the values in a constructor

I am using the JavaScript canvas to make a pong-style game. I am attempting to use the values of the pong board's x and y grid values to create a prototype function for the ball to cause it to bounce off of the pong board whenever it touches. I have tried this a few different ways and I can't seem to get the ball to bounce off the pong board. I did not think that this aspect of the game's functionality would be the difficult part. I will provide snippets of the code below that I think are the problem:
var Pongboard = function() {
this.x = 15;
this.y = 15;
}
Ball.prototype.draw = function() {
makeBall(this.x, this.y, 5);
}
var pongboardValues = Object.values(Pongboard);
var pongX = pongboardValues[0];
var pongY = pongboardValues[1];
Ball.prototype.checkPongCollision = function() {
if (this.x < pongX && this.y < pongY) {
this.xSpeed = -this.xSpeed;
this.ySpeed = -this.ySpeed;
};
}
Any suggestions on how to get this working? Any hints would be greatly appreciated. If it helps, I will provide the full code below.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
//Create ball function
function makeBall (x, y, radius) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI*2, false);
ctx.fill();
}
//Create pong board function
function makePong (x, y) {
ctx.fillRect(x, y, 10, 60);
}
//Ball construcor function
var Ball = function() {
this.x = width;
this.y = height/2;
this.xSpeed = 6;
this.ySpeed = Math.random()*8 - 2;
}
//Pong board constructor function
var Pongboard = function() {
this.x = 15;
this.y = 15;
}
//These are the values for the Pongboard object's location
var pongboardValues = Object.values(Pongboard);
var pongX = pongboardValues[0];
var pongY = pongboardValues[1];
Ball.prototype.draw = function() {
makeBall(this.x, this.y, 5);
}
Ball.prototype.move = function() {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 0 || this.x > width) {
this.xSpeed = -this.xSpeed;
};
if (this.y < 0 || this.y > height) {
this.ySpeed = -this.ySpeed;
};
}
Ball.prototype.checkPongCollision = function() {
if (this.x < pongX && this.y < pongY) {
this.xSpeed = -this.xSpeed;
this.ySpeed = -this.ySpeed;
};
}
Pongboard.prototype.draw = function() {
makePong(this.x, this.y);
}
var keyNames = {
38: "up",
40: "down"
};
Pongboard.prototype.moveUpAndDown = function(direction) {
if (direction==="up") {
this.y = this.y += -1*10;
};
if (direction==="down") {
this.y = this.y += 10;
};
};
var ball = new Ball();
var pong = new Pongboard();
$("#start-button").click(function() {
setInterval(function() {
ctx.clearRect(0, 0, width, height);
pong.draw();
ball.draw();
ball.move();
ctx.strokeRect(0, 0, width, height);
}, 30);
})
$("body").keydown(function(event) {
var direction = keyNames[event.keyCode];
pong.moveUpAndDown(direction);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="start-button">Start</button><br>
<canvas width=300 height=200 id="canvas"></canvas>
Here I've got things working the way I think you want it.
You could extend this to make the ball bounce randomly on the Y axis too,..
I've commented out code that really wasn't doing anything too..
Also worth noting, you wasn't even calling checkPongCollision, so I've placed that in the timer.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
//Create ball function
function makeBall (x, y, radius) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI*2, false);
ctx.fill();
}
//Create pong board function
function makePong (x, y) {
ctx.fillRect(x, y, 10, 60);
}
//Ball construcor function
var Ball = function() {
this.x = width;
this.y = height/2;
this.xSpeed = 6;
this.ySpeed = Math.random()*8 - 2;
}
//Pong board constructor function
var Pongboard = function() {
this.x = 15;
this.y = 15;
}
//These are the values for the Pongboard object's location
//not needed..
//var pongboardValues = Object.values(Pongboard);
//var pongX = pongboardValues[0];
//var pongY = pongboardValues[1];
Ball.prototype.draw = function() {
makeBall(this.x, this.y, 5);
}
Ball.prototype.move = function() {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 0 || this.x > width) {
this.xSpeed = -this.xSpeed;
};
if (this.y < 0 || this.y > height) {
this.ySpeed = -this.ySpeed;
};
}
Ball.prototype.checkPongCollision = function() {
//if (this.x < pong.x && this.y < pong.y) {
if (
this.x >= pong.x && this.x < pong.x + 10 &&
this.y >= pong.y && this.y < pong.y + 60)
{
this.xSpeed = -this.xSpeed;
//this.ySpeed = -this.ySpeed;
};
}
Pongboard.prototype.draw = function() {
makePong(this.x, this.y);
}
var keyNames = {
38: "up",
40: "down"
};
Pongboard.prototype.moveUpAndDown = function(direction) {
if (direction==="up") {
this.y = this.y += -1*10;
};
if (direction==="down") {
this.y = this.y += 10;
};
};
var ball = new Ball();
var pong = new Pongboard();
$("#start-button").click(function() {
this.style.display = "none";
setInterval(function() {
ctx.clearRect(0, 0, width, height);
pong.draw();
ball.draw();
ball.move();
ctx.strokeRect(0, 0, width, height);
ball.checkPongCollision();
}, 30);
})
$("body").keydown(function(event) {
var direction = keyNames[event.keyCode];
pong.moveUpAndDown(direction);
});
body {
padding: 0;
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button style="float:left" id="start-button">Start</button>
<canvas width=300 height=180 id="canvas"></canvas>

How to extend a class inside a namespace in javascript?

var sl = sl || {}
sl.Shape = function(){
this.x = 0;
this.y = 0;
};
sl.Shape.prototype.move = function(x,y){
this.x += x;
this.y += y;
};
sl.Rectangle = function(){
sl.Shape.call(this);
this.z = 0;
};
The next line produces the error (Object prototype undefined, has to be Object or null). As far as I can see this is because Shape is "namespaced".
sl.Rectangle.protoype = Object.create(sl.Shape.protoype);
sl.Rectangle.protoype.constructor = sl.Rectangle;
How do I do this correctly?
You should use word prototype instead protoype.
You have misspelled the word "prototype" as Andrii pointed out, try this example:
(function() {
var sl = sl || {};
function Shape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};
function Rectangle() {
Shape.apply(this, arguments);
this.z = 0;
};
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
sl.Shape = Shape;
sl.Rectangle = Rectangle;
// expose
window.sl = sl;
}());
Usage
var shape = new sl.Shape();
var rect = new sl.Rectangle();

How to instantiate a class(ClassA) inside another class(ClassB) and use the ClassA object as a property in ClassB in JavaScript?

Consider the following code:
function Coord(x, y) {
this.x = x;
this.y = y;
}
function Ellipse() {
this.Text = Text;
this.Cx = Cx;
this.Cy = Cy;
this.Rx = Rx;
this.Ry = Ry;
}
Now in the function Ellipseinstead of using Cx, Cy etc. I want to instantiate the function Coord for each pair to achieve something as follows:
function Coord(x, y) {
this.x = x;
this.y = y;
}
function Ellipse() {
this.Text = Text;
Coord C = new C(); // where C has its own properties x and y
Coord R = new R(); // where R has its own properties x and y
}
Try this:
function Coord(x, y) {
this.x = x;
this.y = y;
}
function Ellipse(text, cx, cy, rx, ry) {
this.text = text;
var c = new Coord(cx, cy);
var r = new Coord(rx, ry);
}
I don't know how you thought of Coord C = new C() but it's absolutely wrong. JavaScript variables have no types.
Also from where are you getting Text, Cx, Cy, etc? Shouldn't they be passed as arguments to the constructor?

Why is object property changed for all instances?

I wanted to encapsulate the position of a sprite within another object. So that instead of using tile.x and tile.y I would access via tile.position.x and tile.position.y.
Yet once I set the value of tile.position within the init-method all the instances of the tile-object change to the same value. Why is that?
As when I set tile.x everything works as expected, meaning each object gets the right value.
This is how I create the multiple instances:
In a for loop I am creating multiple instances of said object:
for (var y = 0; y < 10; ++y) {
for (var x = 0; x < 10; ++x) {
var tile = Object.create(tileProperty);
tile.init(x, y);
...
}
}
And this is the cloned object:
var tileProperty = {
// this works
x: null,
y: null,
// this will get changed for ALL instances
position: {
x: null,
y: null
},
init: function(x, y) {
this.name = x.toString() + y.toString();
this.x = x;
this.y = y;
this.position.x = x;
this.position.y = y;
this.canvas = document.createElement('canvas');
var that = this;
$(this.canvas).bind('click', function() {
console.log(that.position, that.x, that.y);
});
document.body.appendChild(this.canvas);
}
}
Use this:
var tileProperty = {
position: { // we will inherit from this
x: null,
y: null,
init: function(x, y) {
this.x = x;
this.y = y;
}
},
init: function(x, y) {
this.name = x.toString() + y.toString();
// create an own Position object for each instance
this.position = Object.create(this.position);
// and initialize it
this.position.init(x, y); // you might inline this invocation of course
…
},
…
}
You're having a reference to the same position object in all your objects.
What you should do is using the standard prototype solution :
function tileProperty() {
this.position = {
x: null,
y: null
};
}
tileProperty.prototype.init = function(x, y) {
this.name = x.toString() + y.toString();
this.x = x;
this.y = y;
this.position.x = x;
this.position.y = y;
this.canvas = document.createElement('canvas');
var that = this;
$(this.canvas).bind('click', function() {
console.log(that.position, that.x, that.y);
});
document.body.appendChild(this.canvas);
}
and then build your instance using
var tp = new tileProperty();

Categories

Resources