Why's this object not working? - javascript

box = new Object();
box.height = 30;
box.length = 20;
box.both = function(box.height, box.length) {
return box.height * box.length;
}
document.write(box.both(10, 20));
Well as the title says.
First off I'd created an object.
Made to properties, height and length.
Assigned a value to each.
Made a method BOTH
In function I'd put 2 arguments which are object properties.
Returned their product.
And finally called the function giving it numerical value..
Why's this not working :(

The problem is:
box.both=function(box.height,box.length){
box.height and box.length are not valid names for function parameters. This should be:
box.both=function(h, l) {
return h * l;
}
However, it seems you might be looking to get the area of the current box instance. In that case, you don't need any parameters:
box.both=function() {
return this.height * this.length;
}
document.write(box.both());

I think you probably want it this way:
box = new Object();
box.height = 30;
box.length = 20;
box.both = function(height,length){
this.height = height;
this.length = length;
return height*length;
}
document.write(box.both(10,20));

box = new Object();
box.height = 30;
box.length = 20;
box.both = function() {
return box.height * box.length;
}

Related

Why does this Function (Which Pushes Objects to an Array) Crash p5.js?

I am building an evolution simulation app where if a certain organism has health above 75%, it reproduces, then the health is subtracted by half. To do this, I create a new instance of the class the object belongs to then push said object to the array where the other organisms are stored. This crashes p5.js for a reason I am not aware of.
I have tried to lessen the number of organisms (3) and write it as a function of the class.
var organisms = []; // array where organisms instances go
function reproduce(){
for (let i = 0; i < organisms.length; i++){
if(organisms[i].life > 0.75){
// create a genetically similar size
let size = organisms[i].size + (random() > 0.5 ? 1 : -1 * random() * 2);
// declare instance
let org = new Organism(width, height, size)
organisms.push(org);
// prevent infinite reproduction
organisms[i].life -= 0.5;
}
}
}
I expect this to just create new class instances, but it crashes p5.js.
Iterate through the array and create the new organisms and then after the loop add the array of newly created organisms to your original array.
Here is a runnable snippet that creates a minimal example. The random method call from the question has been replaced with a call to Math.random() and width and height have been declared to eliminate the need for p5.js.
var organisms = []; // array where organisms instances go
var width = 100;
var height = 100;
function Organism(w, h, s){
this.width = w;
this.height = h;
this.size = s;
this.life = .76;
}
organisms.push(new Organism(1,1,1));
console.log("Organisms length before reproduce: " + organisms.length);
reproduce();
console.log("Oganisms length after reproduce: "+organisms.length);
function reproduce(){
var organismsToAdd = [];
for (let i = 0; i < organisms.length; i++){
if(organisms[i].life > 0.75){
// create a genetically similar size
let size = organisms[i].size + (Math.random() > 0.5 ? 1 : -1 * Math.random() * 2);
// declare instance
let org = new Organism(width, height, size)
organismsToAdd.push(org);
// prevent infinite reproduction
organisms[i].life -= 0.5;
}
}
//organisms = organisms.concat(organismsToAdd);
// or
organisms.push.apply(organisms, organismsToAdd)
}
Here is a runnable snippet with p5.js
var organisms = []; // array where organisms instances go
function setup(){
createCanvas(100,100);
organisms.push(new Organism(1,1,1));
noLoop();
}
function draw(){
console.log("Organisms length before reproduce: " + organisms.length);
reproduce();
console.log("Organisms length after reproduce: " + organisms.length);
}
function reproduce(){
var organismsToAdd = [];
for (let i = 0; i < organisms.length; i++){
if(organisms[i].life > 0.75){
// create a genetically similar size
let size = organisms[i].size + (random() > 0.5 ? 1 : -1 * random() * 2);
// declare instance
let org = new Organism(width, height, size)
organismsToAdd.push(org);
// prevent infinite reproduction
organisms[i].life -= 0.5;
}
}
// organisms = organisms.concat(organismsToAdd);
organisms.push.apply(organisms, organismsToAdd)
}
function Organism(w, h, s){
this.width = w;
this.height = h;
this.size = s;
this.life = .76;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>
You've created a loop condition which may never end.
for (let i = 0; i < organisms.length; i++){
On the first iteration, let's say organisms has 5 elements. If the if condition on the next line is met, you will add another element to your organisms array. The next iteration will alter the next element in organisms, but since your array grows by one each time, you will never reach the end of the array!

Get div's width for p5.js

I'm learning on my own JavaScript so I'm doing something like a website using p5.js
The thing is that a div holding my canvas for p5.js and I want it to be responsive. In this canvas, I do have an object that needs the div width and height to be constructed.
Problem is that I don't know how to get this information. I tried jQuery but I don't know how to extract value out of a jQuery function and I'm don't know if it's an excessive way to do it.
//--------------------------constant--------------------------------------------
//Canvas
const DROPNUMBER = 1500;
//--------------------------classe---------------------------------------------
function Drop(width, heigth) {
//declaring and setting drop's attribute
this.spawn = function(width) {
//size and position
this.x = Math.random() * -width*1.5;
this.y = Math.random() * heigth;
this.size = Math.random() * 20 ;
//color
this.colorR = 138 + Math.random() * 50;
this.colorV = 43 + Math.random() * 50;
this.colorB = 226 + Math.random() * 50;
this.colorA = Math.random() * 127 +50;
//speed and landing
this.speed = Math.random();
this.hasLanded = false;
}
//call func to set the attribute
this.spawn(width);
//make the drop falls
this.fall = function() {
//if the drop can fall
if (this.x < width) {
this.x = this.x + this.speed;
this.speed = this.speed + 0.01;
//if the drop did land
if (this.y + this.size > width && this.hasLanded == false) {
this.hasLanded = true;
}
}
//if the drop did fall
else {
this.spawn(width);
}
}
//display the drop
this.display = function() {
noStroke();
//Some kind of purple color
fill(this.colorR, this.colorV, this.colorB, this.colorA);
rect(this.x, this.y, this.size, this.size)
}
}
//--------------------------setup---------------------------------------------
function setup() {
clientHeight = document.getElementById('header').clientHeight;
clientWidth = document.getElementById('header').clientWidth;
canvas = createCanvas(clientWidth, clientHeight);
canvas.parent('sketch-holder');
window.canvas = canvas;
}
//-------------------------Variable---------------------------------------------
var n = DROPNUMBER;
var drops = new Array();
//creating an array of drop for the rain
for (let i = 0; i < n; i++) {
//800 800 is height and the width that i want to change !
drops.push(new Drop(800,800));
}
//--------------------------draw------------------------------------------------
function draw() {
background(48, 64, 96);
//each drop
for (let i = 0; i < n; i++) {
//Make them falling
drops[i].fall();
//display the result
drops[i].display();
}
}
The code is just showing that drops ( the object that needs height and width) are being constructed out of draw or setup function.
I did search already on Stack Overflow to this kind of problem too.
use a regular DOM js it's worked:
let b = document.getElementById("parentElement");
let w = b.clientWidth;
let h = b.clientHeight;
console.log(w, h);
You don't need to use JQuery for this. Take a look at the P5.dom library that provides a bunch of functionality for manipulating HTML elements in P5.js.
I'm not sure exactly what you're trying to do, but here's a simple example. If we have a div on the page with and ID of myId, then to get its width we could use P5.dom to do this:
var myDiv = select('myId');
var myWidth = myDiv.style.width;
console.log('width: ' + myWidth);
To get the width of an element in JavaScript, you can select that element using document.querySelector(). Any CSS selector is a valid first argument to that function. E.g. the following will select the <body> tag:
document.querySelector('body')
Once you have an element selected, you can get it's width by accessing the clientWidth property. E.g. the following tells you the width of the <body> tag:
document.querySelector('body').clientWidth
So just replace body with a CSS selector for the element you want to select.

Class method is not a function?

I'm getting "Uncaught TypeError: this.time_to_x is not a function" when incorporating some open source ES5 code into my ES6 Class. Here is the class (I've removed some of the bulk, but most of the essential stuff is there). Assume Diamond() is called. It's this line that gets the error: x = this.time_to_x(frame.time);
Why is time_to_x() not being considered a function?
export default class TimelinePanel {
constructor(ctx) {
this.ctx = ctx;
this.ctx_wrap = ctx;
}
create (ctx) {
this.rect({ctx, x: 20, y: 15, width: 130, height: 10}); // ***
this.drawLayerContents();
}
Diamond(frame, y) {
var x, y2;
x = this.time_to_x(frame.time);
y2 = y + LINE_HEIGHT * 0.5 - DIAMOND_SIZE / 2;
var self = this;
var isOver = false;
this.path = function() {
this.ctx_wrap
.beginPath()
.moveTo(x, y2)
.lineTo(x + DIAMOND_SIZE / 2, y2 + DIAMOND_SIZE / 2)
.lineTo(x, y2 + DIAMOND_SIZE)
.lineTo(x - DIAMOND_SIZE / 2, y2 + DIAMOND_SIZE / 2)
.closePath();
};
}
drawLayerContents() {
// ...
for (i = 0; i < il; i++) {
// ...
for (j = 0; j < values.length; j++) {
// Dimonds
frame = values[j];
renderItems.push(new this.Diamond(frame, y));
}
}
}
y_to_track(y) {
if (y - MARKER_TRACK_HEIGHT < 0) return -1;
return (y - MARKER_TRACK_HEIGHT + scrollTop) / LINE_HEIGHT | 0;
}
x_to_time(x) {
var units = time_scale / tickMark3;
return frame_start + ((x - LEFT_GUTTER) / units | 0) / tickMark3;
}
time_to_x(s) {
var ds = s - frame_start;
ds *= time_scale;
ds += LEFT_GUTTER;
return ds;
}
}
You are creating an instance of this.Diamond class when you do new this.Diamond(frame, y). As a result, inside the function, this is this new instance, not the instance of TimelinePanel where it has originally been created from. Hence, this does not have the members of TimelinePanel.
Because it seems y_to_track and x_to_time does not make use of this, you could make them static (add the keyword static before them) and call them as follow: TimelinePanel.y_to_track.
If you need to access methods bound to a particular instance of TimelinePanel, then I don't see any other solution than passing this instance to the Diamond constructor or refactoring TimelinePanel and use closure around the Diamond constructor.
In any case it seems you are trying to replicate the behavior of Java-like internal classes (e.g. where you can access the container class instance with ClassName.this or just access the container class members), there is no such things in JS (at least with class).
EDIT: I just noticed that you are accessing TimelinePanel's ctx_wrap member that you will not be able to put as class member. The easiest seem to pass the TimelinePanel to the Diamond constructor: Diamond(frame, y, panel) and new this.Diamond(frame, y, this). It puts into question the usefulness of adding Diamond as a member of TimelinePanel.
Because the way you have it it's supposed time_to_x from closure, not from this. In this there is no such function, so this.time_to_x name returns undefined which is not a function indeed.
I suggest smth like this:
put var self = this; inside the class but outside of the Diamond method.
Then call self.time_to_x() inside Diamond.

Using 'This' within an IIFE constructor

I'm working on a small retro-style side-scrolling space shooter game (or, that's the theory anyway) and I've recently moved over to using IIFEs for managing my separate 'classes'.
However, most of the examples I've seen tend to use var when declaring variables, E.g, var x = 0. I'm wondering though, is it possible to use this.x = 0 and if so, are there any benefits or drawbacks?
I've tried googling it, and can't find much on the subject, which leads me to think it's a non-issue.
My classes are as follows;
var Player = function () {
// ------------------------------------------------------------------------------------------------
// PLAYER VARIABLES
// ------------------------------------------------------------------------------------------------
var w = 50;
var h = 50;
var x = 0;
var y = 0;
var color = 'white';
var projectiles = [];
// ------------------------------------------------------------------------------------------------
// BIND EVENTS TO THE GLOBAL CANVAS
// ------------------------------------------------------------------------------------------------
Canvas.bindEvent('mousemove', function(e){
y = (e.pageY - Canvas.element.getBoundingClientRect().top) - (h / 2);
});
Canvas.bindEvent('click', function(e){
createProjectile(50, (y + (h / 2)) - 10);
});
// ------------------------------------------------------------------------------------------------
// FUNCTIONS
// ------------------------------------------------------------------------------------------------
var createProjectile = function(x, y){
projectiles.push({
x: x,
y: y
})
};
var update = function(){
for(var p = projectiles.length - 1; p >= 0; p--){
projectiles[p].x += 10;
if(projectiles[p].x > Canvas.element.width)projectiles.splice(p, 1);
}
};
var render = function () {
Canvas.context.fillStyle = color;
Canvas.context.fillRect(x, y, w, h);
console.log(projectiles.length);
for(var p = 0; p < projectiles.length; p++){
Canvas.context.fillStyle = 'red';
Canvas.context.fillRect(projectiles[p].x, projectiles[p].y, 20, 20);
}
};
// ------------------------------------------------------------------------------------------------
// Exposed Variables and Functions
// ------------------------------------------------------------------------------------------------
return{
update: update,
render: render
}
}();
are there any benefits or drawbacks?
The drawbacks are that in strict mode, you will get a runtime error (because this is undefined).
In non-strict mode, this will refer to window, so this.x = ... creates a global variable (which is what you want to avoid with the IIFE in the first place I guess).
There are no benefits.

When two objects are dependent on each other? How to de-couple them?

Bit of a generic question but non the less I am in a situation where I do not know what to do and google has failed me!
I am trying to re-write a grid array collision with canvas that I built.
Now there is a grid object and a block object. The grid cellSize is dependent on being the same size of the block size and vice versa. The reason being is that to work out the grid array to store the blocks into I must first work out how to build it and that is dependent on the size of the block. Example,
var grid = new grid();
function grid() {
this.cellSize = 50;
this.cellsX = canvas.width / this.cellSize;
this.cellsY = canvas.height / this.cellSize;
this.buildGrid = function() {
var arr = new Array(this.cellsX);
for(var i = 0; i < arr.length; ++i) {
arr[i] = new Array(this.cellsY);
}
return arr;
};
this.arr = this.buildGrid();
this.getGridCoords = function(i) {
return Math.floor(i / this.cellSize);
};
}
function block() {
this.size = grid.cellSize; // size of the block is same as cellSize
this.x = 0;
this.y = 0 - (this.size * 1.5);
this.baseVelocity = 1;
this.velocity = this.baseVelocity;
this.update = function() {
this.y += this.velocity;
};
}
Doing it the way I have done it couples the two objects together and from what I have percieved that is a bad thing. How can I make sure that the two variables are the same size without coupling the objects if that makes sense?
The real issue is that your block() function is taking a value directly from an instance of grid().
If you want your block() function to be reusable and decoupled, its as easy as changing block() to take the size during construction.
arr[i] = new block({size: this.cellSize});

Categories