I'm making 3D tetris in p5.js. But right now I have a bug that makes the pieces fall through the bottom! I'm not sure why that is because i wrote a function, "fallingPieceIsLegal" that should prevent this. Thanks so much for your help!
//Audrey Zheng
//3D Tetris
var cx;
var cy;
// set board dimensions and margin
var rows = 15;
var cols = 10;
var margin = 50;
let emptyColor;
//make board
var state = new Array();
for (var i = 0; i < cols; i ++) {
state.push(emptyColor);
}
var board = new Array();
for (var i = 0; i< rows; i ++) {
board.push(state);
}
//seven "standard" pieces (tetrominoes)
var iPiece = [
[ true, true, true, true]
];
var jPiece = [
[ true, false, false ],
[ true, true, true]
];
var lPiece = [
[ false, false, true],
[ true, true, true]
];
var oPiece = [
[ true, true],
[ true, true]
];
var sPiece = [
[ false, true, true],
[ true, true, false ]
];
var tPiece = [
[ false, true, false ],
[ true, true, true]
];
var zPiece = [
[ true, true, false ],
[ false, true, true]
];
var tetrisPieces = [ iPiece, jPiece, lPiece, oPiece, sPiece, tPiece, zPiece ];
var tetrisPieceColors = [ "green", "pink", "orange", "yellow", "purple", "blue", "red" ];
//the falling piece
var fallingPiece;
var fallingPieceCols;
var fallingPieceCol;
var fallingPieceRow;
function setup() {
frameRate(10);
createCanvas(550, 800);
background(220);
// osc = new p5.TriOsc();
// osc.freq(880.0);
// osc.amp(0.1);
// osc.start();
cx = width/2;
cy = width/2;
newFallingPiece();
//fallingPieceIsLegal();
}
function draw() {
fill(255,255,220);
rect(0,0,width,height);
emptyColor = color(255,0,0,63);
drawBoard(rows,cols, 450,675);
placeFallingPiece();
rectMode(CORNER);
drawFallingPiece();
if (moveFallingPiece(-1,0) == false) {
placeFallingPiece();
newFallingPiece();
}
}
function newFallingPiece(){
fallingPiece = random(tetrisPieces);
fallingPieceCols = fallingPiece[0].length;
fallingPieceCol = cols/2 - Math.floor(fallingPieceCols/2);
fallingPieceRow = 0;
//console.log(fallingPiece);
}
function placeFallingPiece() {
for (var r = 0; r < fallingPiece.length; r ++) {
for (var c = 0; c < fallingPiece[0].length; c ++) {
if (fallingPiece[r][c]) {
board[r + fallingPieceRow][c + fallingPieceCol] = "magenta";
}
//print("hi");
}
}
}
function drawFallingPiece() {
for (var r = 0; r < fallingPiece.length; r ++) {
for (var c = 0; c < fallingPiece[0].length; c ++) {
if (fallingPiece[r][c]) {
var bnds = getCellBounds(r + fallingPieceRow, c + fallingPieceCol, 450, 675);
fill(255);
rect(bnds[0],bnds[2],45,45);
var tetrisCube = new cube(bnds[0],bnds[2], true);
//systems.push(tetrisCube);
tetrisCube.display();
//fill(230,245,255);
rect(bnds[0], bnds[2], 45,45);
}
//print("hi");
}
}
}
function fallingPieceIsLegal() {
for (var r = 0; r < fallingPiece.length; r++) {
for (var c = 0; c < fallingPieceCols; c++) {
if (fallingPiece[r][c] == true) {
if ((c + fallingPieceCol > cols - 1) || (c + fallingPieceCol < 0)) {
return false;
}
if (r + fallingPieceRow > rows -1) {
return false;
}
}
}
}
return true;
}
function moveFallingPiece(drow, dcol) {
if ((drow == 0) && (dcol == -1)) { //move left
fallingPieceCol -= 1;
if (fallingPieceIsLegal() == false) {
fallingPieceCol += 1;
print('hi');
}
}
if ((drow == 0) && (dcol == 1)) { //move right
fallingPieceCol += 1;
if (fallingPieceIsLegal() == false) {
print("yo");
fallingPieceCol -= 1;
}
}
if ((drow == -1) && (dcol == 0)) { //move down
fallingPieceRow += 1;
if (fallingPieceIsLegal() == false) {
fallingPieceRow -= 1;
return false;
}
return true;
}
}
function rotate1(L) {
var result = [];
var a;
for (var col = L[0].length -1; col > -1; col--) {
//print("yeet");
var result1 = [];
for (var row = 0; row < L.length; row++) {
a = L[row][col];
result1.push(a);
print(a);
}
result.push(result1);
}
return result;
}
function rotateFallingPiece() {
fallingPiece = rotate1(fallingPiece);
fallingPieceCols = fallingPiece[0].length;
if (fallingPieceIsLegal == false) {
for (var i = 0; i < 3; i ++) {
fallingPiece = rotate1(fallingPiece);
fallingPieceCols = fallingPiece[0].length;
}
}
print(fallingPiece);
}
function getCellBounds(row,col, width,height) {
var gridWidth = width - 2 * margin;
var gridHeight = height - 2 * margin;
var x0 = margin + width * col/ cols;
var x1 = margin + width * (col + 1)/ cols;
var y0 = margin + height * row / rows;
var y1 = margin + height * (row + 1)/ rows;
return [x0,x1,y0,y1];
}
//console.log(getCellBounds(0,0, 450,600));
function drawBoard(rows, cols, width,height) {
for (var row = 0; row < rows; row ++) {
for (var col = 0; col < cols; col++) {
drawCell(row,col,width,height);
}
}
}
function drawCell(row, col, width, height) {
var bounds = getCellBounds(row,col, width, height);
x0 = bounds[0];
x1 = bounds[1];
y0 = bounds[2];
y1 = bounds[3];
rectMode(CORNER);
var cellCube = new cube(x0 ,y0, false);
cellCube.display();
//quad(x0,y0, x0,y0 + 40, x0+40, y0+40, x0 + 40, y0 );
}
function cube(x,y, isSolid) { //the cube
this.x = x;
this.y = y;
this.width = 45;
this.NW =[this.x, this.y];
this.NE = [x+this.width, this.y];
this.SE = [this.x+this.width, y+this.width];
this.SW = [this.x, y+this.width];
this.larger = new square(x,y,this.width, this.width);
this.smaller = new square(x + (cx -x) * 0.25, y + (cy - y) *0.25, this.width * 0.75, this.width * 0.75);
this.NWs =[(this.x + (cx - this.x) * 0.20), this.y + (cy - this.y) * 0.20];
this.NEs = [(this.x + (cx - this.x) * 0.20) + (this.width * 0.8), this.y + (cy - this.y) * 0.20];
this.SEs = [(this.x + (cx - this.x) * 0.20) + (this.width * 0.8), this.y + (cy - this.y) * 0.20 + (this.width * 0.8)];
this.SWs = [(this.x + (cx - this.x) * 0.20), this.y + (cy - this.y) * 0.20 +(this.width * 0.8)];
this.display = function() {
//rect(this.x, this.y, this.width, this.width);
//rect(this.x + (cx - this.x) * 0.20, this.y + (cy - this.y) * 0.20, this.width * 0.8, this.width * 0.8);
stroke(127);
//bigger square
line(this.x,this.y, this.x + this.width, this.y);
line(this.x,this.y, this.x, this.y + this.width);
line(this.x + this.width, this.y, this.x + this.width, this.y + this.width);
line(this.x, this.y+ this.width, this.x + this.width, this.y + this.width);
//smaller square
line(this.x + (cx - this.x) * 0.20, this.y + (cy - this.y) * 0.20, (this.x + (cx - this.x) * 0.20 )+ this.width * 0.8, this.y + (cy - this.y) * 0.20);
line(this.x + (cx - this.x) * 0.20, this.y + (cy - this.y) * 0.20, this.x + (cx - this.x) * 0.20, this.y + (cy - this.y) * 0.20 + this.width * 0.8);
line(this.x + (cx - this.x) * 0.20 + this.width * 0.8, this.y + (cy - this.y) * 0.20,this.x + (cx - this.x) * 0.20 + this.width * 0.8,this.y + (cy - this.y) * 0.20 + this.width * 0.8);
line(this.x + (cx - this.x) * 0.20, this.y + (cy - this.y) * 0.20 + this.width * 0.8, (this.x + (cx - this.x) * 0.20 )+ this.width * 0.8, this.y + (cy - this.y) * 0.20 + this.width * 0.8);
if (isSolid == false) {
line(this.NW[0], this.NW[1], this.NWs[0], this.NWs[1]);
line(this.NE[0], this.NE[1], this.NEs[0], this.NEs[1]);
line(this.SE[0], this.SE[1], this.SEs[0], this.SEs[1]);
line(this.SW[0], this.SW[1], this.SWs[0], this.SWs[1]);
}
if (isSolid) {
noStroke();
fill(230);
quad(this.SW[0], this.SW[1], this.SE[0], this.SE[1], this.SEs[0], this.SEs[1], this.SWs[0], this.SWs[1]); //bottom
quad(this.NE[0], this.NE[1], this.NEs[0], this.NEs[1], this.SEs[0], this.SEs[1], this.SE[0], this.SE[1]); // right
quad(this.NW[0], this.NW[1], this.NWs[0], this.NWs[1], this.SWs[0], this.SWs[1], this.SW[0], this.SW[1]); //fill left
quad(this.NE[0], this.NE[1], this.NEs[0], this.NEs[1], this.NWs[0], this.NWs[1], this.NW[0], this.NW[1]); //fill top
fill(240);
quad(this.NE[0], this.NE[1], this.SE[0], this.SE[1], this.SW[0], this.SW[1], this.NW[0], this.NW[1]);
}
};
}
function square(x,y,w,h) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.getCorners = function() {
var NW =[x-w/2,y-h/2];
//print(NW);
var NE = [x+w/2, y-h/2];
var SE = [x+w/2, y-h/2];
var SW = [x-w/2, y+h/2];
return [NW,NE,SE,SW];
};
}
function keyPressed() {
if (keyCode == LEFT_ARROW) {
moveFallingPiece(0, -1);
}
if (keyCode == RIGHT_ARROW) {
moveFallingPiece(0,1);
}
if (keyCode == DOWN_ARROW) {
moveFallingPiece(-1,0);
}
if (keyCode == UP_ARROW) {
rotateFallingPiece();
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>p5.js vers 0.7.1, Edit index.html to Change This Title</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/addons/p5.dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/addons/p5.sound.js"></script>
<script src="sketch.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
The placeFallingPiece function is quite similar to drawFallingPiece, only rather than draw the cells, it loads the corresponding cells of the fallingPiece onto the board with the fallingPieceColor. In this way, the piece is placed on the board.