I have a javascript "class", which looks like that:
function MapObject(x, y, size){
var x = x;
var y = y;
var size = size;
var color = "red";
this.draw = function(g2d){
g2d.setFillColor(color);
g2d.fillRect(x, y, size, size);
}
this.setColor = function(newColor){
color = newColor;
}
this.collision = function(mousex, mousey){
return mousex > x && mousex < x + size && mousey > y && mousey < y + size;
}
}
My problem is, i want to name the paremeter in the "setColor" function "color", too.
I know this from java:
void setColor(Color color){ this.color = color; }
Is there a way to achieve this in javascript?
I already tried:
this.setColor = function(color){
this.color = color;
}
That does not work.
I dont get any error, but the value isnt changing..
If you want to keep your setup with local variables (i.e. var color) then no, you can't name the parameter color, since it shadows the outer variable.
You need to tell the function which color variable you're amending. In your sample, setColor creates a new private variable of that function, and assigns the value of newColor to it. You should prepend the this keyword to the assignment operator within the setColor() function:
this.setColor = function(color){
this.color = color;
}
jsFiddle Demo
You'll need to update your draw() function too, if you wish to use the object property:
this.draw = function(g2d){
g2d.setFillColor(this.color);
g2d.fillRect(this.x, this.y, this.size, this.size);
}
Related
I am attempting to create a JavaScript Text Animation but i am getting particleArray is undefined
i am not sure how to resolve the issue i have tried moving the code from the mounted method since it would load before being defined but same results.
export default {
data : function (){
return {
particleArray: null,
x:null,
y:null,
radius: 150,
vuedata: null,
}
},
class Particle{
constructor(x, y){
this.x = x + 100;
this.y = y;
this.size = 3;
this.baseX = this.x;
this.baseY = this.y;
this.density = (Math.random() *30) + 1;
}
draw(){
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.ard(this.x, this.y, this.size,0,Math.PI * 2);
ctx.closePath();
ctx.fill();
}
}
function init(){
this.particleArray = [];
particleArray.push(new Particle(50,50));
}
The answer is this.particleArray.push(new Particle(50,50));
this.particleArray = []; assigns the data property particleArray the value [].
particleArray.push(new Particle(50,50)); attempts a method on a local variable that does not exist.
Not sure if i'm getting the scope wrong but iv'e tried moving the function around a bit but it just gives me that is not a function error.
let bubbles = [];
function setup() {
createCanvas(400, 400);
for (let i = 0; i < 10; i++){
bubbles[i] = new Bubble(200, 200, 40)
}
}
function draw() {
background(0);
for (i = 0; i < bubbles.length; i++){
bubbles[i].show();
}}
function show() {
stroke(20);
strokeWeight(2);
fill(random(255), 0, random(255))
ellipse(this.x, this.y, this.r * 2)
}
class Bubble {
constuctor(x, y, r){
this.x = x;
this.y = y;
this.r = r;
}}
As said in the comments by Rabbid76, your main problem is that you are calling a function within the Bubble object which doesn't exist. So you should pop that into the Bubble class:
class Bubble {
constructor(x, y, r){
this.x = x;
this.y = y;
this.r = r;
}
show() {
stroke(20);
strokeWeight(2);
fill(random(255), 0, random(255))
ellipse(this.x, this.y, this.r * 2)
}
}
Also, just so you know you misspelt constructor and if you're using the p5 online editor it doesn't flag it as an error, it thinks you've defined a new function called constuctor it is completely valid syntax.
One more thing, you are passing in the x and y location of each bubble as 200, 200, which basically means each bubble is going to be on top of each other, I'm assuming you'd want them to be spread out around the screen:
bubbles[i] = new Bubble(random(width), random(height), 20);
Oh and also, you may want to store the r,g,b colours in the Bubble object so it doesn't choose a new colour each frame!
So I have built a circular random colour picker utility in javascript and HTML5 Canvas and all the components are dynamic, the size of the objects adjusts to the size of the screen and the spacing also adjusts to the size of the screen. Furthermore, if the user resizes the display the utility also dynamically resizes.
I am using an array to store the colours for the circles. When the circles are generated they use the first colour in the array, delete that colour from the array, and then shuffle the array.
The problem is that when the user resizes the display the colour array does not have enough colours left to draw all the circles, this is because the code removes used colours so that there are no duplicates. However, i tried to fix this by declaring a constant array of the colours called origColours and setting the colours array equal to the origColours array.
Below is the code I have written. I cannot see how or why the origColours array is being manipulated, hopefully you can help
:)
//########//SETUP
var canvas = document.getElementById("myCanvas");
var c = canvas.getContext("2d");
canvas.height = innerHeight;
canvas.width = innerWidth;
document.documentElement.style.overflow = 'hidden'; // firefox, chrome
document.body.scroll = "no"; // ie only
//########//COLORS
const origColours = ["#1c2133", "#2b6ea8", "#5d99bf", "#333968", "#000000", "#b000b0", "#0000aa", "#ff0000", "#00aaaa", "#7CFC00", "#00FF7F", "#8B0000", "#F0E68C"];
var colours = ["#1c2133", "#2b6ea8", "#5d99bf", "#333968", "#000000", "#b000b0", "#0000aa", "#ff0000", "#00aaaa", "#7CFC00", "#00FF7F", "#8B0000", "#F0E68C"];
//########//VARIABLES
var backgroundColour = 0;
var mouse = {
x: undefined,
y: undefined,
};
var key = {
keyCode: undefined,
}
var mainRadius = 0;
var smallRadius = 0;
var pointerCircle;
var circles = [];
//########//EVENTS
window.addEventListener("mousemove", function(event) {
mouse.x = event.x;
mouse.y = event.y;
})
window.addEventListener("keypress", function(event) {
key.keyCode = event.keyCode;
if (key.keyCode == 32) {
switchBg();
}
})
window.addEventListener('resize', function(event) {
canvas.width = innerWidth
canvas.height = innerHeight
setup();
})
//########//OBJECTS
function Circle(x, y, radius, colour) {
this.x = x;
this.y = y;
this.radius = radius;
//this.n = Math.floor(Math.random()*colours.length);
if (colour == undefined) {
//this.fill = colours[this.n];
this.fill = colours[0];
this.orignalFill = this.fill;
colours.shift();
colours = shuffleArray(colours);
} else {
this.fill = colour;
this.orignalFill = this.fill;
}
this.draw = function() {
c.fillStyle = this.fill;
c.strokeStyle = this.colour;
c.beginPath();
c.arc(this.x,this.y,this.radius,0,Math.PI*2);
c.fill();
}
this.update = function() {
//Bounce off the edges
// if (this.x + this.radius > innerWidth || this.x - this.radius < 0) {
// this.dx = -this.dx;
// }
// if (this.y + this.radius > innerHeight || this.y - this.radius < 0) {
// this.dy = -this.dy;
// }
//Move circle
// this.x += this.dx;
// this.y += this.dy;
//Draw the circle after all calculations have been made
this.draw();
}
}
//########//UTILITY FUNCTIONS
function shuffleArray(arr) {
var j, x, i;
for (i = arr.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = arr[i];
arr[i] = arr[j];
arr[j] = x;
}
return arr;
}
function checkCollisions(obj1, objs) {
for (var i = 0; i < objs.length; i++) {
if (checkCollision(obj1, objs[i])) {
return objs[i]
}
}
}
function renderCircles(arr) {
for (var i = 0; i < arr.length; i++) {
arr[i].update();
}
}
function checkCollision(object1, object2) {
var obj_s = getDistance(object1.x, object1.y, object2.x, object2.y);
if (obj_s < object1.radius + object2.radius) {
return true;
} else {
return false;
}
}
function getDistance(x1, y1, x2, y2) {
xs = x2 - x1;
ys = y2 - y1;
return Math.sqrt(Math.pow(xs, 2) + Math.pow(ys, 2));
}
function switchBg() {
if (backgroundColour == 0) {
document.body.style.backgroundColor = "black"
backgroundColour = 1
} else if (backgroundColour == 1) {
document.body.style.backgroundColor = "white"
backgroundColour = 0
}
}
//########//ANIMATION
function animate() {
requestAnimationFrame(animate);
c.clearRect(0,0,innerWidth,innerHeight);
pointerCircle.x = mouse.x;
pointerCircle.y = mouse.y;
var result = checkCollisions(pointerCircle, circles);
if (result != undefined) {
circles[0].fill = result.fill;
} else {
circles[0].fill = circles[0].orignalFill;
}
pointerCircle.update();
renderCircles(circles);
}
//########//RUNNING CODE
function setup() {
if (innerHeight >= innerWidth) {
mainRadius = innerWidth/6;
} else {
mainRadius = innerHeight/6;
}
smallRadius = mainRadius/2;
c.clearRect(0,0,innerWidth,innerHeight);
circles = [];
colours = origColours
pointerCircle = new Circle(0,0,1, "rgba(0,0,0,0)");
circles.push(new Circle(innerWidth/2, innerHeight/2, mainRadius, "white"));
circles.push(new Circle((innerWidth/2)-mainRadius*2, innerHeight/2, smallRadius));
circles.push(new Circle((innerWidth/2)+mainRadius*2, innerHeight/2, smallRadius));
circles.push(new Circle((innerWidth/2), (innerHeight/2)-mainRadius*2, smallRadius));
circles.push(new Circle((innerWidth/2), (innerHeight/2)+mainRadius*2, smallRadius));
var angCoE = mainRadius / 2 * 3;
circles.push(new Circle((innerWidth/2)+angCoE, (innerHeight/2)-angCoE, smallRadius));
circles.push(new Circle((innerWidth/2)+angCoE, (innerHeight/2)+angCoE, smallRadius));
circles.push(new Circle((innerWidth/2)-angCoE, (innerHeight/2)-angCoE, smallRadius));
circles.push(new Circle((innerWidth/2)-angCoE, (innerHeight/2)+angCoE, smallRadius));
}
setup();
animate();
Note: So I was a little too hasty and didn't read your question thoroughly enough. The real solution was posted by Hey24sheep and pooyan below -- I'm leaving this here to explain a different facet of the question.
Declaring a variable as const means you cannot change its value. If the variable in question holds a reference to an object (such as an array), this means you cannot make the variable refer to a different object.
For example, if you tried this:
const colors = [ 'red', 'green', 'blue' ];
colors = [ 'yellow', 'cyan', 'magenta' ];
This would fail, because you're trying to change what colors refers to. However, the array itself is a separate entity from your variable, and its properties are still free to be manipulated.
What you're looking for in this case is Object.freeze():
const colors = Object.freeze([ 'red', 'green', 'blue' ]);
Now you will find that you cannot add, remove, or change any elements of the array. And, since you delcared it with const, you cannot reassign the variable colors either.
Further info:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
In JavaScript objects are passed and assigned by reference (more accurately the value of a reference), so colours is a reference to the same object.
Because you are doing this in your Setup function.
colours = origColours
You need to create a copy if you need to modify one and not the other.
Basically, the slice() operation clones the array and returns the reference to the new array
colours = origColours.slice();
you should clone your array instead of colours = origColours. one way to clone your array is colours = origColours.slice(0); otherwise when you change your colours array, your origColours would be effected too.
you can make a copy of the array and this will leave the original array untouched theres a few ways you can copy an array
colours = origColours.slice();
or if you're using es7 polyfills
colours = [...origColours]
const means you can't change the assignment but you can change the insides of the assignmeant
//you can do this
const a = [1, 2]; // [1]
a.pop()
console.log(a)
// but you cant do this
const i = 5;
i = 4; // erro
I've got this object variable:
var Background = {
x: 0,
y: 0,
speed: 4,
initialize: function (x, y){
this.x = x;
this.y = y;
move: function(){
this.x -= this.speed;
}
};
And I'd like to create new object variable and add it to an array:
background_container = []
background_container.push(new Background())
But it throws an error:
"Uncaught TypeError: Background is not a constructor"
Although it works with normal:
function name() {}
var test_var = new name()
So my guess is that "new" works only for functions. But how can I do it with variable objects like the one before? (I want to have multiple of them in one array and not just multiple references to one object)
With ES5 and below you can create a function which acts as a constructor. Use this inside to bind properties to the current object which is returned from the new operator. Also you can leave the initalize function (if you intend to use this only one time) and pass parameters into the function or constructor directly.
function Background(x, y) {
this.x = x || 0;
this.y = y || 0;
this.speed = 4;
this.move = function() {
this.x -= this.speed;
}
};
var backgrounds = [];
backgrounds.push(new Background(1, 3));
console.log(backgrounds[0].x);
console.log(backgrounds[0].y);
With ES6 and higher you can use Ecmascript's new syntax for creating classes.
class Background {
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
this.speed = 4;
}
move() {
this.x -= this.speed;
}
};
const backgrounds = [];
backgrounds.push(new Background(1,3));
console.log(backgrounds[0].x);
console.log(backgrounds[0].y);
Im trying to get a very simple inheritance pattern for my Project going, extending from a base class into a specialized class. However, my specialized class's attributes are being overwritten by the parent's attributes.
Why is that and how can i fix it ?
thanks,
function Ship(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 0;
}
function Corvette(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 100;
Ship.call(this, className, x, y)
}
Corvette.prototype = Object.create(Ship.prototype);
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(Corvette.className) // "Smallish" - correct via parameter.
console.log(Corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(Corvette.constructor.name) // Ship
Why you have the same properties in the child object which are already in the parent's?
I suggest you to do
function Ship(className, x, y, speed = 0) {
this.className = className;
this.x = x;
this.y = y;
this.speed = speed;
}
function Corvette(className, x, y, speed = 100) {
Ship.call(this, className, x, y, speed);
}
Corvette.prototype = Object.create(Ship.prototype);
Corvette.prototype.constructor = Corvette;
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className) // "Smallish" - correct via parameter.
console.log(corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(corvette.constructor.name) // Ship
and if your browser supports some features of ES6 use this feature ES6 classes.
class Ship { // And also Ship is an abstractionm so you can use `abstract` keyword with it
constructor(className, x, y, speed = 0) {
this.className = className;
this.x = x;
this.y = y;
this.speed = speed;
}
}
class Corvette extends Ship {
constructor(className, x, y, speed = 100) {
super(className, x, y, speed);
}
}
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className) // "Smallish" - correct via parameter.
console.log(corvette.speed) // should be 100, is 0 - not correct, "static" from parent attribute
console.log(corvette.constructor.name) // Ship
You only need to move Ship.call(this, className, x, y) at the start of Corvette function.
Also, next time, before posting code, check it is correct, you wrote console.log(Corvette) instead of console.log(corvette)
Another thing: you do not need to repeat params you do not want to overwrite
function Ship(className, x, y){
this.className = className;
this.x = x;
this.y = y;
this.speed = 0;
}
function Corvette(className, x, y){
Ship.call(this, className, x, y)
this.speed = 100;
}
Corvette.prototype = Object.create(Ship.prototype);
var ship = new Ship("Biggie", 50, 50);
var corvette = new Corvette("Smallish", 50, 50);
console.log(corvette.className)
console.log(corvette.speed)
console.log(corvette.constructor.name)
You should invoke the parentclass contructor first and then override the properties, this way the properties set by Corvette will not be changed by the parent class i.e.:
function Corvette(className, x, y){
Ship.call(this, className, x, y)
this.speed = 100;
}