OSDN Git Service

速度計実装。
authorMandhelingFreak <mandheling30-freak@yahoo.co.jp>
Sun, 2 Feb 2014 14:37:08 +0000 (23:37 +0900)
committerMandhelingFreak <mandheling30-freak@yahoo.co.jp>
Mon, 3 Feb 2014 09:49:38 +0000 (18:49 +0900)
針路予測線の色をマゼンダに変更。

GVONavish/GVONavish/GVONavish.cpp
GVONavish/GVONavish/GVONavish.vcxproj
GVONavish/GVONavish/GVONavish.vcxproj.filters
GVONavish/GVONavish/GVOShip.cpp
GVONavish/GVONavish/GVOShip.h
GVONavish/GVONavish/GVOSpeedMeter.h [new file with mode: 0644]
GVONavish/GVONavish/GVOWorldMap.cpp

index a30f3d5..d7e4695 100644 (file)
@@ -21,6 +21,7 @@
 #include "GVOGameProcess.h"
 #include "GVOWorldMap.h"
 #include "GVOShip.h"
+#include "GVOSpeedMeter.h"
 
 
 
@@ -29,7 +30,7 @@
 //#define GVO_PERF_CHECK
 
 // \93K\93\96\82É\93®\82«\89ñ\82é\83f\83o\83b\83O\83R\81[\83h
-#define DEBUG_AUTO_CRUISE
+//#define DEBUG_AUTO_CRUISE
 
 
 
@@ -92,6 +93,7 @@ static GVOConfig s_config( k_configFileName );
 static GVOGameProcess s_gvoGameProcess;
 static GVOWorldMap s_worldMap;
 static GVOShip s_ship;
+static GVOSpeedMeter s_speedMeter;
 
 static UINT s_pollingInterval = 1000;  // \8fó\91Ô\8aÄ\8e\8b\8aÔ\8au\81i1\95b\81j
 static bool s_isUpdated = false;               // \8fó\91Ô\8dX\90V\83t\83\89\83O
@@ -106,7 +108,7 @@ static double xAutoCruise = s_config.m_initialSurveyCoord.x;
 static double yAutoCruise = s_config.m_initialSurveyCoord.y;
 static const double k_AutoCruiseLength = 3.3;
 static const int k_autoCruiseAngle = 12;
-static const DWORD k_refreshIntervalForAutoCruise = 1000;
+static const DWORD k_refreshIntervalForAutoCruise = 1;
 static const DWORD k_autoCruiseTurnInterval = 7 * 1000;
 
 static double s_autoCruiseAngle = 0;
@@ -115,10 +117,6 @@ static double s_autoCruiseAngle = 0;
 
 
 
