1 #ifndef _global_h
2 #	include "global.h"
3 #endif
4 
5 #ifndef _arcs_h
6 #	include "arcs.h"
7 #endif
8 #ifndef _ball_h
9 #	include "ball.h"
10 #endif
11 #ifndef _game_h
12 #	include "game.h"
13 #endif
14 
15 //
16 // ============================================================================
17 // class StaticArc
18 // ============================================================================
19 //
20 
StaticArc(double x,double y,double r_in,double start_in,double angle_in)21 StaticArc::StaticArc( double x, double y, double r_in, double start_in, double angle_in )
22 : p( x, y )
23 {
24 	type			= StaticArcObj;
25 	this->r     = r_in;
26 	this->start = start_in;
27 	this->angle = angle_in;
28 }
StaticArc(const Vec2 & v,const Real & r_in,const Real & start_in,const Real & angle_in)29 StaticArc::StaticArc( const Vec2 &v, const Real &r_in,
30 										const Real &start_in, const Real &angle_in )
31 : p( v ), r(r_in), start(start_in), angle(angle_in)
32 {
33 	type			= StaticArcObj;
34 }
~StaticArc()35 StaticArc::~StaticArc() { }
36 
HitFromBallTwice(int outer_hit,Ball * b,const Vec2 & dv,Real md,Real * time_out)37 int StaticArc::HitFromBallTwice( int outer_hit, Ball *b, const Vec2 &dv,
38 											Real md, Real *time_out )
39 {
40 	Vec2	d  = P() - b->P();				// Abstandsvektor
41 
42 #if (ABORT_CALC_BALL)
43 //
44 // Abstand mit maximal Geschwindigkeitsbetrag vergleichen
45 //
46 		if ( (d.Norm()-md)/sqrt(sq)>b->collision_time-current_time+EPS)
47 																						return 2;
48 #endif
49 
50 	Real	m  = (d.X()*dv.X()+d.Y()*dv.Y());
51 			if (outer_hit&&(m<-EPS))		return 1;
52 
53 	Real	sq = dv.SqrNorm();
54 			if (sq<EPS)							return 1;
55 
56 			m /= sq;
57 	Real	f  = (md*md-d.SqrNorm())/sq + (m*m);
58 			if (f<=0.0)							return 1;
59 			f = sqrt(f);
60 
61 	Real	f1 =  f+m;
62 	Real	f2 = -f+m;
63 
64 			if (f1<f2) {	*time_out = (outer_hit)?f1:f2;	}
65 			else {			*time_out = (outer_hit)?f2:f1;	}
66 
67 			return 0;
68 }
69 
IsOnArc(const Vec2 & d)70 int StaticArc::IsOnArc( const Vec2 &d )
71 {
72 Real	a = P().AngleDeg(d);
73 
74 		a-=start;
75 		if ( angle>=0.0 ) {
76 			if (a<0.0)		a+=360.0;
77 			return ( (a>=0.0)&&(a<=angle) )?1:0;
78 		}
79 		else {
80 			if (a>0.0)		a-=360.0;
81 			return ( (a<=0.0)&&(a>=angle) )?1:0;
82 		}
83 }
84 
CollideWithBall(Ball * b)85 void StaticArc::CollideWithBall( Ball *b ) {
86 Vec2	x, y;
87 Vec2	dist=P()-b->P();
88 
89 	g->HitWall(b);
90 	b->V().Split( dist, &x, &y );			// Ball b wird direkt zur�ckgesto�en
91 	b->SetV( y-x );
92 }
93 
Info()94 void StaticArc::Info() {
95 	printf( "%02d: StaticArc: %08lx: P()=(%4.1f,%4.1f), R()=%3.1f, %f-%f\n",
96 				id, (unsigned long)this,
97 				(double)PX(), (double)PY(), (double)R(),
98 				(double)start, (double)angle );
99 }
100 
OuterHitFromBall(Ball * b,const Vec2 & dv)101 Real StaticArc::OuterHitFromBall( Ball *b, const Vec2 &dv ) {
102 Real	otime;
103 
104 	switch( HitFromBallTwice( 1, b, dv, R()+b->R(), &otime ) ) {
105 	case 1:		return NO_HIT;
106 #if (ABORT_CALC_BALL)
107 	case 2:
108 				DBG2(AbortCalc,"    OuterHit from %d to %d aborted.\n", b->Object::id, id );
109 				return NOT_REACHABLE;
110 #endif
111 	default:
112 		if (otime>-EPS)	return otime;
113 		else					return NO_HIT;
114 	}
115 }
116 
InnerHitFromBall(Ball * b,const Vec2 & dv)117 Real StaticArc::InnerHitFromBall( Ball *b, const Vec2 &dv ) {
118 Real	itime;
119 
120 	if (b->R()>r)		return NO_HIT;	// Ball zu gro� f�r inneren Treffer
121 
122 	switch (HitFromBallTwice( 0, b, dv, R()-b->R(), &itime )) {
123 	case 1:		return NO_HIT;
124 #if (ABORT_CALC_BALL)
125 	case 2:
126 				DBG2(AbortCalc,"    InnerHit from %d to %d aborted.\n", b->Object::id, id );
127 				return NOT_REACHABLE;
128 #endif
129 	default:
130 		if (itime>-EPS)	return itime;
131 		else					return NO_HIT;
132 	}
133 }
134 
135 //
136 // class OuterArc
137 //
~OuterArc()138 OuterArc::~OuterArc()		{}
139 
Info()140 void OuterArc::Info() {
141 	printf( "%02d: OuterArc:   %08lx: P()=(%4.1f,%4.1f), R()=%3.1f, %f-%f\n",
142 				id, (unsigned long)this,
143 				(double)PX(), (double)PY(), (double)R(),
144 				(double)start, (double)angle );
145 }
146 
HitFromBall(Ball * b)147 Real OuterArc::HitFromBall( Ball *b ) {
148 	if (b->IsIdle())		return MAX_TIME;
149 	return OuterHitFromBall(b,b->V());
150 }
151 
152 //
153 // class InnerArc
154 //
~InnerArc()155 InnerArc::~InnerArc()	{}
156 
Info()157 void InnerArc::Info() {
158 	printf( "%02d: InnerArc:   %08lx: P()=(%4.1f,%4.1f), R()=%3.1f, %f-%f\n",
159 				id, (unsigned long)this,
160 				(double)PX(), (double)PY(), (double)R(),
161 				(double)start, (double)angle );
162 }
163 
HitFromBall(Ball * b)164 Real InnerArc::HitFromBall( Ball *b ) {
165 	if (b->IsIdle())		return MAX_TIME;
166 	return InnerHitFromBall(b,b->V());
167 }
168 
169 //
170 // class ArcWall
171 //
~ArcWall()172 ArcWall::~ArcWall()	{}
173 
Info()174 void ArcWall::Info() {
175 	printf( "%02d: ArcWall:    %08lx: P()=(%4.1f,%4.1f), R()=%3.1f, %f-%f\n",
176 				id, (unsigned long)this,
177 				(double)PX(), (double)PY(), (double)R(),
178 				(double)start, (double)angle );
179 }
180 
HitFromBall(Ball * b)181 Real ArcWall::HitFromBall( Ball *b ) {
182 Real	itime, otime;
183 
184 	if (b->IsIdle())		return MAX_TIME;
185 
186 	itime = InnerHitFromBall(b,b->V());
187 	if ( (itime<NO_HIT)&&(!IsOnArc(b->P()+itime*b->V())))	itime = NO_HIT;
188 	otime = OuterHitFromBall(b,b->V());
189 	if ( (otime<NO_HIT)&&(!IsOnArc(b->P()+otime*b->V())))	otime = NO_HIT;
190 	return( (itime<otime)?itime:otime );
191 }
192 
193 //
194 // ============================================================================
195 // class StaticBall, unbewegliche Kugel (unendlicher Masse)
196 // ============================================================================
197 //
Info()198 void StaticBall::Info() {
199 	printf( "%02d: StaticBall: %08lx: P()=(%4.1f,%4.1f), R()=%3.1f\n",
200 				id, (unsigned long)this,
201 				(double)PX(), (double)PY(), (double)R() );
202 }
203 
~StaticBall()204 StaticBall::~StaticBall()	{}
205