this.CreateGraphics() flackert, ausweichen auf e.Graphics im PaintEvent nicht möglich.



  • Hallo,

    Der komplette Quellcode sieht folgendermaßen aus:

    struct Player
        {
            public float Angle;
            public Color clr;
    
            public void DrawCannon(Graphics g)
            {
                g.TranslateTransform(100, 250);
                g.RotateTransform(Angle);
                g.DrawLine(new Pen(clr, 10), 0, 0, 50, 0);
                //g.Dispose();
            }
        }
    
        public partial class Form1 : Form
        {
            Player player1;
            Player player2;
    
            public Form1()
            {
                InitializeComponent();
                this.DoubleBuffered = true;
                this.FormBorderStyle = FormBorderStyle.FixedSingle;
                this.MaximizeBox = false;
                this.Size = new Size(500, 500);
    
                this.Paint += new PaintEventHandler(Form1_Paint);
                this.KeyDown += new KeyEventHandler(Form1_KeyDown);
    
                player1 = new Player();
                player1.clr = Color.Green;
                player1.Angle = 0;
                player2 = new Player();
                player2.clr = Color.Red;
                player2.Angle = 0;
    
                Timer timer = new Timer();
                timer.Interval = 1;
                timer.Enabled = true;
                timer.Tick += new EventHandler(timer_tick);
            }
    
            void Form1_Paint(object sender, PaintEventArgs e)
            {
            }
    
            void Form1_KeyDown(object sender, KeyEventArgs e)
            {
                switch (e.KeyCode)
                { 
                    case Keys.Right:
                        player1.Angle--;
                        break;
                    case Keys.Left:
                        player1.Angle++;
                        break;
                    case Keys.S:
                        player2.Angle--;
                        break;
                    case Keys.A:
                        player2.Angle++;
                        break;
                }
            }
    
            void timer_tick(object o, EventArgs e)
            {
                player1.DrawCannon(this.CreateGraphics());
                player2.DrawCannon(this.CreateGraphics());
                this.Invalidate();
            }
        }
    

    Ich versuche hier zwei Linien(eine rot und eine grün) unabhängig voneinader zu bewegen, würde ich auf das Paint-Event zurückgreifen, so würde ich nur auf eine Graphics-Instanz zugreifen können.Wenn ich von dieser Instanz aus allerdings zum Beispiel die Methode RotateTransform für die eine Linie aufrufen, muss ich, um eine Drehung um den Ausgangspunkt der Linie zu gewährleisten, zuerst TranslateTransform() aufrufen, um entweder den Ausgangspunkt der Linie auf diese Koordinaten zu zeichnen oder die Koordinaten von TranslateTransform() dem Ausgangspunkt der Linie anzupassen, was allerdings, sobald ich die zweite Linie drehen will(deren Position ungleich der der ersten Linie ist[<-Springender Punkt]) nicht um den Ausgangspunkt von sich selbst gedreht wird, sondern um den der ersten Linie. Im Prinzip wäre dies kein Problem, wenn ich "rundenbasiert" arbeiten würde. Da ich aber simultan und unabhängig voneinader die Linien drehen will, funktioniert mein jetziger Ansatz nicht mehr.

    Meine Fragen sind:

    Wie kann ich die Linien unabhängig voneinader drehen, ohne ein "Flickern" hervorzurufen?

    Ist es möglich zwei parallele Tasteneingaben parallel zu verarbeiten, denn in meinem Fall wird, sobald eine zweite, andere, Taste gedrückt wird, die zuvorige Eingabe verworfen.

    Sollte ich lieber auf XNA oder Ähnliches umsteigen, wenn ich versuche ein "CannonHill(http://www.freegamesite.de/freegame/download/Cannon-Hill/23.htm)"-Ähnliches spiel zu programmieren(Tutorial wäre da(http://www.riemers.net/eng/Tutorials/XNA/Csharp/series2d.php))?



  • So ich sehe das nun etwas länger und will, obwohl ich ein Anfänger bin helfen.
    Mit dem Flickern kann ich dir leider nicht helfen, aber mit den unabhängigen Bewegen.

    Ich habe es bei mir meistens so gelöst: Ich habe eine Variable genommen und die hatte von Anfang an den Wert 0. Wenn nun eine Taste gedrückt wird zB -> dann ist diese Variable 1, wenn <- gedrückt wird ist diese Variable 2. Dies alles geschieht in einen KeyDown Event.Nun lasst man nebenbei immer einen Timer laufen der prüft welchen Wert diese Variable hat und dementsprechend handelt. Wird nun diese Taste losgelassen, bekommt diese Variable einfach ind dem KeyUp Event den Wert 0 zugesprochen.

    Also in deinen Code hätte ich das so umgesetzt:

    Erstmal der Anfang:

    public partial class Form1 : Form
        {
            Player player1;
            Player player2;
            public int Player1Bewegung;
            public int Player2Bewegung;
    

    Dann das KeyDown Event:

    void Form1_KeyDown(object sender, KeyEventArgs e)
            {
                switch (e.KeyCode)
                {
                    case Keys.Right:
                        Player1Bewegung = 1;
                        break;
                    case Keys.Left:
                        Player1Bewegung = 2;
                        break;
                    case Keys.S:
                        Player2Bewegung = 1;
                        break;
                    case Keys.A:
                        Player2Bewegung = 2;
                        break;
                }
            }
    

    Dann muss noch beim Fenster ein KeyUp Event hinzgefügt werden(Kein extra Code weil ich glaube, dass du das kannst^^

    Dann im Timer:

    void timer_tick(object o, EventArgs e)
            {
                if (Player1Bewegung == 1)
                    player1.Angle--;
                if (Player1Bewegung == 2)
                    player1.Angle++;
                if (Player2Bewegung == 1)
                    player2.Angle--;
                if (Player2Bewegung == 2)
                    player2.Angle++;
                player1.DrawCannon(this.CreateGraphics());
                player2.DrawCannon(this.CreateGraphics());
                this.Invalidate();
            }
    

    Und abschließend noch das KeyUp event:

    void Form1_KeyUp(object sender, KeyEventArgs e)
            {
                switch (e.KeyCode)
                {
                    case Keys.Right:
                        Player1Bewegung = 0;
                        break;
    
                    case Keys.Left:
                        Player1Bewegung = 0;
                        break;
    
                    case Keys.S:
                        Player2Bewegung = 0;
                        break;
    
                    case Keys.A:
                        Player2Bewegung = 0;
                        break;
    
                }
            }
    

    So habe ich es in meinen Programmen meistens gelöst. Es gibt noch irgendeine Funktion Flag oder so(ich editiere Link noch rein), aber mit dem kenne ich mich selber noch nicht aus^^

    Ich hoffe ich habe jetzt keinen Blödsinn geschrieben, aber bei mir hat es funktioniert( halt mit Flackern)
    Und ich denke nicht, dass mein Code die beste Variante ist, aber notfalls gehts.

    mfg Mongole


Log in to reply