Реализация тетриса p5.js имеет ошибку, из-за которой куски проваливаются сквозь дно - PullRequest
0 голосов
/ 29 января 2019

Я делаю 3D тетрис в p5.js.Но сейчас у меня есть ошибка, из-за которой куски проваливаются сквозь дно!Я не уверен, почему это так, потому что я написал функцию «fallPieceIsLegal», которая должна предотвратить это.Большое спасибо за вашу помощь!

//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>

Функция placeFallingPiece очень похожа на drawFallingPiece, только вместо того, чтобы рисовать ячейки, она загружает соответствующие ячейки падающей фигуры на доску с помощью fallPieceColor.Таким образом, часть помещается на доску.

1 Ответ

0 голосов
/ 29 января 2019

Ух ты, это похоже на большую работу!Возможно, вы захотите либо упростить, либо начать заново, чтобы решить вашу проблему.(Вы всегда можете сделать его более сложным позже, но если это не сработает так, как вам нужно, лучше сначала сделать его проще / удобнее настроить).

К сожалению, я не смогу предоставитьФрагмент для каждой отдельной проблемы, но я могу указать несколько вещей, которые могут помочь вам исправить вашу ошибку:

  1. У вас уже есть условие, которое проверяет, находится ли падающая часть внизу и работает ли она: if (moveFallingPiece(-1,0) == false) {
  2. В настоящее время у вас есть только одна фигура, и когда она достигает дна, вы «перерабатываете» ее как новую (изменяя тип фигуры Тетриса и сбрасывая строку в 0): вы можете захотеть создатьмассив для хранения кусков, которые упали.Таким образом, вы можете выбрать остановку обновления строки (остановить их падение), но продолжать отображать их на экране, а также решить логику того, какие части какой части соединяются как непрерывная последняя строка
  3. Код очень жестко связанных .Возможно, вы захотите реорганизовать ваши объекты, чтобы было проще обрабатывать несколько частей, каждая часть которых состоит из частей.

(например, создать класс и экземпляры (объекты) , решить любыестолкновения (будь то с нижней части экрана или других частей) и добавить несколько объектов в массив при обнаружении столкновений, чтобы сформировать полные строки (точки усиления) или складывать)

Я бы предложил сделать 2D версиюсначала с помощью p5.js, а затем просто измените рендерер p5.js на WEBGL и поменяйте ваши rect() вызовы на box() вызовы (учитывая, что они взяты из центра и используют * 1025)* / pop() вызывает выделение координатных пространств для каждого поля ).(Чуть дальше вы можете взглянуть на шаблон MVC и отделить рендеринг / представление от логики данных и управления, что позволит вам переключиться с 2D на 3D тетрис, если вы хотите)

...