Hello,
This is my first post on the site and I am not sure my question is posted in the right forum, so I apologize if this is the wrong place. Anyway, this is my very first game and I am doing it in C# and XNA. Currently everything in my tetris game so far is working (left/right movements, dropping down quickly, rotations, etc) and the board is being drawn correctly except when the player fills 10 squares in a row what happens is that the row is just deleted and the rows above it don't fall down. What is confusing is that I am updating the board to shift every row down, but for some reason it is not being updated graphically. Here are the relevant parts of my code.
TetrisBoard class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tetris
{
public class TetrisBoard
{
public const int boardCols = 10;
public const int boardRows = 22;
public Square[,] board;
public TetrisBoard()
{
board = new Square[boardRows, boardCols];
}
public bool isCellFull(int row, int col)
{
return board[row, col] != null;
}
public void fillCell(int row, int col, Square square)
{
board[row, col] = square;
}
public void deleteCell(int row, int col)
{
board[row, col] = null;
}
public void fillTetromino(Tetromino tetromino)
{
for (int i = 0; i < tetromino.squares.Length; i++)
{
int col = tetromino.squares[i].square.X / Square.width;
int row = tetromino.squares[i].square.Y / Square.height;
fillCell(row, col, tetromino.squares[i]);
}
}
public bool canMoveDown(Square square)
{
int col = (square.square.X / Square.width);
int row = (square.square.Y / Square.height) + 1;
if (row >= boardRows)
return false;
return !isCellFull(row, col);
}
public bool canMoveDown(Tetromino tetromino)
{
for(int i = 0; i < tetromino.squares.Length; i++)
if(!canMoveDown(tetromino.squares[i]))
return false;
return true;
}
public bool canAccelerateDown(Square square)
{
int col = (square.square.X / Square.width);
int row = (square.square.Y / Square.height) + 2;
if (row >= boardRows)
return false;
return !isCellFull(row, col);
}
public bool canAccelerateDown(Tetromino tetromino)
{
for (int i = 0; i < tetromino.squares.Length; i++)
if (!canAccelerateDown(tetromino.squares[i]))
return false;
return true;
}
public bool canMoveLeft(Square square)
{
int col = (square.square.X / Square.width) - 1;
int row = (square.square.Y / Square.height);
if (col < 0)
return false;
return !isCellFull(row , col);
}
public bool canMoveLeft(Tetromino tetromino)
{
for (int i = 0; i < tetromino.squares.Length; i++)
if (!canMoveLeft(tetromino.squares[i]))
return false;
return true;
}
public bool canMoveRight(Square square)
{
int col = (square.square.X / Square.width) + 1;
int row = (square.square.Y / Square.height);
if(col >= boardCols)
return false;
return !isCellFull(row, col);
}
public bool canMoveRight(Tetromino tetromino)
{
for (int i = 0; i < tetromino.squares.Length; i++)
if (!canMoveRight(tetromino.squares[i]))
return false;
return true;
}
public bool hasLanded(Tetromino tetromino)
{
return !canMoveDown(tetromino);
}
public void checkTenInARow()
{
for (int i = boardRows - 1; i >= 0; i--)
{
bool score = true;
for (int j = 0; j < boardCols; j++)
{
if (!isCellFull(i, j))
{
score = false;
break;
}
}
if (score)
{
printBoard();
dropDownSquares(i);
printBoard();
}
}
}
public void dropDownSquares(int row)
{
for (int i = row; i > 0; i--)
{
for (int j = 0; j < boardCols; j++)
{
fillCell(i, j, board[i - 1, j]);
deleteCell(i - 1, j);
}
}
}
public void printBoard()
{
for (int i = 0; i < boardRows; i++)
{
for (int j = 0; j < boardCols; j++)
if (isCellFull(i, j))
Console.WriteLine(i + " " + j);
}
}
}
}
And this is part of the Game1.cs class
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
timeSinceLastInput += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (timeSinceLastInput >= minTimeSinceLastInput)
keyboardInputHandler();
timeSinceLastMove += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (!pause)
{
if (timeSinceLastMove >= minTimeSinceLastMove)
{
if (board.canMoveDown(currentPiece))
{
currentPiece.moveDown();
timeSinceLastMove = 0;
}
}
if (board.hasLanded(currentPiece))
{
board.fillTetromino(currentPiece);
board.checkTenInARow();
spawnRandomTetromino();
}
}
base.Update(gameTime);
}
public void drawTetromino()
{
for (int i = 0; i < currentPiece.squares.Length; i++)
drawSquare(currentPiece.squares[i]);
}
public void drawSquare(Square square)
{
spriteBatch.Draw(squareTex, square.square, Color.White);
}
public void drawBoard()
{
for (int i = 0; i < TetrisBoard.boardRows; i++)
{
for (int j = 0; j < TetrisBoard.boardCols; j++)
{
if (board.isCellFull(i, j))
drawSquare(board.board[i, j]);
}
}
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
drawBoard();
drawTetromino();
spriteBatch.End();
base.Draw(gameTime);
}
}
I have been trying to figure out this bug for a while, and I sure could use a new pair of eyes to look at it. I have attached the whole project if you need to see more of the code. Thanks