home *** CD-ROM | disk | FTP | other *** search
/ The Best of Select: Games 9 / CD_1.iso / kids / apool / physics.c < prev    next >
C/C++ Source or Header  |  1995-04-23  |  21KB  |  461 lines

  1. /* This is "physics.c", part of of the pool (billiards)-program
  2.                    
  3.                      "ANOTHER POOL" (V 0.97).
  4.  
  5.    "physics.c" includes the 'physic' of the game, such as the 
  6.    collision of the balls, the reflection on the walls, ...
  7.  
  8.    Copyright (C) 1995 by Gerrit Jahn (email: ub1g@rz.uni-karlsruhe.de)
  9.  
  10.    "ANOTHER POOL" (V 0.97) is free software; you can redistribute it 
  11.    and/or modify it under the terms of the GNU General Public License 
  12.    as published by the Free Software Foundation; either version 2 of 
  13.    the License, or (at your option) any later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.    You should have received a copy of the GNU General Public License
  21.    along with GNU CC; see the file COPYING.  If not, write to
  22.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  23.  
  24. /* ------------------------------ physics.c ------------------------------ */
  25.  
  26. #include <math.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <time.h>
  30. #include <mousex.h>
  31. #include "apool.h"
  32.  
  33. #define CURVES 2.5 /* wie stark bricht Weiße bei 'Curve-Ball' senkr. aus */
  34. #define CURVEP 7.5 /* wie stark bricht Weiße bei 'Curve-Ball' parall. aus */
  35.  
  36. clock_t t1=0, old_time;
  37.  
  38. void calc_v_end( int n ) 
  39. /* berechnet aus "eingegebener" Anfangsgeschwindigkeit der Kugel die 
  40.    End-Roll- UND -Transl.geschwindigkeit; es ist v_tr = sqrt(5/7)*v_0.
  41.    Es wird mit vex,y die (teilweise, eben zu sqrt(2/7) anteilige) Umwandlung
  42.    von Translations- in Rotationsgeschwindigkeit beschrieben. Dadurch fängt
  43.    die Kugel nach kurzem "Rutschen" an  zu "rollen" .... */
  44.  {
  45. /* double ges_energie, dummy;
  46.  ges_energie = (dummy = k[n].v.x*k[n].v.x+k[n].v.y*k[n].v.y) + 
  47.    sqrt(ROLL) * (k[n].vr.x*k[n].vr.x+k[n].vr.y*k[n].vr.y);
  48.  if( dummy )
  49.   {
  50.   k[n].ve.x = sqrt(ROLL) * ges_energie * k[n].v.x/dummy;
  51.   k[n].ve.y = sqrt(ROLL) * ges_energie * k[n].v.y/dummy;
  52.   }
  53.  if( k[n].vr.x || k[n].vr.y )
  54.   {
  55.   ??? !!! !!! !!!
  56.   } */
  57.  k[n].v.x += sqrt(ROLL)*k[n].vr.x;
  58.  k[n].v.y += sqrt(ROLL)*k[n].vr.y;
  59.  k[n].vr.x *= (1-sqrt(ROLL));
  60.  k[n].vr.y *= (1-sqrt(ROLL));
  61.  k[n].ve.x = sqrt(ROLL)*k[n].v.x;                                    
  62.  k[n].ve.y = sqrt(ROLL)*k[n].v.y;
  63.  }
  64.  
  65. void translate_spin( void ) 
  66. /* Nachdem die Richtung der Geschw. feststeht, wird der Spin, der bisher im
  67.    lokalen Koordinatensystem der Kugel festgelegt war auf globale (x,y)-
  68.    Koordinaten umgerechnet. Das ist wichtig, da sich das lokale KS drehen
  69.    kann, da auch "Curve-Balls" möglich sind... */
  70.  {
  71.  double puffer, dummy=0;  /* k.e.x : senkr., k.e.y: parall. zu k.v(x,y) !!! */
  72.  struct vect s, add = { 0, 0 };
  73.  /* senkr. Vektor zu v bestimmen: warum: s. unten */
  74.  if( alph )
  75.   {
  76.   s.x = -k[WHITE].v.y; s.y = k[WHITE].v.x;
  77.   if( (dummy = BETR( s )) )
  78.    {
  79.     s.x /= dummy; s.y /= dummy;
  80.     dummy = sin( alph * M_PI / 180.0 );
  81.     add.x = - s.x * dummy * k[WHITE].ez / DIFFX / CURVES;
  82.     add.y = - s.y * dummy * k[WHITE].ez / DIFFX / CURVES;
  83.    }
  84.   s.x = k[WHITE].v.x; s.y = k[WHITE].v.y;
  85.   if( (dummy = BETR( s )) ) /* dummy = dasselbe wie oben !!! !!! !!!*/
  86.    {
  87.    s.x /= dummy; s.y /= dummy;
  88.    dummy = sin( alph * M_PI / 180.0 );
  89.    add.x += s.x * dummy * k[WHITE].e.y / DIFFX / CURVEP;
  90.    add.y += s.y * dummy * k[WHITE].e.y / DIFFX / CURVEP;
  91.    }
  92.   }
  93.  /* bis hier wurde das "Ausbrechen" des weißen Balls beim Curve-Ball,
  94.     also die Zusatzgeschw., die der Ball durch den nicht mittigen Treffpkt
  95.     bekommt, wenn der Queue noch dazu nicht parallel zum Tisch steht, 
  96.     berechnet. jetzt kommt der "normale" Spin und Curve-Ball ... */
  97.  if( (k[WHITE].v.x ) || (k[WHITE].v.y ) )
  98.   {
  99.   dummy = ( k[WHITE].ez*sin( M_PI*alph/180.0) ) / 
  100.    sqrt(k[WHITE].v.x*k[WHITE].v.x + k[WHITE].v.y*k[WHITE].v.y);
  101.   }
  102.  puffer = k[WHITE].e.y;
  103.  k[WHITE].e.y = k[WHITE].v.x * dummy; 
  104.  k[WHITE].e.x = - k[WHITE].v.y * dummy;
  105.  if( k[WHITE].v.x || k[WHITE].v.y )
  106.   {
  107.   dummy = puffer / 
  108.    sqrt(k[WHITE].v.x*k[WHITE].v.x + k[WHITE].v.y*k[WHITE].v.y);
  109.   }
  110.  else dummy = 0;
  111.  k[WHITE].e.y += (- k[WHITE].v.y * dummy); 
  112.  k[WHITE].e.x += (- k[WHITE].v.x * dummy); 
  113.  k[WHITE].ez *= cos( M_PI*alph/180.0);
  114.  k[WHITE].e.x /= (RADIUS * DIFFX);
  115.  k[WHITE].e.y /= (RADIUS * DIFFX);
  116.  k[WHITE].v.x += add.x;
  117.  k[WHITE].v.y += add.y;
  118. }
  119.  
  120. void refl_kk( int n, struct vect p)   
  121. /* Kollisionsberechnugn zw. Kugeln und der Königsbande, die als infinitesimale
  122.    Kugel an der jeweiligen Stelle angenommen wird, sodaß prinzipiell (fast)
  123.    jeder Abprall-Winkel an diese Bande möglich ist, Die Berechnung erfolgt 
  124.    ähnlich wie der Stoß zwischen zwei Kugeln (s. coll() ) und ansonsten analog
  125.    reflextion() ... */
  126.  {
  127.  struct vect ab; /* ab := Abstandsvektor zw. den Mittelpunkten */
  128.  double dummy;
  129.  ab.x = (k[n].p.x*DIFFX-p.x); ab.y = (k[n].p.y*DIFFX-p.y); 
  130.  ab.x /= (dummy = BETR( ab )); /* Abfrage, ob dummy != 0 ??? !!! !!! !!!*/
  131.  ab.y /= dummy;
  132.  if( (ab.x*k[n].v.x+ab.y*k[n].v.y) >= 0 ) return;
  133.  /* Berechnung der Geschwindigkeit der Kugel nach der Kollision */       
  134.  dummy = (k[n].v.x * ab.x + k[n].v.y * ab.y);
  135.  k[n].v.x = (BANDEREF * (k[n].v.x - 2 * ab.x * dummy) 
  136.   - BANDES * ab.y * dummy * k[n].ez);
  137.  k[n].v.y = (BANDEREF * (k[n].v.y - 2 * ab.y * dummy)
  138.   + BANDES * ab.x * dummy * k[n].ez);
  139.  dummy = k[n].vr.x*ab.x + k[n].vr.y*ab.y;
  140.  k[n].vr.x -= ab.x * dummy;
  141.  k[n].vr.y -= ab.y * dummy;
  142.  k[n].vr.x *= BANDEREF;
  143.  k[n].vr.y *= BANDEREF;
  144.  dummy = k[n].e.x * ab.x+k[n].e.y*ab.y;
  145.  k[n].e.x -= ab.x * dummy;
  146.  k[n].e.y -= ab.y * dummy;
  147.  k[n].e.x *= BANDEREF;
  148.  k[n].e.y *= BANDEREF;
  149.  k[n].ez *= (1-BANDEREF);
  150.  if( n == WHITE ) set_spin( k[WHITE].e.x, k[WHITE].e.y, k[WHITE].ez );
  151.  calc_v_end( n );
  152.  bande_hit = 1;
  153.  }
  154.  
  155. void coll( int a, int b) 
  156. /* Stoß: Kollisionsberechnung zwischen den Kugeln a und b. Dabei wird die
  157.    Masse der jeweiligen Kugel berücksichtigt, da die Weiße wohl manchmal
  158.    schwerer ist. Außerdem wird berücksichtigt, daß Kugeln, die ROLLEN, nur
  159.    ihre Translationsenergie abgeben könne, während sie die Rotationsenergie
  160.    dazu befähigt, noch ein bißchen weiter zu rollen (mit entsprechen 
  161.    langsamerer Geschwindigkeit. Außerdem verlieren stoßende Kugel einen 
  162.    Teil ihres z-Spins, da ansonsten an den Banden interessante Effekt, wie
  163.    negative Winkel auftreten können (immer noch ?? )*/
  164.  { 
  165.  struct vect ab, v; /* ab := Abstandsvektor zw. den Mittelpunkten */
  166.  double dummy, dummy2;
  167.  /* Abfrage, ob Kugeln kollidieren dürfen. Das ist der Fall, wenn der
  168.     Winkel zwischen Relativgeschw. und Abst.vektor < 90° ist */
  169.  if( ( (ab.x = k[a].p.x-k[b].p.x) * (k[a].v.x-k[b].v.x) +
  170.        (ab.y = k[a].p.y-k[b].p.y) * (k[a].v.y-k[b].v.y) ) >= 0 )
  171.         return;
  172.  /* Abstand i.allg. zu klein (wg. Zeitschritten) -> Korrektur: */
  173.  v.x = k[a].v.x - k[b].v.x; v.y = k[a].v.y - k[b].v.y;
  174.  dummy2 = SKALP( ab, v ) / SKALP( v, v );
  175.  dummy = ( SKALP( ab, ab ) - 4*RADIUS*RADIUS/(DIFFX*DIFFX) )
  176.   / SKALP( v, v );
  177.  dummy2 += sqrt( dummy2 * dummy2 - dummy );
  178.  k[a].p.x -= k[a].v.x * dummy2;
  179.  k[a].p.y -= k[a].v.y * dummy2;
  180.  k[b].p.x -= k[b].v.x * dummy2;
  181.  k[b].p.y -= k[b].v.y * dummy2;
  182.  ab.x = k[a].p.x - k[b].p.x;
  183.  ab.y = k[a].p.y - k[b].p.y;
  184.  /* Ende der "zu kleinen Abstands-korrektur" */
  185.  dummy = BETR( ab );  /* ab = abst-vektor normieren */
  186.  ab.x /= dummy;
  187.  ab.y /= dummy;
  188.  /* Abnahme des z-Spins, wenn Kugeln stoßen (gibt's hoffentlich) */
  189.  if( k[a].ez && (k[a].v.x || k[a].v.y) )
  190.   k[a].ez *= (ab.x * k[a].v.x + ab.y*k[a].v.y) /  
  191.    sqrt(k[a].v.x*k[a].v.x+k[a].v.y*k[a].v.y) * SPINC;
  192.  if( k[b].ez && (k[b].v.x || k[b].v.y) )
  193.   k[b].ez *= (ab.x * k[b].v.x + ab.y*k[b].v.y) / 
  194.    sqrt(k[b].v.x*k[b].v.x+k[b].v.y*k[b].v.y) * SPINC;
  195.  /* Berechnung der Geschwindigkeit der Kugeln nach der Kollision mittels: 
  196.   v2'=(v1*a)*a+v2-(v2*a)*a; v1'=v1-(v1*a)*a+(v2*a)*a (|a|=1, a=Abst.vekt.) */
  197.  dummy = (k[a].v.x - k[b].v.x) * ab.x + (k[a].v.y - k[b].v.y) * ab.y;
  198.  k[a].v.x -= (2.0*k[b].m/(k[a].m+k[b].m)) * ab.x* du