Haben Sie jemals davon geträumt, Ihr eigenes Tetris zu programmieren? Dieser klassische Puzzle-Spiel ist nicht nur unterhaltsam, sondern auch ein hervorragendes Übungsprojekt, um Ihre Programmierkenntnisse zu verbessern. In diesem Artikel führen wir Sie Schritt für Schritt durch den Prozess, wie Sie die Tetrisblöcke in C# mit Windows Forms mithilfe der Pfeiltasten steuern können. Wir werden uns auf die grundlegenden Bewegungsmechanismen konzentrieren und eine solide Basis für Ihr eigenes Tetris-Spiel schaffen.
Voraussetzungen
Bevor wir beginnen, stellen Sie sicher, dass Sie Folgendes installiert haben:
- Visual Studio (oder eine andere C#-IDE)
- Grundlegende Kenntnisse in C#
- Grundkenntnisse in Windows Forms
Erstellen eines neuen Windows Forms-Projekts
Öffnen Sie Visual Studio und erstellen Sie ein neues Projekt. Wählen Sie die Vorlage „Windows Forms App (.NET Framework)” oder „Windows Forms App (.NET)” (je nachdem, welche Version von .NET Sie verwenden). Geben Sie Ihrem Projekt einen Namen, z. B. „TetrisGame”.
Die grundlegende Struktur
Zuerst müssen wir eine grundlegende Struktur für unser Spiel erstellen. Dies beinhaltet die Definition der Spielbrettgröße, die Darstellung der Tetrisblöcke und die Implementierung der Spiellogik.
1. Das Spielbrett:
Erstellen Sie eine 2D-Array, um das Spielbrett zu repräsentieren. Jedes Element im Array repräsentiert eine Zelle auf dem Brett. Verwenden Sie beispielsweise einen `int`-Array, bei dem 0 für eine leere Zelle steht und andere Werte für verschiedene Arten von Tetrisblöcken.
private int[,] _board = new int[20, 10]; // 20 Zeilen, 10 Spalten
2. Die Tetrisblöcke (Tetrominos):
Tetrisblöcke, auch Tetrominos genannt, sind die verschiedenen Formen, die im Spiel fallen. Definieren Sie diese Formen als 2D-Arrays, wobei 1 für einen Block und 0 für eine leere Zelle steht. Jeder Tetromino hat normalerweise mehrere Rotationen.
// Beispiel: I-Tetromino
private int[][,] _iTetromino = {
new int[,] {{1, 1, 1, 1}},
new int[,] {{1}, {1}, {1}, {1}}
};
// Variable, um den aktuellen Tetromino und seine Rotation zu speichern
private int[,]? _currentTetromino;
private int _currentRotation = 0;
private int _currentX = 0;
private int _currentY = 0;
3. Zeichnen des Spielbretts und der Blöcke:
Verwenden Sie das `Paint`-Ereignis des Forms, um das Spielbrett und die Tetrisblöcke zu zeichnen. Iterieren Sie durch das `_board`-Array und zeichnen Sie für jede Zelle ein Rechteck. Verwenden Sie verschiedene Farben, um die verschiedenen Blocktypen darzustellen.
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
// Zeichnen des Spielbretts
for (int row = 0; row < _board.GetLength(0); row++)
{
for (int col = 0; col < _board.GetLength(1); col++)
{
if (_board[row, col] != 0)
{
// Beispiel: Zeichnen eines roten Rechtecks für einen gefüllten Block
g.FillRectangle(Brushes.Red, col * 20, row * 20, 20, 20);
g.DrawRectangle(Pens.Black, col * 20, row * 20, 20, 20);
} else {
g.DrawRectangle(Pens.LightGray, col * 20, row * 20, 20, 20);
}
}
}
// Zeichnen des aktuellen Tetromino
if (_currentTetromino != null)
{
for (int row = 0; row < _currentTetromino.GetLength(0); row++)
{
for (int col = 0; col < _currentTetromino.GetLength(1); col++)
{
if (_currentTetromino[row, col] == 1)
{
g.FillRectangle(Brushes.Blue, (_currentX + col) * 20, (_currentY + row) * 20, 20, 20);
g.DrawRectangle(Pens.Black, (_currentX + col) * 20, (_currentY + row) * 20, 20, 20);
}
}
}
}
}
Steuerung der Tetrisblöcke mit Pfeiltasten
Der Kern dieses Artikels ist die Implementierung der Blocksteuerung mit den Pfeiltasten. Wir verwenden das `KeyDown`-Ereignis des Forms, um Tastenanschläge zu erkennen. Wenn eine Pfeiltaste gedrückt wird, bewegen wir den aktuellen Tetromino entsprechend.
1. Ereignisbehandlung für Tastenanschläge:
Doppelklicken Sie im Designer auf das Formular, um das `KeyDown`-Ereignis zu erstellen. Fügen Sie den folgenden Code hinzu, um die Pfeiltasten zu verarbeiten:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left:
MoveLeft();
break;
case Keys.Right:
MoveRight();
break;
case Keys.Down:
MoveDown();
break;
case Keys.Up:
Rotate();
break;
}
// Zeichnen Sie das Formular neu, um die Änderungen anzuzeigen
Invalidate();
}
2. Implementierung der Bewegungsfunktionen:
Erstellen Sie die Funktionen `MoveLeft()`, `MoveRight()`, `MoveDown()` und `Rotate()`. Diese Funktionen sollten die Position des aktuellen Tetromino ändern und sicherstellen, dass die Bewegung innerhalb der Grenzen des Spielbretts liegt und nicht mit vorhandenen Blöcken kollidiert.
private void MoveLeft()
{
if (CanMove(_currentTetromino, _currentX - 1, _currentY))
{
_currentX--;
}
}
private void MoveRight()
{
if (CanMove(_currentTetromino, _currentX + 1, _currentY))
{
_currentX++;
}
}
private void MoveDown()
{
if (CanMove(_currentTetromino, _currentX, _currentY + 1))
{
_currentY++;
}
else
{
// Tetromino ist unten angekommen, fixiere ihn auf dem Brett
FixTetromino();
SpawnNewTetromino();
}
}
private void Rotate()
{
int nextRotation = (_currentRotation + 1) % _iTetromino.Length; // Beispielrotation für I-Tetromino
if (CanMove(_iTetromino[nextRotation], _currentX, _currentY))
{
_currentRotation = nextRotation;
_currentTetromino = _iTetromino[_currentRotation];
}
}
// Hilfsfunktion, um zu überprüfen, ob die Bewegung möglich ist
private bool CanMove(int[,]? tetromino, int x, int y)
{
if(tetromino == null) return false;
for (int row = 0; row < tetromino.GetLength(0); row++)
{
for (int col = 0; col < tetromino.GetLength(1); col++)
{
if (tetromino[row, col] == 1)
{
int boardX = x + col;
int boardY = y + row;
// Überprüfen der Grenzen
if (boardX < 0 || boardX >= _board.GetLength(1) || boardY >= _board.GetLength(0))
{
return false;
}
// Überprüfen auf Kollisionen mit bestehenden Blöcken
if (boardY >= 0 && _board[boardY, boardX] != 0)
{
return false;
}
}
}
}
return true;
}
private void FixTetromino() {
if(_currentTetromino == null) return;
for (int row = 0; row < _currentTetromino.GetLength(0); row++)
{
for (int col = 0; col < _currentTetromino.GetLength(1); col++)
{
if (_currentTetromino[row, col] == 1)
{
_board[_currentY + row, _currentX + col] = 1; // Hier müsste eigentlich der Typ des Tetrominos gespeichert werden
}
}
}
}
private void SpawnNewTetromino() {
_currentTetromino = _iTetromino[0]; // Beispiel: immer den I-Tetromino erzeugen
_currentRotation = 0;
_currentX = _board.GetLength(1) / 2 - _currentTetromino.GetLength(1) / 2;
_currentY = 0;
// Spiel beenden, falls der neue Tetromino nicht platziert werden kann
if (!CanMove(_currentTetromino, _currentX, _currentY)) {
MessageBox.Show("Game Over!");
Application.Exit();
}
}
3. Aktivieren der Tastenereignisse:
Stellen Sie sicher, dass das Formular Tastenereignisse empfängt. Setzen Sie die `KeyPreview`-Eigenschaft des Formulars auf `true` im Designer oder im Code:
public Form1()
{
InitializeComponent();
KeyPreview = true;
SpawnNewTetromino(); // Initialen Tetromino erzeugen
}
Zusätzliche Funktionen
Dies ist nur die Basis für die Tetrisblock-Steuerung. Um Ihr Spiel vollständig zu machen, können Sie folgende Funktionen hinzufügen:
- Fallgeschwindigkeit: Erhöhen Sie die Fallgeschwindigkeit der Blöcke mit der Zeit.
- Score: Berechnen und anzeigen Sie den Score basierend auf der Anzahl der gelöschten Zeilen.
- Verschiedene Tetrominos: Implementieren Sie alle sieben Tetrominos.
- Rotation: Verbessern Sie die Rotationslogik, um sicherzustellen, dass sie korrekt funktioniert.
- Spielende: Erkennen Sie, wann das Spiel endet.
- Grafische Verbesserungen: Verbessern Sie die Grafiken, um das Spiel ansprechender zu gestalten.
Fazit
In diesem Artikel haben wir die Grundlagen der Tetrisblock-Steuerung in C# mit Windows Forms mithilfe der Pfeiltasten behandelt. Sie haben gelernt, wie man ein Spielbrett erstellt, Tetrisblöcke definiert und die Bewegung der Blöcke mithilfe von Tastenanschlägen steuert. Dies ist ein großartiger Ausgangspunkt für Ihr eigenes Tetris-Spiel. Experimentieren Sie mit zusätzlichen Funktionen, um Ihr Spiel noch unterhaltsamer und herausfordernder zu gestalten!
Viel Spaß beim Programmieren!