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
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);
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>
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();
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?
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();