1919#include " PreRTS.h"
2020#include " GameClient/Intro.h"
2121
22+ #include " Common/FramePacer.h"
2223#include " Common/GameLOD.h"
2324
2425#include " GameClient/Display.h"
26+ #include " GameClient/DisplayStringManager.h"
2527#include " GameClient/GameWindowManager.h"
28+ #include " GameClient/GlobalLanguage.h"
29+ #include " GameClient/Image.h"
2630
2731
32+ Intro::DisplayEntity::~DisplayEntity ()
33+ {
34+ TheDisplayStringManager->freeDisplayString (displayString);
35+ }
36+
2837Intro::Intro ()
2938 : m_currentState(IntroState_Start)
3039 , m_allowedStateFlags(0 )
3140 , m_waitUntilMs(0 )
41+ , m_fadeValue(0 .0f )
3242{
3343 if (TheGlobalData->m_playIntro )
3444 {
45+ // Please be kind and do not remove the EA logo movie. This game was built by EA. It lasts just 3 seconds.
3546 m_allowedStateFlags |= 1u << IntroState_EALogoMovie;
47+ // Please be kind and do not remove the custom logo screen when building on top of the work of The Super Hackers.
48+ m_allowedStateFlags |= 1u << IntroState_TheSuperHackersWait;
49+ m_allowedStateFlags |= 1u << IntroState_TheSuperHackers;
3650 }
3751
3852 if (TheGlobalData->m_playSizzle )
@@ -69,13 +83,23 @@ void Intro::update()
6983 switch (m_currentState)
7084 {
7185 case IntroState_EALogoMovie: doEALogoMovie (); break ;
86+ case IntroState_TheSuperHackersWait: doAsyncWait (800 ); break ;
87+ case IntroState_TheSuperHackers: doTheSuperHackers (); break ;
7288 case IntroState_SizzleMovieWait: doAsyncWait (1000 ); break ;
7389 case IntroState_SizzleMovie: doSizzleMovie (); break ;
7490 case IntroState_Done: doPostIntro (); break ;
7591 }
7692 }
7793}
7894
95+ void Intro::draw ()
96+ {
97+ switch (m_currentState)
98+ {
99+ case IntroState_TheSuperHackers: drawDisplayEntities (); break ;
100+ }
101+ }
102+
79103void Intro::doEALogoMovie ()
80104{
81105 TheWritableGlobalData->m_allowExitOutOfMovies = FALSE ;
@@ -85,6 +109,110 @@ void Intro::doEALogoMovie()
85109 TheDisplay->playMovie (" EALogoMovie640" );
86110}
87111
112+ void Intro::doTheSuperHackers ()
113+ {
114+ struct Setting
115+ {
116+ Setting ()
117+ : imageName(nullptr )
118+ , text(nullptr )
119+ , screenHeightFactor(0 .5f )
120+ , sizeX(10 )
121+ , sizeY(10 )
122+ , bold(false )
123+ , centered(false )
124+ {}
125+
126+ const Char* imageName;
127+ const WideChar* text;
128+ Real screenHeightFactor;
129+ Int sizeX;
130+ Int sizeY;
131+ Bool bold;
132+ Bool centered;
133+ };
134+
135+ std::vector<Setting> settings;
136+
137+ {
138+ // China Hacker image
139+ Setting setting;
140+ setting.imageName = " SNHacker2_L" ;
141+ setting.screenHeightFactor = 0 .15f ;
142+ setting.sizeX = (Int)(122 * 0 .70f );
143+ setting.sizeY = (Int)(98 * 0 .70f );
144+ settings.push_back (setting);
145+ }
146+ {
147+ // Team name
148+ Setting setting;
149+ setting.text = L" The Super Hackers" ;
150+ setting.screenHeightFactor = 0 .35f ;
151+ setting.sizeY = 30 ;
152+ setting.bold = true ;
153+ setting.centered = true ;
154+ settings.push_back (setting);
155+ }
156+ {
157+ // Website
158+ Setting setting;
159+ setting.text = L" www.github.com/TheSuperHackers" ;
160+ setting.screenHeightFactor = 0 .45f ;
161+ setting.sizeY = 15 ;
162+ setting.bold = false ;
163+ setting.centered = true ;
164+ settings.push_back (setting);
165+ }
166+ {
167+ // Code contributors with 10 or more commits to main branch.
168+ // Sort by alphabet or commit count.
169+ Setting setting;
170+ setting.text =
171+ L" bobtista "
172+ L" Caball009 "
173+ L" feliwir "
174+ L" helmutbuhler\n "
175+ L" JohnsterID "
176+ L" Mauller "
177+ L" OmniBlade "
178+ L" SkyAero\n "
179+ L" slurmlord "
180+ L" Stubbjax "
181+ L" tomsons26 "
182+ L" xezon\n " ;
183+ setting.screenHeightFactor = 0 .55f ;
184+ setting.sizeY = 12 ;
185+ setting.bold = false ;
186+ setting.centered = true ;
187+ settings.push_back (setting);
188+ }
189+
190+ m_displayEntities.resize (settings.size ());
191+
192+ for (size_t i = 0 ; i < m_displayEntities.size (); ++i)
193+ {
194+ Setting& s = settings[i];
195+ DisplayEntity& e = m_displayEntities[i];
196+ e.sizeX = TheGlobalLanguageData->adjustFontSize (s.sizeX );
197+ e.sizeY = TheGlobalLanguageData->adjustFontSize (s.sizeY );
198+ if (s.text != nullptr )
199+ {
200+ e.displayString = TheDisplayStringManager->newDisplayString ();
201+ e.displayString ->setText (s.text );
202+ e.displayString ->setFont (TheFontLibrary->getFont (" Cascadia Code" , e.sizeY , s.bold ));
203+ e.displayString ->setWordWrapCentered (s.centered );
204+ }
205+ if (s.imageName != nullptr )
206+ {
207+ e.image = TheMappedImageCollection->findImageByName (s.imageName );
208+ }
209+ e.screenHeightFactor = s.screenHeightFactor ;
210+ }
211+
212+ doAsyncWait (3000 );
213+ m_fadeValue = 0 .0f ;
214+ }
215+
88216void Intro::doSizzleMovie ()
89217{
90218 TheWritableGlobalData->m_allowExitOutOfMovies = TRUE ;
@@ -104,3 +232,56 @@ void Intro::doAsyncWait(UnsignedInt milliseconds)
104232{
105233 m_waitUntilMs = timeGetTime () + milliseconds;
106234}
235+
236+ void Intro::drawDisplayEntities ()
237+ {
238+ const Real alpha = 255 .0f * clamp (0 .0f , m_fadeValue, 1 .0f );
239+ const Color color = GameMakeColor (255 , 255 , 255 , (Int)alpha);
240+ const Color dropColor = GameMakeColor (255 , 255 , 255 , 0 );
241+ const Int screenWidth = TheDisplay->getWidth ();
242+ const Int screenHeight = TheDisplay->getHeight ();
243+
244+ for (size_t i = 0 ; i < m_displayEntities.size (); ++i)
245+ {
246+ DisplayEntity& e = m_displayEntities[i];
247+ if (e.displayString != nullptr )
248+ {
249+ ICoord2D pos;
250+ e.displayString ->getSize (&pos.x , &pos.y );
251+ pos.x = (screenWidth / 2 ) - (pos.x / 2 );
252+ pos.y = (Int)(e.screenHeightFactor * screenHeight);
253+ e.displayString ->setWordWrap (screenWidth);
254+ e.displayString ->draw (pos.x , pos.y , color, dropColor);
255+ }
256+ if (e.image != nullptr )
257+ {
258+ IRegion2D region;
259+ region.lo .x = (screenWidth / 2 ) - (e.sizeX / 2 );
260+ region.hi .x = (screenWidth / 2 ) + (e.sizeX / 2 );
261+ region.lo .y = (Int)(e.screenHeightFactor * screenHeight);
262+ region.hi .y = region.lo .y + e.sizeY ;
263+ TheDisplay->drawImage (e.image , region.lo .x , region.lo .y , region.hi .x , region.hi .y , color);
264+ }
265+ }
266+
267+ constexpr const Real fadeInMs = 500 .f ;
268+ constexpr const Real fadeOutMs = 125 .f ;
269+
270+ if (timeGetTime () + fadeOutMs > m_waitUntilMs)
271+ {
272+ if (m_fadeValue > 0 .0f )
273+ {
274+ // Fade out
275+ m_fadeValue -= TheFramePacer->getUpdateTime () * (1000 .f / fadeOutMs);
276+ if (m_fadeValue < 0 .0f )
277+ m_fadeValue = 0 .0f ;
278+ }
279+ }
280+ else if (m_fadeValue < 1 .0f )
281+ {
282+ // Fade in
283+ m_fadeValue += TheFramePacer->getUpdateTime () * (1000 .f / fadeInMs);
284+ if (m_fadeValue > 1 .0f )
285+ m_fadeValue = 1 .0f ;
286+ }
287+ }
0 commit comments