Button wie Ping Pong abprallen lassen.



  • Hallo.

    Ich habe mich mal an einem kleinen Programm versucht, dass so wie Ping Pong gehen soll.
    Ich habe die Koordinaten von einem Button (Y, 😵 und mag ihn halt ständig so geheen lassen ( X-1, Y -1).
    Das funktioniert ja halbwegs.
    Nun möchte ich, dass wenn der Button auf der X Korrdinate auf 0 steht, dass sich X-1 zu X+1 ändert.
    Genau das selbe bei Y.
    Vom rechten und vom unteren Rand abzuprallen habe ich mir noch nicht überlegt, weil ich als erster Das schaffen will.

    Ich habe das ganze versucht mit einem Timer zu regeln(Intervall 100 ms), aber irgendwas mache ich falsch.
    Um die ständige Bewegung hinzukriegen habe ich alles in eine for Schleife gepackt.

    So sieht im Moment mein Code aus:

    private void timer1_Tick(object sender, EventArgs e)
            {
                Point location = this.button1.Location;
    
                for (int p = 1; p >= 0; p++)
                {
                    this.button1.Location = new Point(location.X - 1, location.Y - 1);
                    if (location.X == 0)
                        this.button1.Location = new Point(location.X + 1, location.Y + 1);
                    if (location.Y == 0)
                        this.button1.Location = new Point(location.X + 1, location.Y + 1);
                }
    
            }
    

    mfg Mongole



  • Und welche konkreten Fragen und Probleme hast du jetzt?



  • Der Button bewegt sich immer nur bis er ansteht und ändert seine Richtug dann nicht. Bei diesem Code bewegt der Button sich garnicht.
    Ich hatte vorher nämlich die X Koordinate statt P verwendet.
    Aber da ich so nicht beide gleichzeitig bewegen kann habe ich es so versucht.

    Problem: Button bewegt sich nicht oder prallt nicht ab.

    Frage: Wie sollte ich das ganze Anfangen? Den Timer und die for Schleife lassen oder doch etwas anderes.

    mfg Wandernder Mongole



  • Wenn du eine for-Schleife verwendest siehst du keine Bewegung, da das Fenster nicht neugezeichnet wird, so lange du in der Schleife steckst. (Ausgenommen du würdest ein Neuzeichen erzwingen, was ich allerdings für unsauber halte.) Deswegen solltest du die for-Schleife ganz weglassen und nur mit dem Timer-Tick arbeiten.

    Du solltest bei jedem Timer-Tick die Position des Buttons um einen festen Wert verschieben. Dabei ist es sinnvoll die Bewegung auf x- und y-Richtung aufzuteilen.
    Erreicht der Button eine "Wand" so kehrst du die Bewegung in die entsprechnde Richtung einfach um. (linke & rechte Wand die Bewegung in x-Richtung, oben & unten respektive)

    Wie du das in Code umsetzt überlasse ich mal dir. Wir wollen ja schließlich, dass du etwas lernst bei der Sache. 😃



  • Ich wollte das ganze jetzt wieder unprofessionel mit weiteren Timern lösen.
    Dies ist aber ziemlich kompliziert da ich für jede Art von aufkommen einen neuen Timer benötige.
    Und ein Problem ist noch wenn der Button die Position X == 0 erreicht. Da fährt der Button einfach in die Richtung weiter xD
    Mein Code

    private void timer1_Tick(object sender, EventArgs e)
            {
                Point location = this.button1.Location;
    
                this.button1.Location = new Point(location.X - 1, location.Y - 1);
    
                if (location.X == 0)
                {
                    timer2.Start();
                    timer1.Stop();
                }
                if (location.Y == 0)
                {
                    timer3.Start();
                    timer1.Stop();
                }
    
                    }
    
            private void timer2_Tick(object sender, EventArgs e)
            {
    
                Point location = this.button1.Location;
    
                this.button1.Location = new Point(location.X + 1, location.Y - 1);
            }
    
            private void timer3_Tick(object sender, EventArgs e)
            {
                Point location = this.button1.Location;
    
                this.button1.Location = new Point(location.X - 1, location.Y + 1);
            } 
    
            }
    

    Gibt es irgendeine möglichkeit ur mit einem Timer zu Arbeiten.
    Ich habe das schon so probiert:

    private void timer1_Tick(object sender, EventArgs e)
            {
                Point location = this.button1.Location;
    
                    if (location.X == 0)
                        this.button1.Location = new Point(location.X + 1, location.Y + 1);
                    if (location.Y == 0)
                        this.button1.Location = new Point(location.X + 1, location.Y + 1);
                    else
                this.button1.Location = new Point(location.X - 1, location.Y - 1);
                    } 
    
            }
    

    Aber da ist mir aufgefallen, dass der Button eig nur einmal die Pos X == 0 hat und so nicht funktionieren konnte.

    Kann man das irgendwie trotzdem mit nur einem Timer lösen.

    Oder hat du gemeint, dass ich das mit mehreren machen solL? 😃

    mfg Mongole^^



  • Problem 1 gelöst.

    Es wurde immer nur der 2te Timer ausgelöst aber vom 2 Timer aus nicht der Dritte^^

    Geht das aber nicht irgendwie einfacher?

    Mfg Areusus



  • Nun habe ich das ganze mit dem Button abprallen lassen geschafft.

    Nun habe ich einen Balken(auch ein Button^^) der sozusagen ein Hinderniss darstelt.
    Der Balken ist länger als der sich bewegende Button und ich möchte, dass wenn er gegen den Balken fährt sich in die entgegengesetzte Richtung bewegt.
    Das alles wäre ja kein großes Problem, aber wenn ich das so mache:

    if (this.button1.Location == this.button2.Location)
                    this.button1.Location = new Point(location.X - 1, location.Y);
    

    Dann passiert dieses EReigniss nur, wenn der Button1 genau in der Mitte vom Button 2 ist. Sonst geht er einfach durch.

    Kann ich das irgendwie programmieren, dass wenn der Button den Balken an irgendeiner Stelle berührt, der Button in die andere Richtug fährt?
    Mir geht es nur um das Ereigniss wenn der Button auf den Balken trifft. Den Rest habe ich schon einigermaßen zusammengebracht.

    mfg Mongole



  • warum verschiedene timer ?? versteh ich nicht
    speicher doch eine direction ab

    pseudo:

    private int X = 1;
    private int Y = 1;
    
    private void OnTimer()
    {
        if button on wall on the top or below then
            Y *= -1; // change direction
        if button on wall on the left or right then
            X *= -1; // change direction
    
        button.pos.Y += Y;
        button.pos.X += X;
    }
    

    du brauchst nur wissen wie die richtung war - sobald dann irgendwo eine wand auf taucht - musst du die entsprechende richtung einfach umkehren
    geht alles in einen timer



  • Leider weiß ich nicht wie eine Direction funktioniert

    if (this.button1.Location == this.button2.Location)
                    this.button1.Location = new Point(location.X - 1, location.Y);
    

    Warum ist es dort genau 1? Ich dachte x wäre die Position vom Button. Muss nicht 1 sein^^

    Undwarum#
    ist da ein *

    if button on wall on the top or below then
            Y *= -1; // change direction
    

    Gehört das ganze noch zum Grundkurs?

    Ich habe den eig schon gemacht, aber sowas weiß ich zB ned^^
    WEnn ja wo kann ich das nachlesen?

    mfg Mongolide^^



  • Ahh jetzt weiß ich was du meinst. Sry.

    Ich werde das mal testen.

    thx und mfg Mongole



  • Sry wegegen dem MehrfachPost^^

    Ich habe ein Problem. Da mein "Baken" größer ist als der button der sich bewegt, kann ich nicht einfach schreiben if(location.Button1 == location.button2) WEil der button 1 sonst genau in der Mitte sein müsste.

    Wie kann ich das machen?

    mfg



  • einfach die dicke des balkens durch 2 dazu addieren - schon hast du den auesseren rand

    zb
    rand rechts = balken.center + (balken.dicke / 2)
    rand links = balken.center - (balken.dicke / 2)
    rand oben = balken.center + (balken.hoehe / 2)
    rand unten= balken.center - (balken.hoehe / 2)

    wegen der richtung hast du verstanden?
    falls nicht nochmal genauer

    jede richtung wird jeweils um ein wert erhoeht - zb 1 fuer nach links und 1
    fuer nach oben
    dirX = 1;
    dirY = 1;

    pos.X += dirX;
    pos.Y += dirY;

    nun trifft der ball auf eine wand - also muss die jeweilige richtung umgekehrt werden

    dirX *= -1;
    dirY *= -1;
    (wert mal -1 kehrt ihn um)

    feddich ist
    wenn du irgendwann die "geschwindigkeit" erhoehen willst, brauchst du nur dirX und dirY einen hoeheren wert zuweisen



  • Vielen Dank.

    ja ich habe es jetzt kapiert.

    Ich war nur verwundert warum *= -1 aber ich habe dann eh verstanden, dass damit die richtung umgekehrt wird.

    mfg Mongole.

    Vll habe ich noch andere Fragen, aber soweit ist alles Klar^^



  • Nein eins verstehe ich immer noch nicht.

    ICh weiß jetzt die Balken Dicke usw.

    Aber wie kann ich es jetzt machen, dass es nur am Balken abpralllet?

    WEnn ich das so eingebe:

    if(location.X == balken.seite.rechts)
    tue was;
    

    Dann prallt er immer ab wenn er auf gleicher Linie ist wie der Balken. Auch wenn er darüber ist.
    Gibts da nen extra WEg ohne jede Mögliche Koordinatenpaarungen durchzugehen?

    mfg Wandelnder Mongole



  • Das Problem habe ich nun auch gelöst^^

    Aber ich habe jetzt versucht das ganze so zu machen, dass man den Balken bewegen kann.

    Dies habe ich, um nicht dauernd die Taste zu drücken, dass sich der Button bewegt, mit einem Timer versucht.

    Der ERgebnisscode wäre bei mir der:

    private void timer1_Tick(object sender, EventArgs e)
            {
    
                Point location = this.button1.Location;
                switch(e.KeyCode) 
                {
                    case Keys.Up:
                        this.button1.Location = new Point(location.X, location.Y - 1);
                        break;
    
                    case Keys.Down:
                        this.button1.Location = new Point(location.X, location.Y + 1);
                        break;
    
                }
            }
    

    Aber nun erkennt er e.KeyCode nicht.
    "System.EventArgs" enthält keine Definition für "KeyCode", und es konnte keine Erweiterungsmethode "KeyCode" gefunden werden, die ein erstes Argument vom Typ "System.EventArgs" akzeptiert. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)

    Das ist die Fehlermeldung.

    Ich weiß nun aber nicht, was ich stattdessen verwenden soll.

    ODer gibt es eine noch bessere Methode?

    mfg Wandelnder Mongole



  • also ich hab keine ahnung von spiele programmierung aber ich find die idee gut ein timer laufen zu lassen der den button bewegt bei bedarf

    keyboard events werden nicht in timern weiter geleitet
    nimm statt dessen die statische funktion

    Keyboard.IsKeyDown(Key.Down)
    Keyboard.IsKeyDown(Key.Up)
    

    dann kannst du entsprechend reagieren
    ------------

    ich moechte dich nicht rein reden, nur, wie hast du dein design? loest du alles direkt mit buttons und location?

    ich wuerde es so gestalten
    es gibt ein "balken" objekt, das erfaehrt wie tief und wie hoch er maximal darf sowie wie weit er sich bewegen darf, und er definiert eine "Area", das ist der bereich den der button einnimmt
    das selbe mit den waenden - diese definieren ebenfalls eine Area
    dann gibts ein objekt "Ball" - welches auch eine Area definiert - bietet sich also an das alle 3 objekte vom selben parent erben

    wenn der ball sich dann bewegt hat - kannst du fragen wie die neue richtung ist
    z.B.:

    if(Balken.Area.Cross(Ball.Area))
        Y = Balken.Area.Direction;
    if(Wall.Area.Cross(Ball.Area))
        X = Wand.Area.Direction;
    

    und wenn du es ganz simpel machen moechtest dann

    Y = Balken.Area.NewDirection(Ball.Area);
    X = Wand.Area.NewDirection(Ball.Area);
    

    dann prueft die Area selber ob die uebergebene area im eigenen bereich ist - wenn ja wird die umgekehrte richtung an gegeben

    animation des ball flugs in einem timer, und die der tasten drucke auch in einen eigenen - da kannst du ja sowas machen

    Ball.Move(X, Y);
    Balken.Move(X, Y);
    

    sobald du das alles design technisch n bissl umgesetzt hast, dann brauchst du keine buttons mehr sondern kannst andere objekte nehmen - zb rectangles fuer balken und waende und eine ellipse fuer den ball - buttons sind eigentlich eh unnuetz da du keine button funktionalitaet brauchst
    farben - formen - groessen usw brauchst du dann nur noch beim erstellen der spielflaeche definieren - die das eigentliche objekt und die Areas nehmen es an und arbeiten dann damit - dann hast du die magic numbers auch reduziert

    alles nur ansaetze die ich gehen wuerde - wie gesagt ich moechte dir nicht rein reden {o; (wobei das hier alles nur pseudo ist, hab ich mich grossteils beim tippen ausgedacht #gg)



  • Okay.
    Da verstehe ich jetzt einiges nicht.

    Ich soll also nun ein Objekt Ball, Wand, und Balken machen.
    Dann soll ich eine Area machen??(Wie geht das und was ist damit gemeint?)

    Das mit den Balken und Buttons war immer grundsätlich ein Problem, da wenn ich einen Button bewegen mochte. Die auswahl von dem Button sich dauernd ändert.(Einaml button1 dann Button2)

    Nun noch ne Frage: Area = Bereich in Koordinaten angegeben??
    Und ich finde keine Elippsen und ricliwas^^ Wo finde ich die?

    mfg Mongole

    Ps: Ich bin jetzt auch angemeldet.



  • Jetzt nachdem ich das entsprechende Kapitel in meinem Buch nochhmal gelsesn habe. habe ich es verstanden.
    Mein Code:

    private void Form1_Paint(object sender, PaintEventArgs e)
            {
    
                SolidBrush Pinsel = new SolidBrush(Color.Firebrick);
    
                e.Graphics.FillEllipse(Pinsel, XBall, YBall, 20, 20);
    
                SolidBrush PinselStange = new SolidBrush(Color.Black);
    
                e.Graphics.FillRectangle(PinselStange, XBalken, YBalken, 20, 200);
    
                SolidBrush PinselWand = new SolidBrush(Color.Blue);
    
                e.Graphics.FillRectangle(PinselWand,0,0, 20,395);
                e.Graphics.FillRectangle(PinselWand, 0, 0, 550, 20);
                e.Graphics.FillRectangle(PinselWand, 0, 395, 550, 20);
            }
    

    Nun ist meine Frage wie ich nun ein Objekt Ball herstellen kann. Das objekt Ball soll nämlich genau diese Ellipse sein.
    Wie könnte ich das machen?

    mfg Mongole



  • Na siehste geht doch 🙂

    Jezt machst du dir für den Ball und die Paddels noch ein eigenes Object. Diesen Objekten kannst du dann auch gleich den Pinsel zuordnen und must diesen nicht jedesmal mal in der Paint-Methode neu erzeugen.

    Aus YBall und XBall wird dann z.B. Ball.X und Ball.Y 🙂

    MfG
    Marco



  • Ja mein Problem ist es wie ich diese obejecte mache...

    Obj.Ball geht iwie ned....
    Und ich weiß bnicht wo ich das hinmachen muss...
    Ob ichs gleich zur DrawMethode geben soll oder waonders.

    mfg


Anmelden zum Antworten