Pong, Ball-Winkel

  • C++

  • obi--wan
  • 2987 Aufrufe 7 Antworten

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Pong, Ball-Winkel

    Also ich schreibe zur Zeit ein Pong in C++ mit Allegro. Ist mit Allegro auch recht einfach. Funktioniert auch schon alles das einzige was noch fehlt ist der Winkel des Balles. Bis jetzt fliegt er immer in einem 45° Winkel aber das ist etwas langweilig weil er so immer genau die selbe Flugbahn hat. Ich hab ein paar Pongs gespielt und festgestellt das der Winkel von der Position mit der er am schläger aufkommt abhängt. Die Frage ist jetzt wie ich aus der Position mit der er am Schläger aufkommt die Geschwindigkeit in x und y richtung errechne. Trefferzonen wären mir in denn Sinn gekommen, aber in denn Pongs die ich gespielt habe ist es mir vogekommen als ob die schon bei einer abweichung von wenigen pixel einen leicht anderen Winkel haben.

    Hoffe ihr könnt mir helfen.

    mfg
    obi--wan
  • Sollte der ball nicht eigentlich abhängig vom Aufprallwinkel abprallen? Oder hab ich das falsch verstanden un du meist beim ersten Aufschlag?
    Ich habe soein Spiel mal in der Schule programmiern müssen, allerdings mit ActionScript :D.
    Da habe ich das beim Aufschlag mit Sektoren gemacht. Aber nicht jedes einzelne Pixel als Sektor sondern ich hab den Schläger in 5 Sektoren geteilt, aber du kannst ja auch noch viel mehr Sektoren nehmen. Und sonst natürlich wenn er im 35° Winkel aufkommt soller er auch im 35° Winkel, spiegelverkehrt (also ka wieviel Grad das dann sind ich will nicht rechnen^^) wieder abprallen, ist ja klar.
    Was bringt schon Pixel für Pixel?
    [COLOR="DarkRed"][SIZE="3"]Godspeed[/SIZE][/color] on [COLOR="DarkRed"][SIZE="3"]Devils[/SIZE][/color] Thunder
  • Eine andere Alternative wäre die Abhängigkeit von der Schlägerbewegung. Der Winkel würde dann mit der Bewegung flacher. Das wäre so etwas wie Spin.
    Es ist besser zu schweigen und für einen Narren gehalten zu werden, als zu reden und damit alle Zweifel zu beseitigen ...
  • Ich hab mir das nochmal überlegt und ich werde es mit Trefferzonen machen (wenn auch recht vielen). Ich will das so machen das der Ball wenn er über der mitte aufkommt nach schräg oben und wenn er unter der mitte auftrifft nach schräg untern wegfliegt. Am besten wäre es natürlich wenn der Winkel nicht absolut gesetzt wird sondern relativ zum Aufprallwinkel. Ich hab übrigens festgestellt das ich das ganze antscheinend schlecht programmiert habe da ich das pong auf einem etwas älterem PC ausprobiert habe und es ziemlich geruckelt hat, und auch auf meinem Laptop verursacht es ~50% CPU Auslastung. Werde den Source noch heute hier posten hab aber jetzt keine Zeit dafür. Dann könnt ihr mir hoffentlich ein paar Tipps zur Optimierung geben.

    mfg
    obi--wan

    edit:
    So hier der Source:

    C-Quellcode

    1. #include <iostream>
    2. #include <rechteck.h>
    3. #include <winalleg.h>
    4. #include <allegro.h>
    5. #include <alfont.h>
    6. using namespace std;
    7. class pongBall {
    8. int x, y, length, height, screenx, screeny, color;
    9. bool visible;
    10. public:
    11. int speedx, speedy;
    12. pongBall(int bildschirmx, int bildschirmy, int posx = 0, int posy = 0, int laenge = 0, int hoehe = 0, int geschwindigkeit = 0, int farbe = 0x000000) {
    13. if(posx == 0 && posy == 0 && laenge == 0 && hoehe == 0) {
    14. visible = false;
    15. }
    16. else {
    17. x = posx;
    18. y = posy;
    19. visible = true;
    20. }
    21. color = farbe;
    22. length = laenge;
    23. height = hoehe;
    24. speedx = geschwindigkeit;
    25. speedy = geschwindigkeit;
    26. screenx = bildschirmx;
    27. screeny = bildschirmy;
    28. }
    29. void print(BITMAP* bitmap) {
    30. rectfill(bitmap, x, y, x + length, y + height, color);
    31. }
    32. void setPosition(int posx, int posy) {
    33. x = posx,
    34. y = posy;
    35. }
    36. int getPositionX() {
    37. return x;
    38. }
    39. int getPositionY() {
    40. return y;
    41. }
    42. void setSize(int laenge, int hoehe) {
    43. length = laenge;
    44. height = hoehe;
    45. }
    46. int getSizeX() {
    47. return length;
    48. }
    49. int getSizeY() {
    50. return height;
    51. }
    52. void overprint(BITMAP* bitmap, int farbe = 0x000000) {
    53. rectfill(bitmap, x, y, x + length, y + height, farbe);
    54. }
    55. void setColor(int farbe) {
    56. color = farbe;
    57. }
    58. int getColor() {
    59. return color;
    60. }
    61. bool collide(rechteck recht2) {
    62. if( (recht2.getPositionX() <= (x + length)) && ((recht2.getPositionX() + recht2.getSizeX()) >= x) && (recht2.getPositionY() <= (y + height)) && ((recht2.getPositionY() + recht2.getSizeY()) >= y) ) {
    63. return true;
    64. }
    65. else {
    66. return false;
    67. }
    68. }
    69. short wand() {
    70. if((y <= 0) || ((y + height) >= screeny)) {
    71. return 3;
    72. }
    73. else if(x <= 0) {
    74. return 1;
    75. }
    76. else if((x + length) >= screenx) {
    77. return 2;
    78. }
    79. else {
    80. return 0;
    81. }
    82. }
    83. };
    84. int main() {
    85. //Bildschrimauflösung einlesen
    86. int x = GetSystemMetrics(SM_CXSCREEN);
    87. int y = GetSystemMetrics(SM_CYSCREEN);
    88. //Allegro und Alfont initialisieren
    89. allegro_init();
    90. install_keyboard();
    91. alfont_init();
    92. set_color_depth(16);
    93. set_gfx_mode(GFX_AUTODETECT, x, y, 0, 0);
    94. BITMAP *buffer;
    95. buffer = create_bitmap(x, y);
    96. ALFONT_FONT *myfont;
    97. myfont = alfont_load_font("digital.ttf");
    98. alfont_set_font_size(myfont, 30);
    99. rechteck schlaeger1(0, 0, 10, 40, 0xFFFFFF, true);
    100. rechteck schlaeger2(x - 10, 400, 10, 40, 0xFFFFFF, true);
    101. pongBall ball(x, y, x/2, y/2, 15, 15, 4, 0xFFFFFF);
    102. int punkte1 = 0, punkte2 = 0;
    103. while(!key[KEY_ESC]) {
    104. clear(buffer);
    105. //Schläger 1 bewegen
    106. if(key[KEY_DOWN]) {
    107. schlaeger1.setPosition(0, schlaeger1.getPositionY() + 6);
    108. }
    109. else if(key[KEY_UP]) {
    110. schlaeger1.setPosition(0, schlaeger1.getPositionY() - 6);
    111. }
    112. //Schläger 2 bewegen
    113. if(key[KEY_S]) {
    114. schlaeger2.setPosition(x - schlaeger2.getSizeX(), schlaeger2.getPositionY() + 6);
    115. }
    116. else if(key[KEY_W]) {
    117. schlaeger2.setPosition(x - schlaeger2.getSizeX(), schlaeger2.getPositionY() - 6);
    118. }
    119. //Kolisionsabfrage mit den Schlägern und dann mit den Wänden
    120. if(ball.collide(schlaeger1) || ball.collide(schlaeger2)) {
    121. ball.speedx *= -1;
    122. ball.speedy *= -1;
    123. }
    124. else if(ball.wand() == 1) {
    125. ball.setPosition(x/2, y/2);
    126. punkte2++;
    127. }
    128. else if(ball.wand() == 2) {
    129. ball.setPosition(x/2, y/2);
    130. punkte1++;
    131. }
    132. else if(ball.wand() == 3) {
    133. ball.speedy *= -1;
    134. }
    135. alfont_textprintf_centre_aa(buffer, myfont, x/2, 5, 0xFFFFFF, "%d : %d", punkte1, punkte2); //Punkte ausgeben
    136. ball.setPosition(ball.getPositionX() + ball.speedx, ball.getPositionY() + ball.speedy); //Position des Balles neu setzen
    137. //Schläger und Ball in den Buffer zeichnen
    138. schlaeger2.print(buffer);
    139. schlaeger1.print(buffer);
    140. ball.print(buffer);
    141. //Buffer auf Bildschirm ausgeben
    142. blit(buffer, screen, 0, 0, 0, 0, x, y);
    143. Sleep(5);
    144. }
    145. return 0;
    146. }
    147. END_OF_MAIN();
    Alles anzeigen


    So hoffe es ist soweit kommentiert das es jeder versteht. Die rechteck-Klasse is mit der pongball Klasse ident, auser das die Funktionen collide und wand fehlen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von obi--wan ()

  • Ich hab' mir den Code zwar nicht durchgelesen, aber warum brauchst du überhaupt einen Winkel, als ich letztlich ein Pong-Spiel geschrieben habe, habe ich beim Schläger einfach die Richtung geändert, dann war der Einfallswinkel automatisch der Ausfallwinkel.
    Dann ist das ganze aber halt ohne Spin.
  • Wenn der einfalswinkel gleich dem Ausfallswinkel ist fliegt der Ball doch ewig hin und her wenn man die zwei Schläger richtig positioniert stehen lässt, oder irre ich da?

    Für den Winkel habe ich inzwischen auch schon eine Lösung, mein derzeitiges Hauptproblem ist die Performance. Ich verstehe einfach nicht was an meinem Programm eine so schlechte performance verursacht bzw wie ich sie verbessern kann.
  • Ich vermute das es an den allegro funktionen liegt, weil ich spontan bei dir keine wirklich teuren Funktionen erkennen kann.

    Du könntest den code mal profilen indem du die Zeit für einzelne Funktionsaufrufe misst (insbesondere die allegro funktionen).
    [SIZE="1"]i'm a signature virus. copy me into your signature to help me spread. - smart questions[/SIZE]
  • So hab mich jetzt mal ein bischen schlau gemacht. Bin jetzt auf SFML umgestiegen, und ich muss sagen es ist viel viel besser als Allegro, viel neuer und vorallem Objektorientiert.

    Bin damit schon wieder beim Problem Ballwinkel angekommen. Hab mich entschlossen Trefferzonen am Schläger zu machen, und dann je nachdem wo der Ball auftrifft den Winkel relativ zum aufprallwinkel verändern (für anfagng tuts auch absolut). Das Problem ist ich weiß nicht wirklich wie ich die Trefferzonen dann in eine x/y Bewegung umsetzen soll. Derzeit bewege ich denn Ball mit

    Quellcode

    1. ball.Move(ballspeedx * elapsedtime, ballspeedy * elapsedtime);
    Wobei elapsedtime die Zeit in Sekunden ist die Seit dem letzten Frame vergangen ist.

    Und ich habe noch ein Problem, wenn ich unter Linux ein SFML Programm mache funktioniert das auch und er öffnet das Render-Fenster aber sobald ich Ereignisshandling hinzufüge öffnet er das Render-Fenster nicht. Es liegt aber nicht am Code da der selbe Code unter Windows kompiliert und Fehlerfrei funktioniert. Wenn ich das Fenster im Vollbild öffnen lasse öffnet es sich auch nicht aber ganz Gnome hängt sich auf und ich mus mit [ALT] + [STRG] + [F1] in eine tty-Shell wechseln und mein Programm beenden.

    mfg
    obi--wan