1

I'm trying to recreate Tetris in P5.js. I want my shape that falls to pass on its coordinates once it has reached the bottom. I want to pass on the object x/y coordinates (translated into indexes) to my board Class' state named grid which is a 2d array of Cell objects.

The strange thing is that when I run my function it ends up changing all of the objects even though I am targeting one.

In breaking it down my array is working as usual until it runs the update function.

In P5.js the setup function runs automatically at the beginning and then the draw function runs, but is always looping until it is told to stop.

sketch.js

let canvas, tetromino, gridSize, board;
let fallingShapes = new Array();

function setup() {
    canvas = createCanvas(400, 800);
    centerCanvas();
    frameRate(5); // Initial speed of level

    gridSize = 40;
    board = new Board(width / gridSize, height / gridSize);
    board.initialize();
    createShape();
}

function draw() {
    let fallingShape = fallingShapes[0];
    background(100);
    fallingShape.update();
    fallingShape.show();
    checkIfLanded(fallingShape);
    // board.show();
}

function checkIfLanded(fallingShape) {
    if (fallingShape.hasLanded()) {
        board.update(fallingShape.x, fallingShape.y);
        // TODO gotta move this tetromino object to the board object
        fallingShapes.pop(1);
        noLoop();
        // createShape();
    }
}

tetromino.js

class Tetromino {
    constructor(x, y, height, width) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
        this.xDir = 0;
        this.yDir = gridSize;
    }

    setDir(x, y) {
        this.xDir = x;
        this.yDir = y;
    }

    show() {
        fill(0);
        rect(this.x, this.y, this.height, this.width);
    }

    update() {
        this.x += this.xDir;
        this.xDir = 0;
        this.y += this.yDir;
        this.yDir = gridSize;
        this.constrainToBorders();
        this.hasLanded()
            ? new Tetromino(width / 2 - gridSize, 0, gridSize, gridSize)
            : null;
    }

    hasLanded() {
        return this.y >= height - this.height;
    }
}

board.js

class Board {
    constructor(columns, rows) {
        this.columns = columns;
        this.rows = rows;
        this.grid;
    }

    initialize() {
        let cell = new Cell();
        let colsArray = new Array(this.columns).fill(cell);
        this.grid = new Array(this.rows).fill(colsArray);
    }

    update(cellX, cellY) {
        let indexX = cellX / gridSize;
        let indexY = cellY / gridSize;
        console.log(indexX, indexY, this.grid, this.grid[indexY][indexX]);
        this.grid[indexY][indexX].isTaken = true;
        console.log(this.grid);
    }

    show() {
        this.grid.map((row, rowIndex) => {
            row.map((singleCell, colIndex) => {
                singleCell.isTaken ? fill(255) : noFill();
                rect(
                    colIndex * gridSize,
                    rowIndex * gridSize,
                    gridSize,
                    gridSize
                );
            });
        });
    }
}

cell.js

class Cell {
    constructor() {
        this.taken = false;
        this.top = false;
    }
}

The expected outcome would be that only one Cell object will have this.taken = true

This image is me using the console to test the current behaviour of my code.

screen shot 2019-01-05 at 18 15 04

Full code is here if needs be.

pyan
  • 865
  • 2
  • 12
  • 23
  • See the linked answer - use `Array.from` when filling with non-primitives – CertainPerformance Jan 06 '19 at 12:31
  • Thanks for pointing that out! For reference I used Array.from to create the 2d array as pointed out; `this.grid = Array.from({ length: this.rows }, () => Array.from({ length: this.columns }, () => { return new Cell(); }) );` – pyan Jan 07 '19 at 14:48

0 Answers0