JavaScript Cannot Set Property '0' of undefined (2-dimensional array) - javascript

I know a bunch of people have already asked this, but nothing I have tried has worked. I have been stuck for days.
I suspect it may just be because the thing I am using (code.org) is a pile of flaming garbage, and it uses ES5. If you notice anything wrong, though, please let me know!
function Vector2(x, y)
{
this.x = x;
this.y = y;
return this;
}
function Pixel(x, y, darkness)
{
this.position = Vector2(x, y);
this.darkness = darkness;
this.rgbDarkness = this.darkness * 255;
return this;
}
function DataTexture2D(offsetX, offsetY, width, height)
{
this.offset = Vector2(offsetX, offsetY);
this.size = Vector2(width, height);
this.pixels = [];
for (var x = 0; x < width; x++)
{
this.pixels[x] = [];
for (var y = 0; y < height; y++)
{
this.pixels[x][y] = Pixel(x + this.offset.x, y + this.offset.y, 0.5);
}
}
return this;
}
var test = DataTexture2D(100, 50, 200, 300);
console.log(test.offset.x);

Related

I cant figure out how to make my loop work in my space invader like game in Javascript

For my space invader like game I want to make bullets that get shot by the enemies but the problem is that the bullets dont appear in this loop that I made. I tried several things like making only one bullet appear while that works it is not the result that I want. My idea behind the code is that a new bullet gets shot from the position of the enemies when the enemybullet.position == 1 and if it exceeds the height of the canvas I want the bullet to return to the enemies and be shot again.
The code that I used for this result is here:
sketch.js
var enemies = [];
var enemybullet = [];
function setup() {
createCanvas(800, 600);
for (var i = 0; i < 2; i++) {
enemies[i] = new Enemy(i*300+300, 100);
}
// I tried enemybullet = new Enemybullet(120, 200); and that drew the bullet but it wasnt assigned to the enemy
rectMode(CENTER);
}
function draw() {
background(0);
// enemybullet.show(); this is wat I used to draw the single projectile
// enemybullet.move();
var edge = false;
for (var i = 0; i < enemies.length; i++) {
enemies[i].show();
enemies[i].move();
if(enemies[i].x > width || enemies[i].x < 0) {
edge = true;
}
}
if (edge) {
for (var i = 0; i < enemies.length; i++) {
enemies[i].shiftDown();
}
}
for (var i = 0; i < enemybullet.length; i++) {
enemybullet[i].show();
enemybullet[i].move();
for (var j = 0; j < enemies.length; j++) {
if(enemybullet[i].position == 1){
var enemybullets = new Enemybullet(enemies[j].x(), enemies[j].y());
enemybullet.push(enemybullets);
enemybullet[i].x = enemybullet[i].x;
enemybullet[i].y = enemybullet[i].y + enemybullet[i].speed;
if(enemybullet[i].y >= height){
enemybullet[i].position = 2;
}
}
else{
enemybullet[i].y = enemies[i].y;
enemybullet[i].x = enemies[i].x;
}
if(enemybullet[i].position == 2 ){
enemybullet[i].y = enemies[i].y;
enemybullet[i].x = enemies[i].x;
enemybullet[i].position = 1;
}
}
}
enemybullet.js
function Enemybullet(x, y) {
this.x = x;
this.y = y;
this.width = 10;
this.height = 20;
this.position = 1;
this.speed = 2;
this.show = function() {
fill('#ADD8E6');
rect(this.x, this.y, this.width, this.height);
}
this.move = function() {
this.x = this.x;
this.y = this.y + this.speed;
}
}
enemy.js
function Enemy(x, y) {
this.x = x;
this.y = y;
this.r = 100;
this.xdir = 1;
this.shot = function() {
this.r = this.r * 0;
this.xdir = this.xdir * 0;
}
this.shiftDown = function() {
this.xdir *= -1;
this.y += this.r/2;
}
this.show = function() {
fill('#0000FF');
rect(this.x, this.y, this.r, this.r);
}
this.move = function() {
this.x = this.x + this.xdir;
}
}
Rather than having the bullets be in their own global array, try having the bullets be a variable in the Enemy class.
this.bullet = new Enemybullet(this.x, this.y);
Then you can give the enemies functions such as the following to update the bullets.
this.updateBullet = function() {
this.bullet.move();
this.bullet.show();
}
this.resetBullet = function() {
this.bullet = new Enemybullet(this.x, this.y);
}
Where you were looping through each bullet before, you can instead call enemies[i].updateBullet(); when you move and show the enemies.
And when you want the enemies to shoot another shot, call enemies[i].resetBullet();
You can see my implementation here.

Program integrated into html that creates a 4x4 grid and draws like Armin Hoffman

So far, I've done research into the design by Armin Hoffman (rubber band design). The objective is to create a grid of circles which can be selected to change from white to black and connect these circles in a natural fluid shape that avoids white circles but never traps them. I've been using Codecademy to learn the basics while copying and studying examples on the p5.js website and additionally following The Coding Train on Youtube (specifically: 7.4 mouse interaction and 7.6 clicking on objects).
Check #MauriceMeilleur on Twitter between Feb 2021 and Aug 2021
Also: https://discourse.processing.org/t/shape-generator-help-armin-hofmanns-rubber-band-shape-generator/33190
Every time I try to make a matrix or array of x and y values stored and to be used in the for loop within the draw/setup functions, it becomes invalid and it doesn't show the shapes I would like.
I know I'm missing info.
This is my latest trial:
class boundingBox {
createBox() {
stroke(0);
strokeWeight(3);
fill(255, 255, 255, 255);
rect(100, 100, 700, 700);
}
}
function Bubble(x, y, x1, y1, x2, y2, x3, y3) {
// creating a distinction from x/y private and x/y public
this.x = x;
this.y = y;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
//this.x = x = [225,350,475,600];
//this.y = y = [225,350,475,600];
// creating color public for later use
this.col = color(255);
// this expression works to make a public function within a private function
this.display = function() {
stroke(0);
fill(this.col);
// creating the ability to display the circles within the parameters set
//ellipse(this.x, this.y, 48,48);
// in theory this should loop through the x array position values against all the y values in it's array creating multiple circles
for (i = 0; i < 4; i++) {
ellipse(this.x /*[i]*/ , this.y, 100, 100);
ellipse(this.x1, this.y1, 100, 100);
ellipse(this.x2, this.y2, 100, 100);
ellipse(this.x3, this.y3, 100, 100);
}
}
//this.move = function() {
// //making the circles change position and act like they are moving within air
// this.x = this.x + random(-0.5, 0.5);
// this.y = this.y + random(-0.5, 0.5);
// this.x1 = this.x1 + random(-0.5, 0.5);
// this.y1 = this.y1 + random(-0.5, 0.5);
// //this.x = this.x + random(1, 0.5);
// //this.y = this.y + random(1, 0.5);
//}
// again expression to make function but this time implementing a clicking function
this.clicked = function() {
// calculating the distance from the circle center to help fill it with color and nothing else
var d = dist(mouseX, mouseY, this.x, this.y)
// diameter of the circle
if (d < 50) {
this.col = color(0, 0, 0)
}
}
//joinBubbles(bubbles); {
// bubbles.forEach(element => {
// let dis = dist(this.x, this.y, element.x, element.y);
// stroke(200, 200, 200, 127);
// line(this.x, this.y, element.x, element.y);
// });
//}
//}
//class lines {
// constructor(){
// this.x4 = x4;
// this.y4 = y4;
// this.x5 = x5;
// this.y5 = y5;
// }
// this.displayLine = function(){
// stroke(0)
// }
}
let bubbles = [];
let boxii = [];
function setup() {
createCanvas(1536, 1250);
for (let i = 0; i < 1; i++) {
boxii.push(new boundingBox());
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x = 200;
var y = i;
bubbles.push(new Bubble(x, y /*x1,y1*/ ));
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x1 = 375;
var y1 = i;
bubbles.push(new Bubble(x1, y1 /*x1,y1*/ ));
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x2 = 550;
var y2 = i;
bubbles.push(new Bubble(x2, y2 /*x1,y1*/ ));
}
for (let i = 200; i < 860; i += 165) {
//var x = random (width);
var x3 = 700;
var y3 = i;
bubbles.push(new Bubble(x3, y3 /*x1,y1*/ ));
}
//for (let i = 0; i < 1; i++) {
//var x1 = 400;
//var y1 = 200;
//bubbles.push(new Bubble(x1,y1));
//}
//for (let i = 200; i < 1000; i+=200){
//var x2 = 200;
//var y2 = i;
//bubbles.push(new Bubble(x2,y2));
//}
}
function mousePressed() {
// checking where the mouse presses so that clicking outside the circle does nothing
for (let i = 0; i < bubbles.length; i++) {
//for (let i = 0; i < 4; i++) {
// using this function on all the circles and again using .this to bring properties from /bubble
bubbles[i].clicked();
}
}
function draw() {
background(140);
for (let i = 0; i < 1; i++) {
boxii[i].createBox();
}
for (let i = 0; i < bubbles.length; i++) {
//bubbles[i].move();
bubbles[i].display();
}
if (mousePressed) {
for (let i = 0; i < bubbles.length; i++) {
bubbles[i].display(fill(0))
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>

Question Regarding some Haverbeke "Eloquent JavaScript" Constructor Code

I am having a bit of difficulty understanding a few lines of code from page 108 of Marijn Haverbeke's "Eloquent JavaScript" book.
Namely, in the example below, I don't understand what "element = (x, y) => undefined" in the constructor parameter list is doing, when the Matrix object is instantiated with "let matrix = new Matrix(3, 3, (x, y) => value ${x}, ${y});"
Can some step-by-step it for me? It seems like we are passing a function to the constructor, but I don't get why the constructor parameter list is setup the way it is with another arrow function.
var Matrix = class Matrix {
constructor(width, height, element = (x, y) => undefined) {
this.width = width;
this.height = height;
this.content = [];
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
this.content[y * width + x] = element(x, y);
}
}
}
get(x, y) {
return this.content[y * this.width + x];
}
set(x, y, value) {
this.content[y * this.width + x] = value;
}
}
var MatrixIterator = class MatrixIterator {
constructor(matrix) {
this.x = 0;
this.y = 0;
this.matrix = matrix;
}
next() {
if (this.y == this.matrix.height) return {done: true};
let value = {x: this.x,
y: this.y,
value: this.matrix.get(this.x, this.y)};
this.x++;
if (this.x == this.matrix.width) {
this.x = 0;
this.y++;
}
return {value, done: false};
}
}
Matrix.prototype[Symbol.iterator] = function() {
return new MatrixIterator(this);
};
let matrix = new Matrix(3, 3, (x, y) => `value ${x}, ${y}`);
for (let {x, y, value} of matrix) {
console.log(x, y, value);
}
Ok, I forgot in ES6+ an equal sign after a parameter is a default value if the parameter is missing or undefined. The way he did this is just a little awkward.

2 dimensional array of class objects in Javascript

Trying to make an array of class objects in JS. I don't know how Javascript handles this but instead of a 10x10 grid, all numbers are set to 10 instead of the i and j values I want to assign.
class Box {
constructor(width, height, x, y, inside) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.inside = inside;
}
getHeight() {
return this.height;
}
setHeight(newHeight) {
this.height = newHeight;
}
let boxes = [
[]
];
let testBox = new Box(1, 1, 1, 1, "Test")
for (let i = 0; i < 11; i++) {
for (let j = 0; j < 11; j++) {
boxes[i[j]] = new Box(i, j, i, j, "Test");
}
}
console.log(testBox.getHeight()); //Working Example
console.log(boxes[3[3]].getHeight()); //outputs 10?
console.log(boxes[4[6]].getHeight()); //outputs 10?
An example of what i wrote about in the comments
class Box {
constructor(width, height, x, y, inside) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.inside = inside;
}
getHeight() {
return this.height;
}
setHeight(newHeight) {
this.height = newHeight;
}
}
let boxes = [];
for (let i = 0; i < 11; i++) {
for (let j = 0; j < 11; j++) {
boxes[i] = [...(boxes[i] ? boxes[i] : []),
new Box(i, j, i, j, "Test")
];
}
}
console.log(boxes[3][3].getHeight());
console.log(boxes[4][6].getHeight());
From what I understand, you have declared a class box and you want to create an array of objects of this class. Considering this is the case,
you code has syntax error : the array and loop must be outside of the class definition.
Now since you want to make an array of objects, it's not a 2-D array it is just a one dimensional array.So the code should look like this
class Box {
constructor( width, height, x ,y, inside) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.inside = inside;
}
getHeight(){
return this.height;
}
setHeight(newHeight){
this.height = newHeight;
}}
let boxes = [];
for(let i = 0; i < 11; i++){
boxes.push(new Box(i,i+2,i,i+2,"Test"));
}
for(var cnt in boxes)
console.log(boxes[cnt]);

