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