1 /* $Id: SoloPlay.cpp,v 1.23 2003/07/19 14:25:44 nan Exp $ */
2 
3 // Copyright (C) 2000-2003  $B?@Fn(B $B5H9((B(Kanna Yoshihiro)
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19 #include "ttinc.h"
20 #include "SoloPlay.h"
21 #include "Player.h"
22 #include "Ball.h"
23 #include "Event.h"
24 #include "BaseView.h"
25 #include "RCFile.h"
26 
27 extern RCFile *theRC;
28 
29 extern Ball theBall;
30 extern long mode;
31 extern long wins;
32 
33 //extern void CopyPlayerData( struct PlayerData& dest, Player* src );
34 extern void CopyPlayerData( Player& dest, Player* src );
35 
SoloPlay()36 SoloPlay::SoloPlay() {
37   m_smash = false;
38   m_smashCount = 0;
39   m_smashPtr = -1;
40 }
41 
~SoloPlay()42 SoloPlay::~SoloPlay() {
43 }
44 
45 bool
Init()46 SoloPlay::Init() {
47   m_View = (PlayGameView *)View::CreateView( VIEW_PLAYGAME );
48 
49   m_View->Init( this );
50 
51   BaseView::TheView()->AddView( m_View );
52 
53   return true;
54 }
55 
56 void
Create(long player,long com)57 SoloPlay::Create( long player, long com ) {
58   Control::ClearControl();
59 
60   m_theControl = new SoloPlay();
61   m_theControl->Init();
62 
63 #ifdef SCREENSHOT
64   m_thePlayer = Player::Create( 0, 1, 1 );
65   m_comPlayer = Player::Create( 0, -1, 1 );
66 #else
67   m_thePlayer = Player::Create( player, 1, 0 );
68   m_comPlayer = Player::Create( com, -1, 1 );
69 #endif
70 
71   m_thePlayer->Init();
72   m_comPlayer->Init();
73 }
74 
75 bool
Move(SDL_keysym * KeyHistory,long * MouseXHistory,long * MouseYHistory,unsigned long * MouseBHistory,int Histptr)76 SoloPlay::Move( SDL_keysym *KeyHistory, long *MouseXHistory,
77 		    long *MouseYHistory, unsigned long *MouseBHistory,
78 		    int Histptr ) {
79   bool reDraw = false;
80   long prevStatus = theBall.GetStatus();
81 
82   if ( KeyHistory[Histptr].unicode == 'Q' ) {
83     wins = 0;
84     mode = MODE_TITLE;
85     return true;
86   }
87 
88   if ( m_smashPtr >= 0 ) {	// Smash replay
89     ReplayAction( Histptr );
90 
91     if ( Histptr == m_smashPtr ) {
92       SmashEffect(false, Histptr);
93       m_smashCount++;
94       if ( m_smashCount > 1 ) {
95 	m_smashCount = 0;
96 	m_smashPtr = -1;
97 	m_smash = false;
98       } else {
99 	m_smashPtr = SmashEffect(true, Histptr);
100       }
101     } else {
102       theBall.Move();
103 #ifdef SCREENSHOT
104       reDraw |= m_thePlayer->Move( NULL, NULL, NULL, NULL, 0 );
105 #else
106       reDraw |= m_thePlayer->Move( KeyHistory, MouseXHistory,
107 				 MouseYHistory, MouseBHistory, Histptr );
108 #endif
109       reDraw |= m_comPlayer->Move( NULL, NULL, NULL, NULL, 0 );
110 
111       Event::TheEvent()->BackTrack(Histptr);
112     }
113 
114     return true;
115   }
116 
117   theBall.Move();
118 #ifdef SCREENSHOT
119   reDraw |= m_thePlayer->Move( NULL, NULL, NULL, NULL, 0 );
120 #else
121   reDraw |= m_thePlayer->Move( KeyHistory, MouseXHistory,
122 			     MouseYHistory, MouseBHistory, Histptr );
123 #endif
124   reDraw |= m_comPlayer->Move( NULL, NULL, NULL, NULL, 0 );
125 
126   // Check smash replay
127   if ( theBall.GetStatus() == 1 && prevStatus != 1 ) {
128     if ( hypot( theBall.GetVY(), theBall.GetVZ() ) > 8.0 ) {
129       m_smash = true;
130     } else
131       m_smash = false;
132   } else if ( theBall.GetStatus() == 2 || theBall.GetStatus() == 8 ) {
133     m_smash = false;
134   }
135 
136   if ( m_smash && theBall.GetStatus() < 0 )
137     m_smashPtr = SmashEffect(true, Histptr);
138 
139   return true;
140 }
141 
142 bool
LookAt(double & srcX,double & srcY,double & srcZ,double & destX,double & destY,double & destZ)143 SoloPlay::LookAt( double &srcX, double &srcY, double &srcZ,
144 		  double &destX, double &destY, double &destZ ) {
145   if (m_thePlayer) {
146     if ( m_smashPtr >= 0 ) {	// Smash replay
147       switch (m_smashCount) {
148       case 0:
149 	srcX = 0;
150 	srcY = TABLELENGTH*m_thePlayer->GetSide();
151 	srcZ = 1.6;
152 
153 	destX = 0;
154 	destY = -TABLELENGTH/2*m_thePlayer->GetSide();
155 	destZ = TABLEHEIGHT;
156 	break;
157       case 1:
158 	srcX = -TABLEWIDTH;
159 	srcY = 0;
160 	srcZ = 1.6;
161 
162 	destX = theBall.GetX();
163 	destY = theBall.GetY();
164 	destZ = theBall.GetZ();
165 	break;
166       default:
167 	printf( "%d\n", (int)m_smashCount );
168       }
169     } else {
170       srcX = m_thePlayer->GetX() + m_thePlayer->GetEyeX();
171       srcY = m_thePlayer->GetY() + m_thePlayer->GetEyeY();
172       srcZ = m_thePlayer->GetZ() + m_thePlayer->GetEyeZ();
173       destX = m_thePlayer->GetLookAtX();
174       destY = m_thePlayer->GetLookAtY();
175       destZ = m_thePlayer->GetLookAtZ();
176     }
177   }
178 
179   return true;
180 }
181 
182 long
SmashEffect(bool start,long histPtr)183 SoloPlay::SmashEffect( bool start, long histPtr ) {
184   static Player p1, p2;
185   static Ball b;
186   static long score1, score2;
187 
188   long smashPtr;
189 
190   smashPtr = histPtr-1;
191   if ( smashPtr < 0 )
192     smashPtr = MAX_HISTORY-1;
193 
194   if (start) {
195     CopyPlayerData( p1, m_thePlayer );
196     CopyPlayerData( p2, m_comPlayer );
197     b = theBall;
198     score1 = m_Score1;
199     score2 = m_Score2;
200 
201     for ( int i = 0 ; i < MAX_HISTORY ; i++ ) {
202       Event::TheEvent()->BackTrack( histPtr );
203       if ( theBall.GetStatus() == 2 )
204 	break;
205 
206       histPtr--;
207       if ( histPtr < 0 )
208 	histPtr = MAX_HISTORY-1;
209     }
210 
211     Event::TheEvent()->BackTrack( histPtr );
212   } else {
213     m_thePlayer->Reset( &p1 );
214     m_comPlayer->Reset( &p2 );
215     theBall = b;
216     m_Score1 = score1;
217     m_Score2 = score2;
218   }
219 
220   return smashPtr;
221 }
222 
223 void
ReplayAction(int & Histptr)224 SoloPlay::ReplayAction( int &Histptr ) {
225   static long delayCounter = 0;
226 
227   // If mouse button is pressed, stop replay
228   // (Unless it is the last 1 second).
229   if ( Event::TheEvent()->m_mouseButton && m_smashCount < 1 ) {
230     Histptr = m_smashPtr;
231     SmashEffect( false, Histptr );
232     m_smashCount = 0;
233     m_smashPtr = -1;
234     m_smash = false;
235 
236     return;
237   }
238 
239   delayCounter++;
240   if ( theBall.GetStatus() == 3 &&
241        (delayCounter%5) != 0 ) {
242     Histptr--;
243     if ( Histptr < 0 )
244       Histptr = MAX_HISTORY-1;
245     Event::TheEvent()->BackTrack(Histptr);
246     return;
247   }
248 }
249