JavaScript 俄罗斯方块四联骨牌移动旋转后分开
JavaScript Tetris tetrominoes move apart after movement and rotation
通过制作俄罗斯方块游戏来学习JavaScript。
问题:
当我尝试移动(从起始位置向左、向右或向下)一块然后旋转它时,旋转的块会伸展开来。当我回到起始位置时,一切正常。
另外,当我不旋转棋子而只是将其移动到 left/right/down 时,一切也都很好。
我在想我的旋转中心是靠在网格上而不是在棋子上。
在这里你可以玩游戏:Here
这是我的github:Here
临时控件:
进入向上箭头后:开始游戏
向左箭头:向左移动
向右箭头:向右移动
向上箭头:旋转
向下箭头:向下移动一行
描述:
我的四联骨牌和我的网格由数组组成(基于class)。网格来自 SimpleBlock{} 和 GridBlock{}。我的四联骨牌是由 Simple Block{} 和
制作的
class SimpleBlock{
constructor(tempSquareColor, boardPosX, boardPosY){
this.x = boardPosX;
this.y = boardPosY;
this.squareColor = tempSquareColor;
}
}
class GridBlock extends SimpleBlock{
constructor(tempSquareColor, boardPosX, boardPosY){
super(tempSquareColor, boardPosX, boardPosY);
ctx.fillStyle = this.squareColor;
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
ctx.strokeRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
}
}
var gameBoardSquared = [];
function drawSquaredGameBoard() {
for(var row = 0; row < gameBoardRows; row++){
gameBoardSquared[row] = [];
for(var col = 0; col < gameBoardColumns; col++){
gameBoardSquared[row][col] = new GridBlock("white", row, col);
}
}
}
我的四联骨牌:
class BasicBlock extends SimpleBlock{
constructor(tempSquareColor, boardPosX, boardPosY){
super(tempSquareColor, boardPosX, boardPosY);
}
drawBlock(){
ctx.fillStyle = this.squareColor;
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
ctx.strokeRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
}
undrawBlock(){
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
ctx.strokeRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
}
moveLeft(){
this.x--;
}
moveRight(){
this.x++;
}
slowFall(){
this.y++;
}
}
//Tetrominos
//Declaration of variables, of a [4x4] tetromino array. Excluding the cells, that will never be used (like tetro3)
var tetrominoes = [];
var tetrominoI = [];
var tetrominoJ = [];
var tetrominoL = [];
var tetrominoO = [];
var tetrominoS = [];
var tetrominoT = [];
var tetrominoZ = [];
function makeNewRandomTetromino(){
var tetro = [];
tetro[0] = new BasicBlock("blue", 4, 0);
tetro[1] = new BasicBlock("blue", 5, 0);
tetro[2] = new BasicBlock("blue", 6, 0);
tetro[4] = new BasicBlock("blue", 4, 1);
tetro[5] = new BasicBlock("blue", 5, 1);
tetro[6] = new BasicBlock("blue", 6, 1);
tetro[7] = new BasicBlock("blue", 7, 1);
tetro[8] = new BasicBlock("blue", 4, 2);
tetro[9] = new BasicBlock("blue", 5, 2);
tetro[10] = new BasicBlock("blue", 6, 2);
tetro[11] = new BasicBlock("blue", 7, 2);
tetro[13] = new BasicBlock("blue", 5, 3);
tetro[14] = new BasicBlock("blue", 6, 3);
// var tetrominoJ0 = [
// tetro[1].tempSquareColor = "yellow",
// tetro[5].tempSquareColor = "yellow",
// tetro[8].tempSquareColor = "yellow",
// tetro[9].tempSquareColor = "yellow",
// ];
// var tetrominoJ1 = [
// tetro[4].tempSquareColor = "yellow",
// tetro[5].tempSquareColor = "yellow",
// tetro[6].tempSquareColor = "yellow",
// tetro[10].tempSquareColor = "yellow",
// ];
// var tetrominoI = [];
tetrominoI[0] = [tetro[1], tetro[5], tetro[9], tetro[13]];
tetrominoI[1] = [tetro[8], tetro[9], tetro[10], tetro[11]];
tetrominoI[2] = [tetro[2], tetro[6], tetro[10], tetro[14]];
tetrominoI[3] = [tetro[4], tetro[5], tetro[6], tetro[7]];
// for(var i of tetrominoI){
// i.squareColor == "magenta";
// }
// var tetrominoJ = [];
tetrominoJ[0] = [tetro[1], tetro[5], tetro[8], tetro[9]];
tetrominoJ[1] = [tetro[6], tetro[4], tetro[5], tetro[10]];
tetrominoJ[2] = [tetro[1], tetro[2], tetro[5], tetro[9]];
tetrominoJ[3] = [tetro[0], tetro[4], tetro[5], tetro[6]];
// var tetrominoL = [];
tetrominoL[0] = [tetro[0], tetro[1], tetro[5], tetro[9]];
tetrominoL[1] = [tetro[4], tetro[5], tetro[6], tetro[8]];
tetrominoL[2] = [tetro[1], tetro[5], tetro[9], tetro[10]];
tetrominoL[3] = [tetro[2], tetro[4], tetro[5], tetro[6]];
// for(var i of tetrominoL){
// i.squareColor == "orange";
// }
// var tetrominoO = [];
tetrominoO[0] = [tetro[1], tetro[2], tetro[5], tetro[6]];
tetrominoO[1] = [tetro[1], tetro[2], tetro[5], tetro[6]];
tetrominoO[2] = [tetro[1], tetro[2], tetro[5], tetro[6]];
tetrominoO[3] = [tetro[1], tetro[2], tetro[5], tetro[6]];
// for(var i of tetrominoO){
// i.squareColor == "yellow";
// }
// var tetrominoS = [];
tetrominoS[0] = [tetro[0], tetro[4], tetro[5], tetro[9]];
tetrominoS[1] = [tetro[5], tetro[6], tetro[8], tetro[9]];
tetrominoS[2] = [tetro[1], tetro[5], tetro[6], tetro[10]];
tetrominoS[3] = [tetro[1], tetro[2], tetro[4], tetro[5]];
// for(var i of tetrominoS){
// i.squareColor == "green";
// }
// var tetrominoT = [];
tetrominoT[0] = [tetro[1], tetro[4], tetro[5], tetro[9]];
tetrominoT[1] = [tetro[4], tetro[5], tetro[6], tetro[9]];
tetrominoT[2] = [tetro[1], tetro[5], tetro[6], tetro[9]];
tetrominoT[3] = [tetro[1], tetro[4], tetro[5], tetro[6]];
// for(var i of tetrominoT){
// i.squareColor == "purple";
// }
// var tetrominoZ = [];
tetrominoZ[0] = [tetro[1], tetro[4], tetro[5], tetro[8]];
tetrominoZ[1] = [tetro[4], tetro[5], tetro[9], tetro[10]];
tetrominoZ[2] = [tetro[2], tetro[5], tetro[6], tetro[9]];
tetrominoZ[3] = [tetro[0], tetro[1], tetro[5], tetro[6]];
// for(var i of tetrominoZ){
// i.squareColor == "red";
// }
var i = Math.floor(Math.random() * tetrominoZ.length);
var tetrominoesArr = [tetrominoO[i], tetrominoJ[i], tetrominoS[i], tetrominoZ[i], tetrominoT[i], tetrominoL[i], tetrominoI[i]];
var x = Math.floor(Math.random() * tetrominoesArr.length);
tetrominoes = tetrominoesArr[x];
}
以及控制它们的函数:
function rotateTetromino(){
for(let i of tetrominoes){
i.undrawBlock();
}
if(tetrominoes == tetrominoI[0]){
tetrominoes = tetrominoI[1];
} else if(tetrominoes == tetrominoI[1]){
tetrominoes = tetrominoI[2];
} else if(tetrominoes == tetrominoI[2]){
tetrominoes = tetrominoI[3];
} else if(tetrominoes == tetrominoI[3]){
tetrominoes = tetrominoI[0];
} else if(tetrominoes == tetrominoJ[0]){
tetrominoes = tetrominoJ[1];
} else if(tetrominoes == tetrominoJ[1]){
tetrominoes = tetrominoJ[2];
} else if(tetrominoes == tetrominoJ[2]){
tetrominoes = tetrominoJ[3];
} else if(tetrominoes == tetrominoJ[3]){
tetrominoes = tetrominoJ[0];
} else if(tetrominoes == tetrominoL[0]){
tetrominoes = tetrominoL[1];
} else if(tetrominoes == tetrominoL[1]){
tetrominoes = tetrominoL[2];
} else if(tetrominoes == tetrominoL[2]){
tetrominoes = tetrominoL[3];
} else if(tetrominoes == tetrominoL[3]){
tetrominoes = tetrominoL[0];
} else if(tetrominoes == tetrominoO[0]){
tetrominoes = tetrominoO[1];
} else if(tetrominoes == tetrominoO[1]){
tetrominoes = tetrominoO[2];
} else if(tetrominoes == tetrominoO[2]){
tetrominoes = tetrominoO[3];
} else if(tetrominoes == tetrominoO[3]){
tetrominoes = tetrominoO[0];
} else if(tetrominoes == tetrominoS[0]){
tetrominoes = tetrominoS[1];
} else if(tetrominoes == tetrominoS[1]){
tetrominoes = tetrominoS[2];
} else if(tetrominoes == tetrominoS[2]){
tetrominoes = tetrominoS[3];
} else if(tetrominoes == tetrominoS[3]){
tetrominoes = tetrominoS[0];
} else if(tetrominoes == tetrominoT[0]){
tetrominoes = tetrominoT[1];
} else if(tetrominoes == tetrominoT[1]){
tetrominoes = tetrominoT[2];
} else if(tetrominoes == tetrominoT[2]){
tetrominoes = tetrominoT[3];
} else if(tetrominoes == tetrominoT[3]){
tetrominoes = tetrominoT[0];
} else if(tetrominoes == tetrominoZ[0]){
tetrominoes = tetrominoZ[1];
} else if(tetrominoes == tetrominoZ[1]){
tetrominoes = tetrominoZ[2];
} else if(tetrominoes == tetrominoZ[2]){
tetrominoes = tetrominoZ[3];
} else if(tetrominoes == tetrominoZ[3]){
tetrominoes = tetrominoZ[0];
}
for(let i of tetrominoes){
i.drawBlock();
}
}
function moveTetrominoesLeft(){
if(tetrominoes.some(k => k.x - 1 < 0) || tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x-1][k.y].squareColor)){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(let i of tetrominoes){
i.undrawBlock();
}
for(let i of tetrominoes){
i.moveLeft();
i.drawBlock();
}
}
}
function moveTetrominoesRight(){
if(tetrominoes.some(k => k.x + 1 > gameBoardSquared.length-1) || tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x+1][k.y].squareColor)){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(var i of tetrominoes){
i.undrawBlock();
}
for(var i of tetrominoes){
i.moveRight();
i.drawBlock();
}
}
}
function tetrominoesSlowFall(){
for(let i of tetrominoes){
i.undrawBlock();
}
for(let i of tetrominoes){
i.slowFall();
i.drawBlock();
}
}
function collisionDetection(){
const topBoardBorder = 3;
for(var i of tetrominoes){
if(tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x][k.y].squareColor) && tetrominoes.some(k => k.y < topBoardBorder)){
console.log("Game Over");
gameOver = true;
}
if(tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x][k.y+1].squareColor)){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
return true;
}
else if(tetrominoes.some(k => k.y > playableGameBoardLength-1)){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
return true;
}
}
return false;
}
function clearRow(){
for(var rows = 0; rows < gameBoardColumns - 1; rows++){
while(gameBoardSquared.every(k => k[rows].squareColor == "blue")){
for(var i = 0; i < gameBoardSquared.length; i++){
gameBoardSquared[i].splice(rows, 1);
}
for(var i = 0; i < gameBoardSquared.length; i++){
gameBoardSquared[i].unshift(new GridBlock("white", i, rows));
}
console.log("clearRow(): ");
console.log(gameBoardSquared);
}
}
}
我认为旋转中心有问题,它位于四联骨牌的起始位置,而不是四联骨牌的当前中心。但也许你们可以帮助我更好地解决问题?
Tecnogirl建议的解决方案:
我正在移动将制作四联骨牌的所有块(因此整个四联体阵列)但我只为实际使用的那些(那些在四联骨牌下的)着色。删除了 collisionDetection() 函数并将其部分放在 moveTetrominoesLeft()、moveTetrominoesRight()、tetrominoesSlowFall() 中。
这是我更改的部分:
function moveTetrominoesLeft(){
if(tetrominoes.some(k => k.x - 1 < 0) || tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x-1][k.y].squareColor !== "white")){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(let i of tetro){
i.undrawBlock();
i.moveLeft();
}
for(let i of tetrominoes){
i.drawBlock();
}
}
}
function moveTetrominoesRight(){
if(tetrominoes.some(k => k.x + 1 > gameBoardSquared.length-1) || tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x+1][k.y].squareColor !== "white")){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(let i of tetro){
i.undrawBlock();
i.moveRight();
}
for(let i of tetrominoes){
i.drawBlock();
}
}
}
function tetrominoesSlowFall(){
const topBoardBorder = 3;
for(var i of tetrominoes){
if(tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x][k.y].squareColor !== "white" && tetrominoes.some(k => k.y < topBoardBorder))){
console.log("Game Over");
gameOver = true;
}
}
if(tetrominoes.some(k => k.y > playableGameBoardLength-1)){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
isCollision = true;
}
else if(tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x][k.y+1].squareColor !== "white")){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
isCollision = true;
}
for(let i of tetro){
i.undrawBlock();
i.slowFall();
}
for(let i of tetrominoes){
i.drawBlock();
}
}
并且在主游戏循环中也有一些变化(因为不再有 collisionDetection():
function updateGameBoard(){
if(!gameOver){
colourTetromino();
if(isCollision){
clearRow();
drawUpdatedGameBoard();
makeNewRandomTetromino();
isCollision = false;
}
else{
tetrominoesSlowFall();
drawUpdatedGameBoard();
}
}
else{
clearInterval(myInterval);
alert("Game Over");
}
}
function startGame(key){
if (key === "Enter"){
myInterval;
drawSquaredGameBoard();
makeNewRandomTetromino();
}
else if (key==="ArrowUp"){
rotateTetromino();
}
else if (key==="ArrowLeft"){
moveTetrominoesLeft();
}
else if (key==="ArrowRight"){
moveTetrominoesRight();
}
else if (key==="ArrowDown"){
updateGameBoard();
}
else
console.log("Psst, press 'Enter' to start");
}
您首先将旋转位置定义为 BasicBlock 数组。这是对构成旋转位置的每个基本块的引用数组。
当您执行 block.moveLeft() 时,您将 x 值更改为与原始值不同的数字。
这意味着保存在每个位置数组中的对象已更改为具有新的 x 值,因此当您尝试旋转时,这些位置不再有意义。
示例:
看看四联骨牌。它的第一个位置是
tetrominoS[0] = [tetro[0], tetro[4], tetro[5], tetro[9]] // the position you first defined
记忆中:
tetro[0]
= 参考 BasicBlock (x = 4, y = 0)
tetro[4]
= 参考 BasicBlock (x = 4, y = 1)
tetro[5]
= 参考 BasicBlock (x = 5, y = 1)
tetro[9]
= 参考 BasicBlock (x = 5, y = 2)
然后你做:moveLeft()(例如)
向左移动会将所有 x
值更改为 x-1
所以你正在做
BasicBlock (x = 4, y = 0).x--;
tetro[0]
现在指向 BasicBlock (x = 3, y = 0)
BasicBlock (x = 4, y = 1).x--;
tetro[4]
现在指向 BasicBlock (x = 3, y = 1)
BasicBlock (x = 5, y = 1).x--;
tetro[5]
现在指向 BasicBlock (x = 4, y = 1)
BasicBlock (x = 5, y = 2).x--;
tetro[9]
现在指向 BasicBlock (x = 4, y = 2)
然后你旋转:
tetrominoS
的下一个位置是tetrominoS[1]
也就是
tetrominoS[1] = [tetro[5], tetro[6], tetro[8], tetro[9]];
但请记住,tetro[5] 和 tetro[9] 已更改!所以我们得到:
tetrominoS[1] = [BasicBlock (x = 4, y = 1), tetro[6] (unchanged), tetro[8] (unchanged), BasicBlock (x = 4, y = 2)];
这不是你想要的。
解决方案:
当您想向左移动棋子时,无需更改方块的 X 值,只需移除当前方块的颜色并在其旁边的方块上绘制颜色即可。
通过制作俄罗斯方块游戏来学习JavaScript。
问题: 当我尝试移动(从起始位置向左、向右或向下)一块然后旋转它时,旋转的块会伸展开来。当我回到起始位置时,一切正常。 另外,当我不旋转棋子而只是将其移动到 left/right/down 时,一切也都很好。 我在想我的旋转中心是靠在网格上而不是在棋子上。
在这里你可以玩游戏:Here
这是我的github:Here
临时控件:
进入向上箭头后:开始游戏
向左箭头:向左移动
向右箭头:向右移动
向上箭头:旋转
向下箭头:向下移动一行
描述:
我的四联骨牌和我的网格由数组组成(基于class)。网格来自 SimpleBlock{} 和 GridBlock{}。我的四联骨牌是由 Simple Block{} 和
制作的 class SimpleBlock{
constructor(tempSquareColor, boardPosX, boardPosY){
this.x = boardPosX;
this.y = boardPosY;
this.squareColor = tempSquareColor;
}
}
class GridBlock extends SimpleBlock{
constructor(tempSquareColor, boardPosX, boardPosY){
super(tempSquareColor, boardPosX, boardPosY);
ctx.fillStyle = this.squareColor;
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
ctx.strokeRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
}
}
var gameBoardSquared = [];
function drawSquaredGameBoard() {
for(var row = 0; row < gameBoardRows; row++){
gameBoardSquared[row] = [];
for(var col = 0; col < gameBoardColumns; col++){
gameBoardSquared[row][col] = new GridBlock("white", row, col);
}
}
}
我的四联骨牌:
class BasicBlock extends SimpleBlock{
constructor(tempSquareColor, boardPosX, boardPosY){
super(tempSquareColor, boardPosX, boardPosY);
}
drawBlock(){
ctx.fillStyle = this.squareColor;
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
ctx.strokeRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
}
undrawBlock(){
ctx.fillStyle = "white";
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
ctx.fillRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
ctx.strokeRect(this.x * squareSize, this.y * squareSize, squareSize, squareSize);
}
moveLeft(){
this.x--;
}
moveRight(){
this.x++;
}
slowFall(){
this.y++;
}
}
//Tetrominos
//Declaration of variables, of a [4x4] tetromino array. Excluding the cells, that will never be used (like tetro3)
var tetrominoes = [];
var tetrominoI = [];
var tetrominoJ = [];
var tetrominoL = [];
var tetrominoO = [];
var tetrominoS = [];
var tetrominoT = [];
var tetrominoZ = [];
function makeNewRandomTetromino(){
var tetro = [];
tetro[0] = new BasicBlock("blue", 4, 0);
tetro[1] = new BasicBlock("blue", 5, 0);
tetro[2] = new BasicBlock("blue", 6, 0);
tetro[4] = new BasicBlock("blue", 4, 1);
tetro[5] = new BasicBlock("blue", 5, 1);
tetro[6] = new BasicBlock("blue", 6, 1);
tetro[7] = new BasicBlock("blue", 7, 1);
tetro[8] = new BasicBlock("blue", 4, 2);
tetro[9] = new BasicBlock("blue", 5, 2);
tetro[10] = new BasicBlock("blue", 6, 2);
tetro[11] = new BasicBlock("blue", 7, 2);
tetro[13] = new BasicBlock("blue", 5, 3);
tetro[14] = new BasicBlock("blue", 6, 3);
// var tetrominoJ0 = [
// tetro[1].tempSquareColor = "yellow",
// tetro[5].tempSquareColor = "yellow",
// tetro[8].tempSquareColor = "yellow",
// tetro[9].tempSquareColor = "yellow",
// ];
// var tetrominoJ1 = [
// tetro[4].tempSquareColor = "yellow",
// tetro[5].tempSquareColor = "yellow",
// tetro[6].tempSquareColor = "yellow",
// tetro[10].tempSquareColor = "yellow",
// ];
// var tetrominoI = [];
tetrominoI[0] = [tetro[1], tetro[5], tetro[9], tetro[13]];
tetrominoI[1] = [tetro[8], tetro[9], tetro[10], tetro[11]];
tetrominoI[2] = [tetro[2], tetro[6], tetro[10], tetro[14]];
tetrominoI[3] = [tetro[4], tetro[5], tetro[6], tetro[7]];
// for(var i of tetrominoI){
// i.squareColor == "magenta";
// }
// var tetrominoJ = [];
tetrominoJ[0] = [tetro[1], tetro[5], tetro[8], tetro[9]];
tetrominoJ[1] = [tetro[6], tetro[4], tetro[5], tetro[10]];
tetrominoJ[2] = [tetro[1], tetro[2], tetro[5], tetro[9]];
tetrominoJ[3] = [tetro[0], tetro[4], tetro[5], tetro[6]];
// var tetrominoL = [];
tetrominoL[0] = [tetro[0], tetro[1], tetro[5], tetro[9]];
tetrominoL[1] = [tetro[4], tetro[5], tetro[6], tetro[8]];
tetrominoL[2] = [tetro[1], tetro[5], tetro[9], tetro[10]];
tetrominoL[3] = [tetro[2], tetro[4], tetro[5], tetro[6]];
// for(var i of tetrominoL){
// i.squareColor == "orange";
// }
// var tetrominoO = [];
tetrominoO[0] = [tetro[1], tetro[2], tetro[5], tetro[6]];
tetrominoO[1] = [tetro[1], tetro[2], tetro[5], tetro[6]];
tetrominoO[2] = [tetro[1], tetro[2], tetro[5], tetro[6]];
tetrominoO[3] = [tetro[1], tetro[2], tetro[5], tetro[6]];
// for(var i of tetrominoO){
// i.squareColor == "yellow";
// }
// var tetrominoS = [];
tetrominoS[0] = [tetro[0], tetro[4], tetro[5], tetro[9]];
tetrominoS[1] = [tetro[5], tetro[6], tetro[8], tetro[9]];
tetrominoS[2] = [tetro[1], tetro[5], tetro[6], tetro[10]];
tetrominoS[3] = [tetro[1], tetro[2], tetro[4], tetro[5]];
// for(var i of tetrominoS){
// i.squareColor == "green";
// }
// var tetrominoT = [];
tetrominoT[0] = [tetro[1], tetro[4], tetro[5], tetro[9]];
tetrominoT[1] = [tetro[4], tetro[5], tetro[6], tetro[9]];
tetrominoT[2] = [tetro[1], tetro[5], tetro[6], tetro[9]];
tetrominoT[3] = [tetro[1], tetro[4], tetro[5], tetro[6]];
// for(var i of tetrominoT){
// i.squareColor == "purple";
// }
// var tetrominoZ = [];
tetrominoZ[0] = [tetro[1], tetro[4], tetro[5], tetro[8]];
tetrominoZ[1] = [tetro[4], tetro[5], tetro[9], tetro[10]];
tetrominoZ[2] = [tetro[2], tetro[5], tetro[6], tetro[9]];
tetrominoZ[3] = [tetro[0], tetro[1], tetro[5], tetro[6]];
// for(var i of tetrominoZ){
// i.squareColor == "red";
// }
var i = Math.floor(Math.random() * tetrominoZ.length);
var tetrominoesArr = [tetrominoO[i], tetrominoJ[i], tetrominoS[i], tetrominoZ[i], tetrominoT[i], tetrominoL[i], tetrominoI[i]];
var x = Math.floor(Math.random() * tetrominoesArr.length);
tetrominoes = tetrominoesArr[x];
}
以及控制它们的函数:
function rotateTetromino(){
for(let i of tetrominoes){
i.undrawBlock();
}
if(tetrominoes == tetrominoI[0]){
tetrominoes = tetrominoI[1];
} else if(tetrominoes == tetrominoI[1]){
tetrominoes = tetrominoI[2];
} else if(tetrominoes == tetrominoI[2]){
tetrominoes = tetrominoI[3];
} else if(tetrominoes == tetrominoI[3]){
tetrominoes = tetrominoI[0];
} else if(tetrominoes == tetrominoJ[0]){
tetrominoes = tetrominoJ[1];
} else if(tetrominoes == tetrominoJ[1]){
tetrominoes = tetrominoJ[2];
} else if(tetrominoes == tetrominoJ[2]){
tetrominoes = tetrominoJ[3];
} else if(tetrominoes == tetrominoJ[3]){
tetrominoes = tetrominoJ[0];
} else if(tetrominoes == tetrominoL[0]){
tetrominoes = tetrominoL[1];
} else if(tetrominoes == tetrominoL[1]){
tetrominoes = tetrominoL[2];
} else if(tetrominoes == tetrominoL[2]){
tetrominoes = tetrominoL[3];
} else if(tetrominoes == tetrominoL[3]){
tetrominoes = tetrominoL[0];
} else if(tetrominoes == tetrominoO[0]){
tetrominoes = tetrominoO[1];
} else if(tetrominoes == tetrominoO[1]){
tetrominoes = tetrominoO[2];
} else if(tetrominoes == tetrominoO[2]){
tetrominoes = tetrominoO[3];
} else if(tetrominoes == tetrominoO[3]){
tetrominoes = tetrominoO[0];
} else if(tetrominoes == tetrominoS[0]){
tetrominoes = tetrominoS[1];
} else if(tetrominoes == tetrominoS[1]){
tetrominoes = tetrominoS[2];
} else if(tetrominoes == tetrominoS[2]){
tetrominoes = tetrominoS[3];
} else if(tetrominoes == tetrominoS[3]){
tetrominoes = tetrominoS[0];
} else if(tetrominoes == tetrominoT[0]){
tetrominoes = tetrominoT[1];
} else if(tetrominoes == tetrominoT[1]){
tetrominoes = tetrominoT[2];
} else if(tetrominoes == tetrominoT[2]){
tetrominoes = tetrominoT[3];
} else if(tetrominoes == tetrominoT[3]){
tetrominoes = tetrominoT[0];
} else if(tetrominoes == tetrominoZ[0]){
tetrominoes = tetrominoZ[1];
} else if(tetrominoes == tetrominoZ[1]){
tetrominoes = tetrominoZ[2];
} else if(tetrominoes == tetrominoZ[2]){
tetrominoes = tetrominoZ[3];
} else if(tetrominoes == tetrominoZ[3]){
tetrominoes = tetrominoZ[0];
}
for(let i of tetrominoes){
i.drawBlock();
}
}
function moveTetrominoesLeft(){
if(tetrominoes.some(k => k.x - 1 < 0) || tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x-1][k.y].squareColor)){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(let i of tetrominoes){
i.undrawBlock();
}
for(let i of tetrominoes){
i.moveLeft();
i.drawBlock();
}
}
}
function moveTetrominoesRight(){
if(tetrominoes.some(k => k.x + 1 > gameBoardSquared.length-1) || tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x+1][k.y].squareColor)){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(var i of tetrominoes){
i.undrawBlock();
}
for(var i of tetrominoes){
i.moveRight();
i.drawBlock();
}
}
}
function tetrominoesSlowFall(){
for(let i of tetrominoes){
i.undrawBlock();
}
for(let i of tetrominoes){
i.slowFall();
i.drawBlock();
}
}
function collisionDetection(){
const topBoardBorder = 3;
for(var i of tetrominoes){
if(tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x][k.y].squareColor) && tetrominoes.some(k => k.y < topBoardBorder)){
console.log("Game Over");
gameOver = true;
}
if(tetrominoes.some(k => k.squareColor == gameBoardSquared[k.x][k.y+1].squareColor)){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
return true;
}
else if(tetrominoes.some(k => k.y > playableGameBoardLength-1)){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
return true;
}
}
return false;
}
function clearRow(){
for(var rows = 0; rows < gameBoardColumns - 1; rows++){
while(gameBoardSquared.every(k => k[rows].squareColor == "blue")){
for(var i = 0; i < gameBoardSquared.length; i++){
gameBoardSquared[i].splice(rows, 1);
}
for(var i = 0; i < gameBoardSquared.length; i++){
gameBoardSquared[i].unshift(new GridBlock("white", i, rows));
}
console.log("clearRow(): ");
console.log(gameBoardSquared);
}
}
}
我认为旋转中心有问题,它位于四联骨牌的起始位置,而不是四联骨牌的当前中心。但也许你们可以帮助我更好地解决问题?
Tecnogirl建议的解决方案: 我正在移动将制作四联骨牌的所有块(因此整个四联体阵列)但我只为实际使用的那些(那些在四联骨牌下的)着色。删除了 collisionDetection() 函数并将其部分放在 moveTetrominoesLeft()、moveTetrominoesRight()、tetrominoesSlowFall() 中。 这是我更改的部分:
function moveTetrominoesLeft(){
if(tetrominoes.some(k => k.x - 1 < 0) || tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x-1][k.y].squareColor !== "white")){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(let i of tetro){
i.undrawBlock();
i.moveLeft();
}
for(let i of tetrominoes){
i.drawBlock();
}
}
}
function moveTetrominoesRight(){
if(tetrominoes.some(k => k.x + 1 > gameBoardSquared.length-1) || tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x+1][k.y].squareColor !== "white")){
for(let i of tetrominoes){
i.drawBlock();
}
}
else{
for(let i of tetro){
i.undrawBlock();
i.moveRight();
}
for(let i of tetrominoes){
i.drawBlock();
}
}
}
function tetrominoesSlowFall(){
const topBoardBorder = 3;
for(var i of tetrominoes){
if(tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x][k.y].squareColor !== "white" && tetrominoes.some(k => k.y < topBoardBorder))){
console.log("Game Over");
gameOver = true;
}
}
if(tetrominoes.some(k => k.y > playableGameBoardLength-1)){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
isCollision = true;
}
else if(tetrominoes.some(k => k.squareColor !== "white" && gameBoardSquared[k.x][k.y+1].squareColor !== "white")){
for(var i of tetrominoes){
i.drawBlock();
gameBoardSquared[i.x][i.y] = i;
}
isCollision = true;
}
for(let i of tetro){
i.undrawBlock();
i.slowFall();
}
for(let i of tetrominoes){
i.drawBlock();
}
}
并且在主游戏循环中也有一些变化(因为不再有 collisionDetection():
function updateGameBoard(){
if(!gameOver){
colourTetromino();
if(isCollision){
clearRow();
drawUpdatedGameBoard();
makeNewRandomTetromino();
isCollision = false;
}
else{
tetrominoesSlowFall();
drawUpdatedGameBoard();
}
}
else{
clearInterval(myInterval);
alert("Game Over");
}
}
function startGame(key){
if (key === "Enter"){
myInterval;
drawSquaredGameBoard();
makeNewRandomTetromino();
}
else if (key==="ArrowUp"){
rotateTetromino();
}
else if (key==="ArrowLeft"){
moveTetrominoesLeft();
}
else if (key==="ArrowRight"){
moveTetrominoesRight();
}
else if (key==="ArrowDown"){
updateGameBoard();
}
else
console.log("Psst, press 'Enter' to start");
}
您首先将旋转位置定义为 BasicBlock 数组。这是对构成旋转位置的每个基本块的引用数组。
当您执行 block.moveLeft() 时,您将 x 值更改为与原始值不同的数字。 这意味着保存在每个位置数组中的对象已更改为具有新的 x 值,因此当您尝试旋转时,这些位置不再有意义。
示例:
看看四联骨牌。它的第一个位置是
tetrominoS[0] = [tetro[0], tetro[4], tetro[5], tetro[9]] // the position you first defined
记忆中:
tetro[0]
= 参考 BasicBlock (x = 4, y = 0)
tetro[4]
= 参考 BasicBlock (x = 4, y = 1)
tetro[5]
= 参考 BasicBlock (x = 5, y = 1)
tetro[9]
= 参考 BasicBlock (x = 5, y = 2)
然后你做:moveLeft()(例如)
向左移动会将所有 x
值更改为 x-1
所以你正在做
BasicBlock (x = 4, y = 0).x--;
tetro[0]
现在指向 BasicBlock (x = 3, y = 0)
BasicBlock (x = 4, y = 1).x--;
tetro[4]
现在指向 BasicBlock (x = 3, y = 1)
BasicBlock (x = 5, y = 1).x--;
tetro[5]
现在指向 BasicBlock (x = 4, y = 1)
BasicBlock (x = 5, y = 2).x--;
tetro[9]
现在指向 BasicBlock (x = 4, y = 2)
然后你旋转:
tetrominoS
的下一个位置是tetrominoS[1]
也就是
tetrominoS[1] = [tetro[5], tetro[6], tetro[8], tetro[9]];
但请记住,tetro[5] 和 tetro[9] 已更改!所以我们得到:
tetrominoS[1] = [BasicBlock (x = 4, y = 1), tetro[6] (unchanged), tetro[8] (unchanged), BasicBlock (x = 4, y = 2)];
这不是你想要的。
解决方案:
当您想向左移动棋子时,无需更改方块的 X 值,只需移除当前方块的颜色并在其旁边的方块上绘制颜色即可。