home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of Select: Games 9
/
CD_1.iso
/
kids
/
apool
/
physics.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-23
|
21KB
|
461 lines
/* This is "physics.c", part of of the pool (billiards)-program
"ANOTHER POOL" (V 0.97).
"physics.c" includes the 'physic' of the game, such as the
collision of the balls, the reflection on the walls, ...
Copyright (C) 1995 by Gerrit Jahn (email: ub1g@rz.uni-karlsruhe.de)
"ANOTHER POOL" (V 0.97) is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------ physics.c ------------------------------ */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mousex.h>
#include "apool.h"
#define CURVES 2.5 /* wie stark bricht Weiße bei 'Curve-Ball' senkr. aus */
#define CURVEP 7.5 /* wie stark bricht Weiße bei 'Curve-Ball' parall. aus */
clock_t t1=0, old_time;
void calc_v_end( int n )
/* berechnet aus "eingegebener" Anfangsgeschwindigkeit der Kugel die
End-Roll- UND -Transl.geschwindigkeit; es ist v_tr = sqrt(5/7)*v_0.
Es wird mit vex,y die (teilweise, eben zu sqrt(2/7) anteilige) Umwandlung
von Translations- in Rotationsgeschwindigkeit beschrieben. Dadurch fängt
die Kugel nach kurzem "Rutschen" an zu "rollen" .... */
{
/* double ges_energie, dummy;
ges_energie = (dummy = k[n].v.x*k[n].v.x+k[n].v.y*k[n].v.y) +
sqrt(ROLL) * (k[n].vr.x*k[n].vr.x+k[n].vr.y*k[n].vr.y);
if( dummy )
{
k[n].ve.x = sqrt(ROLL) * ges_energie * k[n].v.x/dummy;
k[n].ve.y = sqrt(ROLL) * ges_energie * k[n].v.y/dummy;
}
if( k[n].vr.x || k[n].vr.y )
{
??? !!! !!! !!!
} */
k[n].v.x += sqrt(ROLL)*k[n].vr.x;
k[n].v.y += sqrt(ROLL)*k[n].vr.y;
k[n].vr.x *= (1-sqrt(ROLL));
k[n].vr.y *= (1-sqrt(ROLL));
k[n].ve.x = sqrt(ROLL)*k[n].v.x;
k[n].ve.y = sqrt(ROLL)*k[n].v.y;
}
void translate_spin( void )
/* Nachdem die Richtung der Geschw. feststeht, wird der Spin, der bisher im
lokalen Koordinatensystem der Kugel festgelegt war auf globale (x,y)-
Koordinaten umgerechnet. Das ist wichtig, da sich das lokale KS drehen
kann, da auch "Curve-Balls" möglich sind... */
{
double puffer, dummy=0; /* k.e.x : senkr., k.e.y: parall. zu k.v(x,y) !!! */
struct vect s, add = { 0, 0 };
/* senkr. Vektor zu v bestimmen: warum: s. unten */
if( alph )
{
s.x = -k[WHITE].v.y; s.y = k[WHITE].v.x;
if( (dummy = BETR( s )) )
{
s.x /= dummy; s.y /= dummy;
dummy = sin( alph * M_PI / 180.0 );
add.x = - s.x * dummy * k[WHITE].ez / DIFFX / CURVES;
add.y = - s.y * dummy * k[WHITE].ez / DIFFX / CURVES;
}
s.x = k[WHITE].v.x; s.y = k[WHITE].v.y;
if( (dummy = BETR( s )) ) /* dummy = dasselbe wie oben !!! !!! !!!*/
{
s.x /= dummy; s.y /= dummy;
dummy = sin( alph * M_PI / 180.0 );
add.x += s.x * dummy * k[WHITE].e.y / DIFFX / CURVEP;
add.y += s.y * dummy * k[WHITE].e.y / DIFFX / CURVEP;
}
}
/* bis hier wurde das "Ausbrechen" des weißen Balls beim Curve-Ball,
also die Zusatzgeschw., die der Ball durch den nicht mittigen Treffpkt
bekommt, wenn der Queue noch dazu nicht parallel zum Tisch steht,
berechnet. jetzt kommt der "normale" Spin und Curve-Ball ... */
if( (k[WHITE].v.x ) || (k[WHITE].v.y ) )
{
dummy = ( k[WHITE].ez*sin( M_PI*alph/180.0) ) /
sqrt(k[WHITE].v.x*k[WHITE].v.x + k[WHITE].v.y*k[WHITE].v.y);
}
puffer = k[WHITE].e.y;
k[WHITE].e.y = k[WHITE].v.x * dummy;
k[WHITE].e.x = - k[WHITE].v.y * dummy;
if( k[WHITE].v.x || k[WHITE].v.y )
{
dummy = puffer /
sqrt(k[WHITE].v.x*k[WHITE].v.x + k[WHITE].v.y*k[WHITE].v.y);
}
else dummy = 0;
k[WHITE].e.y += (- k[WHITE].v.y * dummy);
k[WHITE].e.x += (- k[WHITE].v.x * dummy);
k[WHITE].ez *= cos( M_PI*alph/180.0);
k[WHITE].e.x /= (RADIUS * DIFFX);
k[WHITE].e.y /= (RADIUS * DIFFX);
k[WHITE].v.x += add.x;
k[WHITE].v.y += add.y;
}
void refl_kk( int n, struct vect p)
/* Kollisionsberechnugn zw. Kugeln und der Königsbande, die als infinitesimale
Kugel an der jeweiligen Stelle angenommen wird, sodaß prinzipiell (fast)
jeder Abprall-Winkel an diese Bande möglich ist, Die Berechnung erfolgt
ähnlich wie der Stoß zwischen zwei Kugeln (s. coll() ) und ansonsten analog
reflextion() ... */
{
struct vect ab; /* ab := Abstandsvektor zw. den Mittelpunkten */
double dummy;
ab.x = (k[n].p.x*DIFFX-p.x); ab.y = (k[n].p.y*DIFFX-p.y);
ab.x /= (dummy = BETR( ab )); /* Abfrage, ob dummy != 0 ??? !!! !!! !!!*/
ab.y /= dummy;
if( (ab.x*k[n].v.x+ab.y*k[n].v.y) >= 0 ) return;
/* Berechnung der Geschwindigkeit der Kugel nach der Kollision */
dummy = (k[n].v.x * ab.x + k[n].v.y * ab.y);
k[n].v.x = (BANDEREF * (k[n].v.x - 2 * ab.x * dummy)
- BANDES * ab.y * dummy * k[n].ez);
k[n].v.y = (BANDEREF * (k[n].v.y - 2 * ab.y * dummy)
+ BANDES * ab.x * dummy * k[n].ez);
dummy = k[n].vr.x*ab.x + k[n].vr.y*ab.y;
k[n].vr.x -= ab.x * dummy;
k[n].vr.y -= ab.y * dummy;
k[n].vr.x *= BANDEREF;
k[n].vr.y *= BANDEREF;
dummy = k[n].e.x * ab.x+k[n].e.y*ab.y;
k[n].e.x -= ab.x * dummy;
k[n].e.y -= ab.y * dummy;
k[n].e.x *= BANDEREF;
k[n].e.y *= BANDEREF;
k[n].ez *= (1-BANDEREF);
if( n == WHITE ) set_spin( k[WHITE].e.x, k[WHITE].e.y, k[WHITE].ez );
calc_v_end( n );
bande_hit = 1;
}
void coll( int a, int b)
/* Stoß: Kollisionsberechnung zwischen den Kugeln a und b. Dabei wird die
Masse der jeweiligen Kugel berücksichtigt, da die Weiße wohl manchmal
schwerer ist. Außerdem wird berücksichtigt, daß Kugeln, die ROLLEN, nur
ihre Translationsenergie abgeben könne, während sie die Rotationsenergie
dazu befähigt, noch ein bißchen weiter zu rollen (mit entsprechen
langsamerer Geschwindigkeit. Außerdem verlieren stoßende Kugel einen
Teil ihres z-Spins, da ansonsten an den Banden interessante Effekt, wie
negative Winkel auftreten können (immer noch ?? )*/
{
struct vect ab, v; /* ab := Abstandsvektor zw. den Mittelpunkten */
double dummy, dummy2;
/* Abfrage, ob Kugeln kollidieren dürfen. Das ist der Fall, wenn der
Winkel zwischen Relativgeschw. und Abst.vektor < 90° ist */
if( ( (ab.x = k[a].p.x-k[b].p.x) * (k[a].v.x-k[b].v.x) +
(ab.y = k[a].p.y-k[b].p.y) * (k[a].v.y-k[b].v.y) ) >= 0 )
return;
/* Abstand i.allg. zu klein (wg. Zeitschritten) -> Korrektur: */
v.x = k[a].v.x - k[b].v.x; v.y = k[a].v.y - k[b].v.y;
dummy2 = SKALP( ab, v ) / SKALP( v, v );
dummy = ( SKALP( ab, ab ) - 4*RADIUS*RADIUS/(DIFFX*DIFFX) )
/ SKALP( v, v );
dummy2 += sqrt( dummy2 * dummy2 - dummy );
k[a].p.x -= k[a].v.x * dummy2;
k[a].p.y -= k[a].v.y * dummy2;
k[b].p.x -= k[b].v.x * dummy2;
k[b].p.y -= k[b].v.y * dummy2;
ab.x = k[a].p.x - k[b].p.x;
ab.y = k[a].p.y - k[b].p.y;
/* Ende der "zu kleinen Abstands-korrektur" */
dummy = BETR( ab ); /* ab = abst-vektor normieren */
ab.x /= dummy;
ab.y /= dummy;
/* Abnahme des z-Spins, wenn Kugeln stoßen (gibt's hoffentlich) */
if( k[a].ez && (k[a].v.x || k[a].v.y) )
k[a].ez *= (ab.x * k[a].v.x + ab.y*k[a].v.y) /
sqrt(k[a].v.x*k[a].v.x+k[a].v.y*k[a].v.y) * SPINC;
if( k[b].ez && (k[b].v.x || k[b].v.y) )
k[b].ez *= (ab.x * k[b].v.x + ab.y*k[b].v.y) /
sqrt(k[b].v.x*k[b].v.x+k[b].v.y*k[b].v.y) * SPINC;
/* Berechnung der Geschwindigkeit der Kugeln nach der Kollision mittels:
v2'=(v1*a)*a+v2-(v2*a)*a; v1'=v1-(v1*a)*a+(v2*a)*a (|a|=1, a=Abst.vekt.) */
dummy = (k[a].v.x - k[b].v.x) * ab.x + (k[a].v.y - k[b].v.y) * ab.y;
k[a].v.x -= (2.0*k[b].m/(k[a].m+k[b].m)) * ab.x* du