Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

07.07.2007, 09:17

Ping Pong - Die Ballbewegung

Guten Tag,

um mein Wissen zu vertiefen knie ich mich gerade in ein kleines modifiziertes Ping Pong Projekt. Es dient mehr dem Lernen als dem "ich erstelle das beste Spiel der welt".

Mein Problem dabei ist die Berechnung des Austrittswinkels, des Balles wenn er auf die "Bande" trifft.

Nun Eintrittswinkel = Austritswinkel

Mathematisch ist es nicht das Problem, nur fällt es mir schwer es in einen tauglichen Algorythmus für den Quelltext umzusetzen.

Einige Stuktogramme habe ich schon gezeichnet.

Ich denke ich sehe den Wald vor lauter Bäumen nicht :)


mfg
Benni

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

07.07.2007, 09:41

Wenn die Bande parallel zur x- oder y-Achse ist, ist es sehr einfach. Dann musst du einfach nur die y- bzw. x-Komponente des Geschwindigkeitsvektors
umdrehen.

Obere/untere Bande:
v.y = -v.y;

Linke/rechte Bande:
v.x = -v.x;

3

09.07.2007, 08:08

Danke für die Antwort.

Also diese Ballbewegung ist ein echter Kopfknacker......ich bastel da jetzt schon Tagelang daran rum. Bin wohlgemerkt noch anfänger auf diesem Gebiet.

Nur mal ein kurzer Abriss, was ich schon hab, was meines Wissensstandes nach alles zum Ablauf gehört.

Klassen:

Ball
Spieler
Grafik
Sound

Ich denke mehr Klassen sind nicht nötig.

Ich denke ich brauch auch ein Struct für den Richtungsvektor der Ballbewegung (oder?).

In meiner Hauptverarbeitungsschleife (was für ein Wort) werden die Werte die der Callbackhandler liefert verarbeitet, also Spielerbewegung oder wenn der Spieler im Fenstermenü irgendwas macht. Das ist kein Problem. Gut ist das erledigt möchte ich die neuen Koordinaten des Balls berechnen, da er sich ja auch in eine betimmte Richtung (die ich nicht weiß, wie ich sie ermitteln soll) bewegt (weiß nicht genau wie ich mittels des Vektors rechnen soll). Zu letzt werden die neuen Koords der Ball und Spielerinstanz übergeben und der Screen neu gezeichnet.

Es laufen noch ein paar andere Dinge wie Spiel läuft noch? - Schleife, aber das ist eher nebensächlich und stellt kein Problem dar.

Ich sitze etwas auf dem Schlauch irgendwie :) und möchte nicht noch mehr Papier blau färben (armer Wald)

Danke für die Hilfe,


mfg
Benni

4

09.07.2007, 09:47

du könntest eine weitere Klasse Vector2 definieren. Dann bekommt der Ball 2 Vektoren, einen Positionsvektor und einen Bewegungsvektor. Der Bewegungsvektor ist ein Unitvektor. Und dann bewegst du den ball jeden frame um Unitvektor*TimeSinceLastFrame*Geschwindigkeit.
Falls der ball irgendwo anschlägt, drehst du den Richtungsvektor. (Wie das genau geht kann ich dir grade nicht beantworten. Ich hatte selbst bisher nur mit 90 Grad drehungen was am Hut.)

5

09.07.2007, 10:18

Hallo Eldarion und danke für die Antwort.

Hab mal einen Vektor in form eines Structs eingebaut.
Naja komm aber trotzdem nicht so ganz drauf. Ich poste mal den Gesamten Quelltext (keine Angst ist nicht so viel). Man verzeih mir schlechten Programmierstil, aber durch die ganze rumbastelei....naja geht das leider irgendwie unter. Ich überarbeite den Quelltext wenn es denn funktioniert.


*Edit: Habe den Quelltext auf das nötigste minimiert

C-/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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Vektor für Positionen


struct poszeiger {
    float xPos;
    float yPos;
};

// Klasse des Balles


class gameball
{
private:
    DWORD time;
    DWORD now;
    int speed;
public:
    poszeiger ball;
    void init ();
    int move ();
};

// Startwerte setzen


void gameball::init ()
{
    time = timeGetTime ();
    speed = 100;
    ball.xPos = 170;
    ball.yPos = 200;
}

// Ball bewegen (noch nicht komplett)


int gameball::move()
{
    DWORD tick;
    now = timeGetTime ();
    tick = (now-time)*speed;
    ball.xPos = static_cast<float>(ball.xPos + tick);
    ball.yPos = static_cast<float>(ball.yPos + tick);
    return 1;
}

// Instanz der Klasse gameball


gameball rball;

// Klasse des Spiels


class ppb
{
private:
    int points;
    void init ();
    int speed;
    DWORD time;
public:
    void reset_timer () {time = timeGetTime ();}
    void faster () {speed += 50;}
    void slower () {if (speed > 50) speed -= 50;}
    int game_run;
    void start ();
    void display ();
};

void ppb::init ()
{
    game_run = 0;
    points = 0;
}

void ppb::start ()
{
    reset_timer ();
    speed = 100;
    init ();
    game_run = 1;
}

void ppb::display ()
{
    ppb_display.backgrnd ();
    ppb_display.gplayer1 ();
    ppb_display.gball ();
    ppb_display.present ();
}

// Instanz der Spielerklasse


ppb game;

// Ausschnitt WinMain