best design practice to separate common code?

I have a card class:
function Card() {
this.image = new Image();
this.x = 0;
this.y = 400;
this.initialX = 0;
this.initialY = 0;
this.scaleFactor = 4;
this.setImage = function(ii){
this.image.src = ii;
};
this.getWidth = function(){
if (this.image == null){
return 0;
}
return this.image.width / this.scaleFactor;
}
this.getHeight = function(){
if (this.image == null){
return 0;
}
return this.image.height / this.scaleFactor;
}
this.pointIsInCard = function(mx, my){
if (mx >= this.x && mx <= (this.x + this.getWidth()) && my >= this.y && my <= (this.y + this.getHeight()))
{
return true;
}
else{
return false;
}
};
};
I then have a deck class:
function Deck(x, y, w, h){
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.cards = [];
}
I need to add a method in Deck class similar to pointIsInCard instead it will be called pointIsInDeck. The logic will be same i.e to check whether the passed in point falls in the boundary of the object. So seeing this duplication of code I wanted to know what is a good design practice to avoid this duplication? One option I thought of was to extract the method out and create a function for generic object with x, y, width, height but again from OOP principles I thought this method should belong to the class/object. I appreciate any help! Thanks!
A common approach for what you're doing is to attach a Rectangle or similar instance with that functionality to both of your objects, that is:
class Rectangle {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
containsPoint(x, y) {
return x >= this.x && x =< this.width &&
y >= this.y && y =< this.height;
}
}
Then just add it to Card and Deck:
function Card() {
this.rect = new Rectangle(/* Your card shape */);
// ...
}
function Deck() {
this.rect = new Rectangle(/* Your deck shape */);
// ...
}
And you can do:
card.rect.containsPoint();
deck.rect.containsPoint();
If these are classes related to drawing, they would both inherit from something like Rectangle, which they would both inherit this behaviour from.
If they are gameplay-related, I would prefer them each referencing a Rectangle (or its subclass) that they would delegate all UI-related tasks to; then reduce this to the previous paragraph's solution.
You can use Function.prototype.call() to set this at a function call
function Card() {
this.x = 1; this.y = 2;
};
function Deck() {
this.x = 10; this.y = 20;
}
function points(x, y) {
// do stuff
console.log(x, this.x, y, this.y); // `this`: `c` or `d`
}
var c = new Card();
var d = new Deck();
points.call(c, 3, 4); // `this`: `c` within `points` call
points.call(d, 100, 200); // `this`: `d` within `points` call

Categories