Autor Beitrag
YK18415
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 16:25 
Hallo zusammen,

ich habe zwar schon was in WinForms programmiert, dennoch bin ich ein ziemlicher Anfänger. :)

Ich möchte ein Asteroid-Spiel programmieren. Dazu zeichne ich ein Raumschiff (Dreieck) und Asteroiden (Kreise) in einer pictureBox. Das funktioniert ja auch. Um z. B. die Asteroiden bewegen zu lassen, benutze ich einen Timer, der immer nach einer bestimmten Zeit die Y-Koordinate des Kreises verschiebt (dadurch soll er sich nach unten bewegen).
Mein Vorgehen: Ich ziehe den Timer aus der Toolbox einfach auf meine Form und stelle "Enabled" auf True. "Modifiers" steht bei mir auf Private. Nun klicke ich doppelt auf den Timer, wodurch dieser in Form1.cs erscheint und ich Code schreiben kann.

Mein Problem:
Leider geht der Programmablauf gar nicht erst in diesen Timer-Code hinein... Ich frage mich wieso?


Mein Timer-Code:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
  private void timer1_Tick(object sender, EventArgs e)
        {
            foreach (Object item in listBox1.Items)
            {
                Asteroid asteroid = item as Asteroid;

                if (item is Asteroid)
                {
                    asteroid.Y += 20;
                }
               
            }
            pictureBox1.Refresh();
        }



Über Hilfe würde ich mich sehr freuen :D

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 03.01.17 16:59 
Zitat:
Leider geht der Programmablauf gar nicht erst in diesen Timer-Code hinein... Ich frage mich wieso?


Hast du das per Debugger rausgefunden? Also weil ein Breakpoint in der Methode nicht gezogen hat oder z.B. nur weil du keine Reaktion auf deiner Form gesehen hast?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 03.01.17 16:59 
Auf welchen Wert steht die Interval-Eigenschaft (also die Zeit in Millisekunden, die der Timer jeweils ausgelöst werden soll)?
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 17:04 
Mein Interval steht auf 1000 ms @Th69

@Ralf Jansen: Beides hat nicht funktioniert. Also es gab keine Reaktion auf der Form und der Debugger ist nicht bis zum Breakpoint gekommen.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 03.01.17 17:11 
Zu deiner Form1 solltest du auch eine Form1.Designer.cs Datei finden. Darin wirst du Code finden der dem Zusammensetzen des timers entspricht.
Solle ungefähr so in der Datei aussehen.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
// 
// timer1
// 
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//


Zeig uns mal bitte wie das bei dir aussieht.
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 17:14 
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
// 
// timer1
// 
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);


Bei mir sieht es genau so aus.

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 03.01.17 17:21 
Dann sollten wir erstmal davon ausgehen das der auch aufgerufen wird. Wo hast du in der Methode den Breakpoint beim Debuggen gesetzt? Probier mal den direkt auf die öffnende Klammer der Methode zu setzen.
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 17:38 
Das habe ich getan. Allerdings wird dieser Breakpoint, wenn ich auf F11 oder auch auf F5 drücke, nie abgerufen...

Eben gerade hatte ich das Ereignis, dass mein Kreis doch plötzlich an einer anderen Stelle der pictureBox war, allerdings habe ich diese "Animation" nicht gesehen, da ich mit dem Debugger zur Laufzeit beschäftigt war. Als ich dann alle Breakpoints entfernt habe und ich zur Laufzeit wieder F5 drückte, bewegte sich der Kreis nicht, obwohl er doch irgendwie "gewandert" sein muss???
Könnte es sein, das mein Laptop einfach zu langsam ist, um die Bewegung anzuzeigen?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 03.01.17 17:57 
Von hier schwer zu sagen. Kommt drauf an wie das konkrete Zeichnen von dir gelöst ist. Den Code kennen wir aber nicht.
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 18:08 
Mein Quellcode:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Asteroids_Game_Neu.Properties;
using System.Threading;
using System.Timers;

namespace Asteroids_Game_Neu
{
    public partial class Form1 : Form
    {
       
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonPlay_Click(object sender, EventArgs e)
        {
            Asteroid asteroid = new Asteroid() { x = 300, y = 0, height = (int)numericUpDown1.Value, width = (int)numericUpDown1.Value };
            listBox1.Items.Add(asteroid);
            pictureBox1.Refresh();
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            foreach (Object item in listBox1.Items)
            {
                Asteroid asteroid = item as Asteroid;
                if (item is Asteroid)
                {
                    asteroid.Draw(e.Graphics);
                }
            }
            pictureBox1.Refresh();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            foreach (Object item in listBox1.Items)
            {
                Asteroid asteroid = item as Asteroid;

                if (item is Asteroid)
                {
                    asteroid.Y += 20;
                }
               
            }
            pictureBox1.Refresh();
        }
    }
}

Zum Zeichnen der Asteroiden habe ich eine extra Klasse erstellt, die die Draw-Methode von meiner Basisklasse überschreibt (weil ich ja noch andere Objekte wie z. B. Raumschiffe usw. zeichnen möchte).
Die Größe des Asteroiden bestimme ich über einen numericUpDown auf meiner Form zur Laufzeit. Wenn ich den button "Play" drücke, wird ein Asteroid gezeichnet und ab da sollte eigentlich auch der Timer laufen...


Es wäre wirklich sehr nett, wenn einer eine Idee hätte, wie ich das Problem mit dem Timer lösen könnte. :D

Danke! ^^

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 03.01.17 18:55 
Ohne da jetzt länger drauf geguckt zu haben fällt mir nur eins auf. Du rufst im Paint Event der PictureBox Refresh der PictureBox auf. Ich bezweifle das das eine gute Idee ist. Also beim zeichnen der PictureBox der PictureBox zu sagen es soll sich doch mal bitte neuzeichnen(und damit erneut ein Paint Event auszulösen). Nimm das zumindest mal raus.
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 19:10 
Danke erstmal für deine Hilfe @Ralf Jansen. :)

Wenn ich das aber rausnehme, wie genau kann dann der Kreis verschoben werden? Ich meine, wenn die pictureBox nicht neugezeichnet wird, bleibt der Kreis doch immer an der gleichen Stelle, auch wenn der Timer aktiv ist? Oder verstehe ich da was grundlegend falsch...?
Was sollte ich stattdessen benutzen? Die Methode Invalidate? Aber ist die nicht so ziemlich das Gleich wie Refresh?


Gruß

YK18415
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 03.01.17 19:24 
Nur in der Paint-Methode diese Methode entfernen, in den anderen ist sie korrekt.

PS: Du verwendest sowohl as als auch is (das ist doppeltgemoppelt) - besser:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
Asteroid asteroid = item as Asteroid;

if (asteroid != null)
{
  // ...
}
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 19:33 
Ahhhh, jetzt funktioniert es! :D
Tatsächlich musste ich nur die Refresh-Methode in der Paint-Methode entfernen... :o
Das mit der Abfrage habe ich nun auch korrigiert, stimmt, wäre ja wirklich doppelt... :o


Dankeschön!!! :D
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 03.01.17 20:02 
Zur Erklärung: Du hattest eine Endlos-Rekursion beim Zeichnen und deswegen konnte die Timer-Methode nicht aufgerufen werden.
YK18415 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 03.01.17 20:04 
Ja, hätte ich eigentlich schon beim debuggen merken müssen... :/
Naja, aus Fehlern lernt man. ^^

Danke!