[...]


    while( TRUE)
        {
        if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
            {
            if( GetMessage( &msg, NULL, 0, 0 ) == 0)
                return 0; // Message ist WM_QUIT


             if( TranslateAccelerator( ppb_window, acc, &msg) == 0)
                {
                TranslateMessage( &msg); 
                DispatchMessage( &msg);
                }
            }
        else
        {
            HRESULT hr;
            hr = ppb_display.cooperative ();
            if (hr < 0)
            {
                switch (hr)
                {
                case DDERR_EXCLUSIVEMODEALREADYSET:
                    Sleep(10);
                    break;
                case DDERR_WRONGMODE:
                    ppb_display.free_all ();
                    ppb_display.init (ppb_window);
                    PostMessage (ppb_window, WM_PAINT, 0, 0);
                    break;
                
                    if (game.game_run)
                    {
                        if (rball.move ());
                            game.display ();
                    }
                    else
                    {
                        WaitMessage ();
                        game.reset_timer ();
                    }
                }
            }
        }
    
        }
    }


Vielen dank an denjenigen, der sich die Zeit nimmt mein Codegeschnipsel durchzulesen. Ich hoffe jemand kann mir einen Denkanstoß verpassen.

mfg
Benni

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

6

09.07.2007, 11:34

keiner liest sich all den code durch.

edit: schon viel besser ;)

7

09.07.2007, 11:51

also, du brauchst folgende formal fürs berechne des neuen bewegungsvektor nach aufprall an einer zu y parralleln wand/stab/etc:

Bewegungsvektor = (10, 1);
BewegungsvektornachAufprall.x = -Bewegungsvektor.x
BewegungsvektornachAufprall.y = Bewegungsvektor.y

das sollte funktionieren, aber rewb0rn hat recht, ich hab den code auch nur kurz überflogen.

8

09.07.2007, 13:05

Gut kritik angenommen, habe den Quelltext auf das nötigste minimiert :)

Einen Bewegunsvektor also.

Ich denke dabei an eine Struktur mit 2 Punkten. Den Aufprallpunkt und den letzen Punkt vor des Aufpralls. Diese beiden Punkte ergeben einen Vektor (richtig?). Wie fülle ich diesen Vektor nun sinnvoll?

Wenn ich richtig denke brauche ich eine Abfrage welche Seite "getroffen" wurde. Also ob parallel zur X-Achse oder parallel zur Y-Achse.

Danach muss ich feststellen wie die Bande getroffen wurde:


Quellcode

1
2
3
4
5
_______________
           /
         /
       /
     /

oder


Quellcode

1
2
3
4
5
_______________
        \
          \
            \
              \

Quasi :)


Denke ich zu kompliziert?

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

9

09.07.2007, 14:54

Zitat von »"Elloran"«


Denke ich zu kompliziert?


Ich glaube du denkst zu einfach ;)
Bisschen muss man schon selbst tun für eine Kollisionserkennung. Vor allem musst du rauskriegen, welche Wand getroffen wird.

Ich hab mir mal bisschen Gedanken darüber gemacht, wie man die Wände etwas allgemeiner und nicht nur x oder y parallel nutzen kann:

Angenommen A ist der Richtungvektor der Wand, B ist orthogonal zu A, C ist der Richtungvektor vom Ball und D der neue Richtungsvektor nach dem Aufprall, p und q sind reelle Zahlen für eine Linearkombination.

C=p*A + q*B // C als Linearkombination von A und B -> Umstellen, um p und q zu ermitteln

D=p*A - q*B // Durch einsetzen von p und -q wird der neue Richtungsvektor gebildet, wobei die Kugel sich wieder von der Wand entfernt


Ich weiß jetzt nicht, ob ich irgendwas großes übersehen hab, aber ich behaupte mal, so lässt es sich machen ;)

10

10.07.2007, 07:27

Guten Morgen :)

Hab jetzt mal weitergebastelt und oh wunder es rührt sich was....nur aus einem mir unerfassbaren Grund ruckelt mein Ball nur so durch mein Fenster. Ich hab schon gegoogelt und die MSDN sagt mir auch nichts neues. Tüftel schon mit den Werten rum aber das ändert es nur minimal. Ich weiß ich übertreib gern mit Code aber diesmal wirklich richtig kurz:

C-/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
int gameball::move()
{
    curtime = timeGetTime ();
    curtime /= 1000;

    elapsedtime = curtime-lasttime;
    lasttime = curtime;
    xPos = GetxPos ();
    yPos = GetyPos ();

    if (xPos <= 0)
        hitx = LEFT;
    if (xPos >= 735)
        hitx = RIGHT;
    if (yPos <= 0)
        hity = UP;
    if (yPos >= 399)
        hity = DOWN;

    switch (hitx)
    {
    case LEFT:
        incdecx = 1;
        break;
    case RIGHT:
        incdecx = -1;
        break;
    };

    switch (hity)
    {
    case UP:
        incdecy = 1;
        break;
    case DOWN:
        incdecy = -1;
    };

    Setpos (xPos + ((incdecx*speed)*elapsedtime), yPos + ((incdecy*speed)*elapsedtime));

    return 1;
}


lasttime wird beim initialisieren des Spiels mittels timeGetTime() vorbelegt.

Hier noch die Implentrierung in die WinMain (rball ist die instanz der klasse):

C-/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
        HRESULT hr;
        hr = ppb_display.cooperative ();
        if (hr < 0)
            {
                switch (hr)
                {
                case DDERR_EXCLUSIVEMODEALREADYSET:
                    Sleep(10);
                    break;
                case DDERR_WRONGMODE:
                    ppb_display.free_all ();
                    ppb_display.init (ppb_window);
                    PostMessage (ppb_window, WM_PAINT, 0, 0);
                    break;
                }
            }
            else
            {
                if (game.game_run)
                {
                    if (rball.move ())
                        game.display ();
                }
                else
                {
                    WaitMessage ();
                    rball.reset_timer ();
                }
            }



Danke für eure Gedult :)

Werbeanzeige