-
-
-
-
 int APIENTRY _tWinMain( _In_ HINSTANCE hInstance,
        _In_opt_ HINSTANCE hPrevInstance,
        _In_ LPTSTR    lpCmdLine,
@@ -402,6 +400,7 @@ static bool s_onTimer( HWND hwnd, UINT_PTR timerID, TIMERPROC /*timerFunction*/
                        LONG( yAutoCruise )
                };
                s_ship.updateWithSurveyCoord( p );
+               s_speedMeter.updateVelocity( s_ship.velocity(), ::timeGetTime() );
                s_gvoGameProcess.setSurveyCoord( p );
                s_worldMap.setShipPosition( p, s_config.m_traceShipPositionEnabled );
                HDC hdc = ::GetDC( hwnd );
@@ -418,6 +417,7 @@ static bool s_onTimer( HWND hwnd, UINT_PTR timerID, TIMERPROC /*timerFunction*/
        if ( s_isUpdated ) {
                s_config.m_initialSurveyCoord = s_gvoGameProcess.surveyCoord();
                s_ship.updateWithSurveyCoord( s_gvoGameProcess.surveyCoord() );
+               s_speedMeter.updateVelocity( s_ship.velocity(), s_gvoGameProcess.timeStamp() );
                s_worldMap.setShipPosition( s_gvoGameProcess.surveyCoord(), s_config.m_traceShipPositionEnabled );
                HDC hdc = ::GetDC( hwnd );
                s_worldMap.updateShipRouteMap( hdc );
@@ -587,6 +587,20 @@ static void s_onPaint( HWND hwnd )
        // \95`\89æ\82ðhdcBackbuffer\82É\91Î\82µ\82Ä\8ds\82¤\81B
        s_worldMap.drawMap( hdcBackbuffer, s_ship );
 
+       // \91¬\93x\8cv\82ð\95`\89æ
+       {
+               const double velocity = s_speedMeter.velocityByKnot();
+               wchar_t buf[4096] = { 0 };
+               swprintf( buf, _countof( buf ), L"%.2f kt", velocity );
+
+               RECT rc = { 0 };
+               ::DrawText( hdcBackbuffer, buf, -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_TOP | DT_CALCRECT );
+               const int width = rc.right - rc.left;
+               rc.left = s_clientSize.cx - width;
+               rc.right = rc.left + width;
+               ::DrawText( hdcBackbuffer, buf, -1, &rc, DT_SINGLELINE | DT_RIGHT | DT_TOP );
+       }
+
 #ifndef NDEBUG
        // \91ª\97Ê\8dÀ\95W\82ð\95`\89æ
        const GVOImage& surveyCoordImage = s_gvoGameProcess.surveyCoordImage();
index 1bb4c40..67dcea2 100644 (file)
@@ -103,6 +103,7 @@ copy /Y "$(ProjectDir)readme.txt" "$(SolutionDir)archive\$(ProjectName)\readme.t
     <ClInclude Include="GVOGameProcess.h" />
     <ClInclude Include="GVOImage.h" />
     <ClInclude Include="GVONavish.h" />
+    <ClInclude Include="GVOSpeedMeter.h" />
     <ClInclude Include="GVOSurveyCoordExtractor.h" />
     <ClInclude Include="GVOVector.h" />
     <ClInclude Include="GVOWorldMap.h" />
index 20da581..541bdc4 100644 (file)
@@ -48,6 +48,9 @@
     <ClInclude Include="GVOVector.h">
       <Filter>ヘッダー ファイル</Filter>
     </ClInclude>
+    <ClInclude Include="GVOSpeedMeter.h">
+      <Filter>ヘッダー ファイル</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
index 098035a..29b166d 100644 (file)
@@ -1,7 +1,6 @@
 #include "stdafx.h"
-#include "GVOShip.h"
 #include <string>
-
+#include "GVOShip.h"
 
 namespace {
        // \83Q\81[\83\80\93à\8ap\93x\81i\82Q\93x\90¸\93x\81j\82É\8aÛ\82ß\82é
@@ -48,13 +47,14 @@ namespace {
 }
 
 
-void GVOShip::updateWithSurveyCoord( const POINT& surveyCoord)
+void GVOShip::updateWithSurveyCoord( const POINT& surveyCoord )
 {
        const GVOVector v( m_surveyCoord, surveyCoord );
-       const double velocity = v.length();
+
+       m_velocity = v.length();
 
        // \88Ú\93®\82µ\82Ä\82È\82¯\82ê\82Î\96³\8e\8b\82·\82é\81B
-       if ( velocity == 0.0 ) {
+       if ( v.length() == 0.0 ) {
                return;
        }
        m_surveyCoord = surveyCoord;
@@ -77,16 +77,11 @@ void GVOShip::updateWithSurveyCoord( const POINT& surveyCoord)
        }
        m_vector = s_roundInGameVector( headVector.normalizedVector() );
 
-       // \8dÅ\90V\82Ì\83x\83N\83g\83\8b\82ª\83p\83\89\83\81\81[\83^\82Æ\93¯\88ê\95û\8cü\82È\82ç\8d\87\90¬\82·\82é\81B\95Ê\95û\8cü\82È\82ç\83\8a\83X\83g\82É\89Á\82¦\82é\81B
-       if ( !m_vectorArray.empty() && (m_vectorArray.back().angleTo( v ) == 0.0) ) {
-               m_vectorArray.back().composite( v );
-       }
-       else {
-               m_vectorArray.push_back( v );
-       }
+       // \8dÅ\90V\82Ì\83x\83N\83g\83\8b\82ð\83\8a\83X\83g\82É\89Á\82¦\82é\81B
+       m_vectorArray.push_back( v );
 
        // \8cv\8eZ\8fã\82Í90\82 \82ê\82Î\8ap\93x\82ª\8eZ\8fo\82Å\82«\82é\82Í\82¸\82¾\82ª\8cë\8d·\82ð\93¥\82Ü\82¦\82Ä2\94{\82Ì\8b\97\97£\82ð\95Û\8e\9d\82µ\82Ä\82¨\82­
-       if ( 180 < headVector.length() ) {
+       if ( 180 < (headVector.length() - m_vectorArray.front().length()) ) {
                m_vectorArray.pop_front();
        }
 }
index cc8c351..26216b0 100644 (file)
@@ -17,10 +17,12 @@ private:
        GVOVector m_vector;                     //!<@brief \8e©\91D\82Ì\83x\83N\83g\83\8b
 
        VectorArray m_vectorArray;
+       double m_velocity;
 
 public:
        GVOShip() :
-               m_surveyCoord()
+               m_surveyCoord(),
+               m_velocity()
        {
        }
 
@@ -48,4 +50,9 @@ public:
                };
                return p;
        }
+
+       inline double velocity() const
+       {
+               return m_velocity;
+       }
 };
diff --git a/GVONavish/GVONavish/GVOSpeedMeter.h b/GVONavish/GVONavish/GVOSpeedMeter.h
new file mode 100644 (file)
index 0000000..e5fd7ff
--- /dev/null
@@ -0,0 +1,121 @@
+#pragma once
+#include <deque>
+#include <algorithm>
+
+
+class GVOSpeedMeter {
+private:
+       typedef std::deque<double> Array;
+       struct VelocityLogItem {
+               uint32_t timeStamp;
+               double velocity;
+
+               VelocityLogItem() :
+                       timeStamp(),
+                       velocity()
+               {
+               }
+               VelocityLogItem( const uint32_t timeStamp, const double velocity ) :
+                       timeStamp( timeStamp ),
+                       velocity( velocity )
+               {
+               }
+       };
+       typedef std::deque<VelocityLogItem> VelocityyArray;
+       typedef std::deque<double> VelocityLog;
+       const uint32_t k_velocityMeasuringDistance = 5000;
+
+private:
+       VelocityyArray m_velocityArray;
+       VelocityLog m_velocityLog;
+       double m_velocity;
+
+public:
+
+       GVOSpeedMeter() :
+               m_velocity()
+       {
+       }
+
+       ~GVOSpeedMeter()
+       {
+       }
+
+       inline void updateVelocity( const double velocity, const uint32_t timeStamp )
+       {
+               m_velocityArray.push_back( VelocityLogItem( timeStamp, velocity ) );
+
+               removeOldItem( timeStamp );
+               updateVelocityLog();
+
+               m_velocity = fastestVelocity();;
+       }
+
+       // Google\90æ\90\9eH\82­\81u\92n\8b\85\82Ì\8aO\8eü\82Í40,075km\81v\81u1\83m\83b\83g\82Í1.85200km\81v
+       // 1\90¢\8aE\8dÀ\95W\82Í40,075km/16384points
+       // \8eÀ\8e\9e\8aÔ1\95b\82Å\83Q\81[\83\80\93à0.4\8e\9e\8aÔ
+       //
+       // \90Ô\93¹\94¼\8ca\82Í6378.137\82Æ\82·\82é\82Æ\8aO\8eü\82Í2*M_PI_*6378.137=40075.016685578483111
+       inline double velocityByKnot() const
+       {
+               // 
+               //static const double k_knotFactor = 40075.0 / 16384.0 / 0.4 / 1.85200;
+               static const double k_knotFactor = (2 * M_PI * 6378.137) / 16384.0 / 0.4 / 1.85200;
+               return m_velocity * k_knotFactor;
+       }
+
+private:
+       inline double calcVelocity()
+       {
+               double velocity = 0.0;
+
+               if ( m_velocityArray.size() < 2 ) {
+                       return 0.0;
+               }
+
+               // \88Ú\93®\95½\8bÏ\92l
+               for ( VelocityyArray::const_iterator it = m_velocityArray.begin(); it != m_velocityArray.end(); ++it ) {
+                       velocity += it->velocity;
+               }
+               velocity /= m_velocityArray.size();
+
+               // 1\95b\93\96\82½\82è\82Ì\88Ú\93®\97Ê\82ð\8eZ\8fo\82·\82é
+               const uint32_t dt = m_velocityArray.back().timeStamp - m_velocityArray.front().timeStamp;
+               const double normalizedDeltaTime = (double)k_velocityMeasuringDistance / (double)dt;
+               return velocity / normalizedDeltaTime;
+       }
+
+       inline void removeOldItem(const uint32_t timeStamp)
+       {
+               VelocityyArray::const_iterator removeMark = m_velocityArray.end();
+               for ( VelocityyArray::const_iterator it = m_velocityArray.begin(); it != m_velocityArray.end(); ++it ) {
+                       const uint32_t dt = timeStamp - it->timeStamp;
+                       if ( dt <= k_velocityMeasuringDistance ) {
+                               break;
+                       }
+                       removeMark = it;
+               }
+               if ( removeMark != m_velocityArray.end() ) {
+                       m_velocityArray.erase( m_velocityArray.begin(), removeMark );
+               }
+       }
+
+       inline void updateVelocityLog()
+       {
+               m_velocityLog.push_back( calcVelocity() );
+               if ( 3 < m_velocityLog.size() ) {
+                       m_velocityLog.pop_front();
+               }
+       }
+
+       inline double fastestVelocity() const
+       {
+               double fastest = 0.0;
+
+               VelocityLog::const_iterator it = std::min_element( m_velocityLog.begin(), m_velocityLog.end() );
+               if ( it != m_velocityLog.end() ) {
+                       fastest = *it;
+               }
+               return fastest;
+       }
+};
index 5fbf071..eb5380b 100644 (file)
@@ -172,7 +172,7 @@ void GVOWorldMap::drawMap( HDC hdc, const GVOShip& ship )
        // \90j\98H\97\\91ª\90ü\82ð\95`\89æ
        if ( ship.isVectorEnabled() ) {
                const int penWidth = max( 1, int(1 * m_viewScale) );
-               HPEN courseLinePen = ::CreatePen( PS_SOLID, penWidth, RGB( 255, 0, 0 ) );
+               HPEN courseLinePen = ::CreatePen( PS_SOLID, penWidth, RGB( 255, 0, 255 ) );
                HGDIOBJ oldPen = ::SelectObject( hdc, courseLinePen );
 
                const LONG k_lineLength = k_worldHeight;