Is it possible to draw a class that draws sub-classes within itself? For example, a 4x4 block made up of 1x1 blocks


#1

I’m attempting to make a Tetris-like game, where the game’s pieces are all made up of smaller pieces that share properties.

Currently I have:

    export class SquareTetromino {
      [x: string]: any;
      constructor(x, y, w, h) {
      ...
      }

      show(p5) {
         p5.push();
         p5.translate(this.posX, this.posY);
         p5.fill("#D8B6FF")
         p5.rect(0,0,this.w, this.h);
         p5.pop();

      }
     ...
    }

and:

    export class BlockTetromino {
      [x: string]: any;
      constructor(x, y, w, h) {
      ...
      }

      test(p5) {
          this.testArray.push(new SquareTetromino(this.posX,this.posY,this.w,this.h));
          this.testArray.push(new SquareTetromino(this.posX - 50,this.posY,this.w,this.h));
          this.testArray.push(new SquareTetromino(this.posX - 50,this.posY + 50,this.w,this.h));
          this.testArray.push(new SquareTetromino(this.posX,this.posY + 50,this.w,this.h));
      }

      show(p5) {
          p5.push();
          this.testArray.forEach((block) => {
            block.show(p5)
          })
          p5.pop();

      }
    }

And from my main component:

  s.setup = () => {

  ...

            bodies.push(new BlockTetromino(200,-50,50,50))
            bodies[0].test(s);
  ...
          }

  s.draw = () => {
         ...


          for (let i = 0; i < bodies.length; i++) {
            bodies[i].show(s)
          }

I’d like to be able to have a class Block which draws a small block, and then call that Block within a class Square, which draws 4 small blocks. Then, by instantiating Square I’ll have 4 blocks chained together as one object.

I think I’m missing a for loop somewhere.


#2

If you want Block to be small blocks that make up each tetromino, and Square to be the 2x2 tetromino, then you’ve got the classes for those two essentially reversed right now.

The individual small block class would look something like this:

class Block {
	constructor(x, y, w) { // no need for h, because it's square
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = w;
	}

	show() {
		rect(this.x, this.y, this.w, this.h);
	}
}

With the square tetromino (made up of blocks) looking like this:

class SquareTetromino {
	constructor(x, y, w) {
		this.blocks = [];
		const blockW = w / 2;
		this.blocks.push(new Block(x, y, blockW, blockW));
		this.blocks.push(new Block(x + blockW, y, blockW, blockW));
		this.blocks.push(new Block(x, y + blockW, blockW, blockW));
		this.blocks.push(new Block(x + blockW, y + blockW, blockW, blockW));
	}

	show() {
		push();
		for (const block of this.blocks) {
			block.show();
		}
		pop();
	}
}

And then in your code you would

const bodies = [];
bodies.push(new SquareTetromino(100, 100, 100));

function setup() {
	createCanvas(500, 500);
	background(50);
}

function draw() {
	for (const body of bodies) {
		body.show();
	}
}

You may also want to consider giving the individual blocks an intrinsic width and height of 50, so they all stay the same size and you can build the tetromino classes without requiring inputting the same sizes on all of them (or giving them a size multiplier argument rather than direct width and height arguments, if you need to change the sizes).