4 #include "GVOGameProcess.h"
5 #include "GVOWorldMap.h"
6 #include "GVOSurveyCoordExtractor.h"
9 //
\89æ
\91\9c\89ð
\90Í
\83f
\83o
\83b
\83O
\97p
\81BGVOGameProcess
10 //#define GVO_ANALYZE_DEBUG
12 extern HWND g_hwndMain;
16 #ifdef GVO_ANALYZE_DEBUG
17 LPCWSTR const k_debugImageFileName = L"..\\debug.png";
21 //
\83f
\83o
\83b
\83O
\97p
\8e©
\93®
\8dq
\8ds
\95Ï
\90\94
22 static double s_xDebugAutoCruise;
23 static double s_yDebugAutoCruise;
24 static double s_debugAutoCruiseAngle = 0;
25 static bool s_debugAutoCruiseEnabled = false;
26 static double s_debugAutoCruiseVelocity = 0;
27 static uint32_t s_debugAutoCruiseTurnInterval;
28 static double s_debugAutoCruiseTurnAngle;
31 LPWSTR const k_gvoWindowClassName = L"Greate Voyages Online Game MainFrame";
32 LPWSTR const k_gvoWindowCaption = L"
\91å
\8dq
\8aC
\8e\9e\91ã Online";
34 const POINT k_surveyCoordOffsetFromRightBottom = { 70, 273 };
35 const SIZE k_surveyCoordSize = { 60, 11 };
40 void GVOGameProcess::clear()
43 ::CloseHandle( m_process );
50 void GVOGameProcess::setup( const GVOConfig& config )
52 m_surveyCoord = config.m_initialSurveyCoord;
53 m_ship.setInitialSurveyCoord( config.m_initialSurveyCoord );
54 m_pollingInterval = config.m_pollingInterval;
56 s_xDebugAutoCruise = config.m_initialSurveyCoord.x;
57 s_yDebugAutoCruise = config.m_initialSurveyCoord.y;
58 s_debugAutoCruiseEnabled = config.m_debugAutoCruiseEnabled;
59 s_debugAutoCruiseVelocity = config.m_debugAutoCruiseVelocity;
60 s_debugAutoCruiseTurnInterval = config.m_debugAutoCruiseTurnInterval;
61 s_debugAutoCruiseTurnAngle = config.m_debugAutoCruiseTurnAngle;
64 m_pollingTimerEventID = ::timeSetEvent( m_pollingInterval, 1, LPTIMECALLBACK( m_pollingTimerEvent ), 0, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET );
65 m_threadQuitSignal = ::CreateEvent( NULL, TRUE, FALSE, NULL );
66 m_workerThread = (HANDLE)::_beginthreadex( NULL, 0, threadMainThunk, this, 0, NULL );
70 void GVOGameProcess::teardown()
72 if ( m_workerThread ) {
73 ::SetEvent( m_threadQuitSignal );
74 ::WaitForSingleObject( m_workerThread, INFINITE );
75 ::CloseHandle( m_workerThread );
76 ::CloseHandle( m_threadQuitSignal );
77 m_threadQuitSignal = NULL;
78 m_workerThread = NULL;
80 if ( m_pollingTimerEventID ) {
81 ::timeKillEvent( m_pollingTimerEventID );
82 m_pollingTimerEventID = 0;
88 void GVOGameProcess::enableDebugAutoCruise( bool enabled )
90 s_debugAutoCruiseEnabled = enabled;
94 bool GVOGameProcess::updateState()
99 #ifdef GVO_ANALYZE_DEBUG
101 static bool done = false;
109 static GVOImage debugImage;
110 if ( !debugImage.bitmapHandle() ) {
111 if ( !debugImage.loadFromFile( ::g_makeFullPath( k_debugImageFileName ) ) ) {
112 ::MessageBox( NULL, L"
\83f
\83o
\83b
\83O
\83C
\83\81\81[
\83W
\82ª
\82È
\82¢
\82æ", L"
\82¦
\82ç
\81[", MB_ICONERROR );
116 HDC hdc = ::GetWindowDC( ::GetDesktopWindow() );
117 HDC hdcMem = ::CreateCompatibleDC( hdc );
119 ::SelectObject( hdcMem, debugImage.bitmapHandle() );
120 grabImage( hdcMem, POINT(), debugImage.size() );
122 ::RestoreDC( hdcMem, -1 );
123 ::DeleteDC( hdcMem );
124 ::ReleaseDC( NULL, hdc );
132 if ( s_debugAutoCruiseEnabled ) {
133 static bool isRandInitialized = false;
134 if ( !isRandInitialized ) {
135 srand( ::timeGetTime() );
136 isRandInitialized = true;
139 const double rad = ((s_debugAutoCruiseAngle)* M_PI) / 180;
140 const double vx = ::cos( rad );
141 const double vy = ::sin( rad );
143 s_xDebugAutoCruise += vx * s_debugAutoCruiseVelocity;
144 s_yDebugAutoCruise += vy * s_debugAutoCruiseVelocity;
146 static DWORD tick = ::timeGetTime();
147 static DWORD count = 0;
148 if ( (tick + s_debugAutoCruiseTurnInterval) < ::timeGetTime() ) {
149 if ( 10 < (++count) ) {
151 s_debugAutoCruiseAngle += 90 + (LONG( rand() / double( RAND_MAX ) * 90 ) & ~0x1);
154 s_debugAutoCruiseAngle += (rand() & 1) ? s_debugAutoCruiseTurnAngle : -s_debugAutoCruiseTurnAngle;
156 tick = ::timeGetTime();
158 s_debugAutoCruiseAngle = fmod( ::fabs( s_debugAutoCruiseAngle ), 360 );
160 if ( s_xDebugAutoCruise < 0 ) {
161 s_xDebugAutoCruise += k_worldWidth;
163 if ( s_yDebugAutoCruise < 0 ) {
164 s_yDebugAutoCruise += k_worldHeight;
166 s_xDebugAutoCruise = fmod( s_xDebugAutoCruise, (double)k_worldWidth );
167 s_yDebugAutoCruise = fmod( s_yDebugAutoCruise, (double)k_worldHeight );
169 ////
\92n
\90}
\82ð
\8c×
\82®
\8f\88\97\9d\82Ì
\8am
\94F
\97p
\83f
\83o
\83b
\83O
\83R
\81[
\83h
170 //if ( 100 <= s_xDebugAutoCruise && s_xDebugAutoCruise <= (GVOWorldMap::k_worldWidth - 100) ) {
171 // s_xDebugAutoCruise = 0;
174 m_surveyCoord.x = LONG( s_xDebugAutoCruise );
175 m_surveyCoord.y = LONG( s_yDebugAutoCruise );
176 uint32_t timeStamp = ::timeGetTime();
177 m_speedMeter.updateVelocity( m_ship.velocity(), timeStamp );
178 m_ship.updateWithSurveyCoord( m_surveyCoord, timeStamp );
180 status.m_surveyCoord = m_surveyCoord;
181 status.m_shipVector = m_ship.vector();
182 status.m_shipVelocity = m_speedMeter.velocity();
183 status.m_timeStamp = timeStamp;
185 ::EnterCriticalSection( &m_lock );
186 m_statusArray.push_back( status );
187 ::SetEvent( m_dataReadyEvent );
188 ::LeaveCriticalSection( &m_lock );
194 m_window = ::FindWindow( k_gvoWindowClassName, k_gvoWindowCaption );
199 ::GetWindowThreadProcessId( m_window, &pid );
200 m_process = ::OpenProcess( SYNCHRONIZE, FALSE, pid );
204 POINT clientOrg = { 0 };
205 ::ClientToScreen( m_window, &clientOrg );
206 ::GetClientRect( m_window, &rc );
211 HDC hdc = ::GetDC( ::GetDesktopWindow() );
215 grabImage( hdc, clientOrg, size );
216 ::ReleaseDC( ::GetDesktopWindow(), hdc );
217 m_timeStamp = ::timeGetTime();
219 if ( !updateSurveyCoord() ) {
223 m_speedMeter.updateVelocity( m_ship.velocity(), m_timeStamp );
224 m_ship.updateWithSurveyCoord( m_surveyCoord, m_timeStamp );
226 status.m_surveyCoord = m_surveyCoord;
227 status.m_shipVector = m_ship.vector();
228 status.m_shipVelocity = m_speedMeter.velocity();
229 status.m_timeStamp = m_timeStamp;
231 ::EnterCriticalSection( &m_lock );
232 m_statusArray.push_back( status );
233 ::SetEvent( m_dataReadyEvent );
234 ::LeaveCriticalSection( &m_lock );
241 std::vector<GVOGameStatus> GVOGameProcess::getState()
243 std::vector<GVOGameStatus> statusArray;
245 ::EnterCriticalSection( &m_lock );
246 m_statusArray.swap( statusArray );
247 ::ResetEvent( m_dataReadyEvent );
248 ::LeaveCriticalSection( &m_lock );
254 UINT CALLBACK GVOGameProcess::threadMainThunk( LPVOID arg )
256 GVOGameProcess *self = reinterpret_cast<GVOGameProcess *>(arg);
262 void GVOGameProcess::threadMain()
264 std::vector<HANDLE> signals;
265 signals.push_back( m_threadQuitSignal );
266 signals.push_back( m_pollingTimerEvent );
269 const DWORD ret = ::WaitForMultipleObjects( signals.size(), &signals[0], FALSE, INFINITE );
270 if ( signals.size() <= ret ) {
273 HANDLE const active = signals[ret];
274 if ( active == m_threadQuitSignal ) {
278 if ( active == m_pollingTimerEvent ) {
279 ::ResetEvent( m_pollingTimerEvent );
289 void GVOGameProcess::grabImage( HDC hdc, const POINT& offset, const SIZE& size )
291 if ( !m_surveyCoordImage.bitmapHandle() ) {
292 m_surveyCoordImage.createDIBImage( k_surveyCoordSize );
295 HDC hdcMem = ::CreateCompatibleDC( hdc );
298 const int leftEdge = offset.x;
299 const int rightEdge = leftEdge + size.cx;
300 const int topEdge = offset.y;
301 const int bottomEdge = offset.y + size.cy;
303 //
\91ª
\97Ê
\8dÀ
\95W
\83L
\83\83\83v
\83`
\83\83
304 const int xSurvey = rightEdge - k_surveyCoordOffsetFromRightBottom.x;
305 const int ySurvey = bottomEdge - k_surveyCoordOffsetFromRightBottom.y;
306 ::SelectObject( hdcMem, m_surveyCoordImage.bitmapHandle() );
307 ::BitBlt( hdcMem, 0, 0, k_surveyCoordSize.cx, k_surveyCoordSize.cy, hdc, xSurvey, ySurvey, SRCCOPY );
310 ::RestoreDC( hdcMem, -1 );
311 ::DeleteDC( hdcMem );
315 bool GVOGameProcess::updateSurveyCoord()
317 bool succeeded = false;
318 GVOSurveyCoordExtractor extractor( m_surveyCoordImage );
320 const std::vector<int>& values = extractor.extractNumbers();
321 if ( values.size() == 2 ) {
322 m_surveyCoord.x = values[0];
323 m_surveyCoord.y = values[1];