/// <summary> /// Wird aufgerufen, wenn auf den Menüpunkt "Neues Spiel" geklickt wird /// </summary> private void miNeuesSpiel_Click(object sender, EventArgs e) { if (this.a.isRunning) { bool h = this.a.isPause; this.a.isPause = true; DialogResult res = MessageBox.Show( this, "Willst du das laufende Spiel wirklich beenden?", this.Text, MessageBoxButtons.YesNo); this.a.isPause = h; if (res == System.Windows.Forms.DialogResult.No) { return; } } TSegmentBase.stopAnimation(); this.a.stopGame(); this.Display.reset(); this.Data.reset(); this.a = new TArena(this.Display, this.Data); this.Segment.registerArena(this.a); this.myArena = new TVisualArena(a, this.paTetris, this.Data, this.Segment); this.paTetris.Refresh(); this.paNext.Refresh(); }
} //Ende Methode blinkTrapez /// <summary> /// Der Spieler hat einen Tetris gemacht. Die vollen Ringe/Trapeze blinken, bevor sie gelöscht werden /// </summary> /// <param name="positionSchicht">Die oberste Schicht, wo das Teil liegt</param> /// <param name="g">Graphics-Objekt zum Zeichnen</param> /// <param name="backColor">Hintergrundfarbe zum Löschen</param> /// <param name="arena">Verweis auf die Arena</param> public void blink(int positionSchicht, Graphics g, Color backColor, TVisualArena arena) { if (Mode == EDisplayMode.Ring) { blinkRings(positionSchicht, g, backColor, arena); } else if (Mode == EDisplayMode.Trapez) { blinkTrapez(positionSchicht, g, backColor, arena); } }
/// <summary> /// Standard-Konstruktor /// </summary> public foMain() { InitializeComponent(); this.Data = new TSharedData(); this.Display = new TDisplayFoMain(this, this.Data); this.a = new TArena(this.Display, this.Data); this.Segment = new TVisualSegment(this.paTetris); this.Segment.registerArena(this.a); this.myArena = new TVisualArena(a, this.paTetris, this.Data, this.Segment); TSegmentBase.registerForm(this); }
/// <summary> /// Löscht das Teil und alle seine Segmente /// </summary> /// <param name="g">Graphics-Objekt zum Zeichnen</param> /// <param name="t">Das zu zeichnende Teil</param> /// <param name="backColor">Hintergrundfarbe des Panels</param> /// <param name="arena">Verweis auf die Arena</param> /// <param name="segment">Verweis auf das Segment zum Zeichnen</param> public static void deleteTeil(Graphics g, TTeil t, Color backColor, TVisualArena arena, TSegmentBase segment) { for (int i = 0; i < TTeil.MaxBreite; i++) { for (int k = 0; k < TTeil.MaxHoehe; k++) { if (t.hasSegment(i, k)) { int positionSektor = (t.PositionSektor + i) % TArena.AnzahlSektoren; int positionSchicht = t.PositionSchicht - k; segment.deleteSegment(positionSektor, positionSchicht, g, backColor); arena.repairNachbarn(positionSektor, positionSchicht, g); } } } }
/// <summary> /// Der Spieler hat einen Tetris gemacht. Die vollen Ringe blinken, bevor sie gelöscht werden /// </summary> /// <param name="positionSchicht">Die oberste Schicht, wo das Teil liegt</param> /// <param name="g">Graphics-Objekt zum Zeichnen</param> /// <param name="backColor">Hintergrundfarbe zum Löschen</param> /// <param name="arena">Verweis auf die Arena</param> private void blinkRings(int positionSchicht, Graphics g, Color backColor, TVisualArena arena) { AnimationIsRunning = true; int n = TTeil.MaxHoehe; //Radien berechnen float rInnen = (float)((positionSchicht - n + 1) * this.SegmentBreite); float rAussen = (float)((positionSchicht + 1) * this.SegmentBreite); //Rechtecke berechnen float r = rInnen; RectangleF recInnen = new RectangleF( this.CenterX - r, this.CenterY - r, 2 * r, 2 * r); r = rAussen; RectangleF recAussen = new RectangleF( this.CenterX - r, this.CenterY - r, 2 * r, 2 * r); //Pfad berechnen int winkel = 360; GraphicsPath path = new GraphicsPath(); path.AddArc(recAussen, 0, winkel); //Bogen A-B //Punkt C berechnen double winkel2 = winkel * (Math.PI / 180); double Cx = this.CenterX + Math.Cos(winkel2) * rInnen; double Cy = this.CenterY + Math.Sin(winkel2) * rInnen; PointF C = new PointF((float)Cx, (float)Cy); PointF B = path.GetLastPoint(); path.AddLine(B, C); //B-C path.AddArc(recInnen, winkel, -winkel); //Bogen C-D path.CloseFigure(); //D-A for (int i = 1; i <= anzBlinken; i++) { //Die Farbe muss jedes Mal neu gesetzt werden, weil sie sonst beim Update verfälscht wird _MyPen.Color = backColor; _MyBrush.Color = backColor; g.FillPath(_MyBrush, path); g.DrawPath(_MyPen, path); foMain.wait(500); while (arena.myArena.isPause) { Application.DoEvents(); if (!AnimationIsRunning) { return; } } if (!AnimationIsRunning) { return; } arena.update(); foMain.wait(500); while (arena.myArena.isPause) { Application.DoEvents(); if (!AnimationIsRunning) { return; } } if (!AnimationIsRunning) { return; } } AnimationIsRunning = false; } //Ende Methode blinkRings
} //Ende Methode animateClearRingsTrapez /// <summary> /// Animation: Die vollen Zeilen werden gelöscht /// </summary> /// <param name="positionSchicht">Die oberste Schicht, wo das Teil liegt</param> /// <param name="g">Graphics-Objekt zum Zeichnen</param> /// <param name="backColor">Hintergrundfarbe zum Löschen</param> /// <param name="lines">Gibt an, welche Zeilen voll sind</param> /// <param name="arena">Verweis auf die Arena (nötig für Reparatur)</param> public void animateClearLines(int positionSchicht, Graphics g, Color backColor, bool[] lines, TVisualArena arena) { if (Mode == EDisplayMode.Ring) { animateClearRings(positionSchicht, g, backColor, lines, arena); } else if (Mode == EDisplayMode.Trapez) { animateClearRingsTrapez(positionSchicht, g, backColor, lines, arena); } }
} //Ende Methode clearRings /// <summary> /// Animation: Die vollen Trapez-Zeilen werden gelöscht /// </summary> /// <param name="positionSchicht">Die oberste Schicht, wo das Teil liegt</param> /// <param name="g">Graphics-Objekt zum Zeichnen</param> /// <param name="backColor">Hintergrundfarbe zum Löschen</param> /// <param name="lines">Gibt an, welche Zeilen voll sind</param> /// <param name="arena">Verweis auf die Arena (nötig für Reparatur)</param> private void animateClearRingsTrapez(int positionSchicht, Graphics g, Color backColor, bool[] lines, TVisualArena arena) { AnimationIsRunning = true; this._TrapezData.positionSchicht = positionSchicht; this._TrapezData.backColor = backColor; this._TrapezData.lines = lines; this._TrapezData.isActive = true; //Pfade zum Reparieren bestimmen List <int> repairLines = findLinesToRepair(lines, positionSchicht); List <GraphicsPath> repairPaths = new List <GraphicsPath>(1); int m = repairLines.Count; for (int l = 0; l < m; l++) { arena.getRepairPaths(repairLines[l], repairPaths); } Pen myPenRepair = new Pen(Color.Black); PointF Center = new PointF(this.CenterX, this.CenterY); double r = SegmentBreite; float alpha = (float)berechneAlpha(); float degree = 1 * (float)Math.PI / 180; int n = lines.Length; //Für alle Sektoren for (int i = 0; i < TArena.AnzahlSektoren; i++) { this._TrapezData.CurrentSektor = i; float angle = i * alpha; float end = angle + alpha; //Für Winkelstücke kleiner Alpha while (angle < end) { for (int k = 0; k < n; k++) { if (lines[k]) { PositionSektor = i; PositionSchicht = positionSchicht - k; //Punkte berechnen PointF A = berechnePunktA(); PointF B = berechnePunktB(); PointF C = berechnePunktC(); PointF D = berechnePunktD(); //Punkt auf Kreis berechnen double x = this.CenterX + Math.Cos(angle + Shift) * r; double y = this.CenterY + Math.Sin(angle + Shift) * r; PointF pCircle = new PointF((float)x, (float)y); //Schnittpunkte berechnen PointF S1 = calcSchnittpunkt(Center, pCircle, A, B); PointF S2 = calcSchnittpunkt(Center, pCircle, C, D); //Pfad erstellen GraphicsPath path = new GraphicsPath(); path.AddLine(A, S1); path.AddLine(S1, S2); path.AddLine(S2, D); path.AddLine(D, A); //UNDONE: Man müsste auch die Trapeze neu löschen //Farbe jedes Mal neu setzen (nötig, wenn das Fenster zwischendurch minimiert wird) _MyPen.Color = backColor; _MyBrush.Color = backColor; //Pfad löschen g.FillPath(_MyBrush, path); g.DrawPath(_MyPen, path); //Reparieren int anz = repairPaths.Count; for (int loop = 0; loop < anz; loop++) { GraphicsPath pathRepair = repairPaths[loop]; g.DrawPath(myPenRepair, pathRepair); } //kurz warten foMain.wait(10); while (arena.myArena.isPause) { Application.DoEvents(); if (!AnimationIsRunning) { return; } } if (!AnimationIsRunning) { return; } //Nächster Winkel angle += degree; } } } //Den letzten Rest löschen (es entstehen sonst unschöne Ränder) for (int k = 0; k < n; k++) { if (lines[k]) { PositionSchicht = positionSchicht - k; deleteSegment(PositionSektor, PositionSchicht, g, backColor); } } } AnimationIsRunning = false; this._TrapezData.isActive = false; } //Ende Methode animateClearRingsTrapez
} //Ende Methode findLinesToRepair /// <summary> /// Animation: Die vollen Ring-Zeilen werden gelöscht /// </summary> /// <param name="positionSchicht">Die oberste Schicht, wo das Teil liegt</param> /// <param name="g">Graphics-Objekt zum Zeichnen</param> /// <param name="backColor">Hintergrundfarbe zum Löschen</param> /// <param name="lines">Gibt an, welche Zeilen voll sind</param> /// <param name="arena">Verweis auf die Arena (nötig für Reparatur)</param> private void animateClearRings(int positionSchicht, Graphics g, Color backColor, bool[] lines, TVisualArena arena) { AnimationIsRunning = true; //Pfade zum Reparieren bestimmen List <int> repairLines = findLinesToRepair(lines, positionSchicht); List <GraphicsPath> repairPaths = new List <GraphicsPath>(1); int m = repairLines.Count; for (int l = 0; l < m; l++) { arena.getRepairPaths(repairLines[l], repairPaths); } Pen myPenRepair = new Pen(Color.Black); int n = lines.Length; //Radien berechnen float[] rInnen = new float[n]; for (int i = 0; i < n; i++) { int schicht = positionSchicht - i; rInnen[i] = (float)(schicht * this.SegmentBreite); } float[] rAussen = new float[n]; for (int i = 0; i < n; i++) { int schicht = positionSchicht - i; rAussen[i] = (float)((schicht + 1) * this.SegmentBreite); } //Rechtecke berechnen RectangleF[] recInnen = new RectangleF[n]; for (int i = 0; i < n; i++) { float r = rInnen[i]; recInnen[i] = new RectangleF( this.CenterX - r, this.CenterY - r, 2 * r, 2 * r); } RectangleF[] recAussen = new RectangleF[n]; for (int i = 0; i < n; i++) { float r = rAussen[i]; recAussen[i] = new RectangleF( this.CenterX - r, this.CenterY - r, 2 * r, 2 * r); } for (int winkel = 1; winkel <= 360; winkel++) { for (int k = 0; k < n; k++) { if (lines[k]) { //Pfad berechnen GraphicsPath path = new GraphicsPath(); path.AddArc(recAussen[k], 0 + ShiftDegree, winkel); //Bogen A-B //Punkt C berechnen double winkel2 = winkel * (Math.PI / 180); double Cx = this.CenterX + Math.Cos(winkel2 + Shift) * rInnen[k]; double Cy = this.CenterY + Math.Sin(winkel2 + Shift) * rInnen[k]; PointF C = new PointF((float)Cx, (float)Cy); PointF B = path.GetLastPoint(); path.AddLine(B, C); //B-C path.AddArc(recInnen[k], winkel + ShiftDegree, -winkel); //Bogen C-D path.CloseFigure(); //D-A //Farbe jedes Mal neu setzen (nötig, wenn das Fenster zwischendurch minimiert wird) _MyPen.Color = backColor; _MyBrush.Color = backColor; g.FillPath(_MyBrush, path); g.DrawPath(_MyPen, path); } } //Reparieren int anz = repairPaths.Count; for (int loop = 0; loop < anz; loop++) { GraphicsPath path = repairPaths[loop]; g.DrawPath(myPenRepair, path); } //kurz warten foMain.wait(10); while (arena.myArena.isPause) { Application.DoEvents(); if (!AnimationIsRunning) { return; } } if (!AnimationIsRunning) { return; } } AnimationIsRunning = false; } //Ende Methode clearRings
} //Ende Methode blinkRings /// <summary> /// Der Spieler hat einen Tetris gemacht. Die vollen Trapeze blinken, bevor sie gelöscht werden /// </summary> /// <param name="positionSchicht">Die oberste Schicht, wo das Teil liegt</param> /// <param name="g">Graphics-Objekt zum Zeichnen</param> /// <param name="backColor">Hintergrundfarbe zum Löschen</param> /// <param name="arena">Verweis auf die Arena</param> private void blinkTrapez(int positionSchicht, Graphics g, Color backColor, TVisualArena arena) { AnimationIsRunning = true; GraphicsPath path = new GraphicsPath(); //Pfad innen int schichtInnen = positionSchicht - TTeil.MaxHoehe + 1; int n = TArena.AnzahlSektoren; double alpha = 2 * Math.PI / TArena.AnzahlSektoren; List <PointF> EckpunkteInnen = new List <PointF>(n); double rInnen = schichtInnen * this.SegmentBreite; //Eckpunkte innen for (int i = 0; i < n; i++) { double phi = i * alpha; double x = this.CenterX + Math.Cos(phi) * rInnen; double y = this.CenterY + Math.Sin(phi) * rInnen; PointF p = new PointF((float)x, (float)y); EckpunkteInnen.Add(p); } //Pfad innen for (int i = 0; i < n - 1; i++) { PointF a = EckpunkteInnen[i]; PointF b = EckpunkteInnen[i + 1]; path.AddLine(a, b); } path.CloseFigure(); //Pfad aussen List <PointF> EckpunkteAussen = new List <PointF>(n); double rAussen = (positionSchicht + 1) * this.SegmentBreite; for (int i = n; i >= 0; i--) { double phi = i * alpha; double x = this.CenterX + Math.Cos(phi) * rAussen; double y = this.CenterY + Math.Sin(phi) * rAussen; PointF p = new PointF((float)x, (float)y); EckpunkteAussen.Add(p); } //Pfad aussen PointF last = path.GetLastPoint(); path.AddLine(last, EckpunkteAussen[0]); for (int i = 0; i < EckpunkteAussen.Count - 1; i++) { PointF a = EckpunkteAussen[i]; PointF b = EckpunkteAussen[i + 1]; path.AddLine(a, b); } path.CloseFigure(); //Blinken for (int i = 1; i <= anzBlinken; i++) { //Die Farbe muss jedes Mal neu gesetzt werden, weil sie sonst beim Update verfälscht wird _MyBrush.Color = backColor; _MyPen.Color = backColor; g.FillPath(_MyBrush, path); g.DrawPath(_MyPen, path); foMain.wait(500); while (arena.myArena.isPause) { Application.DoEvents(); if (!AnimationIsRunning) { return; } } if (!AnimationIsRunning) { return; } arena.update(); foMain.wait(500); while (arena.myArena.isPause) { Application.DoEvents(); if (!AnimationIsRunning) { return; } } if (!AnimationIsRunning) { return; } } AnimationIsRunning = false; } //Ende Methode blinkTrapez
/// <summary> /// Registriert eine Arena /// </summary> /// <param name="arena">Die zu registrierende Arena</param> public override void registerArena(TVisualArena arena) { this._Arena = arena; this._Segment.registerArena(arena.myArena); }
/// <summary> /// Registriert eine Arena /// </summary> /// <param name="arena">Die zu registrierende Arena</param> public virtual void registerArena(TVisualArena arena) { this._Arena = arena; }
/// <summary> /// Registriert eine Arena für die visuelle Darstellung /// </summary> /// <param name="a">Die zu registrierende Arena</param> public void registerArena(TVisualArena a) { this.myVisual = a; this._MyDisplay.registerArena(a); }